obstacles finally spawning
This commit is contained in:
@@ -21,7 +21,7 @@ inline void spawn_obstacle(CrawlObstacleType type, int x_start) {
|
|||||||
obstacle_pool[i].active = true;
|
obstacle_pool[i].active = true;
|
||||||
obstacle_pool[i].type = type;
|
obstacle_pool[i].type = type;
|
||||||
obstacle_pool[i].data.x = x_start;
|
obstacle_pool[i].data.x = x_start;
|
||||||
obstacle_pool[i].data.y = 0; // hangs from ceiling
|
obstacle_pool[i].data.y = 10; // hangs from ceiling
|
||||||
if (type == CrawlObstacleType::Crawl1) {
|
if (type == CrawlObstacleType::Crawl1) {
|
||||||
obstacle_pool[i].data.width = OBSTACLE_CRAWL1_COLLISION_WIDTH;
|
obstacle_pool[i].data.width = OBSTACLE_CRAWL1_COLLISION_WIDTH;
|
||||||
obstacle_pool[i].data.height = OBSTACLE_CRAWL1_COLLISION_HEIGHT;
|
obstacle_pool[i].data.height = OBSTACLE_CRAWL1_COLLISION_HEIGHT;
|
||||||
|
|||||||
97
semestralka1/src/game/obstacle_system.h
Normal file
97
semestralka1/src/game/obstacle_system.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// src/game/obstacle_system.h
|
||||||
|
#pragma once
|
||||||
|
#include "obstacle_manager.h"
|
||||||
|
#include "../render/player_positioning.h"
|
||||||
|
#include "../assets/obstacle_crawl_frames.h"
|
||||||
|
#include "collision.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_max(int a, int b) { return (a < b) ? a : b; }
|
||||||
|
|
||||||
|
// Handles spawning, movement, rendering, and collision of obstacles
|
||||||
|
class ObstacleSystem {
|
||||||
|
public:
|
||||||
|
ObstacleSystem() : tick_counter_(0), spawn_index_(0) {}
|
||||||
|
|
||||||
|
// Called once per frame
|
||||||
|
bool update_and_draw(const CharacterPosition &player_pos,
|
||||||
|
MovementType player_movement) {
|
||||||
|
// Update timers, move existing obstacles
|
||||||
|
tick_counter_++;
|
||||||
|
if (tick_counter_ % UPDATE_INTERVAL == 0) {
|
||||||
|
update_obstacles(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Periodically spawn new obstacle
|
||||||
|
if (tick_counter_ % SPAWN_EVERY_TICKS == 0) {
|
||||||
|
auto type = (spawn_index_++ % 2 == 0)
|
||||||
|
? CrawlObstacleType::Crawl1
|
||||||
|
: CrawlObstacleType::Crawl2;
|
||||||
|
const int w = (type == CrawlObstacleType::Crawl1)
|
||||||
|
? OBSTACLE_CRAWL1_FRAME_WIDTH
|
||||||
|
: OBSTACLE_CRAWL2_FRAME_WIDTH;
|
||||||
|
spawn_obstacle(type, VIEW_WIDTH - w - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw & collision check
|
||||||
|
for (int i = 0; i < MAX_OBSTACLES; i++) {
|
||||||
|
if (!obstacle_pool[i].active)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char **frame = nullptr;
|
||||||
|
int height = 0;
|
||||||
|
if (obstacle_pool[i].type == CrawlObstacleType::Crawl1) {
|
||||||
|
frame = OBSTACLE_CRAWL1_FRAME;
|
||||||
|
height = OBSTACLE_CRAWL1_FRAME_HEIGHT;
|
||||||
|
} else {
|
||||||
|
frame = OBSTACLE_CRAWL2_FRAME;
|
||||||
|
height = OBSTACLE_CRAWL2_FRAME_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_clipped_obstacle(obstacle_pool[i], frame, height);
|
||||||
|
|
||||||
|
// Collision check
|
||||||
|
if (check_collision(player_pos, player_movement,
|
||||||
|
obstacle_pool[i].data)) {
|
||||||
|
printf("\033[2J\033[H");
|
||||||
|
printf("GAME OVER\r\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr int SPAWN_EVERY_TICKS = 35;
|
||||||
|
static constexpr int UPDATE_INTERVAL = 1; // move obstacles each frame
|
||||||
|
int tick_counter_;
|
||||||
|
int spawn_index_;
|
||||||
|
|
||||||
|
static void draw_clipped_obstacle(const MovingObstacle &obs,
|
||||||
|
const char **frame,
|
||||||
|
int frame_height) {
|
||||||
|
int x = obs.data.x;
|
||||||
|
int y = obs.data.y;
|
||||||
|
int w = obs.data.width;
|
||||||
|
|
||||||
|
for (int r = 0; r < frame_height; ++r) {
|
||||||
|
int left = x;
|
||||||
|
int right = x + w;
|
||||||
|
if (right <= 0 || left >= VIEW_WIDTH)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int vis_left = clamp_min(left, 0);
|
||||||
|
int vis_right = clamp_max(right, VIEW_WIDTH);
|
||||||
|
int start = vis_left - left;
|
||||||
|
int count = vis_right - vis_left;
|
||||||
|
if (count <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *row = frame[r] + start;
|
||||||
|
printf("\033[%d;%dH%.*s", y + r + 1, vis_left + 1, count, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -7,10 +7,13 @@
|
|||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "../game/state.h"
|
#include "../game/state.h"
|
||||||
#include "../game/animation.h"
|
#include "../game/animation.h"
|
||||||
|
#include "../game/collision.h"
|
||||||
#include "../hardware/uart.h"
|
#include "../hardware/uart.h"
|
||||||
#include "../render/player.h"
|
#include "../render/player.h"
|
||||||
|
#include "../render/obstacle.h"
|
||||||
#include "../timing/speed_controller.h"
|
#include "../timing/speed_controller.h"
|
||||||
#include "../timing/movement_controller.h"
|
#include "../timing/movement_controller.h"
|
||||||
|
#include "../game/obstacle_system.h"
|
||||||
|
|
||||||
extern BufferedSerial serial_port;
|
extern BufferedSerial serial_port;
|
||||||
extern DigitalOut led;
|
extern DigitalOut led;
|
||||||
@@ -38,9 +41,14 @@ void render_loop(int speed) {
|
|||||||
int anim_tick_counter = 0;
|
int anim_tick_counter = 0;
|
||||||
int tick_counter = 0;
|
int tick_counter = 0;
|
||||||
int player_speed = 6;
|
int player_speed = 6;
|
||||||
|
bool game_over = false;
|
||||||
|
|
||||||
player_state.set_state(PlayerState::Run);
|
player_state.set_state(PlayerState::Run);
|
||||||
while (true) {
|
|
||||||
|
spawn_obstacle(CrawlObstacleType::Crawl1, 40);
|
||||||
|
obstacle_pool[0].data.y = 8;
|
||||||
|
obstacle_pool[0].active = true;
|
||||||
|
while (!game_over) {
|
||||||
tick_counter++;
|
tick_counter++;
|
||||||
|
|
||||||
mover.update_position(player_speed, timing.get_ground_speed());
|
mover.update_position(player_speed, timing.get_ground_speed());
|
||||||
@@ -56,11 +64,9 @@ void render_loop(int speed) {
|
|||||||
if (uart_event == UartEvent::Triggered) {
|
if (uart_event == UartEvent::Triggered) {
|
||||||
PlayerState current = player_state.get_state();
|
PlayerState current = player_state.get_state();
|
||||||
|
|
||||||
// pressing UART trigger while walking/running -> Crawl1
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
// pressing again while crawling -> Crawl2
|
|
||||||
else if (current == PlayerState::Crawl1) {
|
else if (current == PlayerState::Crawl1) {
|
||||||
player_state.start_crawl(PlayerState::Crawl2);
|
player_state.start_crawl(PlayerState::Crawl2);
|
||||||
}
|
}
|
||||||
@@ -84,6 +90,17 @@ 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++) {
|
||||||
|
if (!obstacle_pool[i].active)
|
||||||
|
continue;
|
||||||
|
draw_obstacle(obstacle_pool[i].data.x,
|
||||||
|
obstacle_pool[i].data.y,
|
||||||
|
obstacle_pool[i].type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game_over)
|
||||||
|
break;
|
||||||
|
|
||||||
ThisThread::sleep_for(50ms);
|
ThisThread::sleep_for(50ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
31
semestralka1/src/render/obstacle.cpp
Normal file
31
semestralka1/src/render/obstacle.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// src/render/obstacle.cpp
|
||||||
|
#include "obstacle.h"
|
||||||
|
#include "../assets/obstacle_crawl_frames.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
// Draw a single obstacle ASCII sprite at (x, y)
|
||||||
|
void draw_obstacle(int x, int y, CrawlObstacleType type) {
|
||||||
|
const char **obstacle = nullptr;
|
||||||
|
int obstacle_height = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case CrawlObstacleType::Crawl1:
|
||||||
|
obstacle = OBSTACLE_CRAWL1_FRAME;
|
||||||
|
obstacle_height = OBSTACLE_CRAWL1_FRAME_HEIGHT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CrawlObstacleType::Crawl2:
|
||||||
|
obstacle = OBSTACLE_CRAWL2_FRAME;
|
||||||
|
obstacle_height = OBSTACLE_CRAWL2_FRAME_HEIGHT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return; // in case of invalid type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each obstacle row is printed using ANSI cursor positioning
|
||||||
|
for (int i = 0; i < obstacle_height; i++) {
|
||||||
|
printf("\033[%d;%dH%s", y + i + 1, x + 1, obstacle[i]);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
7
semestralka1/src/render/obstacle.h
Normal file
7
semestralka1/src/render/obstacle.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// src/render/obstacle.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../assets/obstacle_crawl_frames.h"
|
||||||
|
|
||||||
|
// Draw the obstacle ASCII block starting at given (x, y)
|
||||||
|
void draw_obstacle(int x, int y, CrawlObstacleType type);
|
||||||
Reference in New Issue
Block a user