phantasia

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

commit 89a7fdc431dca06034c31c6c81b9081feba4d50b
parent ea6ee34572d0f5103be1022f0ae4b6f3b27fe158
Author: beep <beep@wimdupont.com>
Date:   Sat,  4 Apr 2026 17:11:24 +0000

Use 4-way movement and facing sprites

Diffstat:
Msrc/engine/world.c | 24+++++++++++++++++++-----
Msrc/game/main.c | 41+++++++++++++++++++++++++++++++----------
2 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/src/engine/world.c b/src/engine/world.c @@ -135,6 +135,21 @@ ph_try_pickup(PhWorld *world, PhEntity *entity) } } +static PhInput +ph_orthogonal_input(PhInput input, const PhEntity *entity) +{ + if (input.move_x == 0 || input.move_y == 0) { + return input; + } + + if (entity->facing_x != 0) { + input.move_y = 0; + } else { + input.move_x = 0; + } + return input; +} + void ph_world_init(PhWorld *world, PhArea area, float viewport_w, float viewport_h) { @@ -294,7 +309,6 @@ ph_world_tick(PhWorld *world, PhInput input, float dt) PhEntity *player; const PhEntityDef *def; PhVec2 next; - float len; if (world->player_index < 0 || world->player_index >= world->entity_count) { return; @@ -306,15 +320,15 @@ ph_world_tick(PhWorld *world, PhInput input, float dt) return; } + input = ph_orthogonal_input(input, player); next = player->pos; - len = sqrtf((float)(input.move_x * input.move_x + input.move_y * input.move_y)); - if (len > 0.0f) { + if (input.move_x != 0 || input.move_y != 0) { float speed = (float)def->move_speed; player->facing_x = input.move_x; player->facing_y = input.move_y; - next.x += ((float)input.move_x / len) * speed * dt; - next.y += ((float)input.move_y / len) * speed * 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))) { player->pos.x = next.x; diff --git a/src/game/main.c b/src/game/main.c @@ -32,9 +32,7 @@ enum { enum { PH_TILESET_COLUMNS = 12, - PH_HERO_COLUMNS = 8, PH_ITEMS_COLUMNS = 8, - PH_CRITTERS_COLUMNS = 16, PH_TILE_GRASS = 13, PH_TILE_BLOCKED = 61, }; @@ -184,8 +182,8 @@ ph_destroy_assets(PhAssets *assets) } static void -ph_draw_sprite(SDL_Renderer *renderer, SDL_Texture *texture, int columns, - int sprite_tile_x, int sprite_tile_y, SDL_FRect dst) +ph_draw_sprite(SDL_Renderer *renderer, SDL_Texture *texture, + int sprite_tile_x, int sprite_tile_y, SDL_FRect dst, SDL_FlipMode flip) { SDL_FRect src = { .x = (float)(sprite_tile_x * PH_TILE_SIZE), @@ -194,8 +192,25 @@ ph_draw_sprite(SDL_Renderer *renderer, SDL_Texture *texture, int columns, .h = (float)PH_TILE_SIZE, }; - (void)columns; - SDL_RenderTexture(renderer, texture, &src, &dst); + SDL_RenderTextureRotated(renderer, texture, &src, &dst, 0.0, NULL, flip); +} + +static int +ph_player_sprite_row(const PhEntity *entity) +{ + if (entity->facing_y > 0) { + return 0; + } + if (entity->facing_y < 0) { + return 2; + } + return 1; +} + +static SDL_FlipMode +ph_player_sprite_flip(const PhEntity *entity) +{ + return entity->facing_x > 0 ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; } static void @@ -250,8 +265,8 @@ ph_draw_items(SDL_Renderer *renderer, const PhAssets *assets, const PhWorld *wor rect.y = drop->pos.y - world->camera.pos.y - 8.0f; rect.w = 16.0f; rect.h = 16.0f; - ph_draw_sprite(renderer, assets->items, PH_ITEMS_COLUMNS, - def->sprite_tile_x, def->sprite_tile_y, rect); + ph_draw_sprite(renderer, assets->items, + def->sprite_tile_x, def->sprite_tile_y, rect, SDL_FLIP_NONE); } else { SDL_SetRenderDrawColor(renderer, 242, 214, 80, 255); SDL_RenderFillRect(renderer, &rect); @@ -276,13 +291,19 @@ ph_draw_entities(SDL_Renderer *renderer, const PhAssets *assets, const PhWorld * if (def->sprite_tile_x >= 0 && def->sprite_tile_y >= 0 && (def->kind == PH_ENTITY_PLAYER || def->kind == PH_ENTITY_MONSTER)) { SDL_Texture *sheet = def->kind == PH_ENTITY_PLAYER ? assets->hero : assets->critters; - int columns = def->kind == PH_ENTITY_PLAYER ? PH_HERO_COLUMNS : PH_CRITTERS_COLUMNS; + int sprite_tile_y = def->sprite_tile_y; + SDL_FlipMode flip = SDL_FLIP_NONE; rect.x = entity->pos.x - world->camera.pos.x - 8.0f; rect.y = entity->pos.y - world->camera.pos.y - 12.0f; rect.w = 16.0f; rect.h = 16.0f; - ph_draw_sprite(renderer, sheet, columns, def->sprite_tile_x, def->sprite_tile_y, rect); + + if (def->kind == PH_ENTITY_PLAYER) { + sprite_tile_y = ph_player_sprite_row(entity); + flip = ph_player_sprite_flip(entity); + } + ph_draw_sprite(renderer, sheet, def->sprite_tile_x, sprite_tile_y, rect, flip); } else { rect.x = entity->pos.x - world->camera.pos.x - 7.0f; rect.y = entity->pos.y - world->camera.pos.y - 12.0f;