From dd410c6f6c7515105a73f057a78f1d474d7c2fdf Mon Sep 17 00:00:00 2001 From: Priec Date: Tue, 18 Nov 2025 01:02:13 +0100 Subject: [PATCH] collisions happen properly now --- .../src/assets/obstacle_crawl_frames.h | 4 +- semestralka1/src/game/collision.h | 28 ++++++------ semestralka1/src/game/obstacle_manager.h | 14 +++++- semestralka1/src/game/obstacle_system.h | 25 ++--------- semestralka1/src/render/loop.cpp | 12 ++--- semestralka1/src/render/obstacle.cpp | 45 ++++++++++++++----- 6 files changed, 74 insertions(+), 54 deletions(-) diff --git a/semestralka1/src/assets/obstacle_crawl_frames.h b/semestralka1/src/assets/obstacle_crawl_frames.h index 80c7bcb..675f676 100644 --- a/semestralka1/src/assets/obstacle_crawl_frames.h +++ b/semestralka1/src/assets/obstacle_crawl_frames.h @@ -31,8 +31,8 @@ static const char **OBSTACLE_CRAWL_FRAMES[] = { OBSTACLE_CRAWL1_FRAME, OBSTACLE_ // Crawl1 dimensions and collision static const int OBSTACLE_CRAWL1_FRAME_HEIGHT = sizeof(OBSTACLE_CRAWL1_FRAME) / sizeof(OBSTACLE_CRAWL1_FRAME[0]); static const int OBSTACLE_CRAWL1_FRAME_WIDTH = std::strlen(OBSTACLE_CRAWL1_FRAME[0]); -static const int OBSTACLE_CRAWL1_COLLISION_LEFT_OFFSET = 0; -static const int OBSTACLE_CRAWL1_COLLISION_RIGHT_OFFSET = 0; +static const int OBSTACLE_CRAWL1_COLLISION_LEFT_OFFSET = 3; +static const int OBSTACLE_CRAWL1_COLLISION_RIGHT_OFFSET = 3; static const int OBSTACLE_CRAWL1_COLLISION_WIDTH = OBSTACLE_CRAWL1_FRAME_WIDTH - (OBSTACLE_CRAWL1_COLLISION_LEFT_OFFSET + OBSTACLE_CRAWL1_COLLISION_RIGHT_OFFSET); static const int OBSTACLE_CRAWL1_COLLISION_TOP_OFFSET = 4; // first 4 rows are just empty ('.') // collision box height = bottom 2 rows diff --git a/semestralka1/src/game/collision.h b/semestralka1/src/game/collision.h index badc88f..2163bbf 100644 --- a/semestralka1/src/game/collision.h +++ b/semestralka1/src/game/collision.h @@ -1,7 +1,6 @@ // src/game/collision.h #pragma once #include "../render/player_positioning.h" -#include "../render/player.h" #include "../assets/character_walk_frames.h" #include "../assets/character_run_frames.h" #include "../assets/character_crawl_frames.h" @@ -18,9 +17,13 @@ struct Obstacle { inline bool check_collision(const CharacterPosition& player, MovementType movement, const Obstacle& obs) { - int player_x = player.x; - int player_y = (VIEW_HEIGHT - player.y) - CHARACTER_WALK_FRAME_HEIGHT; - int box_x = 0, box_w = 0, box_h = 0; + + // Player is given in bottom-based world coordinates (0 = bottom line) + const int player_x = player.x; + const int player_bottom = player.y; + int box_x = 0; + int box_w = 0; + int box_h = 0; switch (movement) { case MovementType::Walk: @@ -46,19 +49,18 @@ inline bool check_collision(const CharacterPosition& player, } // Player's bounding box - int player_left = box_x; - int player_right = player_left + box_w; - int player_top = player_y; - int player_bottom = player_top + box_h; + const int player_left = box_x; + const int player_right = player_left + box_w; + const int player_top = player_bottom + box_h; // Obstacle bounding box - int obs_left = obs.x; - int obs_right = obs.x + obs.width; - int obs_top = obs.y; - int obs_bottom = obs.y + obs.height; + const int obs_left = obs.x; + const int obs_right = obs.x + obs.width; + const int obs_bottom = obs.y; + const int obs_top = obs_bottom + obs.height; // Simple overlap check bool horizontal = player_left < obs_right && player_right > obs_left; - bool vertical = player_top < obs_bottom && player_bottom > obs_top; + bool vertical = player_bottom < obs_top && player_top > obs_bottom; return horizontal && vertical; } diff --git a/semestralka1/src/game/obstacle_manager.h b/semestralka1/src/game/obstacle_manager.h index c3ef84a..2a7722c 100644 --- a/semestralka1/src/game/obstacle_manager.h +++ b/semestralka1/src/game/obstacle_manager.h @@ -25,7 +25,19 @@ 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.height = (type == CrawlObstacleType::Crawl1) ? OBSTACLE_CRAWL1_COLLISION_HEIGHT : OBSTACLE_CRAWL2_COLLISION_HEIGHT; - obstacle_pool[i].data.y = 0; + + // Default Y so that the SPRITE touches the top of the screen. + // We store Y as the bottom of the COLLISION BOX in bottom-based world coords. + int top_offset = 0; + if (type == CrawlObstacleType::Crawl1) { + top_offset = OBSTACLE_CRAWL1_COLLISION_TOP_OFFSET; + } else { + top_offset = 0; + } + const int i_bottom_of_collision = top_offset + obstacle_pool[i].data.height - 1; + // Top of screen in world coords is VIEW_HEIGHT - 1 + const int collision_bottom_world_y = (VIEW_HEIGHT - 1) - i_bottom_of_collision; + obstacle_pool[i].data.y = collision_bottom_world_y; return i; } diff --git a/semestralka1/src/game/obstacle_system.h b/semestralka1/src/game/obstacle_system.h index 307072a..636fc8f 100644 --- a/semestralka1/src/game/obstacle_system.h +++ b/semestralka1/src/game/obstacle_system.h @@ -71,27 +71,8 @@ private: 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); - } + const char ** /*frame*/, + int /*frame_height*/) { + draw_obstacle(obs.data.x, obs.data.y, obs.type); } }; diff --git a/semestralka1/src/render/loop.cpp b/semestralka1/src/render/loop.cpp index cd58a2c..242f3a4 100644 --- a/semestralka1/src/render/loop.cpp +++ b/semestralka1/src/render/loop.cpp @@ -122,12 +122,12 @@ void render_loop(int speed) { obstacle_pool[i].data.y, obstacle_pool[i].type); - if (check_collision(draw_pos, frame.movement, obstacle_pool[i].data)) { - printf("\033[2J\033[H"); // clear screen & home cursor - printf("GAME OVER\r\n"); - game_over = true; - break; - } + if (check_collision(pos, frame.movement, obstacle_pool[i].data)) { + printf("\033[2J\033[H"); + printf("GAME OVER\r\n"); + game_over = true; + break; + } } if (game_over) diff --git a/semestralka1/src/render/obstacle.cpp b/semestralka1/src/render/obstacle.cpp index 04879d4..f545f94 100644 --- a/semestralka1/src/render/obstacle.cpp +++ b/semestralka1/src/render/obstacle.cpp @@ -4,28 +4,53 @@ #include "../assets/background_frame.h" #include -// Draw a single obstacle ASCII sprite at (x, y) where y is ground‑based (0 = bottom) +// Draws an obstacle using bottom‑based world coordinates. +// x = left edge of the collision box in world space +// y = bottom edge of the collision box in world space (0 = ground) void draw_obstacle(int x, int y, CrawlObstacleType type) { - const char **obstacle = nullptr; - int obstacle_height = 0; + const char **obstacle_frame = nullptr; + int frame_total_height = 0; + + // Collision‑model parameters for this obstacle + int collision_top_offset = 0; // rows from visual top to top of collision box + int collision_height = 0; // rows tall + int collision_left_offset = 0; // columns from visual left to collision left switch (type) { case CrawlObstacleType::Crawl1: - obstacle = OBSTACLE_CRAWL1_FRAME; - obstacle_height = OBSTACLE_CRAWL1_FRAME_HEIGHT; + obstacle_frame = OBSTACLE_CRAWL1_FRAME; + frame_total_height = OBSTACLE_CRAWL1_FRAME_HEIGHT; + collision_top_offset = OBSTACLE_CRAWL1_COLLISION_TOP_OFFSET; + collision_height = OBSTACLE_CRAWL1_COLLISION_HEIGHT; + collision_left_offset = OBSTACLE_CRAWL1_COLLISION_LEFT_OFFSET; break; case CrawlObstacleType::Crawl2: - obstacle = OBSTACLE_CRAWL2_FRAME; - obstacle_height = OBSTACLE_CRAWL2_FRAME_HEIGHT; + obstacle_frame = OBSTACLE_CRAWL2_FRAME; + frame_total_height = OBSTACLE_CRAWL2_FRAME_HEIGHT; + collision_top_offset = 0; + collision_height = OBSTACLE_CRAWL2_COLLISION_HEIGHT; + collision_left_offset = OBSTACLE_CRAWL2_COLLISION_LEFT_OFFSET; break; default: - return; // in case of invalid type + return; // no rendering for invalid type } - for (int i = 0; i < obstacle_height; i++) { - printf("\033[%d;%dH%s", y + i + 1, x + 1, obstacle[i]); + // Convert bottom‑based (world) coordinates to screen coordinates. + // Y of the collision bottom is given; translate to where to start drawing the visual frame. + const int frame_row_index_bottom = collision_top_offset + collision_height - 1; + const int frame_top_world_y = y + frame_row_index_bottom; + const int frame_top_screen_row = VIEW_HEIGHT - frame_top_world_y; + + // X of the collision box is given; shift left to the visual frame's starting column. + const int frame_screen_x = x - collision_left_offset; + + for (int i = 0; i < frame_total_height; i++) { + const int screen_row = frame_top_screen_row + i; + if (screen_row < 1 || screen_row > VIEW_HEIGHT) continue; + printf("\033[%d;%dH%s", screen_row, frame_screen_x + 1, obstacle_frame[i]); } + fflush(stdout); }