Add very basic attack animation
authorStan_Lewry <stanley.jml@gmail.com>
Sat, 31 Aug 2024 16:41:19 +0000 (17:41 +0100)
committerStan_Lewry <stanley.jml@gmail.com>
Sat, 31 Aug 2024 16:41:19 +0000 (17:41 +0100)
combat.cpp

index 6fc0f39..59b2cd9 100644 (file)
@@ -27,7 +27,7 @@ struct Character {
        // how to handle "moves"
        S2DE::Vec2<float> combatMoveDestination = { 0.0f, 0.0f };
 
-       int basicAttackRange = 1.5f;
+       int basicAttackRange = 1.75f;
 
        bool canMove = true;
        bool canAttack = true;
@@ -68,6 +68,7 @@ static const double frameTime = 1.0f / 60.0f;
 SDL_Texture* arrowSprite = nullptr;
 SDL_Texture* indicatorSprite = nullptr;
 SDL_Texture* indicatorRedSprite = nullptr;
+SDL_Texture* hitAnim = nullptr;
 
 static constexpr int arenaWidth = 100;
 static constexpr int arenaHeight = 100;
@@ -310,6 +311,8 @@ void initCombatScene()
        arrowSprite = S2DE::loadTexture("assets/arrow.png", &renderer);
        indicatorSprite = S2DE::loadTexture("assets/little_indicator.png", &renderer);
        indicatorRedSprite = S2DE::loadTexture("assets/little_indicator_red.png", &renderer);
+       hitAnim = S2DE::loadTexture("assets/hit_anim_1.png", &renderer);
+
 
        //Character player = { true, "Player", 100, 100, 50, 50, 10.0f, 3.0f, player_sheet, { 23.0f, 13.0f } };
        Character player;
@@ -405,55 +408,82 @@ void moveToPosition(Character* c, S2DE::Vec2<float> destination, float speed) {
 void actionSelectState(double delta) {
        S2DE::updateInputState(&inputState);
 
-       // handle inputs
-       if (inputState.up) {
-               inputState.up = false;
-               currentAction--;
-               if (currentAction < 0) currentAction = numActions - 1;
-       }
-       else if (inputState.down) {
-               inputState.down = false;
-               currentAction++;
-               if (currentAction > numActions - 1) currentAction = 0;
-       }
-       else if (inputState.rtrn) {
-               inputState.rtrn = false;
-               switch (currentAction) {
-               case 0:
-                       if (activeCombatant->canMove) {
-                               currentCombatState = PLAYER_MOVE;
-                               moveCursorPos = activeCombatant->position;
-                       }
-                       break;
-               case 1: // attack selected
-                       if (activeCombatant->canAttack) {
-                               // filter the targets - Have to do it here too in case the player attacks without moving?
-                               targets.clear();
-                               for (auto& c : combatants) {
-                                       if (!c.allied && c.alive) {
-                                               float dist = distance(activeCombatant->position, c.position);
-                                               if (dist <= activeCombatant->basicAttackRange) {
-                                                       targets.push_back(&c);
+       static double animTimer = 0;
+       double animFramerate = 1.0 / 10.0;
+
+
+       frameTimer += delta;
+       animTimer += delta;
+
+       static int animFrame = 0;
+       int animFrameSize = 48;
+
+       if (frameTimer > frameTime) {
+
+               frameTimer = 0;
+               // handle inputs
+               if (inputState.up) {
+                       inputState.up = false;
+                       currentAction--;
+                       if (currentAction < 0) currentAction = numActions - 1;
+               }
+               else if (inputState.down) {
+                       inputState.down = false;
+                       currentAction++;
+                       if (currentAction > numActions - 1) currentAction = 0;
+               }
+               else if (inputState.rtrn) {
+                       inputState.rtrn = false;
+                       switch (currentAction) {
+                       case 0:
+                               if (activeCombatant->canMove) {
+                                       currentCombatState = PLAYER_MOVE;
+                                       moveCursorPos = activeCombatant->position;
+                               }
+                               break;
+                       case 1: // attack selected
+                               if (activeCombatant->canAttack) {
+                                       // filter the targets - Have to do it here too in case the player attacks without moving?
+                                       targets.clear();
+                                       for (auto& c : combatants) {
+                                               if (!c.allied && c.alive) {
+                                                       float dist = distance(activeCombatant->position, c.position);
+                                                       if (dist <= activeCombatant->basicAttackRange) {
+                                                               targets.push_back(&c);
+                                                       }
                                                }
                                        }
+
+                                       currentCombatState = SELECT_TARGET;
                                }
+                               break;
+                       case 2: // end selected
+                               currentCombatState = TURN_ORDER;
+                               break;
 
-                               currentCombatState = SELECT_TARGET;
+                       default:
+                               inputState.quit = true;
+                               break;
                        }
-                       break;
-               case 2: // end selected
-                       currentCombatState = TURN_ORDER;
-                       break;
-
-               default:
-                       inputState.quit = true;
-                       break;
                }
        }
 
+       if (animTimer > animFramerate) {
+               animTimer = 0;
+               animFrame += 1;
+               if (animFrame > 4) animFrame = 0;
+       }
+       
+       
+       
        SDL_RenderClear(renderer);
        renderCombat();
        renderUIFull();
+
+       /*SDL_Rect animDRect = { 0, 0, 96, 96 };
+       SDL_Rect animSRect = { 48 * animFrame, 0, 48, 48 };
+       S2DE::renderTexture(&renderer, &hitAnim, &animSRect, &animDRect);*/
+
        SDL_RenderPresent(renderer);
 }
 
@@ -635,25 +665,56 @@ void selectAttackTarget(double delta) {
 void doAttack(double delta) {
        // for now just subtract the combatants' dmg from the targets hp and move on
        
+       static int animFrame = 0;
+       static double animTimer = 0;
+       static const double animFrameRate = 1.0 / 10.0;
+       
+
+       animTimer += delta;
+
+       Character* target = targets.at(currentTargetIdx);
 
        if (currentTargetIdx == -1) {
                // AOE, apply to all targets in range ?
        }
        else {
-               Character* target = targets.at(currentTargetIdx);
-               target->currentHP -= activeCombatant->attack;
+               
+               if (animTimer > animFrameRate) {
+                       animTimer = 0;
+                       animFrame += 1;
+
+                       if (animFrame > 4) {
+                               // anim is complete, apply damage and move on.
+                               // reset timers etc.
+                               target->currentHP -= activeCombatant->attack;
+
+                               if (target->currentHP <= 0) {
+                                       target->alive = false;
+                                       target->currentHP = 0;
+                               }
+
 
-               if (target->currentHP <= 0) {
-                       target->alive = false;
-                       target->currentHP = 0;
+                               animFrame = 0;
+                               targets.clear();
+                               
+                               currentCombatState = ACTION_SELECT;
+                               activeCombatant->canAttack = false;
+                       }
                }
        }
+       
+       // render the attacking anim
+
+       SDL_RenderClear(renderer);
 
+       renderCombat();
+       S2DE::Rect animDRect = S2DE::worldToScreenRect(&combatCam, &target->position, 2, WINDOW_WIDTH, WINDOW_HEIGHT, 32, 32);
+       S2DE::Rect animSRect = { 48 * animFrame, 0, 48, 48 };
+       S2DE::renderTexture(&renderer, &hitAnim, &animSRect, &animDRect);
 
+       renderUIFull();
 
-       targets.clear();
-       currentCombatState = ACTION_SELECT;
-       activeCombatant->canAttack = false;
+       SDL_RenderPresent(renderer);
 }