diff options
| author | Nikita Kostovsky <nikita@kostovsky.me> | 2025-12-23 15:28:05 +0100 |
|---|---|---|
| committer | Nikita Kostovsky <nikita@kostovsky.me> | 2025-12-23 15:28:05 +0100 |
| commit | c055eeef6d41269d11b2ddf7f9aba6f8867da65d (patch) | |
| tree | dcd9baaec93c50a8ab49656be86ea248c17421fd /core/src/cpp/player.cpp | |
Diffstat (limited to 'core/src/cpp/player.cpp')
| -rw-r--r-- | core/src/cpp/player.cpp | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/core/src/cpp/player.cpp b/core/src/cpp/player.cpp new file mode 100644 index 0000000..ce2b421 --- /dev/null +++ b/core/src/cpp/player.cpp @@ -0,0 +1,154 @@ +#include "player.h" + +Player::Player(SDL_Renderer* renderer) + : renderer{renderer} + , sprites{ + Animation{renderer, "rest.bmp", 256, 1.0, true}, + Animation{renderer, "takeoff.bmp", 256, 0.3, false}, + Animation{renderer, "flight.bmp", 256, 1.3, false}, + Animation{renderer, "landing.bmp", 256, 0.3, false}, + Animation{renderer, "walk.bmp", 256, 1.0, true}, + Animation{renderer, "fall.bmp", 256, 1.0, true} + } +{ +} + +void Player::set_state(const States& s) +{ + timestamp = Clock::now(); + state = s; + + if (state != States::FLIGHT && state != States::WALK) + { + speed.x = 0; + } + else if (state == States::WALK) + { + speed.x = backwards ? -150 : 150; + } + else if (state == States::FLIGHT) + { + speed.y = jump.y; + speed.x = backwards ? -jump.x : jump.x; + } +} + +void Player::handle_keyboard() +{ + const Uint8* kbstate{SDL_GetKeyboardState(nullptr)}; + + if (state == States::WALK && !kbstate[SDL_SCANCODE_RIGHT] && + !kbstate[SDL_SCANCODE_LEFT]) + { + set_state(States::REST); + } + + if ((state == States::REST || state == States::WALK) && + kbstate[SDL_SCANCODE_UP]) + { + if (kbstate[SDL_SCANCODE_LEFT] || kbstate[SDL_SCANCODE_RIGHT]) + { + jump.x = 200; // long jump + jump.y = -200; + } + else + { + jump.x = 50; // high jump + jump.y = -300; + } + + set_state(States::TAKEOFF); + } + + if (state == States::REST && + (kbstate[SDL_SCANCODE_LEFT] || kbstate[SDL_SCANCODE_RIGHT])) + { + backwards = kbstate[SDL_SCANCODE_LEFT]; + set_state(States::WALK); + } +} + +const Animation& Player::sprite(const States& state) +{ + return sprites.at(static_cast<int>(state)); +} + +void Player::update_state(const double dt, const Map& map) +{ + // takeoff -> flight + if (state == States::TAKEOFF && sprite(state).animation_ended(timestamp)) + { + set_state(States::FLIGHT); + } + + // landing -> rest + if (state == States::LANDING && sprite(state).animation_ended(timestamp)) + { + set_state(States::REST); + } + + // put free falling sprite if no ground under the feet + if (state != States::FLIGHT && + map.is_empty(pos.x / map.tile_size.w, pos.y / map.tile_size.h + 1)) + { + set_state(States::FALL); + } + + // prior to collision detection + pos.x += dt * speed.x; + + // horizontal collision detection + if (!map.is_empty(pos.x / map.tile_size.w, pos.y / map.tile_size.h)) + { + // snap the coorinate to the boundary of last free tile + int snap = std::round(pos.x / map.tile_size.w) * map.tile_size.w; + + // be careful to snap to the left or to the right side of the free tile + pos.x = snap + (snap > pos.x ? 1 : -1); + // stop + speed.x = 0; + } + + // prior to collision detection + pos.y += dt * speed.y; + // gravity + speed.y += dt * 300; + + // vertical collision detection + if (!map.is_empty(pos.x / map.tile_size.w, pos.y / map.tile_size.h)) + { + // snap the coorinate to the boundary of last free tile + int snap = std::round(pos.y / map.tile_size.h) * map.tile_size.h; + + // be careful to snap to the top or the bottom side of the free tile + pos.y = snap + (snap > pos.y ? 1 : -1); + // stop + speed.y = 0; + + if (state == States::FLIGHT || state == States::FALL) + { + set_state(States::LANDING); + } + } +} + +void Player::draw() +{ + const SDL_Rect src{sprite(state).rect(timestamp)}; + const SDL_Rect dest{ + static_cast<int>(pos.x) - sprite_size.w / 2, + static_cast<int>(pos.y) - sprite_size.h, + sprite_size.w, + sprite_size.h + }; + + SDL_RenderCopyEx( + renderer, + sprite(state).texture, + &src, + &dest, + 0, + nullptr, + backwards ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE + ); +} |
