diff --git a/semestralka1/src/game/state.cpp b/semestralka1/src/game/state.cpp index ac8cadc..912edb3 100644 --- a/semestralka1/src/game/state.cpp +++ b/semestralka1/src/game/state.cpp @@ -1,6 +1,7 @@ // src/game/state.cpp #include "state.h" #include "../render/player.h" +#include "../timing/speed_controller.h" void WalkingState::update() { // stop crawling after duration @@ -18,8 +19,8 @@ void WalkingState::start_crawl() { } // TODO THIS NEEDS REDESIGN ACCORDING TO SPEED -void WalkingState::toggle_walk_frame() { - if ((run_index += 3) >= 7) run_index = 0; +void WalkingState::toggle_walk_frame(int step) { + run_index = (run_index + step) % 7; } // void RunningState::toggle_run_frame() { // if (++run_index >= 7) run_index = 0; diff --git a/semestralka1/src/game/state.h b/semestralka1/src/game/state.h index 8532cfc..bb4cd24 100644 --- a/semestralka1/src/game/state.h +++ b/semestralka1/src/game/state.h @@ -23,7 +23,7 @@ private: public: void update(); void start_crawl(); - void toggle_walk_frame(); + void toggle_walk_frame(int step); FrameSelection get_frame_selection() const; PlayerState get_state() const { return current_state; } diff --git a/semestralka1/src/main.cpp b/semestralka1/src/main.cpp index eab7434..119483d 100644 --- a/semestralka1/src/main.cpp +++ b/semestralka1/src/main.cpp @@ -22,5 +22,5 @@ int main(void) { printf("Baud: %d, Format: 8-N-1\r\n", BAUD_RATE); // Just call into render feature - render_loop(6); + render_loop(1); } diff --git a/semestralka1/src/render/loop.cpp b/semestralka1/src/render/loop.cpp index eb4b064..3d51c26 100644 --- a/semestralka1/src/render/loop.cpp +++ b/semestralka1/src/render/loop.cpp @@ -9,6 +9,7 @@ #include "../game/animation.h" #include "../hardware/uart.h" #include "../render/player.h" +#include "../timing/speed_controller.h" extern BufferedSerial serial_port; extern DigitalOut led; @@ -23,13 +24,19 @@ void render_loop(int speed) { WalkingState player_state; AnimationController animation; UartReader uart(serial_port); + SpeedController timing; + timing.set_ground_speed(speed); CharacterPosition pos = {PLAYER_X, PLAYER_Y}; const char *bg_file = "background_dark_inverted.txt"; bool need_redraw = false; + int tick_counter = 0; + int player_speed = 3; + while (true) { + tick_counter++; need_redraw = false; UartEvent uart_event = uart.poll(); @@ -57,8 +64,11 @@ void render_loop(int speed) { 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); + if (player_state.get_state() != PlayerState::Crawl) { - player_state.toggle_walk_frame(); + int step = timing.frame_advance_for(player_speed, tick_counter); + if (step > 0) + player_state.toggle_walk_frame(step); } ThisThread::sleep_for(50ms); diff --git a/semestralka1/src/timing/speed_controller.cpp b/semestralka1/src/timing/speed_controller.cpp new file mode 100644 index 0000000..64afc1c --- /dev/null +++ b/semestralka1/src/timing/speed_controller.cpp @@ -0,0 +1,34 @@ +// src/timing/speed_controller.cpp +#include "speed_controller.h" + +void SpeedController::set_ground_speed(int spd) { + if (spd < 0) spd = 0; + if (spd > 30) spd = 30; + ground_speed = spd; +} + +int SpeedController::frame_advance_for(int object_speed, int tick_counter) const { + if (object_speed <= 0) { + return 0; + } + + if (ground_speed == 0) { + return 1 + object_speed; + } + + const int delta = object_speed - ground_speed; + + if (delta > 0) { + return 1 + delta; + } + + if (delta == 0) { + return 1; + } + + float ratio_f = static_cast(ground_speed) / object_speed; + int ratio = static_cast(ratio_f + 0.3f); + if (ratio < 1) ratio = 1; + + return (tick_counter % ratio == 0) ? 1 : 0; +} diff --git a/semestralka1/src/timing/speed_controller.h b/semestralka1/src/timing/speed_controller.h new file mode 100644 index 0000000..00eb74b --- /dev/null +++ b/semestralka1/src/timing/speed_controller.h @@ -0,0 +1,19 @@ +// src/timing/speed_controller.h +#pragma once +#include "mbed.h" + +class SpeedController { +private: + int ground_speed = 1; + +public: + SpeedController() = default; + + void set_ground_speed(int spd); + int get_ground_speed() const { return ground_speed; } + + // Calculates how many frames to advance for current tick. + // Takes object’s current speed and a global tick counter + // to automatically handle slower "wait" behavior. + int frame_advance_for(int object_speed, int tick_counter) const; +};