diff --git a/Adventures in Lestoria/GhostOfPirateCaptain.cpp b/Adventures in Lestoria/GhostOfPirateCaptain.cpp index 9c9712b4..f9108b81 100644 --- a/Adventures in Lestoria/GhostOfPirateCaptain.cpp +++ b/Adventures in Lestoria/GhostOfPirateCaptain.cpp @@ -52,6 +52,7 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std enum PhaseName{ INIT, NORMAL, + AFTERIMAGE_FADEIN, }; enum CannonShotType{ @@ -75,6 +76,10 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std if(!m.B(A::FIRST_WAVE_COMPLETE)){ m.B(A::FIRST_WAVE_COMPLETE)=true; m.ForceSetPos(m.spawnPos); + m.SetupAfterImage(); + m.SetCollisionRadius(0.f); + m.F(A::CASTING_TIMER)=1.f; + SETPHASE(AFTERIMAGE_FADEIN); } } }}; @@ -160,5 +165,12 @@ void Monster::STRATEGY::GHOST_OF_PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std }break; } }break; + case AFTERIMAGE_FADEIN:{ + m.F(A::CASTING_TIMER)-=fElapsedTime; + if(m.F(A::CASTING_TIMER)<=0.f){ + SETPHASE(NORMAL); + m.SetCollisionRadius(m.GetOriginalCollisionRadius()); + } + }break; } } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index 18227a07..c5b48298 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -82,6 +82,8 @@ Monster::Monster(vf2d pos,MonsterData data,bool upperLevel,bool bossMob): monsterWalkSoundTimer=util::random(1.f); UpdateFacingDirection(game->GetPlayer()->GetPos()); animation.UpdateState(internal_animState,randomFrameOffset); + const vf2d¤tRect{GetFrame().GetSourceRect().size}; + afterImage.Create(currentRect.x,currentRect.y); } const vf2d&Monster::GetPos()const{ return pos; @@ -406,6 +408,29 @@ void Monster::Update(const float fElapsedTime){ animation.UpdateState(internal_animState,fElapsedTime); if(HasMountedMonster())mounted_animation.value().UpdateState(internal_mounted_animState,fElapsedTime); attackedByPlayer=false; + + #pragma region Afterimage Handling + const auto RemoveScanLine=[&](uint8_t scanLine){ + for(int x:std::ranges::iota_view(0,afterImage.Sprite()->width)){ + afterImage.Sprite()->SetPixel({x,scanLine},BLANK); + } + afterImage.Decal()->Update(); + }; + + //Scan Line goes through 1-(height-1) (odd numbers) first, then 0-22. + const bool ScanLineFinished{scanLine==afterImage.Sprite()->height}; + if(!ScanLineFinished){ + removeLineTimer-=fElapsedTime; + if(removeLineTimer<=0.f){ + removeLineTimer=TIME_BETWEEN_LINE_REMOVALS; + RemoveScanLine(scanLine); + scanLine+=2; + if(scanLine>afterImage.Sprite()->height-1&&scanLine%2==1){ + scanLine=0; + } + } + } + #pragma endregion } Direction Monster::GetFacingDirection()const{ return facingDirection; @@ -512,6 +537,7 @@ void Monster::Draw()const{ }; if(glowPurpleBuff.has_value())DrawBaseMonster(glowPurpleImageScale,{43,0,66,blendCol.a}); + DrawAfterImage:game->view.DrawRotatedDecal(afterImagePos,afterImage.Decal(),0.f,afterImage.Sprite()->Size()/2,{GetSizeMult(),GetSizeMult()},Pixel{0xFFDCDA}); DrawBaseMonster(imageScale,blendCol); if(overlaySprite.length()!=0){ if(glowPurpleBuff.has_value())DrawOverlayMonster(imageScale,{43,0,66,overlaySpriteTransparency}); @@ -574,8 +600,8 @@ void Monster::Draw()const{ #pragma endregion if(GameSettings::TerrainCollisionBoxesEnabled()&&IsSolid()&&solidFadeTimer>0.f){ - float distToPlayer=geom2d::line(game->GetPlayer()->GetPos(),GetPos()).length(); - const float collisionRadiusFactor=GetCollisionRadius()/12.f; + const float distToPlayer{geom2d::line(game->GetPlayer()->GetPos(),GetPos()).length()}; + const float collisionRadiusFactor{GetCollisionRadius()/12.f}; if(distToPlayer<24*3*collisionRadiusFactor){ game->DrawPie(game->view.WorldToScreen(GetPos()),GetCollisionRadius(),0.f,{255,0,0,uint8_t(128*(blendColAlpha/255.f)/sqrt(distToPlayer*collisionRadiusFactor))}); game->SetDecalMode(DecalMode::WIREFRAME); @@ -1676,4 +1702,13 @@ void Monster::SetLifetime(const float lifetime){ void Monster::ForceSetPos(vf2d pos){ this->pos=pos; Moved(); +} +void Monster::SetupAfterImage(){ + game->SetDrawTarget(afterImage.Sprite()); + game->Clear(BLANK); + game->DrawPartialSprite({},animation.GetFrame(internal_animState).GetSourceImage()->Sprite(),animation.GetFrame(internal_animState).GetSourceRect().pos,animation.GetFrame(internal_animState).GetSourceRect().size,1U,0U,{255,255,254}); //Off-white so that the sprite is rendered completely in white. + game->SetDrawTarget(nullptr); + afterImage.Decal()->Update(); + removeLineTimer=TIME_BETWEEN_LINE_REMOVALS; + scanLine=1U; } \ No newline at end of file diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index a7f6bb0c..b7c164f3 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -338,6 +338,12 @@ private: float collisionRadius{}; //The collision radius can be modified, it's just set initially to the monster database entry. //Ignores collision checking and sets the monster at the given position. void ForceSetPos(vf2d pos); + Renderable afterImage; + void SetupAfterImage(); + float removeLineTimer{}; + const float TIME_BETWEEN_LINE_REMOVALS{0.025f}; + uint8_t scanLine{24}; + vf2d afterImagePos{}; struct STRATEGY{ static std::string ERR; diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index 39d1a412..330e0cd7 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 3 #define VERSION_PATCH 0 -#define VERSION_BUILD 12001 +#define VERSION_BUILD 12003 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 0404f1da..a30b7d61 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ