From 8d7ef2b2ae3ddff204f5934fe67c535d7f1345e9 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 3 Feb 2021 02:03:59 -0500 Subject: Converted Party into CharacterSystem --- src/animation_system.cpp | 8 +- src/character_system.cpp | 229 ++++++++++++++++++++++++++++++++++++++++++++++ src/character_system.h | 32 +++++++ src/main.cpp | 18 ++-- src/party.cpp | 231 ----------------------------------------------- src/party.h | 46 ---------- src/sprite.h | 17 ++++ src/system.h | 3 +- 8 files changed, 293 insertions(+), 291 deletions(-) create mode 100644 src/character_system.cpp create mode 100644 src/character_system.h delete mode 100644 src/party.cpp delete mode 100644 src/party.h (limited to 'src') diff --git a/src/animation_system.cpp b/src/animation_system.cpp index 3320e1d..cf34066 100644 --- a/src/animation_system.cpp +++ b/src/animation_system.cpp @@ -91,9 +91,11 @@ void AnimationSystem::tick(double dt) { animTimer_.accumulate(dt); while (animTimer_.step()) { for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { - sprite.animationFrame++; - if (sprite.animationFrame >= sprite.animations[sprite.animationId].size()) { - sprite.animationFrame = 0; + if (sprite.isAnimated) { + sprite.animationFrame++; + if (sprite.animationFrame >= sprite.animations[sprite.animationId].size()) { + sprite.animationFrame = 0; + } } } } diff --git a/src/character_system.cpp b/src/character_system.cpp new file mode 100644 index 0000000..64e2f3b --- /dev/null +++ b/src/character_system.cpp @@ -0,0 +1,229 @@ +#include "character_system.h" +#include "consts.h" +#include "mixer.h" +#include "sprite.h" +#include "game.h" +#include "transform_system.h" +#include "animation_system.h" + +void CharacterSystem::addSpriteToParty(int leaderId, int followerId) { + Sprite& leader = game_.getSprite(leaderId); + Sprite& follower = game_.getSprite(followerId); + + int index = leader.followers.size() + 1; + follower.trail = std::deque(PARTY_FRAME_DELAY * index, {.pos = follower.loc, .dir = follower.dir}); + + leader.followers.push_back(followerId); + + game_.getSystem().setSpriteAnimation(followerId, "still"); +} + +void CharacterSystem::moveSprite(int spriteId, Mixer& mixer, const Input& keystate) { + Sprite& sprite = game_.getSprite(spriteId); + Direction dir = sprite.dir; + + if (!keystate.up && !keystate.down && !keystate.left && !keystate.right) { + if (sprite.characterState != CharacterState::Running) { + if (sprite.characterState == CharacterState::Normal) { + game_.getSystem().setSpriteAnimation(spriteId, "still"); + for (int followerId : sprite.followers) { + game_.getSystem().setSpriteAnimation(followerId, "still"); + } + } + + return; + } + } else { + if (keystate.up) + { + dir = Direction::up; + } else if (keystate.down) + { + dir = Direction::down; + } + + if (keystate.left) + { + if (dir == Direction::up) { + dir = Direction::up_left; + } else if (dir == Direction::down) { + dir = Direction::down_left; + } else { + dir = Direction::left; + } + } else if (keystate.right) + { + if (dir == Direction::up) { + dir = Direction::up_right; + } else if (dir == Direction::down) { + dir = Direction::down_right; + } else { + dir = Direction::right; + } + } + } + + vec2i pLoc = sprite.loc; + game_.getSystem().setSpriteDirection(spriteId, dir); + + if (sprite.characterState == CharacterState::Crouching) { + for (int followerId : sprite.followers) { + game_.getSystem().setSpriteDirection(followerId, dir); + } + + return; + } + + int speed = MOVEMENT_SPEED; + if (sprite.characterState == CharacterState::Running) { + speed *= 2; + } else { + game_.getSystem().setSpriteAnimation(spriteId, "walk"); + for (int followerId : sprite.followers) { + game_.getSystem().setSpriteAnimation(followerId, "walk"); + } + } + + pLoc += (unitVecInDirection(dir) * speed); + + // Check collision. + const Map& map = game_.getMap(); + bool blocked = false; + + const vec2i UL_COL_BOX = { 8, 8 }; + const vec2i DR_COL_BOX = { 4, 0 }; + vec2i oldColPosUL = (sprite.loc - UL_COL_BOX) / map.getTileSize(); + vec2i newColPosUL = (pLoc - UL_COL_BOX) / map.getTileSize(); + vec2i oldColPosDR = (sprite.loc + DR_COL_BOX) / map.getTileSize(); + vec2i newColPosDR = (pLoc + DR_COL_BOX) / map.getTileSize(); + + if (dirHasDir(dir, Direction::right) && + newColPosDR.x() > oldColPosDR.x()) { + for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { + if (map.isBlocked(newColPosDR.x(), y)) { + blocked = true; + pLoc.x() = sprite.loc.x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } + + if (dirHasDir(dir, Direction::left) && + newColPosUL.x() < oldColPosUL.x()) { + for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { + if (map.isBlocked(newColPosUL.x(), y)) { + blocked = true; + pLoc.x() = sprite.loc.x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } + + if (dirHasDir(dir, Direction::down) && + newColPosDR.y() > oldColPosDR.y()) { + for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { + if (map.isBlocked(x, newColPosDR.y())) { + blocked = true; + pLoc.y() = sprite.loc.y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } + + if (dirHasDir(dir, Direction::up) && + newColPosUL.y() < oldColPosUL.y()) { + for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { + if (map.isBlocked(x, newColPosUL.y())) { + blocked = true; + pLoc.y() = sprite.loc.y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; + break; + } + } + } + + if (blocked && sprite.characterState == CharacterState::Running) { + stopRunning(spriteId); + mixer.playSound("../res/bump.wav"); + } + + // Move everything + if (pLoc != sprite.loc) { + game_.getSystem().moveSprite(spriteId, pLoc); + + for (int followerId : sprite.followers) { + Sprite& pNext = game_.getSprite(followerId); + const Movement& posdir = pNext.trail.front(); + game_.getSystem().moveSprite(followerId, posdir.pos); + game_.getSystem().setSpriteDirection(followerId, posdir.dir); + + pNext.trail.pop_front(); + pNext.trail.push_back({.pos = pLoc, .dir = dir}); + } + } +} + +void CharacterSystem::beginCrouch(int spriteId) { + Sprite& sprite = game_.getSprite(spriteId); + + if (sprite.characterState == CharacterState::Running) { + stopRunning(spriteId); + } else { + sprite.characterState = CharacterState::Crouching; + + game_.getSystem().setSpriteAnimation(spriteId, "crouch"); + for (int followerId : sprite.followers) { + game_.getSystem().setSpriteAnimation(followerId, "crouch"); + } + } +} + +void CharacterSystem::endCrouch(int spriteId) { + Sprite& sprite = game_.getSprite(spriteId); + + if (sprite.characterState == CharacterState::Crouching) { + sprite.characterState = CharacterState::Running; + + game_.getSystem().setSpriteAnimation(spriteId, "run"); + for (int followerId : sprite.followers) { + game_.getSystem().setSpriteAnimation(followerId, "run"); + + // Halve the movement buffer for the followers. + Sprite& follower = game_.getSprite(followerId); + std::deque newMove; + + while (!follower.trail.empty()) { + newMove.push_back(follower.trail.front()); + follower.trail.pop_front(); + follower.trail.pop_front(); + } + + follower.trail = std::move(newMove); + } + } +} + +void CharacterSystem::stopRunning(int spriteId) { + Sprite& sprite = game_.getSprite(spriteId); + sprite.characterState = CharacterState::Normal; + + // Double the movement buffer for the followers. + for (int followerId : sprite.followers) { + Sprite& follower = game_.getSprite(followerId); + + std::deque newMove; + vec2i lastPos = follower.loc; + + while (!follower.trail.empty()) { + Movement m1 = follower.trail.front(); + Movement m2 = m1; + m1.pos = (m1.pos + lastPos) / 2; + lastPos = m2.pos; + + newMove.push_back(m1); + newMove.push_back(m2); + follower.trail.pop_front(); + } + + follower.trail = std::move(newMove); + } +} diff --git a/src/character_system.h b/src/character_system.h new file mode 100644 index 0000000..ff5db02 --- /dev/null +++ b/src/character_system.h @@ -0,0 +1,32 @@ +#ifndef PARTY_H_826F91BA +#define PARTY_H_826F91BA + +#include "system.h" + +class Mixer; +class Game; +class Input; + +class CharacterSystem : public System { +public: + + static constexpr SystemKey Key = SystemKey::Character; + + CharacterSystem(Game& game) : game_(game) {} + + void addSpriteToParty(int leaderId, int followerId); + + void moveSprite(int spriteId, Mixer& mixer, const Input& keystate); + + void beginCrouch(int spriteId); + + void endCrouch(int spriteId); + +private: + + void stopRunning(int spriteId); + + Game& game_; +}; + +#endif /* end of include guard: PARTY_H_826F91BA */ diff --git a/src/main.cpp b/src/main.cpp index ea27511..3ac4d09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,19 +2,20 @@ #include #include "renderer.h" #include "game.h" -#include "party.h" #include "timer.h" #include "map.h" #include "mixer.h" #include "transform_system.h" #include "camera_system.h" #include "animation_system.h" +#include "character_system.h" void loop(Renderer& renderer, Mixer& mixer) { Game game; game.emplaceSystem(); game.emplaceSystem(); game.emplaceSystem(); + game.emplaceSystem(); Input keystate; @@ -28,20 +29,17 @@ void loop(Renderer& renderer, Mixer& mixer) { int kumaSprite = game.emplaceSprite(); game.getSystem().initSprite(kumaSprite, {32, 32}); game.getSystem().initSprite(kumaSprite, "../res/kuma_anim.txt", renderer); + game.getSystem().addSpriteToParty(lucasSprite, kumaSprite); int dusterSprite = game.emplaceSprite(); game.getSystem().initSprite(dusterSprite, {32, 32}); game.getSystem().initSprite(dusterSprite, "../res/duster_anim.txt", renderer); + game.getSystem().addSpriteToParty(lucasSprite, dusterSprite); int boneySprite = game.emplaceSprite(); game.getSystem().initSprite(boneySprite, {32, 32}); game.getSystem().initSprite(boneySprite, "../res/boney_anim.txt", renderer); - - Party party; - party.addMember(game, lucasSprite); - party.addMember(game, kumaSprite); - party.addMember(game, dusterSprite); - party.addMember(game, boneySprite); + game.getSystem().addSpriteToParty(lucasSprite, boneySprite); game.getSystem().setFollowingSprite(lucasSprite); game.getSystem().unlockCamera(); @@ -62,9 +60,9 @@ void loop(Renderer& renderer, Mixer& mixer) { if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) { return; } else if (e.type == SDL_KEYDOWN && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { - party.beginCrouch(game); + game.getSystem().beginCrouch(lucasSprite); } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { - party.endCrouch(game); + game.getSystem().endCrouch(lucasSprite); } } @@ -76,7 +74,7 @@ void loop(Renderer& renderer, Mixer& mixer) { inputTimer.accumulate(frameTime); while (inputTimer.step()) { - party.move(game, mixer, keystate); + game.getSystem().moveSprite(lucasSprite, mixer, keystate); } for (System& system : game.systems()) { diff --git a/src/party.cpp b/src/party.cpp deleted file mode 100644 index 8b0c34e..0000000 --- a/src/party.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "party.h" -#include "consts.h" -#include "mixer.h" -#include "transform_system.h" -#include "animation_system.h" - -void Party::addMember(Game& game, int spriteId) { - int index = members_.size(); - - PartyMember newMember; - newMember.spriteId = spriteId; - - if (index > 0) { - const Sprite& sprite = game.getSprite(spriteId); - - newMember.movement = std::deque(PARTY_FRAME_DELAY * index, {.pos = sprite.loc, .dir = sprite.dir}); - } - - members_.push_back(std::move(newMember)); - - game.getSystem().setSpriteAnimation(spriteId, "still"); -} - -void Party::move(Game& game, Mixer& mixer, const Input& keystate) { - if (members_.empty()) { - return; - } - - Direction dir = Direction::left; - - if (!keystate.up && !keystate.down && !keystate.left && !keystate.right) { - if (state_ == State::Running) { - dir = lastDir_; - } else { - if (state_ == State::Normal) { - for (int i = 0; i < members_.size(); i++) { - game.getSystem().setSpriteAnimation(members_[i].spriteId, "still"); - } - } - - return; - } - } else { - if (keystate.up) - { - dir = Direction::up; - } else if (keystate.down) - { - dir = Direction::down; - } - - if (keystate.left) - { - if (dir == Direction::up) { - dir = Direction::up_left; - } else if (dir == Direction::down) { - dir = Direction::down_left; - } else { - dir = Direction::left; - } - } else if (keystate.right) - { - if (dir == Direction::up) { - dir = Direction::up_right; - } else if (dir == Direction::down) { - dir = Direction::down_right; - } else { - dir = Direction::right; - } - } - } - - lastDir_ = dir; - - const Sprite& p1 = game.getSprite(members_[0].spriteId); - vec2i pLoc = p1.loc; - - if (state_ == State::Crouching) { - for (int i = 0; i < members_.size(); i++) { - game.getSystem().setSpriteDirection(members_[i].spriteId, dir); - } - - return; - } else { - game.getSystem().setSpriteDirection(members_[0].spriteId, dir); - } - - int speed = MOVEMENT_SPEED; - if (state_ == State::Running) { - speed *= 2; - } else { - for (int i = 0; i < members_.size(); i++) { - game.getSystem().setSpriteAnimation(members_[i].spriteId, "walk"); - } - } - - pLoc += (unitVecInDirection(dir) * speed); - - // Check collision. - const Map& map = game.getMap(); - bool blocked = false; - - const vec2i UL_COL_BOX = { 8, 8 }; - const vec2i DR_COL_BOX = { 4, 0 }; - vec2i oldColPosUL = (p1.loc - UL_COL_BOX) / map.getTileSize(); - vec2i newColPosUL = (pLoc - UL_COL_BOX) / map.getTileSize(); - vec2i oldColPosDR = (p1.loc + DR_COL_BOX) / map.getTileSize(); - vec2i newColPosDR = (pLoc + DR_COL_BOX) / map.getTileSize(); - - if (dirHasDir(dir, Direction::right) && - newColPosDR.x() > oldColPosDR.x()) { - for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { - if (map.isBlocked(newColPosDR.x(), y)) { - blocked = true; - pLoc.x() = p1.loc.x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; - break; - } - } - } - - if (dirHasDir(dir, Direction::left) && - newColPosUL.x() < oldColPosUL.x()) { - for (int y = newColPosUL.y(); y <= newColPosDR.y(); y++) { - if (map.isBlocked(newColPosUL.x(), y)) { - blocked = true; - pLoc.x() = p1.loc.x();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; - break; - } - } - } - - if (dirHasDir(dir, Direction::down) && - newColPosDR.y() > oldColPosDR.y()) { - for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { - if (map.isBlocked(x, newColPosDR.y())) { - blocked = true; - pLoc.y() = p1.loc.y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; - break; - } - } - } - - if (dirHasDir(dir, Direction::up) && - newColPosUL.y() < oldColPosUL.y()) { - for (int x = newColPosUL.x(); x <= newColPosDR.x(); x++) { - if (map.isBlocked(x, newColPosUL.y())) { - blocked = true; - pLoc.y() = p1.loc.y();//(newColPosDR * map.getTileSize() - (collisionBox / 2)).x() - 1; - break; - } - } - } - - if (blocked && state_ == State::Running) { - stopRunning(game); - mixer.playSound("../res/bump.wav"); - } - - // Move everything - if (pLoc != p1.loc) { - game.getSystem().moveSprite(members_[0].spriteId, pLoc); - - for (int i = 1; i < members_.size(); i++) { - const Sprite& pNext = game.getSprite(members_[i].spriteId); - const Movement& posdir = members_[i].movement.front(); - game.getSystem().moveSprite(members_[i].spriteId, posdir.pos); - game.getSystem().setSpriteDirection(members_[i].spriteId, posdir.dir); - - members_[i].movement.pop_front(); - members_[i].movement.push_back({.pos = pLoc, .dir = dir}); - } - } -} - -void Party::beginCrouch(Game& game) { - if (state_ == State::Running) { - stopRunning(game); - } else { - state_ = State::Crouching; - - for (int i = 0; i < members_.size(); i++) { - game.getSystem().setSpriteAnimation(members_[i].spriteId, "crouch"); - } - } -} - -void Party::endCrouch(Game& game) { - if (state_ == State::Crouching) { - state_ = State::Running; - - for (int i = 0; i < members_.size(); i++) { - game.getSystem().setSpriteAnimation(members_[i].spriteId, "run"); - - // Halve the movement buffer for the followers. - if (i > 0) { - std::deque newMove; - - while (!members_[i].movement.empty()) { - newMove.push_back(members_[i].movement.front()); - members_[i].movement.pop_front(); - members_[i].movement.pop_front(); - } - - members_[i].movement = std::move(newMove); - } - } - } -} - -void Party::stopRunning(Game& game) { - state_ = State::Normal; - - // Double the movement buffer for the followers. - for (int i = 1; i < members_.size(); i++) { - std::deque newMove; - vec2i lastPos = game.getSprite(members_[i].spriteId).loc; - - while (!members_[i].movement.empty()) { - Movement m1 = members_[i].movement.front(); - Movement m2 = m1; - m1.pos = (m1.pos + lastPos) / 2; - lastPos = m2.pos; - - newMove.push_back(m1); - newMove.push_back(m2); - members_[i].movement.pop_front(); - } - - members_[i].movement = std::move(newMove); - } -} diff --git a/src/party.h b/src/party.h deleted file mode 100644 index 59330c8..0000000 --- a/src/party.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PARTY_H_826F91BA -#define PARTY_H_826F91BA - -#include -#include -#include "game.h" - -class Mixer; - -class Party { -public: - - void addMember(Game& game, int spriteId); - - void move(Game& game, Mixer& mixer, const Input& keystate); - - void beginCrouch(Game& game); - - void endCrouch(Game& game); - -private: - - void stopRunning(Game& game); - - enum class State { - Normal, - Crouching, - Running - }; - - struct Movement { - vec2i pos; - Direction dir; - }; - - struct PartyMember { - int spriteId; - std::deque movement; - }; - - std::vector members_; - State state_ = State::Normal; - Direction lastDir_; -}; - -#endif /* end of include guard: PARTY_H_826F91BA */ diff --git a/src/sprite.h b/src/sprite.h index e842192..65a7a66 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -1,6 +1,7 @@ #ifndef SPRITE_H_70503825 #define SPRITE_H_70503825 +#include #include #include #include @@ -14,6 +15,17 @@ struct SpriteFrame { vec2i size; }; +enum class CharacterState { + Normal, + Crouching, + Running +}; + +struct Movement { + vec2i pos; + Direction dir; +}; + class Sprite { public: @@ -30,6 +42,11 @@ public: std::vector frames; std::vector> animations; std::map> nameDirToAnim; + + // Character + std::vector followers; + std::deque trail; + CharacterState characterState = CharacterState::Normal; }; #endif /* end of include guard: SPRITE_H_70503825 */ diff --git a/src/system.h b/src/system.h index c601bc7..6f09d61 100644 --- a/src/system.h +++ b/src/system.h @@ -4,7 +4,8 @@ enum class SystemKey { Transform, Camera, - Animation + Animation, + Character }; class System { -- cgit 1.4.1