collisions happen properly now

This commit is contained in:
Priec
2025-11-18 01:02:13 +01:00
parent 967b377e76
commit dd410c6f6c
6 changed files with 74 additions and 54 deletions

View File

@@ -31,8 +31,8 @@ static const char **OBSTACLE_CRAWL_FRAMES[] = { OBSTACLE_CRAWL1_FRAME, OBSTACLE_
// Crawl1 dimensions and collision // 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_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_FRAME_WIDTH = std::strlen(OBSTACLE_CRAWL1_FRAME[0]);
static const int OBSTACLE_CRAWL1_COLLISION_LEFT_OFFSET = 0; static const int OBSTACLE_CRAWL1_COLLISION_LEFT_OFFSET = 3;
static const int OBSTACLE_CRAWL1_COLLISION_RIGHT_OFFSET = 0; 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_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 ('.') static const int OBSTACLE_CRAWL1_COLLISION_TOP_OFFSET = 4; // first 4 rows are just empty ('.')
// collision box height = bottom 2 rows // collision box height = bottom 2 rows

View File

@@ -1,7 +1,6 @@
// src/game/collision.h // src/game/collision.h
#pragma once #pragma once
#include "../render/player_positioning.h" #include "../render/player_positioning.h"
#include "../render/player.h"
#include "../assets/character_walk_frames.h" #include "../assets/character_walk_frames.h"
#include "../assets/character_run_frames.h" #include "../assets/character_run_frames.h"
#include "../assets/character_crawl_frames.h" #include "../assets/character_crawl_frames.h"
@@ -18,9 +17,13 @@ struct Obstacle {
inline bool check_collision(const CharacterPosition& player, inline bool check_collision(const CharacterPosition& player,
MovementType movement, MovementType movement,
const Obstacle& obs) { const Obstacle& obs) {
int player_x = player.x;
int player_y = (VIEW_HEIGHT - player.y) - CHARACTER_WALK_FRAME_HEIGHT; // Player is given in bottom-based world coordinates (0 = bottom line)
int box_x = 0, box_w = 0, box_h = 0; 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) { switch (movement) {
case MovementType::Walk: case MovementType::Walk:
@@ -46,19 +49,18 @@ inline bool check_collision(const CharacterPosition& player,
} }
// Player's bounding box // Player's bounding box
int player_left = box_x; const int player_left = box_x;
int player_right = player_left + box_w; const int player_right = player_left + box_w;
int player_top = player_y; const int player_top = player_bottom + box_h;
int player_bottom = player_top + box_h;
// Obstacle bounding box // Obstacle bounding box
int obs_left = obs.x; const int obs_left = obs.x;
int obs_right = obs.x + obs.width; const int obs_right = obs.x + obs.width;
int obs_top = obs.y; const int obs_bottom = obs.y;
int obs_bottom = obs.y + obs.height; const int obs_top = obs_bottom + obs.height;
// Simple overlap check // Simple 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_top < obs_bottom && player_bottom > obs_top; bool vertical = player_bottom < obs_top && player_top > obs_bottom;
return horizontal && vertical; return horizontal && vertical;
} }

View File

@@ -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.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;
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; return i;
} }

View File

@@ -71,27 +71,8 @@ private:
int spawn_index_; int spawn_index_;
static void draw_clipped_obstacle(const MovingObstacle &obs, static void draw_clipped_obstacle(const MovingObstacle &obs,
const char **frame, const char ** /*frame*/,
int frame_height) { int /*frame_height*/) {
int x = obs.data.x; draw_obstacle(obs.data.x, obs.data.y, obs.type);
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);
}
} }
}; };

View File

@@ -122,12 +122,12 @@ void render_loop(int speed) {
obstacle_pool[i].data.y, obstacle_pool[i].data.y,
obstacle_pool[i].type); obstacle_pool[i].type);
if (check_collision(draw_pos, frame.movement, obstacle_pool[i].data)) { if (check_collision(pos, frame.movement, obstacle_pool[i].data)) {
printf("\033[2J\033[H"); // clear screen & home cursor 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)

View File

@@ -4,28 +4,53 @@
#include "../assets/background_frame.h" #include "../assets/background_frame.h"
#include <cstdio> #include <cstdio>
// Draw a single obstacle ASCII sprite at (x, y) where y is groundbased (0 = bottom) // Draws an obstacle using bottombased 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) { void draw_obstacle(int x, int y, CrawlObstacleType type) {
const char **obstacle = nullptr; const char **obstacle_frame = nullptr;
int obstacle_height = 0; int frame_total_height = 0;
// Collisionmodel 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) { switch (type) {
case CrawlObstacleType::Crawl1: case CrawlObstacleType::Crawl1:
obstacle = OBSTACLE_CRAWL1_FRAME; obstacle_frame = OBSTACLE_CRAWL1_FRAME;
obstacle_height = OBSTACLE_CRAWL1_FRAME_HEIGHT; 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; break;
case CrawlObstacleType::Crawl2: case CrawlObstacleType::Crawl2:
obstacle = OBSTACLE_CRAWL2_FRAME; obstacle_frame = OBSTACLE_CRAWL2_FRAME;
obstacle_height = OBSTACLE_CRAWL2_FRAME_HEIGHT; 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; break;
default: default:
return; // in case of invalid type return; // no rendering for invalid type
} }
for (int i = 0; i < obstacle_height; i++) { // Convert bottombased (world) coordinates to screen coordinates.
printf("\033[%d;%dH%s", y + i + 1, x + 1, obstacle[i]); // 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); fflush(stdout);
} }