From 3761c1c810957bb276f7dbb69915d441323697f4 Mon Sep 17 00:00:00 2001 From: Stan_Lewry Date: Tue, 1 Oct 2024 11:22:27 +0100 Subject: [PATCH] Move player characters to global state. Add logic to show simple "being damaged" animation. Expand spell selection. Add "practice dummy" enemy. --- combat.cpp | 155 +++++++++++++++++++++------------------------------- globals.cpp | 36 ++++++++++++ globals.h | 59 +++++++++++++++++++- main.cpp | 1 + 4 files changed, 157 insertions(+), 94 deletions(-) diff --git a/combat.cpp b/combat.cpp index 3d8caa7..d91be2d 100644 --- a/combat.cpp +++ b/combat.cpp @@ -8,10 +8,6 @@ #include #include -enum SpellType { - BASIC_ATTACK, - SLASH -}; SpellType selectedSpell = BASIC_ATTACK; @@ -24,36 +20,6 @@ struct AttackAnim { std::map animLookup; - -struct Character { - bool allied; - std::string name; - int currentHP; - int maxHP; - int currentMP; - int maxMP; - int attack; - int defense; - int agility; // to determine move order - float moveDist; - - // animation stuff? - SDL_Texture* texture; - S2DE::Vec2 position; - // direction vector? - // how to handle "moves" - S2DE::Vec2 combatMoveDestination = { 0.0f, 0.0f }; - - int basicAttackRange = 1.75f; - - bool canMove = true; - bool canAttack = true; - - bool alive = true; - - SpellType basicAttackType = BASIC_ATTACK; -}; - std::vector combatants; int currentCombatantIndex = -1; Character* activeCombatant; @@ -64,6 +30,7 @@ int currentTargetIdx = 0; enum CombatState { TURN_ORDER, ACTION_SELECT, + ABILITY_SELECT, // select an ability or spell to cast PLAYER_MOVE, SELECT_TARGET, DO_ATTACK, @@ -255,8 +222,14 @@ void renderCombatants() { if (c.alive) { S2DE::Vec2 pos = c.position; S2DE::Rect charDRect = S2DE::worldToScreenRect(&combatCam, &pos, 2, WINDOW_WIDTH, WINDOW_HEIGHT, 32, 32); + + S2DE::Rect charSRect = { 0, 0, 32, 32 }; + if (c.beingHurt) { + charSRect.x += 32; + } + // disabled for now //if (c.allied) { // // do the looking logic only for allied characters @@ -337,66 +310,59 @@ void initCombatScene() animLookup[SLASH] = { slashAnim, 5, 48, 48 }; //Character player = { true, "Player", 100, 100, 50, 50, 10.0f, 3.0f, player_sheet, { 23.0f, 13.0f } }; - Character player; - player.allied = true; - player.name = "Player"; - player.maxHP = 100; - player.currentHP = player.maxHP; - player.maxMP = 50; - player.currentMP = player.maxMP; - player.agility = 10.0f; - player.moveDist = 3.0f; - player.texture = player_forward_texture; - player.position = { arenaCenter.x + 0.5f, arenaCenter.y + 2 }; - player.attack = 5; - player.defense = 5; + //Character player; + + eric->position = { arenaCenter.x + 0.5f, arenaCenter.y + 2 }; + monica->position = { arenaCenter.x - 0.5f, arenaCenter.y + 2 }; + + + //Character enemy; + //enemy.allied = false; + //enemy.name = "Bird"; + //enemy.maxHP = 25; + //enemy.currentHP = enemy.maxHP; + //enemy.maxMP = 10; + //enemy.currentMP = enemy.maxMP; + //enemy.agility = 5.0f; + //enemy.moveDist = 1.5f; + //enemy.texture = bird; + //enemy.position = { arenaCenter.x, arenaCenter.y - 2 }; + //enemy.attack = 2; + //enemy.defense = 2; + + //Character frog; + //frog.allied = false; + //frog.name = "Frog"; + //frog.currentHP = frog.maxHP = 10; + //frog.currentMP = frog.maxMP = 10; + //frog.agility = 2; + //frog.moveDist = 2.0f; + //frog.texture = frog_texture; + //frog.position = { arenaCenter.x - 1, arenaCenter.y - 2 }; + //frog.attack = 2; + //frog.defense = 2; + + /*combatants.push_back(enemy); + combatants.push_back(frog);*/ + + + Character dummy; + dummy.allied = false; + dummy.name = "Practice Dummy"; + dummy.currentHP = dummy.maxHP = 25; + dummy.currentMP = dummy.maxMP = 0; + dummy.agility = 0.0f; + dummy.moveDist = 0; + dummy.texture = practice_dummy_texture; + dummy.attack = 0; + dummy.defense = 0; + dummy.position = { arenaCenter.x, arenaCenter.y }; + + combatants.push_back(dummy); + + combatants.push_back(*eric); // push back copies of the players? + combatants.push_back(*monica); - Character monica; - monica.allied = true; - monica.name = "Monica"; - monica.maxHP = 100; - monica.currentHP = monica.maxHP; - monica.maxMP = 50; - monica.currentMP = monica.maxMP; - monica.agility = 8.0f; - monica.moveDist = 6.0f; - monica.texture = monica_texture; - monica.position = { arenaCenter.x - 0.5f, arenaCenter.y + 2 }; - monica.attack = 6; - monica.basicAttackType = SLASH; - monica.defense = 5; - - Character enemy; - enemy.allied = false; - enemy.name = "Bird"; - enemy.maxHP = 25; - enemy.currentHP = enemy.maxHP; - enemy.maxMP = 10; - enemy.currentMP = enemy.maxMP; - enemy.agility = 5.0f; - enemy.moveDist = 1.5f; - enemy.texture = bird; - enemy.position = { arenaCenter.x, arenaCenter.y - 2 }; - enemy.attack = 2; - enemy.defense = 2; - - Character frog; - frog.allied = false; - frog.name = "Frog"; - frog.currentHP = frog.maxHP = 10; - frog.currentMP = frog.maxMP = 10; - frog.agility = 2; - frog.moveDist = 2.0f; - frog.texture = frog_texture; - frog.position = { arenaCenter.x - 1, arenaCenter.y - 2 }; - frog.attack = 2; - frog.defense = 2; - - combatants.push_back(player); - combatants.push_back(monica); - combatants.push_back(enemy); - combatants.push_back(frog); - // calculates turn order. Can expand the lambda to support other things std::sort(combatants.begin(), combatants.end(), [](const Character& a, const Character& b) {return a.agility > b.agility; }); @@ -714,6 +680,8 @@ void doAttack(double delta) { animTimer = 0; animFrame += 1; + target->beingHurt = true; + if (animFrame > anim.numFrames) { // anim is complete, apply damage and move on. // reset timers etc. @@ -734,6 +702,7 @@ void doAttack(double delta) { currentCombatState = ACTION_SELECT; activeCombatant->canAttack = false; + target->beingHurt = false; } } } diff --git a/globals.cpp b/globals.cpp index 7689f2f..e52d17f 100644 --- a/globals.cpp +++ b/globals.cpp @@ -1,5 +1,8 @@ #include "globals.h" +Character* eric = new Character(); +Character* monica = new Character(); + SDL_Texture* environment_sheet = nullptr; SDL_Texture* player_sheet = nullptr; SDL_Texture* water_test_sheet = nullptr; @@ -11,6 +14,7 @@ SDL_Texture* bird = nullptr; SDL_Texture* monica_texture = nullptr; SDL_Texture* player_forward_texture = nullptr; SDL_Texture* frog_texture = nullptr; +SDL_Texture* practice_dummy_texture = nullptr; Mix_Music* background_music = nullptr; @@ -32,6 +36,7 @@ void initResources() font_grey = S2DE::loadTexture("assets/simple_6x8_grey.png", &renderer); ui_frame_sheet = S2DE::loadTexture(ui_frame_sheet_path, &renderer); bird = S2DE::loadTexture(bird_path, &renderer); + practice_dummy_texture = S2DE::loadTexture("assets/practice_dummy.png", &renderer); monica_texture = S2DE::loadTexture("assets/Monica_sprite.png", &renderer); player_forward_texture = S2DE::loadTexture("assets/player_forward.png", &renderer); @@ -39,3 +44,34 @@ void initResources() background_music = Mix_LoadMUS(bg_mus_path); } +void initPlayerParty() { + eric->allied = true; + eric->name = "Player"; + eric->maxHP = 100; + eric->currentHP = eric->maxHP; + eric->maxMP = 50; + eric->currentMP = eric->maxMP; + eric->agility = 10.0f; + eric->moveDist = 3.0f; + eric->texture = player_forward_texture; + eric->position = { 0.0f, 0.0f }; + eric->attack = 5; + eric->defense = 5; + eric->knownSpells = { THROW_ROCK }; + + monica->allied = true; + monica->name = "Monica"; + monica->maxHP = 100; + monica->currentHP = monica->maxHP; + monica->maxMP = 50; + monica->currentMP = monica->maxMP; + monica->agility = 8.0f; + monica->moveDist = 6.0f; + monica->texture = monica_texture; + monica->position = { 0.0f, 0.0f }; + monica->attack = 6; + monica->basicAttackType = SLASH; + monica->defense = 5; + + monica->knownSpells = { AIMED_SHOT, ARROW_RAIN }; +} \ No newline at end of file diff --git a/globals.h b/globals.h index 4d743e9..25aa7ab 100644 --- a/globals.h +++ b/globals.h @@ -25,10 +25,12 @@ extern SDL_Texture* bird; extern SDL_Texture* monica_texture; extern SDL_Texture* player_forward_texture; extern SDL_Texture* frog_texture; +extern SDL_Texture* practice_dummy_texture; extern Mix_Music* background_music; void initResources(); +void initPlayerParty(); extern S2DE::InputState inputState; @@ -54,4 +56,59 @@ enum GameState COMBAT }; -extern GameState gameState; \ No newline at end of file +extern GameState gameState; + + +enum SpellType { + + BASIC_ATTACK, // basic melee attack + SLASH, // slashing attack + THROW_ROCK, // basic ranged attack + + // elemental magics + FIREBALL, // single target fire attack + FIREBURST, // aoe fire attack + LIGHTNING_ZAP, // single target lightning attack + CHAIN_LIGHTNING,// aoe lightning attack + + // archery + AIMED_SHOT, // single target arrow attack + ARROW_RAIN, // archery aoe + + // thief + BACKSTAB, // melee attack that does more damage if the attacker is behind the target +}; + +struct Character { + bool allied; + std::string name; + int currentHP; + int maxHP; + int currentMP; + int maxMP; + int attack; + int defense; + int agility; // to determine move order + float moveDist; + + // animation stuff? + SDL_Texture* texture; + S2DE::Vec2 position; + bool beingHurt = false; + // direction vector? + S2DE::Vec2 combatMoveDestination = { 0.0f, 0.0f }; + + int basicAttackRange = 1.75f; + + bool canMove = true; + bool canAttack = true; + + bool alive = true; + + SpellType basicAttackType = BASIC_ATTACK; + + std::vector knownSpells; +}; + +extern Character* eric; +extern Character* monica; \ No newline at end of file diff --git a/main.cpp b/main.cpp index a86bab2..777221a 100644 --- a/main.cpp +++ b/main.cpp @@ -67,6 +67,7 @@ int main(int argc, char** args) { S2DE::initRendering("Dragon Survivors", WINDOW_WIDTH, WINDOW_HEIGHT, &window, &renderer); initResources(); + initPlayerParty(); initCombatScene(); world = new WorldCell * [WORLD_HEIGHT]; -- 2.20.1