2 Commits

Author SHA1 Message Date
Filipriec
ca7eac70e4 movement class 2025-11-20 17:37:27 +01:00
Filipriec
3e47f855ed cleaning 2025-11-20 16:45:50 +01:00
9 changed files with 31 additions and 38 deletions

View File

@@ -49,7 +49,7 @@ static const int CHARACTER_CRAWL1_COLLISION_RIGHT_OFFSET = 1;
static const int CHARACTER_CRAWL1_COLLISION_WIDTH = CHARACTER_CRAWL1_FRAME_WIDTH - (CHARACTER_CRAWL1_COLLISION_LEFT_OFFSET + CHARACTER_CRAWL1_COLLISION_RIGHT_OFFSET); static const int CHARACTER_CRAWL1_COLLISION_WIDTH = CHARACTER_CRAWL1_FRAME_WIDTH - (CHARACTER_CRAWL1_COLLISION_LEFT_OFFSET + CHARACTER_CRAWL1_COLLISION_RIGHT_OFFSET);
static const int CHARACTER_CRAWL1_COLLISION_HEIGHT = CHARACTER_CRAWL1_FRAME_HEIGHT - 2; static const int CHARACTER_CRAWL1_COLLISION_HEIGHT = CHARACTER_CRAWL1_FRAME_HEIGHT - 2;
// Crawl2 collision box (lower posture smaller collision height) // Crawl2 collision box (lower posture - smaller collision height)
static const int CHARACTER_CRAWL2_FRAME_WIDTH = 8; static const int CHARACTER_CRAWL2_FRAME_WIDTH = 8;
static const int CHARACTER_CRAWL2_COLLISION_LEFT_OFFSET = 1; static const int CHARACTER_CRAWL2_COLLISION_LEFT_OFFSET = 1;
static const int CHARACTER_CRAWL2_COLLISION_RIGHT_OFFSET = 0; static const int CHARACTER_CRAWL2_COLLISION_RIGHT_OFFSET = 0;

View File

@@ -5,7 +5,7 @@
#include "../assets/character_run_frames.h" #include "../assets/character_run_frames.h"
#include "../assets/character_crawl_frames.h" #include "../assets/character_crawl_frames.h"
// Simple obstacle representation // Obstacle representation
struct Obstacle { struct Obstacle {
int x; int x;
int y; int y;
@@ -48,7 +48,7 @@ inline bool check_collision(const CharacterPosition& player,
break; break;
} }
// Player's bounding box // Player bounding box
const int player_left = box_x; const int player_left = box_x;
const int player_right = player_left + box_w; const int player_right = player_left + box_w;
const int player_top = player_bottom + box_h; const int player_top = player_bottom + box_h;
@@ -59,7 +59,7 @@ inline bool check_collision(const CharacterPosition& player,
const int obs_bottom = obs.y; const int obs_bottom = obs.y;
const int obs_top = obs_bottom + obs.height; const int obs_top = obs_bottom + obs.height;
// Simple overlap check // Overlap check
bool horizontal = player_left < obs_right && player_right > obs_left; bool horizontal = player_left < obs_right && player_right > obs_left;
bool vertical = player_bottom < obs_top && player_top > obs_bottom; bool vertical = player_bottom < obs_top && player_top > obs_bottom;
return horizontal && vertical; return horizontal && vertical;

View File

@@ -4,7 +4,7 @@
#include "../assets/obstacle_crawl_frames.h" #include "../assets/obstacle_crawl_frames.h"
#include "../assets/background_frame.h" #include "../assets/background_frame.h"
// One movable obstacle // Movable obstacle
struct MovingObstacle { struct MovingObstacle {
Obstacle data; Obstacle data;
CrawlObstacleType type; CrawlObstacleType type;
@@ -26,7 +26,7 @@ inline int spawn_obstacle(CrawlObstacleType type, int x_start) {
obstacle_pool[i].data.width = (type == CrawlObstacleType::Crawl1) ? OBSTACLE_CRAWL1_COLLISION_WIDTH : OBSTACLE_CRAWL2_COLLISION_WIDTH; obstacle_pool[i].data.width = (type == CrawlObstacleType::Crawl1) ? OBSTACLE_CRAWL1_COLLISION_WIDTH : OBSTACLE_CRAWL2_COLLISION_WIDTH;
obstacle_pool[i].data.height = (type == CrawlObstacleType::Crawl1) ? OBSTACLE_CRAWL1_COLLISION_HEIGHT : OBSTACLE_CRAWL2_COLLISION_HEIGHT; obstacle_pool[i].data.height = (type == CrawlObstacleType::Crawl1) ? OBSTACLE_CRAWL1_COLLISION_HEIGHT : OBSTACLE_CRAWL2_COLLISION_HEIGHT;
// Default Y so that the SPRITE touches the top of the screen. // Default Y so that the character touches the top of the screen.
// We store Y as the bottom of the COLLISION BOX in bottom-based world coords. // We store Y as the bottom of the COLLISION BOX in bottom-based world coords.
int top_offset = 0; int top_offset = 0;
if (type == CrawlObstacleType::Crawl1) { if (type == CrawlObstacleType::Crawl1) {

View File

@@ -6,7 +6,6 @@
#include "collision.h" #include "collision.h"
#include "mbed.h" #include "mbed.h"
// Small helper for minimal mbed-safe clamp
inline int clamp_min(int a, int b) { return (a > b) ? a : b; } inline int clamp_min(int a, int b) { return (a > b) ? a : b; }
inline int clamp_max(int a, int b) { return (a < b) ? a : b; } inline int clamp_max(int a, int b) { return (a < b) ? a : b; }
@@ -26,12 +25,8 @@ public:
// Periodically spawn new obstacle // Periodically spawn new obstacle
if (tick_counter_ % SPAWN_EVERY_TICKS == 0) { if (tick_counter_ % SPAWN_EVERY_TICKS == 0) {
auto type = (spawn_index_++ % 2 == 0) auto type = (spawn_index_++ % 2 == 0) ? CrawlObstacleType::Crawl1 : CrawlObstacleType::Crawl2;
? CrawlObstacleType::Crawl1 const int w = (type == CrawlObstacleType::Crawl1) ? OBSTACLE_CRAWL1_FRAME_WIDTH : OBSTACLE_CRAWL2_FRAME_WIDTH;
: CrawlObstacleType::Crawl2;
const int w = (type == CrawlObstacleType::Crawl1)
? OBSTACLE_CRAWL1_FRAME_WIDTH
: OBSTACLE_CRAWL2_FRAME_WIDTH;
spawn_obstacle(type, VIEW_WIDTH - w - 1); spawn_obstacle(type, VIEW_WIDTH - w - 1);
} }

View File

@@ -91,27 +91,28 @@ static inline int compute_frame_index(int frame_count,
} }
} // namespace } // namespace
void WalkingState::update() { void MovementState::update() {
// stop crawling after duration // stop crawling after duration
if ((current_state == PlayerState::Crawl1 || if ((current_state == PlayerState::Crawl1 ||
current_state == PlayerState::Crawl2) && current_state == PlayerState::Crawl2) &&
state_timer.elapsed_time() >= CRAWL_DURATION) { state_timer.elapsed_time() >= CRAWL_DURATION) {
current_state = PlayerState::Walk; current_state = previous_state;
state_timer.stop(); state_timer.stop();
} }
} }
void WalkingState::start_crawl(PlayerState crawl_type) { void MovementState::start_crawl(PlayerState crawl_type) {
if (crawl_type != PlayerState::Crawl1 && crawl_type != PlayerState::Crawl2) if (crawl_type != PlayerState::Crawl1 && crawl_type != PlayerState::Crawl2)
return; return;
previous_state = current_state;
current_state = crawl_type; current_state = crawl_type;
state_timer.stop(); state_timer.stop();
state_timer.reset(); state_timer.reset();
state_timer.start(); state_timer.start();
} }
void WalkingState::set_state(PlayerState s) { void MovementState::set_state(PlayerState s) {
if (current_state != s) { if (current_state != s) {
walk_index = run_index = crawl1_index = crawl2_index = 0; walk_index = run_index = crawl1_index = crawl2_index = 0;
phase = 0.0f; phase = 0.0f;
@@ -119,7 +120,7 @@ void WalkingState::set_state(PlayerState s) {
current_state = s; current_state = s;
} }
void WalkingState::set_motion_state_for_speed(int player_speed, int ground_speed) { void MovementState::set_motion_state_for_speed(int player_speed, int ground_speed) {
int relative = player_speed - ground_speed; int relative = player_speed - ground_speed;
PlayerState new_state = (relative > 1) ? PlayerState::Run : PlayerState::Walk; PlayerState new_state = (relative > 1) ? PlayerState::Run : PlayerState::Walk;
if (new_state != current_state) { if (new_state != current_state) {
@@ -130,7 +131,7 @@ void WalkingState::set_motion_state_for_speed(int player_speed, int ground_speed
} }
// TODO THIS NEEDS REDESIGN FOR WALK/RUN // TODO THIS NEEDS REDESIGN FOR WALK/RUN
void WalkingState::toggle_walk_frame(float player_speed, int tick_counter) { void MovementState::toggle_walk_frame(float player_speed, int tick_counter) {
switch (current_state) { switch (current_state) {
case PlayerState::Run: case PlayerState::Run:
run_index = compute_frame_index(CHARACTER_RUN_FRAME_COUNT, player_speed, tick_counter); run_index = compute_frame_index(CHARACTER_RUN_FRAME_COUNT, player_speed, tick_counter);
@@ -150,7 +151,7 @@ void WalkingState::toggle_walk_frame(float player_speed, int tick_counter) {
} }
} }
FrameSelection WalkingState::get_frame_selection() const { FrameSelection MovementState::get_frame_selection() const {
FrameSelection f{}; FrameSelection f{};
switch (current_state) { switch (current_state) {
case PlayerState::Walk: case PlayerState::Walk:

View File

@@ -12,9 +12,10 @@ struct FrameSelection {
int frame_index; int frame_index;
}; };
class WalkingState { class MovementState {
private: private:
PlayerState current_state = PlayerState::Walk; PlayerState current_state = PlayerState::Walk;
PlayerState previous_state = PlayerState::Walk;
Timer state_timer; Timer state_timer;
int walk_index = 0; // cycles 06 int walk_index = 0; // cycles 06
int run_index = 0; // cycles 06 int run_index = 0; // cycles 06

View File

@@ -21,6 +21,5 @@ int main(void) {
serial_port.set_format(8, BufferedSerial::None, 1); serial_port.set_format(8, BufferedSerial::None, 1);
printf("Baud: %d, Format: 8-N-1\r\n", BAUD_RATE); printf("Baud: %d, Format: 8-N-1\r\n", BAUD_RATE);
// Just call into render feature
render_loop(6); render_loop(6);
} }

View File

@@ -26,7 +26,7 @@ constexpr int PLAYER_Y = 6;
void draw_mask(const char *unused_filename, int shift, const char *text); void draw_mask(const char *unused_filename, int shift, const char *text);
void render_loop(int speed) { void render_loop(int speed) {
WalkingState player_state; MovementState player_state;
AnimationController animation; AnimationController animation;
UartReader uart(serial_port); UartReader uart(serial_port);
MovementController mover(PLAYER_X, VIEW_WIDTH); MovementController mover(PLAYER_X, VIEW_WIDTH);
@@ -114,21 +114,20 @@ void render_loop(int speed) {
CharacterPosition draw_pos = get_aligned_frame_position(pos, frame.movement, frame.frame_index); CharacterPosition draw_pos = get_aligned_frame_position(pos, frame.movement, frame.frame_index);
draw_character(draw_pos.x, draw_pos.y, frame.movement, frame.frame_index); draw_character(draw_pos.x, draw_pos.y, frame.movement, frame.frame_index);
for (int i = 0; i < MAX_OBSTACLES; i++) { // for (int i = 0; i < MAX_OBSTACLES; i++) {
if (!obstacle_pool[i].active) // if (!obstacle_pool[i].active)
continue; // continue;
draw_obstacle(obstacle_pool[i].data.x, // draw_obstacle(obstacle_pool[i].data.x, obstacle_pool[i].data.y,
obstacle_pool[i].data.y, // obstacle_pool[i].type);
obstacle_pool[i].type);
if (check_collision(pos, frame.movement, obstacle_pool[i].data)) { // if (check_collision(pos, frame.movement, obstacle_pool[i].data)) {
printf("\033[2J\033[H"); // printf("\033[2J\033[H");
printf("GAME OVER\r\n"); // printf("GAME OVER\r\n");
game_over = true; // game_over = true;
break; // break;
} // }
} // }
if (game_over) if (game_over)
break; break;

View File

@@ -13,7 +13,5 @@ public:
int get_ground_speed() const { return ground_speed; } int get_ground_speed() const { return ground_speed; }
// Calculates how many frames to advance for current tick. // Calculates how many frames to advance for current tick.
// Takes objects current speed and a global tick counter
// to automatically handle slower "wait" behavior.
int frame_advance_for(int object_speed, int tick_counter) const; int frame_advance_for(int object_speed, int tick_counter) const;
}; };