multithreading done
This commit is contained in:
6
semestralka1/src/game/game_state.cpp
Normal file
6
semestralka1/src/game/game_state.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
// src/game/game_state.cpp
|
||||||
|
#include "game_state.h"
|
||||||
|
|
||||||
|
GameState g_state;
|
||||||
|
Mutex g_state_mutex;
|
||||||
34
semestralka1/src/game/game_state.h
Normal file
34
semestralka1/src/game/game_state.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// src/game/game_state.h
|
||||||
|
#pragma once
|
||||||
|
#include "mbed.h"
|
||||||
|
#include "../render/player.h"
|
||||||
|
#include "../render/player_positioning.h"
|
||||||
|
#include "../assets/obstacle_crawl_frames.h"
|
||||||
|
|
||||||
|
// POZOR Z OBSTACLE MANAGERA
|
||||||
|
constexpr int MAX_RENDER_OBSTACLES = 6;
|
||||||
|
|
||||||
|
struct ObstacleRenderData {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
CrawlObstacleType type;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
|
||||||
|
// All data needed to render one frame
|
||||||
|
struct GameState {
|
||||||
|
CharacterPosition player_pos;
|
||||||
|
MovementType movement;
|
||||||
|
int frame_index;
|
||||||
|
|
||||||
|
int background_shift;
|
||||||
|
|
||||||
|
ObstacleRenderData obstacles[MAX_RENDER_OBSTACLES];
|
||||||
|
|
||||||
|
bool game_over;
|
||||||
|
bool need_redraw;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global shared state and mutex
|
||||||
|
extern GameState g_state;
|
||||||
|
extern Mutex g_state_mutex;
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "mbed.h"
|
#include "mbed.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "background.h"
|
#include "background.h"
|
||||||
|
#include "../game/game_state.h"
|
||||||
#include "../game/state.h"
|
#include "../game/state.h"
|
||||||
#include "../game/animation.h"
|
#include "../game/animation.h"
|
||||||
#include "../game/collision.h"
|
#include "../game/collision.h"
|
||||||
@@ -22,112 +23,152 @@ extern DigitalOut led;
|
|||||||
// constexpr int PLAYER_X = 9;
|
// constexpr int PLAYER_X = 9;
|
||||||
constexpr int PLAYER_X = 29;
|
constexpr int PLAYER_X = 29;
|
||||||
constexpr int PLAYER_Y = 6;
|
constexpr int PLAYER_Y = 6;
|
||||||
|
constexpr int STACK_SIZE = 4096;
|
||||||
|
|
||||||
void render_loop(int speed) {
|
Thread logic_thread(osPriorityNormal, STACK_SIZE);
|
||||||
|
Thread render_thread(osPriorityNormal, STACK_SIZE);
|
||||||
|
void logic_loop() {
|
||||||
MovementState player_state;
|
MovementState player_state;
|
||||||
AnimationController animation;
|
AnimationController animation;
|
||||||
ButtonHandler button;
|
ButtonHandler button;
|
||||||
MovementController mover(PLAYER_X, VIEW_WIDTH);
|
MovementController mover(PLAYER_X, VIEW_WIDTH);
|
||||||
SpeedController timing;
|
SpeedController timing;
|
||||||
timing.set_ground_speed(speed);
|
timing.set_ground_speed(6);
|
||||||
|
|
||||||
CharacterPosition pos = {PLAYER_X, PLAYER_Y};
|
CharacterPosition pos = {PLAYER_X, PLAYER_Y};
|
||||||
|
|
||||||
const char *bg_file = "background_dark_inverted.txt";
|
|
||||||
bool need_redraw = false;
|
|
||||||
|
|
||||||
int anim_tick_counter = 0;
|
|
||||||
int tick_counter = 0;
|
|
||||||
int player_speed = 6;
|
|
||||||
bool game_over = false;
|
|
||||||
|
|
||||||
player_state.set_state(PlayerState::Walk);
|
player_state.set_state(PlayerState::Walk);
|
||||||
|
|
||||||
CrawlObstacleType type = CrawlObstacleType::Crawl1;
|
|
||||||
int start_x = VIEW_WIDTH + 10;
|
|
||||||
spawn_obstacle(type, start_x);
|
|
||||||
|
|
||||||
Timer spawn_timer;
|
Timer spawn_timer;
|
||||||
spawn_timer.start();
|
spawn_timer.start();
|
||||||
|
|
||||||
|
int anim_tick_counter = 0;
|
||||||
|
int tick_counter = 0;
|
||||||
|
bool game_over = false;
|
||||||
|
|
||||||
|
// Spawn first obstacle
|
||||||
|
spawn_obstacle(CrawlObstacleType::Crawl1, VIEW_WIDTH + 10);
|
||||||
|
|
||||||
while (!game_over) {
|
while (!game_over) {
|
||||||
tick_counter++;
|
tick_counter++;
|
||||||
|
|
||||||
mover.update_position(player_speed, timing.get_ground_speed());
|
mover.update_position(6, timing.get_ground_speed());
|
||||||
pos.x = mover.get_position();
|
pos.x = mover.get_position();
|
||||||
|
|
||||||
|
// Spawn periodically
|
||||||
if (spawn_timer.elapsed_time() > 2s) {
|
if (spawn_timer.elapsed_time() > 2s) {
|
||||||
spawn_timer.reset();
|
spawn_timer.reset();
|
||||||
CrawlObstacleType s_type = CrawlObstacleType::Crawl1;
|
spawn_obstacle(CrawlObstacleType::Crawl1, VIEW_WIDTH);
|
||||||
int spawn_x = VIEW_WIDTH;
|
|
||||||
int idx = spawn_obstacle(s_type, spawn_x);
|
|
||||||
if (idx >= 0) {
|
|
||||||
obstacle_pool[idx].active = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
need_redraw = false;
|
// Handle input
|
||||||
ButtonEvent button_event = button.poll();
|
if (button.poll() == ButtonEvent::Pressed) {
|
||||||
|
|
||||||
if (button_event == ButtonEvent::Pressed) {
|
|
||||||
PlayerState current = player_state.get_state();
|
PlayerState current = player_state.get_state();
|
||||||
|
if (current == PlayerState::Walk || current == PlayerState::Run)
|
||||||
if (current == PlayerState::Walk || current == PlayerState::Run) {
|
|
||||||
player_state.start_crawl(PlayerState::Crawl1);
|
player_state.start_crawl(PlayerState::Crawl1);
|
||||||
} else if (current == PlayerState::Crawl1) {
|
else if (current == PlayerState::Crawl1)
|
||||||
player_state.start_crawl(PlayerState::Crawl2);
|
player_state.start_crawl(PlayerState::Crawl2);
|
||||||
}
|
}
|
||||||
|
|
||||||
need_redraw = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if crawl duration expired
|
|
||||||
player_state.update();
|
player_state.update();
|
||||||
|
|
||||||
if (animation.tick(speed)) {
|
bool anim_tick = animation.tick(6);
|
||||||
|
if (anim_tick) {
|
||||||
anim_tick_counter++;
|
anim_tick_counter++;
|
||||||
|
// move obstacles
|
||||||
int ground_speed = timing.get_ground_speed();
|
int ground_speed = timing.get_ground_speed();
|
||||||
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) {
|
||||||
obstacle_pool[i].data.x -= ground_speed;
|
obstacle_pool[i].data.x -= ground_speed;
|
||||||
// deactivate when offscreen
|
|
||||||
if (obstacle_pool[i].data.x + obstacle_pool[i].data.width < 0)
|
if (obstacle_pool[i].data.x + obstacle_pool[i].data.width < 0)
|
||||||
obstacle_pool[i].active = false;
|
obstacle_pool[i].active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
need_redraw = true;
|
player_state.toggle_walk_frame(6, anim_tick_counter);
|
||||||
|
FrameSelection frame = player_state.get_frame_selection();
|
||||||
|
CharacterPosition draw_pos =
|
||||||
|
get_aligned_frame_position(pos, frame.movement, frame.frame_index);
|
||||||
|
|
||||||
|
// check collision
|
||||||
|
bool collision = false;
|
||||||
|
for (int i = 0; i < MAX_OBSTACLES; i++) {
|
||||||
|
if (obstacle_pool[i].active &&
|
||||||
|
check_collision(pos, frame.movement, obstacle_pool[i].data)) {
|
||||||
|
collision = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_redraw) {
|
g_state_mutex.lock();
|
||||||
player_state.toggle_walk_frame(player_speed, anim_tick_counter);
|
|
||||||
draw_mask(bg_file, animation.get_shift());
|
|
||||||
FrameSelection frame = player_state.get_frame_selection();
|
|
||||||
|
|
||||||
CharacterPosition draw_pos = get_aligned_frame_position(pos, frame.movement, frame.frame_index);
|
g_state.player_pos = draw_pos;
|
||||||
draw_character(draw_pos.x, draw_pos.y, frame.movement, frame.frame_index);
|
g_state.movement = frame.movement;
|
||||||
|
g_state.frame_index = frame.frame_index;
|
||||||
|
g_state.background_shift = animation.get_shift();
|
||||||
|
g_state.need_redraw = true;
|
||||||
|
g_state.game_over = collision;
|
||||||
|
|
||||||
// for (int i = 0; i < MAX_OBSTACLES; i++) {
|
for (int i = 0; i < MAX_OBSTACLES; i++) {
|
||||||
// if (!obstacle_pool[i].active)
|
g_state.obstacles[i].x = obstacle_pool[i].data.x;
|
||||||
// continue;
|
g_state.obstacles[i].y = obstacle_pool[i].data.y;
|
||||||
|
g_state.obstacles[i].type = obstacle_pool[i].type;
|
||||||
|
g_state.obstacles[i].active = obstacle_pool[i].active;
|
||||||
|
}
|
||||||
|
|
||||||
// draw_obstacle(obstacle_pool[i].data.x, obstacle_pool[i].data.y,
|
g_state_mutex.unlock();
|
||||||
// obstacle_pool[i].type);
|
|
||||||
|
|
||||||
// if (check_collision(pos, frame.movement, obstacle_pool[i].data)) {
|
if (collision)
|
||||||
// printf("\033[2J\033[H");
|
game_over = true;
|
||||||
// printf("GAME OVER\r\n");
|
|
||||||
// game_over = true;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (game_over)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ThisThread::sleep_for(50ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThisThread::sleep_for(25ms);
|
ThisThread::sleep_for(25ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// final update
|
||||||
|
g_state_mutex.lock();
|
||||||
|
g_state.game_over = true;
|
||||||
|
g_state_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_loop_thread() {
|
||||||
|
while (true) {
|
||||||
|
g_state_mutex.lock();
|
||||||
|
bool need = g_state.need_redraw;
|
||||||
|
bool over = g_state.game_over;
|
||||||
|
GameState local = g_state;
|
||||||
|
g_state.need_redraw = false;
|
||||||
|
g_state_mutex.unlock();
|
||||||
|
|
||||||
|
if (over) {
|
||||||
|
printf("\033[2J\033[H");
|
||||||
|
printf("GAME OVER\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need) {
|
||||||
|
draw_mask("background", local.background_shift);
|
||||||
|
draw_character(local.player_pos.x, local.player_pos.y, local.movement,
|
||||||
|
local.frame_index);
|
||||||
|
for (int i = 0; i < MAX_RENDER_OBSTACLES; i++) {
|
||||||
|
if (local.obstacles[i].active)
|
||||||
|
draw_obstacle(local.obstacles[i].x, local.obstacles[i].y,
|
||||||
|
local.obstacles[i].type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisThread::sleep_for(50ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_loop(int speed) {
|
||||||
|
g_state_mutex.lock();
|
||||||
|
g_state.need_redraw = false;
|
||||||
|
g_state.game_over = false;
|
||||||
|
g_state_mutex.unlock();
|
||||||
|
|
||||||
|
logic_thread.start(logic_loop);
|
||||||
|
render_thread.start(render_loop_thread);
|
||||||
|
|
||||||
|
logic_thread.join();
|
||||||
|
render_thread.join();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user