bool FlifHandler::read( QImage *img_pointer ) { //Read data on first frame if( !loaded() ) { auto data = device()->readAll(); if( !decoder.decodeMemory( data.constData(), data.size() ) ) return false; } frame++; if( imageCount() <= frame ) return false; auto img = decoder.getImage( frame ); QImage out( img.getWidth(), img.getHeight(), QImage::Format_ARGB32 ); auto buffer = std::make_unique<uint8_t[]>( out.width() * 4 ); for( int iy=0; iy<out.height(); iy++ ) { img.readRowRgba8( iy, buffer.get(), out.width() * 4 ); auto line = (QRgb*)out.scanLine( iy ); for( int ix=0; ix<out.width(); ix++ ) line[ix] = qRgba( buffer[ix*4+0], buffer[ix*4+1], buffer[ix*4+2], buffer[ix*4+3] ); } lastImageDelay = img.getFrameDelay(); *img_pointer = out; return true; }
uint32 VideoDecoder::getFrameWaitTime() { int32 waitTime = (getFrameDelay() + getAudioLag()) / 100; if (waitTime < 0) return 0; return waitTime; }
void Goblin::senseDistance(int wallX, int level){ // +50 lets it overlap castle a bit, for some depth float distance = spriteData.x + 50 - wallX; float maxDistance = GAME_WIDTH - wallX + 50; // change speed based on distance from wall and framedelay // if at tower do not execute large if else if if(distance > 0){ if(distance/maxDistance < .1) { velocity.x = -goblinNS::SPEED - 45; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_9); } else if(distance/maxDistance < .2) { velocity.x = -goblinNS::SPEED - 40; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_8); } else if(distance/maxDistance < .3) { velocity.x = -goblinNS::SPEED - 35; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_7); } else if(distance/maxDistance < .4) { velocity.x = -goblinNS::SPEED - 30; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_6); } else if(distance/maxDistance < .5){ velocity.x = -goblinNS::SPEED - 25; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_5); } else if(distance/maxDistance < .6) { velocity.x = -goblinNS::SPEED - 20; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_4); } else if(distance/maxDistance < .7) { velocity.x = -goblinNS::SPEED - 15; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_3); } else if(distance/maxDistance < .8) { velocity.x = -goblinNS::SPEED - 10; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_2); } else { velocity.x = -goblinNS::SPEED - 5; setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY_1); } } else { velocity.x = 0; setFrames(goblinNS::ATTACK_START_FRAME, goblinNS::ATTACK_END_FRAME); setFrameDelay(goblinNS::GOBLIN_ANIMATION_DELAY); } velocity.x *= level * 0.85; //velocity.x *= .15; setFrameDelay(getFrameDelay() / level); }
// Loads the animation using data from a JSON structure void Animation::deserialize(Json::Value &configData) { std::string frame = DataManager::getString(configData, "frame", getFrameName()); std::string extension = DataManager::getString(configData, "ext", getFrameExtension()); int count = DataManager::getInt (configData, "frames", getFrameCount()); float delay = DataManager::getFloat (configData, "delay", getFrameDelay()); init(frame, extension, count, delay); setName (DataManager::getString (configData, "name", getName())); setLooping (DataManager::getBool (configData, "loop", isLooping())); allowEventGeneration(DataManager::getBool (configData, "alert", isGeneratingEvents())); }
void cMobile::draw(int cellx, int celly, int leftClip, int topClip, int rightClip, int bottomClip) { //return; // Don't draw yet // See if the current action expired if (currentActionEnd_ != 0 && currentActionEnd_ < Utilities::getTicks()) { freeSequence(); // Free current surface currentActionEnd_ = 0; // Reset end time currentAction_ = getIdleAction(); } // Refresh the sequence if (!sequence_) { refreshSequence(); } // Modify cellx/celly based on the smooth move settings // Smooth move handling. if (smoothMoveEnd != 0) { int moveProgress = smoothMoveTime - (smoothMoveEnd - Utilities::getTicks()); if (moveProgress < 0 || moveProgress >= (int)smoothMoveTime) { smoothMoveEnd = 0; } else { if (moveProgress <= 0) { cellx += drawxoffset; celly += drawyoffset; frame = 0; } else { float factor = 1.0f - (float)moveProgress / (float)smoothMoveTime; cellx += (int)(factor * (float)drawxoffset); celly += (int)(factor * (float)drawyoffset); if (sequence_) { frame = (int)(sequence_->frameCount() * factor); } } } } // Draw if (sequence_) { // Skip to next frame if (smoothMoveEnd == 0 && nextFrame < Utilities::getTicks()) { if (++frame >= sequence_->frameCount()) { frame = 0; } nextFrame = Utilities::getTicks() + getFrameDelay(); } // The anims facing right are generated by flipping the ones facing left bool flip = (direction_ > 0 && direction_ < 4); sequence_->draw(frame, cellx, celly, flip); } }
void cMobile::refreshSequence() { if (sequence_) { sequence_->decref(); } sequence_ = Animations->readSequence(body_, currentAction_, direction_, hue_, partialHue_); // Try to maintain the flow of the animation if (sequence_ && frame >= sequence_->frameCount()) { frame = 0; nextFrame = Utilities::getTicks() + getFrameDelay(); } }
int32 VideoDecoder::getAudioLag() { if (!_fileStream) return 0; /* No audio. Calculate the lag by how much time has gone by since the first frame and how much time *should* have passed. */ int32 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100; int32 videoTime = _videoInfo.currentFrame * getFrameDelay(); return videoTime - audioTime; }
int32 DXADecoderWithSound::getAudioLag() { if (!_fileStream) return 0; if (!_mixer->isSoundHandleActive(*_bgSoundHandle)) return 0; int32 frameDelay = getFrameDelay(); int32 videoTime = _videoInfo.currentFrame * frameDelay; int32 audioTime; audioTime = (((int32) _mixer->getSoundElapsedTime(*_bgSoundHandle)) * 100); return videoTime - audioTime; }
void cMobile::draw(int cellx, int celly, int leftClip, int topClip, int rightClip, int bottomClip) { // Save the original cellx, celly for the greyed out stuff int orgCellX = cellx; int orgCellY = celly; static int cellXOffset = 0; static int cellYOffset = 0; if (Config->gameHideMobiles()) { return; } // Test for smoother player movement if (this == Player) { cellx = WorldView->x() + WorldView->width() / 2; celly = WorldView->y() + WorldView->height() / 2; } cellx += cellXOffset; celly += cellYOffset; // See if the current action expired if (currentActionEnd_ != 0 && currentActionEnd_ < Utilities::getTicks()) { // Don't cancel the movement action while we're still moving -or- have movement requests left if (this != Player || ((!WorldView->isMoving() || WorldView->isMovementBlocked()) && (!UoSocket || UoSocket->sequenceQueueLength() == 0))) { freeSequence(); // Free current surface currentActionEnd_ = 0; // Reset end time currentAction_ = getIdleAction(); } } // Refresh the sequence if (!sequence_) { refreshSequence(); } float alpha = 1.0f; // Modify cellx/celly based on the smooth move settings // Smooth move handling. if (smoothMoveEnd != 0) { int moveProgress = smoothMoveTime - (smoothMoveEnd - Utilities::getTicks()); if (moveProgress < 0 || moveProgress >= (int)smoothMoveTime) { smoothMoveEnd = 0; World->removeEntity(this); World->addEntity(this); } else if (this != Player) { if (moveProgress <= 0) { cellx += drawxoffset; celly += drawyoffset; } else { float factor = 1.0f - (float)moveProgress / (float)smoothMoveTime; cellx += (int)(factor * (float)drawxoffset); celly += (int)(factor * (float)drawyoffset); } } } static bool inGreyDraw = false; static bool inBlurDraw = false; if (isHidden()) { glPushAttrib(GL_ENABLE_BIT); glEnable(GL_ALPHA_TEST); // Make sure that transparent pixels wont touch our stencil buffer glAlphaFunc(GL_GREATER, 0.0f); glEnable(GL_STENCIL_TEST); // Enable per-pixel stencil testing glStencilFunc(GL_EQUAL, 1, 1); // Draw if stencil buffer is not zero glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); if (!inGreyDraw) { glClearStencil(1); glClear(GL_STENCIL_BUFFER_BIT); } static uint nextPeak = 0; static uint lastPeak = 0; static bool peakDirection = false; uint time = Utilities::getTicks(); if (time >= nextPeak) { lastPeak = Utilities::getTicks(); nextPeak = lastPeak + 1500 + Random->randInt(1000); peakDirection = !peakDirection; } alpha = (nextPeak - Utilities::getTicks()) / (float)(nextPeak - lastPeak); if (peakDirection) { alpha = 1.0f - alpha; } if (inGreyDraw) { if (inBlurDraw) { alpha *= 0.5f; } else { alpha *= 0.8f; } } else { GLWidget->enableGrayShader(); alpha = 0.8 * (1.0f - alpha); // Invert alpha value } } // Draw if (sequence_) { // Only advance to the next frame if we're not beyond the end of this action if (currentActionEnd_ != 0 && currentActionEnd_ >= Utilities::getTicks()) { // Skip to next frame if (nextFrame < Utilities::getTicks()) { if (++frame >= sequence_->frameCount()) { frame = 0; } nextFrame = Utilities::getTicks() + getFrameDelay(); } } // The anims facing right are generated by flipping the ones facing left bool flip = (direction_ >= 0 && direction_ < 4); // Mounts come always first if (!isHidden()) { if ((bodyType() == HUMAN || bodyType() == EQUIPMENT) && equipment[LAYER_MOUNT] && equipmentSequences[LAYER_MOUNT]) { // Only advance to the next frame if we're not beyond the end of this action if (currentActionEnd_ != 0 && currentActionEnd_ >= Utilities::getTicks()) { // Skip to next frame if (nextMountFrame < Utilities::getTicks()) { if (++mountFrame >= equipmentSequences[LAYER_MOUNT]->frameCount()) { mountFrame = 0; } nextMountFrame = Utilities::getTicks() + getMountFrameDelay(); } } mountFrame = frame; // Until something better is found equipmentSequences[LAYER_MOUNT]->draw(mountFrame, cellx, celly, flip, alpha); } sequence_->draw(frame, cellx, celly, flip, alpha); } // Draw the equipment if (bodyType() == HUMAN || bodyType() == EQUIPMENT) { // Reverse the draw order if hidden if (isHidden()) { uint count = 0; const int *order = drawOrder[direction_ % 8]; while (order[count] != -1) { count++; } for (int i = count - 1; i >= 0; --i) { enLayer layer = (enLayer)order[i]; if (layer < LAYER_VISIBLECOUNT && equipmentSequences[layer]) { // Oh great OSI... Another exception from the rule *sigh* // Don't draw Hair if we're wearing a gm robe if (layer != LAYER_HAIR || !equipmentSequences[LAYER_OUTERTORSO] || equipmentSequences[LAYER_OUTERTORSO]->body() != 0x3db) { equipmentSequences[layer]->draw(frame, cellx, celly, flip, alpha); } } } } else { const int *order = drawOrder[direction_ % 8]; while (*order != -1) { enLayer layer = (enLayer)*order; if (layer < LAYER_VISIBLECOUNT && equipmentSequences[layer]) { // Oh great OSI... Another exception from the rule *sigh* // Don't draw Hair if we're wearing a gm robe if (layer != LAYER_HAIR || !equipmentSequences[LAYER_OUTERTORSO] || equipmentSequences[LAYER_OUTERTORSO]->body() != 0x3db) { equipmentSequences[layer]->draw(frame, cellx, celly, flip, alpha); } } ++order; // Next layer } } } // If we're hidden, mount+body come last if (isHidden()) { sequence_->draw(frame, cellx, celly, flip, alpha); if ((bodyType() == HUMAN || bodyType() == EQUIPMENT) && equipment[LAYER_MOUNT] && equipmentSequences[LAYER_MOUNT]) { // Only advance to the next frame if we're not beyond the end of this action if (currentActionEnd_ != 0 && currentActionEnd_ >= Utilities::getTicks()) { // Skip to next frame if (nextMountFrame < Utilities::getTicks()) { if (++mountFrame >= equipmentSequences[LAYER_MOUNT]->frameCount()) { mountFrame = 0; } nextMountFrame = Utilities::getTicks() + getMountFrameDelay(); } } mountFrame = frame; // Until something better is found equipmentSequences[LAYER_MOUNT]->draw(mountFrame, cellx, celly, flip, alpha); } } } if (isHidden()) { glPopAttrib(); if (!inGreyDraw) { GLWidget->disableGrayShader(); } } drawx_ = cellx; drawy_ = celly; if (isHidden() && !inGreyDraw) { glClearStencil(1); glClear(GL_STENCIL_BUFFER_BIT); inGreyDraw = true; inBlurDraw = true; cellXOffset = 1; draw(orgCellX, orgCellY, leftClip, topClip, rightClip, bottomClip); cellXOffset = -1; draw(orgCellX, orgCellY, leftClip, topClip, rightClip, bottomClip); cellXOffset = 0; cellYOffset = 1; draw(orgCellX, orgCellY, leftClip, topClip, rightClip, bottomClip); cellYOffset = -1; draw(orgCellX, orgCellY, leftClip, topClip, rightClip, bottomClip); cellYOffset = 0; inBlurDraw = false; draw(orgCellX, orgCellY, leftClip, topClip, rightClip, bottomClip); inGreyDraw = false; } }