phantasia

Phantasia - 2D SDL3 RPG prototype.
git clone git://git.beep.wimdupont.com/phantasia.git
Log | Files | Refs | README | LICENSE

commit 3b6199d981cd247037f571ad1740c3c73e4e73d8
parent ae5a1592ddbf20295d9034c62d7a1be9bf2ef2bc
Author: beep <beep@wimdupont.com>
Date:   Thu, 30 Jul 2026 09:48:34 +0000

Clarify doors and area exits

Diffstat:
Mdata/maps/mira-shop.txt | 2+-
Mdata/maps/stonehollow.txt | 4++--
Msrc/engine/world.c | 16++++++++++++++++
Msrc/engine/world.h | 1+
Msrc/game/content.c | 60+++++++++++++++++++++++++++++++++++-------------------------
Msrc/tests/smoke.c | 15+++++++++++++++
6 files changed, 70 insertions(+), 28 deletions(-)

diff --git a/data/maps/mira-shop.txt b/data/maps/mira-shop.txt @@ -13,5 +13,5 @@ name: Mira's Sundries {==================} {==================} {==================} -{========e=========} +{=========e========} (_________<________) diff --git a/data/maps/stonehollow.txt b/data/maps/stonehollow.txt @@ -21,6 +21,6 @@ name: Stonehollow #.............,................# #..:..........,..........;.....# #.............,................# +#..............................# #.............e................# -#.............<................# -################################ +##############<################# diff --git a/src/engine/world.c b/src/engine/world.c @@ -160,6 +160,14 @@ ph_entity_step_blocked(PhWorld *world, int entity_index, PhVec2 pos) const PhEntityDef *def; if (ph_position_blocked(world, pos)) { + int tx = (int)floorf(pos.x / (float)PH_TILE_SIZE); + int ty = (int)floorf(pos.y / (float)PH_TILE_SIZE); + const PhTileDef *tile = ph_area_tile_def(&world->area, tx, ty); + + mover = ph_world_entity_def(world, world->entities[entity_index].type_id); + if (mover && mover->kind == PH_ENTITY_PLAYER && tile && + tile->interaction_notice) + ph_world_set_notice(world, tile->interaction_notice); return 1; } @@ -242,6 +250,14 @@ ph_try_interact(PhWorld *world, const PhEntity *player) closest = distance; world->interaction_id = def->interaction_id; } + if (!world->interaction_id) { + int tx = (int)floorf(target.x / (float)PH_TILE_SIZE); + int ty = (int)floorf(target.y / (float)PH_TILE_SIZE); + const PhTileDef *tile = ph_area_tile_def(&world->area, tx, ty); + + if (tile && tile->interaction_notice) + ph_world_set_notice(world, tile->interaction_notice); + } } static PhInput diff --git a/src/engine/world.h b/src/engine/world.h @@ -113,6 +113,7 @@ typedef struct { int background_sprite_tile_x; int background_sprite_tile_y; int autotile; + const char *interaction_notice; } PhTileDef; enum { diff --git a/src/game/content.c b/src/game/content.c @@ -14,62 +14,72 @@ const PhAreaDef ph_area_defs[PH_AREA_COUNT] = { }; const PhTileDef ph_tile_defs[PH_TILE_DEF_COUNT] = { - { '.', 0, PH_ASSET_TILESET, 1, 1, 0, 0, 0, 0 }, - { ':', 0, PH_ASSET_TILESET, 1, 0, 0, 0, 0, 0 }, - { ';', 0, PH_ASSET_TILESET, 2, 0, 0, 0, 0, 0 }, - { ',', 0, PH_ASSET_TILESET, 6, 2, 0, 0, 0, 0 }, - { 'T', 0, PH_ASSET_TILESET, 6, 2, 0, 0, 0, 0 }, - { '#', 1, PH_ASSET_TILESET, 9, 4, 0, 0, 0, PH_TILE_AUTOTILE_3X3 }, + { '.', 0, PH_ASSET_TILESET, 1, 1, 0, 0, 0, 0, 0 }, + { ':', 0, PH_ASSET_TILESET, 1, 0, 0, 0, 0, 0, 0 }, + { ';', 0, PH_ASSET_TILESET, 2, 0, 0, 0, 0, 0, 0 }, + { ',', 0, PH_ASSET_TILESET, 6, 2, 0, 0, 0, 0, 0 }, + { 'T', 0, PH_ASSET_TILESET, 6, 2, 0, 0, 0, 0, 0 }, + { '#', 1, PH_ASSET_TILESET, 9, 4, 0, 0, 0, + PH_TILE_AUTOTILE_3X3, 0 }, { .symbol = 'J', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 0, .sprite_tile_y = 16, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'K', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 1, .sprite_tile_y = 16, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'L', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 3, .sprite_tile_y = 16, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'M', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 0, .sprite_tile_y = 17, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'N', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 1, .sprite_tile_y = 17, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'O', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 3, .sprite_tile_y = 17, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'P', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 0, .sprite_tile_y = 18, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'Q', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 1, .sprite_tile_y = 18, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'R', .blocks_movement = 1, .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 3, .sprite_tile_y = 18, .background_asset_id = PH_ASSET_TILESET, - .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, + .background_sprite_tile_x = 1, .background_sprite_tile_y = 1, + .interaction_notice = "The door is locked." }, { .symbol = 'j', .asset_id = PH_ASSET_TILESET, .sprite_tile_x = 0, .sprite_tile_y = 16, .background_asset_id = PH_ASSET_TILESET, .background_sprite_tile_x = 1, .background_sprite_tile_y = 1 }, - { '[', 1, PH_ASSET_TILESET, 9, 1, 0, 0, 0, 0 }, - { '^', 1, PH_ASSET_TILESET, 10, 1, 0, 0, 0, 0 }, - { ']', 1, PH_ASSET_TILESET, 11, 1, 0, 0, 0, 0 }, - { '{', 1, PH_ASSET_TILESET, 9, 2, 0, 0, 0, 0 }, - { '=', 0, PH_ASSET_TILESET, 10, 2, 0, 0, 0, 0 }, - { '}', 1, PH_ASSET_TILESET, 11, 2, 0, 0, 0, 0 }, - { '(', 1, PH_ASSET_TILESET, 9, 3, 0, 0, 0, 0 }, - { '_', 1, PH_ASSET_TILESET, 10, 3, 0, 0, 0, 0 }, - { ')', 1, PH_ASSET_TILESET, 11, 3, 0, 0, 0, 0 }, - { '+', 0, PH_ASSET_TILESET, 10, 3, 0, 0, 0, 0 }, + { '[', 1, PH_ASSET_TILESET, 9, 1, 0, 0, 0, 0, 0 }, + { '^', 1, PH_ASSET_TILESET, 10, 1, 0, 0, 0, 0, 0 }, + { ']', 1, PH_ASSET_TILESET, 11, 1, 0, 0, 0, 0, 0 }, + { '{', 1, PH_ASSET_TILESET, 9, 2, 0, 0, 0, 0, 0 }, + { '=', 0, PH_ASSET_TILESET, 10, 2, 0, 0, 0, 0, 0 }, + { '}', 1, PH_ASSET_TILESET, 11, 2, 0, 0, 0, 0, 0 }, + { '(', 1, PH_ASSET_TILESET, 9, 3, 0, 0, 0, 0, 0 }, + { '_', 1, PH_ASSET_TILESET, 10, 3, 0, 0, 0, 0, 0 }, + { ')', 1, PH_ASSET_TILESET, 11, 3, 0, 0, 0, 0, 0 }, + { '+', 0, PH_ASSET_TILESET, 5, 15, 0, 0, 0, 0, 0 }, }; const PhSpellDef ph_spell_defs[PH_SPELL_DEF_COUNT] = { diff --git a/src/tests/smoke.c b/src/tests/smoke.c @@ -346,9 +346,24 @@ ph_area_shop_test(void) !ph_area_tile_blocked(&world.area, 8, 2) || ph_area_tile_blocked(&world.area, 4, 4) || ph_area_tile_blocked(&world.area, 6, 6)) goto fail; + player->pos = (PhVec2){ PH_TILE_CENTER(8), PH_TILE_CENTER(3) }; + player->motion.facing_x = 0; + player->motion.facing_y = -1; + ph_world_tick(&world, (PhInput){ .interact = 1 }, 0.0f); + if (strcmp(world.notice.text, "The door is locked.") != 0) goto fail; if (ph_enter_portal(&world, PH_AREA_MIRA_SHOP) != 1 || world.area_id != PH_AREA_MIRA_SHOP || world.initialized_area_count != 3) goto fail; + for (i = 0; i < world.area.marker_count; ++i) { + const PhMarkerDef *def = ph_area_catalog_marker(ph_game_world.areas, + world.area_id, world.area.markers[i].symbol); + + if (def && def->kind == PH_MARKER_PORTAL && + def->destination_area_id == PH_AREA_STONEHOLLOW) break; + } + if (i == world.area.marker_count || + world.area.markers[i].tile_x != + (int)(player->pos.x / (float)PH_TILE_SIZE)) goto fail; for (i = 0; i < world.entity_count; ++i) { const PhEntityDef *def = ph_world_entity_def(&world, world.entities[i].type_id);