commit e66c15d34176c7ef99ff1114cf3cfe7fff38eab6
parent 0b33409cb0defb788ceb0a21f5ba77457ce0c01b
Author: beep <beep@wimdupont.com>
Date: Sat, 4 Apr 2026 17:34:28 +0000
Block movement through entities
Diffstat:
3 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/src/engine/world.c b/src/engine/world.c
@@ -10,6 +10,7 @@ enum {
PH_MAP_MAGIC = 0x50484d50,
PH_MAP_VERSION = 1,
PH_AREA_NAME_MAX = 64,
+ PH_ENTITY_BLOCK_RADIUS = 10,
};
typedef struct {
@@ -108,6 +109,65 @@ ph_position_blocked(const PhWorld *world, PhVec2 pos)
}
static void
+ph_world_set_notice(PhWorld *world, const char *text)
+{
+ snprintf(world->notice, sizeof(world->notice), "%s", text);
+ world->notice_seconds = 1.25f;
+}
+
+static const PhEntity *
+ph_world_blocking_entity(const PhWorld *world, int self_index, PhVec2 pos)
+{
+ int i;
+
+ for (i = 0; i < world->entity_count; ++i) {
+ const PhEntity *entity = &world->entities[i];
+ const PhEntityDef *def;
+
+ if (i == self_index || !entity->active) {
+ continue;
+ }
+
+ def = ph_world_entity_def(world, entity->type_id);
+ if (!def || !def->blocks_movement) {
+ continue;
+ }
+
+ if (ph_dist2(entity->pos, pos) <
+ (float)(PH_ENTITY_BLOCK_RADIUS * PH_ENTITY_BLOCK_RADIUS)) {
+ return entity;
+ }
+ }
+
+ return NULL;
+}
+
+static int
+ph_player_step_blocked(PhWorld *world, int player_index, PhVec2 pos)
+{
+ const PhEntity *blocker;
+ const PhEntityDef *def;
+
+ if (ph_position_blocked(world, pos)) {
+ return 1;
+ }
+
+ blocker = ph_world_blocking_entity(world, player_index, pos);
+ if (!blocker) {
+ return 0;
+ }
+
+ def = ph_world_entity_def(world, blocker->type_id);
+ if (def && def->name) {
+ char text[PH_NOTICE_SIZE];
+
+ snprintf(text, sizeof(text), "%s blocks your path.", def->name);
+ ph_world_set_notice(world, text);
+ }
+ return 1;
+}
+
+static void
ph_try_pickup(PhWorld *world, PhEntity *entity)
{
int i;
@@ -320,6 +380,14 @@ ph_world_tick(PhWorld *world, PhInput input, float dt)
return;
}
+ if (world->notice_seconds > 0.0f) {
+ world->notice_seconds -= dt;
+ if (world->notice_seconds <= 0.0f) {
+ world->notice_seconds = 0.0f;
+ world->notice[0] = '\0';
+ }
+ }
+
input = ph_orthogonal_input(input, player);
next = player->pos;
if (input.move_x != 0 || input.move_y != 0) {
@@ -330,10 +398,12 @@ ph_world_tick(PhWorld *world, PhInput input, float dt)
next.x += (float)input.move_x * speed * dt;
next.y += (float)input.move_y * speed * dt;
- if (!ph_position_blocked(world, ph_vec2(next.x, player->pos.y))) {
+ if (!ph_player_step_blocked(world, world->player_index,
+ ph_vec2(next.x, player->pos.y))) {
player->pos.x = next.x;
}
- if (!ph_position_blocked(world, ph_vec2(player->pos.x, next.y))) {
+ if (!ph_player_step_blocked(world, world->player_index,
+ ph_vec2(player->pos.x, next.y))) {
player->pos.y = next.y;
}
}
diff --git a/src/engine/world.h b/src/engine/world.h
@@ -9,6 +9,7 @@ enum {
PH_MAX_ITEM_TYPES = 64,
PH_MAX_ENTITIES = 128,
PH_MAX_GROUND_ITEMS = 128,
+ PH_NOTICE_SIZE = 96,
};
typedef enum {
@@ -29,6 +30,7 @@ typedef struct {
int move_speed;
int sprite_tile_x;
int sprite_tile_y;
+ int blocks_movement;
PhEntityKind kind;
} PhEntityDef;
@@ -85,6 +87,8 @@ typedef struct {
int entity_count;
int ground_item_count;
int player_talent_points;
+ char notice[PH_NOTICE_SIZE];
+ float notice_seconds;
} PhWorld;
typedef struct {
diff --git a/src/game/main.c b/src/game/main.c
@@ -65,6 +65,7 @@ ph_make_world(PhWorld *world)
.move_speed = 90,
.sprite_tile_x = 0,
.sprite_tile_y = 2,
+ .blocks_movement = 0,
.kind = PH_ENTITY_PLAYER,
});
ph_world_add_entity_def(world, (PhEntityDef){
@@ -74,6 +75,7 @@ ph_make_world(PhWorld *world)
.move_speed = 45,
.sprite_tile_x = 12,
.sprite_tile_y = 0,
+ .blocks_movement = 1,
.kind = PH_ENTITY_MONSTER,
});
ph_world_add_item_def(world, (PhItemDef){
@@ -334,6 +336,19 @@ ph_render_frame(SDL_Renderer *renderer, const PhAssets *assets, PhWorld *world,
ph_draw_area(renderer, assets, world);
ph_draw_items(renderer, assets, world);
ph_draw_entities(renderer, assets, world);
+ if (world->notice_seconds > 0.0f && world->notice[0] != '\0') {
+ SDL_FRect notice_bg = {
+ .x = 8.0f,
+ .y = (float)(PH_VIEW_H - 28),
+ .w = (float)(PH_VIEW_W - 16),
+ .h = 20.0f,
+ };
+
+ SDL_SetRenderDrawColor(renderer, 20, 24, 34, 255);
+ SDL_RenderFillRect(renderer, ¬ice_bg);
+ SDL_SetRenderDrawColor(renderer, 232, 236, 244, 255);
+ SDL_RenderDebugText(renderer, 14.0f, (float)(PH_VIEW_H - 22), world->notice);
+ }
SDL_RenderPresent(renderer);
}