#include "party.h" #include "consts.h" #include "mixer.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.getDirection()}); } members_.push_back(std::move(newMember)); game.setSpriteState(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.setSpriteState(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.setSpriteDirection(members_[i].spriteId, dir); } return; } else { game.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.setSpriteState(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.getTransformSystem().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.getTransformSystem().moveSprite(members_[i].spriteId, posdir.pos); game.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.setSpriteState(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.setSpriteState(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); } }