#include "pch.h" #include "Player.h" #include "Game.h" #include <algorithm> int Player::m_Score{ 0 }; Player::Player(const Point2f startPos) : m_Hitbox{ startPos.x, startPos.y, 48, 56 } , m_HitBoxHeight{ 56 } , m_SpriteRect {0, 0, 80, 80} , m_ClimbSpeed{ 160.f } , m_CrawlSpeed{ 80.f } , m_WalkSpeed{ 240.0f } , m_RunSpeed { 480.0f } , m_MoveAcceleration{ 4000.f } , m_BrakeSpeed{ 4000.f } , m_BrakeSpeedHurt{ 400.f } , m_SpeedLimit { 200.f } , m_JumpSpeed{ 620.0f } , m_StandUpTimer { } , m_StandUpDelay { 0.1f } , m_LookTimer { } , m_LookDelay { 1.f } , m_JumpTimer{ } , m_MinJumpDuration{ 0.08f } , m_NormalJumpDuration{ 0.08f } , m_JumpOnEnemyDuration{ 0.24f } , m_Velocity{ } , m_GravityAcceleration{ 0, -981.0f * 2 } , m_ActionState{ ActionState::WALKING } , m_LastActionState{ ActionState::WALKING } , m_HurtTimer{ 0.0f } , m_HurtDuration{ 1.25f } , m_Power{ } , m_SpritesTexture { "Resources/Sprites/char_orange.png" } , m_ClipHeight{ 80.0f } , m_ClipWidth{ 80.0f } , m_AnimFirstFrameId{ 0 } , m_AnimLength{ 10 } , m_AnimLoop{ true } , m_NrFramesPerSec{ 20 } , m_AnimTime{ } , m_AnimFrame{ } , m_Direction { Direction::LEFT } , m_Controller { nullptr } , m_GrabbedTile{ nullptr } , m_LastGrabbedTile{ nullptr } , m_HitSFX{ "Resources/Sounds/hit.wav" } , m_JumpSFX{ "Resources/Sounds/jump.wav" } , m_LandSFX{ "Resources/Sounds/land.wav" } , m_GrabLedgeSFX{ "Resources/Sounds/grab.wav" } , m_GoldSmallSFX{ "Resources/Sounds/chime.wav" } , m_GoldBigSFX{ "Resources/Sounds/chime3.wav" } , m_GreenGem{ "Resources/Sounds/gem2.wav" } , m_BlueGem{ "Resources/Sounds/gem3.wav" } , m_RedGem{ "Resources/Sounds/gem4.wav" } , m_Lives{ 4 } , m_Bombs{ 5 } , m_Ropes{ 6 } { for (int i{}; i < int(Buttons::LENGTH); i++) { m_HeldInputs[i] = false; } m_LandSFX.SetVolume(0.5f); m_GrabLedgeSFX.SetVolume(0.5f); } Player::Player(SDL_GameController* gameController, const Point2f startPos) : Player{ startPos } { m_Controller = gameController; } Player::~Player() { //Controller is closed(deleted) in Game.cpp destructor. m_Controller = nullptr; } void Player::SetPosition(const Point2f& pos) { m_Hitbox.left = pos.x; m_Hitbox.bottom = pos.y; } std::vector<Point2f> Player::GetTopVertices() const { std::vector<Point2f> topVertices{ Point2f{ m_Hitbox.left, m_Hitbox.bottom + m_Hitbox.height }, Point2f{ m_Hitbox.left + m_Hitbox.width, m_Hitbox.bottom + m_Hitbox.height } }; return topVertices; } void Player::Draw() const { if (Game::DrawDebug) { //draw hitbox utils::SetColor(Color4f{ 1, 0, 0, 0.5f }); utils::FillRect(m_Hitbox); } Rectf srcRect{ (m_ClipWidth * (m_AnimFirstFrameId % 11)) + (m_ClipWidth * m_AnimFrame), m_ClipHeight + (m_ClipHeight * (m_AnimFirstFrameId / 11)), m_ClipWidth, m_ClipHeight }; Rectf destRect{ -m_SpriteRect.width / 2, 0, m_SpriteRect.width, m_SpriteRect.height }; glPushMatrix(); glTranslatef(m_SpriteRect.left - destRect.left, m_SpriteRect.bottom, 0); if (m_Direction == Direction::LEFT) { glScalef(-1, 1, 1); } //draw player m_SpritesTexture.Draw(destRect, srcRect); glPopMatrix(); } bool Player::GetInput(Buttons button, bool pressedOnce) { bool result{ false }; const Uint8* pStates = SDL_GetKeyboardState(nullptr); if (pressedOnce && m_HeldInputs[int(button)]) { return false; } switch (button) { case Buttons::LEFT: if (pStates[SDL_SCANCODE_LEFT] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) result = true; break; case Buttons::RIGHT: if (pStates[SDL_SCANCODE_RIGHT] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) result = true; break; case Buttons::UP: if (pStates[SDL_SCANCODE_UP] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) result = true; break; case Buttons::DOWN: if (pStates[SDL_SCANCODE_DOWN] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) result = true; break; case Buttons::A: if (pStates[SDL_SCANCODE_Z] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_A)) result = true; break; case Buttons::B: if (pStates[SDL_SCANCODE_S] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_B)) result = true; break; case Buttons::X: if (pStates[SDL_SCANCODE_X] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_X)) result = true; break; case Buttons::Y: if (pStates[SDL_SCANCODE_A] || SDL_GameControllerGetButton(m_Controller, SDL_CONTROLLER_BUTTON_Y)) result = true; break; case Buttons::RIGHT_TRIGGER: if (pStates[SDL_SCANCODE_LSHIFT] || (SDL_GameControllerGetAxis(m_Controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) > 5000)) result = true; break; default: break; } m_HeldInputs[int(button)] = result; return result; } Player::Info Player::GetInfo() const { return Info{ m_Lives, m_Bombs, m_Ropes }; } Player::ActionState Player::GetState() const { return m_ActionState; } bool Player::HandlePickups(std::vector<Item*>& pItems) { bool didPickup{ }; Rectf& hitbox = m_Hitbox; auto IsOverlappingPickup = [hitbox](Item* item) { return (item->GetTypeHash() == typeid(Gold).hash_code() || item->GetTypeHash() == typeid(Diamond).hash_code()) && (utils::IsOverlapping(item->GetHitbox(), hitbox)); }; for (std::vector<Item*>::iterator it{ std::find_if(pItems.begin(), pItems.end(), IsOverlappingPickup) }; it != pItems.end(); it = std::find_if(++it, pItems.end(), IsOverlappingPickup)) { if (dynamic_cast<Gold*>(*it) != nullptr) { m_Score += dynamic_cast<Gold*>(*it)->GetAmount(); switch (dynamic_cast<Gold*>(*it)->GetType()) { case Gold::Type::THREE_COINS: case Gold::Type::BIG_CHUNK: m_GoldBigSFX.Play(0); break; case Gold::Type::COIN: case Gold::Type::SMALL_CHUNK: m_GoldSmallSFX.Play(0); break; default: break; } delete *it; *it = nullptr; } else if (dynamic_cast<Diamond*>(*it) != nullptr) { m_Score += dynamic_cast<Diamond*>(*it)->GetAmount(); switch (dynamic_cast<Diamond*>(*it)->GetType()) { case Diamond::Type::GREEN: m_GreenGem.Play(0); break; case Diamond::Type::BLUE: m_BlueGem.Play(0); break; case Diamond::Type::RED: m_RedGem.Play(0); break; default: break; } delete *it; *it = nullptr; } didPickup = true; } return didPickup; } void Player::Hit(int damage, int direction) { m_HitSFX.Play(0); bool(direction) ? m_Velocity = Vector2f{ 450.f, 200.f } : m_Velocity = Vector2f{ -450.f, 200.f }; SetAction(ActionState::HURT); m_Lives -= damage; } bool Player::DidJumpOnEnemy(const std::vector<Point2f>& topVertices) { if (m_Velocity.y < 0) { float halfHeight{ m_Hitbox.height * 0.5f }; Point2f btmLeft{ m_Hitbox.left, m_Hitbox.bottom }; float halfWidth{ m_Hitbox.width * 0.5f }; utils::HitInfo hitInfo{}; if (utils::Raycast(topVertices, Point2f{ btmLeft.x + halfWidth, btmLeft.y - halfHeight / 2 }, Point2f{ btmLeft.x + halfWidth, btmLeft.y + halfHeight / 2 }, hitInfo)) { if (GetInput(Buttons::A)) { m_Velocity.y = m_JumpSpeed * 1.5f; } else { m_Velocity.y = m_JumpSpeed; } m_MinJumpDuration = m_JumpOnEnemyDuration; SetAction(ActionState::JUMPING); return true; } } return false; } void Player::Update(float elapsedSec, const Level& level, std::vector<Item*>& pItems, Point2f& cameraOffset, float& cameraSmoothing) { /* if (GetInput(Buttons::Y, PRESSED_ONCE)) { //bool(m_Direction) ? m_Velocity = Vector2f{ 1000.f, 800.f } : m_Velocity = Vector2f{ -1000.f, 800.f }; //SetAction(ActionState::HURT); SetAction(ActionState::LOST_BALANCE); } std::cout << "\rm_ActionState: " << int(m_ActionState); std::cout << "\r[ " << m_Hitbox.left << ", " << m_Hitbox.bottom << " ]"; */ if (HandlePickups(pItems)) { pItems.erase(remove_if(pItems.begin(), pItems.end(), [](Item* item) { return item == nullptr; })); } if ((m_ActionState != ActionState::LEDGE_GRAB) && (m_ActionState != ActionState::LADDER_IDLE)) { if (!level.IsOnGround(m_Hitbox)) m_Velocity += elapsedSec * m_GravityAcceleration; m_Hitbox.bottom += m_Velocity.y * elapsedSec; level.HandleCollision(m_Hitbox, m_Velocity); m_Hitbox.left += m_Velocity.x * elapsedSec; level.HandleCollision(m_Hitbox, m_Velocity); } if (m_ActionState != ActionState::CRAWLING) GetInput(Buttons::RIGHT_TRIGGER) ? m_SpeedLimit = m_RunSpeed : m_SpeedLimit = m_WalkSpeed; cameraOffset = Point2f{ 0, 0 }; cameraSmoothing = 6.f; switch (m_ActionState) { case ActionState::IDLE: if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { SetAction(ActionState::WALKING); break; } else { if (GetInput(Buttons::DOWN)) { SetAction(ActionState::CROUCHING); break; } else if (GetInput(Buttons::UP)) { float ladderX{}; if (level.IsOverlappingLadder(m_Hitbox, ladderX)) { m_Hitbox.left = ladderX + 8; SetAction(ActionState::LADDER_CLIMBING); break; } else { SetAction(ActionState::STARING_UP); break; } } if (level.IsNearlyFalling(m_Hitbox, int(m_Direction))) { SetAction(ActionState::LOST_BALANCE); break; } if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } } if (m_Velocity.y < 0) { SetAction(ActionState::FALLING); } break; case ActionState::LADDER_IDLE: if (GetInput(Buttons::A, PRESSED_ONCE)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT)) { m_Direction = Direction::LEFT; } else if (GetInput(Buttons::RIGHT)) { m_Direction = Direction::RIGHT; } if (GetInput(Buttons::DOWN)) { SetAction(ActionState::LADDER_CLIMBING); break; } else if (GetInput(Buttons::UP)) { SetAction(ActionState::LADDER_CLIMBING); break; } break; case ActionState::LADDER_CLIMBING: if (GetInput(Buttons::A, PRESSED_ONCE)) { if (GetInput(Buttons::DOWN)) { SetAction(ActionState::FALLING); break; } else { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { SetAction(ActionState::LADDER_IDLE); break; } if (GetInput(Buttons::DOWN)) { if (level.IsOnGround(m_Hitbox)) { SetAction(ActionState::CROUCHING); break; } else { m_Velocity.y = -m_ClimbSpeed; } } else if (GetInput(Buttons::UP)) { bool isTopPiece{}; float maxY{}; if (level.IsOverlappingLadder(m_Hitbox, maxY, isTopPiece)) { m_Velocity.y = m_ClimbSpeed; if (isTopPiece) { if (m_Hitbox.bottom + m_Hitbox.height - 12 > maxY) { m_Velocity.y = 0; } } } } else { m_Velocity.y = 0; SetAction(ActionState::LADDER_IDLE); break; } break; case ActionState::LOST_BALANCE: if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { SetAction(ActionState::WALKING); break; } else { if (GetInput(Buttons::DOWN)) { SetAction(ActionState::CROUCHING); break; } else if (GetInput(Buttons::UP)) { if (m_LookTimer >= m_LookDelay) { cameraSmoothing = 9.f; cameraOffset = Point2f{ 0, 216 }; } m_LookTimer += elapsedSec; } else { m_LookTimer = 0; } if (!level.IsNearlyFalling(m_Hitbox, int(m_Direction))) { SetAction(ActionState::IDLE); break; } if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } } if (m_Velocity.y < 0) { SetAction(ActionState::FALLING); } break; case ActionState::STANDING_UP: if (GetInput(Buttons::DOWN)) { SetAction(ActionState::CROUCHING); break; } if (m_StandUpTimer >= m_StandUpDelay) { if (level.IsNearlyFalling(m_Hitbox, int(m_Direction))) { SetAction(ActionState::LOST_BALANCE); break; } else { SetAction(ActionState::IDLE); break; } } m_StandUpTimer += elapsedSec; break; case ActionState::STARING_BACK_DOWN: if (GetInput(Buttons::DOWN)) { SetAction(ActionState::CROUCHING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { SetAction(ActionState::WALKING); break; } if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (m_LookTimer >= 0.2f) { SetAction(ActionState::IDLE); break; } m_LookTimer += elapsedSec; break; case ActionState::STARING_UP: if (!GetInput(Buttons::UP)) { SetAction(ActionState::STARING_BACK_DOWN); break; } if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { SetAction(ActionState::CRAWLING); break; } else { if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } } if (m_Velocity.y < 0) { SetAction(ActionState::FALLING); } if (m_LookTimer >= m_LookDelay) { cameraSmoothing = 9.f; cameraOffset = Point2f{ 0, 216 }; } m_LookTimer += elapsedSec; break; case ActionState::CROUCHING: if (!GetInput(Buttons::DOWN)) { SetAction(ActionState::STANDING_UP); break; } if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { SetAction(ActionState::CRAWLING); break; } else { if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } } if (m_Velocity.y < 0) { SetAction(ActionState::FALLING); } if (m_LookTimer >= m_LookDelay) { cameraSmoothing = 9.f; cameraOffset = Point2f{ 0, -216 }; } m_LookTimer += elapsedSec; break; case ActionState::JUMPING: m_JumpTimer += elapsedSec; if ((m_JumpTimer > m_MinJumpDuration) && !GetInput(Buttons::A)) { SetAction(ActionState::FALLING); m_Velocity.y = 0; m_MinJumpDuration = m_NormalJumpDuration; break; } if (GetInput(Buttons::UP, PRESSED_ONCE) || GetInput(Buttons::DOWN)) { float ladderX{}; if (level.IsOverlappingLadder(m_Hitbox, ladderX)) { m_Hitbox.left = ladderX + 8; SetAction(ActionState::LADDER_CLIMBING); break; } } if (GetInput(Buttons::LEFT)) { (m_Velocity.x > -m_SpeedLimit) ? m_Velocity.x += -m_MoveAcceleration * elapsedSec : m_Velocity.x = -m_SpeedLimit; m_Direction = Direction::LEFT; } else if (GetInput(Buttons::RIGHT)) { (m_Velocity.x < m_SpeedLimit) ? m_Velocity.x += m_MoveAcceleration * elapsedSec : m_Velocity.x = m_SpeedLimit; m_Direction = Direction::RIGHT; } else if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } if (m_Velocity.y <= 0) { SetAction(ActionState::FALLING); break; } break; case ActionState::FALLING: m_GrabbedTile = level.IsGrabbingLedge(m_Hitbox, m_Velocity, int(m_Direction)); if (m_GrabbedTile != nullptr && m_GrabbedTile != m_LastGrabbedTile) { m_Velocity.y = 0; SetAction(ActionState::LEDGE_GRAB); break; } if (GetInput(Buttons::UP) || GetInput(Buttons::DOWN, PRESSED_ONCE)) { float ladderX{}; if (level.IsOverlappingLadder(m_Hitbox, ladderX)) { m_Hitbox.left = ladderX + 8; SetAction(ActionState::LADDER_CLIMBING); break; } } if (GetInput(Buttons::LEFT)) { (m_Velocity.x > -m_SpeedLimit) ? m_Velocity.x += -m_MoveAcceleration * elapsedSec : m_Velocity.x = -m_SpeedLimit; m_Direction = Direction::LEFT; } else if (GetInput(Buttons::RIGHT)) { (m_Velocity.x < m_SpeedLimit) ? m_Velocity.x += m_MoveAcceleration * elapsedSec : m_Velocity.x = m_SpeedLimit; m_Direction = Direction::RIGHT; } else if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } if (level.IsOnGround(m_Hitbox)) { m_LandSFX.Play(0); SetAction(ActionState::IDLE); break; } break; case ActionState::CRAWLING: if (m_Velocity.y < 0) { SetAction(ActionState::FALLING); break; } if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { if (!GetInput(Buttons::DOWN)) { SetAction(ActionState::WALKING); break; } if (GetInput(Buttons::LEFT)) { if (m_Velocity.x > -m_CrawlSpeed) m_Velocity.x += -m_MoveAcceleration * elapsedSec; m_Direction = Direction::LEFT; } else if (GetInput(Buttons::RIGHT)) { if (m_Velocity.x < m_CrawlSpeed) m_Velocity.x += m_MoveAcceleration * elapsedSec; m_Direction = Direction::RIGHT; } } else { if (std::fabs(m_Velocity.x) > m_BrakeSpeed * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeed * elapsedSec : m_Velocity.x += m_BrakeSpeed * elapsedSec; } else { m_Velocity.x = 0; } if (!GetInput(Buttons::DOWN)) { SetAction(ActionState::STANDING_UP); break; } else { SetAction(ActionState::CROUCHING); break; } } break; case ActionState::WALKING: GetInput(Buttons::RIGHT_TRIGGER) ? m_NrFramesPerSec = 30 : m_NrFramesPerSec = 20; if (m_Velocity.y < 0) { SetAction(ActionState::FALLING); break; } if (GetInput(Buttons::A, PRESSED_ONCE) && level.IsOnGround(m_Hitbox)) { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); break; } if (GetInput(Buttons::LEFT) || GetInput(Buttons::RIGHT)) { if (GetInput(Buttons::DOWN)) { m_Velocity.x = 0; SetAction(ActionState::CRAWLING); break; } if (GetInput(Buttons::LEFT)) { (m_Velocity.x > -m_SpeedLimit) ? m_Velocity.x += -m_MoveAcceleration * elapsedSec : m_Velocity.x = -m_SpeedLimit; m_Direction = Direction::LEFT; } else if (GetInput(Buttons::RIGHT)) { (m_Velocity.x < m_SpeedLimit) ? m_Velocity.x += m_MoveAcceleration * elapsedSec : m_Velocity.x = m_SpeedLimit; m_Direction = Direction::RIGHT; } } else { SetAction(ActionState::IDLE); break; } break; case ActionState::HURT: if (std::fabs(m_Velocity.x) > m_BrakeSpeedHurt * elapsedSec) { (m_Velocity.x > 0) ? m_Velocity.x -= m_BrakeSpeedHurt * elapsedSec : m_Velocity.x += m_BrakeSpeedHurt * elapsedSec; } else { m_Velocity.x = 0; if (std::fabs(m_Velocity.y) < 1) m_HurtTimer += elapsedSec; } if (m_Lives > 0) { if (m_HurtTimer >= m_HurtDuration) { SetAction(ActionState::WALKING); break; } } break; case ActionState::LEDGE_GRAB: if (m_GrabbedTile == nullptr) { m_LastGrabbedTile = nullptr; SetAction(ActionState::FALLING); break; } if (GetInput(Buttons::DOWN)) { if (m_LookTimer >= m_LookDelay) { cameraSmoothing = 9.f; cameraOffset = Point2f{ 0, -216 }; } m_LookTimer += elapsedSec; } else { cameraSmoothing = 6.f; cameraOffset = Point2f{ 0, 0 }; m_LookTimer = 0; } if (GetInput(Buttons::A, PRESSED_ONCE)) { if (GetInput(Buttons::DOWN)) { m_LastGrabbedTile = m_GrabbedTile; m_GrabbedTile = nullptr; SetAction(ActionState::FALLING); } else { m_Velocity.y = m_JumpSpeed; SetAction(ActionState::JUMPING); } } break; default: break; } m_AnimTime += elapsedSec; if (m_AnimTime >= 1.f / m_NrFramesPerSec) { m_AnimFrame++; if (m_AnimFrame >= m_AnimLength) { if (m_AnimLoop) { m_AnimFrame = 0; } else { m_AnimFrame = m_AnimLength; } } m_AnimTime = 0; } // Check if keys have been released UpdateHeldInputs(); //update Sprite position to fit newly calculated hitbox position m_SpriteRect.left = m_Hitbox.left - 16; m_SpriteRect.bottom = m_Hitbox.bottom - 8; } void Player::UpdateHeldInputs() { for (int i{}; i < int(Buttons::LENGTH); i++) { if (m_HeldInputs[i]) { if (!GetInput(Buttons(i))) { m_HeldInputs[i] = false; } } } } void Player::SetAction(ActionState action) { m_LastActionState = m_ActionState; m_ActionState = action; m_Hitbox.height = m_HitBoxHeight; m_AnimFrame = 0; m_NrFramesPerSec = 20; m_AnimLoop = true; switch (action) { case ActionState::LADDER_IDLE: m_AnimFirstFrameId = 66; m_AnimLength = 1; m_NrFramesPerSec = 1; break; case ActionState::LADDER_CLIMBING: m_Velocity.x = 0; m_Velocity.y = 0; m_AnimFirstFrameId = 66; m_AnimLength = 6; m_NrFramesPerSec = 15; break; case ActionState::LOST_BALANCE: m_LookTimer = 0; m_AnimFirstFrameId = 33; m_AnimLength = 8; m_NrFramesPerSec = 15; break; case ActionState::IDLE: m_AnimFirstFrameId = 0; m_AnimLength = 1; break; case ActionState::WALKING: m_AnimFirstFrameId = 1; m_AnimLength = 8; break; case ActionState::LEDGE_GRAB: m_GrabLedgeSFX.Play(0); m_LookTimer = 0; m_AnimLoop = false; m_AnimFirstFrameId = 41; m_AnimLength = 3; m_NrFramesPerSec = 15; break; case ActionState::CROUCHING: m_Hitbox.height = m_HitBoxHeight / 2; m_LookTimer = 0; if (m_LastActionState == ActionState::CRAWLING) { m_AnimLoop = false; m_AnimFirstFrameId = 13; m_AnimLength = 0; } else { m_AnimLoop = false; m_AnimFirstFrameId = 11; m_AnimLength = 2; } break; case ActionState::STANDING_UP: m_StandUpTimer = 0; m_AnimLoop = false; m_AnimFirstFrameId = 13; m_AnimLength = 2; break; case ActionState::STARING_BACK_DOWN: m_LookTimer = 0; m_AnimLoop = false; m_NrFramesPerSec = 15; m_AnimFirstFrameId = 91; m_AnimLength = 4; break; case ActionState::STARING_UP: m_LookTimer = 0; m_AnimLoop = false; m_NrFramesPerSec = 14; m_AnimFirstFrameId = 88; m_AnimLength = 3; break; case ActionState::HURT: m_HurtTimer = 0; m_AnimLoop = false; m_AnimFirstFrameId = 9; m_AnimLength = 0; break; case ActionState::FALLING: m_AnimLoop = false; m_AnimFirstFrameId = 102; m_AnimLength = 4; m_NrFramesPerSec = 40; break; case ActionState::JUMPING: m_JumpSFX.Play(0); m_LastGrabbedTile = nullptr; m_JumpTimer = 0; m_AnimLoop = false; m_AnimFirstFrameId = 99; m_AnimLength = 4; m_NrFramesPerSec = 40; break; case ActionState::CRAWLING: m_Hitbox.height = m_HitBoxHeight / 2; m_AnimFirstFrameId = 16; m_AnimLength = 7; break; default: break; } } void Player::SetController(SDL_GameController* controller) { m_Controller = controller; } void Player::PowerUpHit() { m_Power++; SetAction(ActionState::HURT); } Rectf& Player::GetHitbox() { return m_Hitbox; } Vector2f Player::GetVelocity() const { return m_Velocity; }