commit 725cd8c35c7be914c4a27db62336bfd915a00749
parent b50d20aa6344cb845ad21b5fd0cdccc6fca23ecf
Author: beep <beep@wimdupont.com>
Date: Tue, 27 Oct 2026 10:58:16 +0000
Separate camera state from world simulation
Diffstat:
16 files changed, 124 insertions(+), 114 deletions(-)
diff --git a/README.adoc b/README.adoc
@@ -69,8 +69,11 @@ Interactions and presentation events are handled after each simulation tick.
Identical input per tick and random seeds reproduce simulation within the same
build; this does not promise identical results across platforms.
-Camera state and compile-time simulation configuration still belong to the
-existing engine; this is an incremental separation, not a general-purpose SDK.
+Camera state belongs to presentation. World drawing accepts a caller-supplied
+camera, and player following reads the world without changing simulation. World
+startup and save loading are independent of viewport dimensions. Compile-time
+simulation configuration remains in the engine; this is an incremental
+separation, not a general-purpose SDK.
For the current implementation, start with `src/engine/*.h` for the engine's
public data types and operations, `src/game/content.c` for a concrete game setup,
diff --git a/TODO.adoc b/TODO.adoc
@@ -8,9 +8,6 @@ that improve the game or demonstrate reuse over speculative framework features.
The shared engine library, independent Parcel Run example, SDL-independent game
flow and media interfaces, and fixed simulation ticks provide the foundation.
-* Separate camera state from `PhWorld` and remove viewport parameters from world
- startup and save loading. Simulation and persistence should not depend on how
- the world is viewed.
* Validate content catalogs and map references before play. Report broken IDs,
destinations, and definitions early, with enough context to fix the data.
* Add a small debug overlay for collision bounds, AI destinations, frame timings,
diff --git a/src/engine/area.c b/src/engine/area.c
@@ -38,8 +38,7 @@ ph_area_catalog_load(PhArea *area, const PhAreaCatalog *catalog, int area_id)
}
int
-ph_world_start(PhWorld *world, const PhWorldSetup *setup,
- float viewport_w, float viewport_h)
+ph_world_start(PhWorld *world, const PhWorldSetup *setup)
{
PhArea area;
int player = -1;
@@ -49,8 +48,7 @@ ph_world_start(PhWorld *world, const PhWorldSetup *setup,
(setup->equipment_count && !setup->equipment) ||
ph_area_catalog_load(&area, setup->areas, setup->start_area_id) < 0)
return -1;
- if (ph_world_init(world, area, setup->start_area_id, setup->content,
- viewport_w, viewport_h) < 0) {
+ if (ph_world_init(world, area, setup->start_area_id, setup->content) < 0) {
ph_area_free(&area);
return -1;
}
diff --git a/src/engine/area.h b/src/engine/area.h
@@ -49,8 +49,7 @@ const PhAreaDef *ph_area_catalog_area(const PhAreaCatalog *catalog, int area_id)
const PhMarkerDef *ph_area_catalog_marker(const PhAreaCatalog *catalog,
int area_id, unsigned char symbol);
int ph_area_catalog_load(PhArea *area, const PhAreaCatalog *catalog, int area_id);
-int ph_world_start(PhWorld *world, const PhWorldSetup *setup,
- float viewport_w, float viewport_h);
+int ph_world_start(PhWorld *world, const PhWorldSetup *setup);
int ph_world_prepare_area(PhWorld *world, const PhArea *area,
const PhAreaCatalog *catalog, int area_id, int *player);
int ph_world_capture_area(PhWorld *world);
diff --git a/src/engine/render.c b/src/engine/render.c
@@ -4,6 +4,19 @@
#include "config.h"
+void
+ph_camera_follow_player(PhCamera *camera, const PhWorld *world)
+{
+ const PhEntity *player = ph_world_player(world);
+ float max_x = fmaxf(0.0f, world->area.width * PH_TILE_SIZE - camera->viewport_w);
+ float max_y = fmaxf(0.0f, world->area.height * PH_TILE_SIZE - camera->viewport_h);
+
+ camera->pos.x = player ? fminf(max_x,
+ fmaxf(0.0f, player->pos.x - camera->viewport_w * 0.5f)) : 0.0f;
+ camera->pos.y = player ? fminf(max_y,
+ fmaxf(0.0f, player->pos.y - camera->viewport_h * 0.5f)) : 0.0f;
+}
+
static float
ph_world_pixel(float position, float camera)
{
@@ -39,22 +52,22 @@ ph_render_entity_frame(const PhEntityDef *def, const PhEntity *entity,
}
static void
-ph_draw_area(PhRenderer *renderer, const PhWorld *world)
+ph_draw_area(PhRenderer *renderer, const PhWorld *world, const PhCamera *camera)
{
int tx;
int ty;
- for (ty = (int)(world->camera.pos.y / PH_TILE_SIZE);
+ for (ty = (int)(camera->pos.y / PH_TILE_SIZE);
ty < world->area.height && (float)(ty * PH_TILE_SIZE) <
- world->camera.pos.y + world->camera.viewport_h; ++ty) {
- for (tx = (int)(world->camera.pos.x / PH_TILE_SIZE);
+ camera->pos.y + camera->viewport_h; ++ty) {
+ for (tx = (int)(camera->pos.x / PH_TILE_SIZE);
tx < world->area.width && (float)(tx * PH_TILE_SIZE) <
- world->camera.pos.x + world->camera.viewport_w; ++tx) {
+ camera->pos.x + camera->viewport_w; ++tx) {
const PhTileDef *def = ph_area_tile_def(&world->area, tx, ty);
int asset_id;
PhRect rect = {
- .x = ph_world_pixel((float)(tx * PH_TILE_SIZE), world->camera.pos.x),
- .y = ph_world_pixel((float)(ty * PH_TILE_SIZE), world->camera.pos.y),
+ .x = ph_world_pixel((float)(tx * PH_TILE_SIZE), camera->pos.x),
+ .y = ph_world_pixel((float)(ty * PH_TILE_SIZE), camera->pos.y),
.w = (float)PH_TILE_SIZE,
.h = (float)PH_TILE_SIZE,
};
@@ -131,7 +144,7 @@ ph_draw_area(PhRenderer *renderer, const PhWorld *world)
}
static void
-ph_draw_items(PhRenderer *renderer, const PhWorld *world)
+ph_draw_items(PhRenderer *renderer, const PhWorld *world, const PhCamera *camera)
{
int i;
@@ -145,17 +158,17 @@ ph_draw_items(PhRenderer *renderer, const PhWorld *world)
continue;
}
- rect.x = ph_world_pixel(drop->pos.x, world->camera.pos.x) - 3.0f;
- rect.y = ph_world_pixel(drop->pos.y, world->camera.pos.y) - 3.0f;
+ rect.x = ph_world_pixel(drop->pos.x, camera->pos.x) - 3.0f;
+ rect.y = ph_world_pixel(drop->pos.y, camera->pos.y) - 3.0f;
rect.w = 6.0f;
rect.h = 6.0f;
if (def) asset_id = def->asset_id;
if (ph_render_has_asset(renderer, asset_id) &&
def->sprite_tile_x >= 0 && def->sprite_tile_y >= 0) {
- rect.x = ph_world_pixel(drop->pos.x, world->camera.pos.x) -
+ rect.x = ph_world_pixel(drop->pos.x, camera->pos.x) -
PH_TILE_SIZE * 0.5f;
- rect.y = ph_world_pixel(drop->pos.y, world->camera.pos.y) -
+ rect.y = ph_world_pixel(drop->pos.y, camera->pos.y) -
PH_TILE_SIZE * 0.5f;
rect.w = PH_TILE_SIZE;
rect.h = PH_TILE_SIZE;
@@ -169,7 +182,7 @@ ph_draw_items(PhRenderer *renderer, const PhWorld *world)
}
static void
-ph_draw_entities(PhRenderer *renderer, const PhWorld *world)
+ph_draw_entities(PhRenderer *renderer, const PhWorld *world, const PhCamera *camera)
{
int i;
@@ -191,17 +204,17 @@ ph_draw_entities(PhRenderer *renderer, const PhWorld *world)
if (ph_render_has_asset(renderer, asset_id) &&
sprite_tile_x >= 0 && sprite_tile_y >= 0) {
- rect.x = ph_world_pixel(entity->pos.x, world->camera.pos.x) -
+ rect.x = ph_world_pixel(entity->pos.x, camera->pos.x) -
PH_TILE_SIZE * 0.5f;
- rect.y = ph_world_pixel(entity->pos.y, world->camera.pos.y) -
+ rect.y = ph_world_pixel(entity->pos.y, camera->pos.y) -
PH_TILE_SIZE * 0.75f;
rect.w = PH_TILE_SIZE;
rect.h = PH_TILE_SIZE;
ph_render_sprite(renderer, asset_id, sprite_tile_x, sprite_tile_y, rect, flip);
} else {
- rect.x = ph_world_pixel(entity->pos.x, world->camera.pos.x) - 7.0f;
- rect.y = ph_world_pixel(entity->pos.y, world->camera.pos.y) - 12.0f;
+ rect.x = ph_world_pixel(entity->pos.x, camera->pos.x) - 7.0f;
+ rect.y = ph_world_pixel(entity->pos.y, camera->pos.y) - 12.0f;
rect.w = 14.0f;
rect.h = 18.0f;
@@ -217,9 +230,9 @@ ph_draw_entities(PhRenderer *renderer, const PhWorld *world)
void
ph_render_world(PhRenderer *renderer,
- const PhWorld *world)
+ const PhWorld *world, const PhCamera *camera)
{
- ph_draw_area(renderer, world);
- ph_draw_items(renderer, world);
- ph_draw_entities(renderer, world);
+ ph_draw_area(renderer, world, camera);
+ ph_draw_items(renderer, world, camera);
+ ph_draw_entities(renderer, world, camera);
}
diff --git a/src/engine/render.h b/src/engine/render.h
@@ -6,6 +6,12 @@
enum { PH_MAX_ASSETS = 32, PH_RENDER_FONT_W = 8 };
+typedef struct {
+ PhVec2 pos;
+ float viewport_w;
+ float viewport_h;
+} PhCamera;
+
typedef struct PhRenderer PhRenderer;
typedef struct { float x, y, w, h; } PhRect;
typedef struct { unsigned char r, g, b, a; } PhColor;
@@ -28,6 +34,9 @@ void ph_render_sprite(PhRenderer *renderer, int asset_id,
int sprite_tile_x, int sprite_tile_y, PhRect dst, PhFlip flip);
void ph_render_entity_frame(const PhEntityDef *def, const PhEntity *entity,
int *sprite_tile_x, int *sprite_tile_y, PhFlip *flip);
-void ph_render_world(PhRenderer *renderer, const PhWorld *world);
+/* Updates only the caller-owned camera; a missing player resets it to origin. */
+void ph_camera_follow_player(PhCamera *camera, const PhWorld *world);
+void ph_render_world(PhRenderer *renderer, const PhWorld *world,
+ const PhCamera *camera);
#endif
diff --git a/src/engine/save.c b/src/engine/save.c
@@ -228,7 +228,7 @@ ph_area_known(const PhAreaCatalog *catalog, int area_id)
static int
ph_load_stream(FILE *fp, PhWorld *world, const PhWorldSetup *setup,
- PhSpellBook *spells, float viewport_w, float viewport_h)
+ PhSpellBook *spells)
{
uint32_t magic;
uint32_t version;
@@ -245,7 +245,7 @@ ph_load_stream(FILE *fp, PhWorld *world, const PhWorldSetup *setup,
ph_read_int(fp, &area_id) < 0 || !ph_area_known(setup->areas, area_id) ||
ph_read_entity(fp, &player, area_id) < 0 ||
ph_area_catalog_load(&area, setup->areas, area_id) < 0) return -1;
- if (ph_world_init(world, area, area_id, setup->content, viewport_w, viewport_h) < 0) {
+ if (ph_world_init(world, area, area_id, setup->content) < 0) {
ph_area_free(&area);
return -1;
}
@@ -328,7 +328,7 @@ fail:
int
ph_save_load(const char *path, PhWorld *world, const PhWorldSetup *setup,
- PhSpellBook *spells, float viewport_w, float viewport_h)
+ PhSpellBook *spells)
{
FILE *fp;
int result;
@@ -336,7 +336,7 @@ ph_save_load(const char *path, PhWorld *world, const PhWorldSetup *setup,
if (!path || !world || !setup || !setup->areas || !spells) return -1;
fp = fopen(path, "rb");
if (!fp) return errno == ENOENT ? 0 : -1;
- result = ph_load_stream(fp, world, setup, spells, viewport_w, viewport_h);
+ result = ph_load_stream(fp, world, setup, spells);
if (fclose(fp) != 0) {
if (result == 0) ph_world_destroy(world);
result = -1;
diff --git a/src/engine/save.h b/src/engine/save.h
@@ -9,6 +9,6 @@ enum { PH_SAVE_VERSION = 1 };
int ph_save_write(const char *path, PhWorld *world, const PhSpellBook *spells);
/* Returns 1 when loaded, 0 when no save exists, and -1 for an invalid save. */
int ph_save_load(const char *path, PhWorld *world, const PhWorldSetup *setup,
- PhSpellBook *spells, float viewport_w, float viewport_h);
+ PhSpellBook *spells);
#endif
diff --git a/src/engine/world.c b/src/engine/world.c
@@ -35,14 +35,6 @@ typedef struct {
uint32_t tile_y;
} PhMapMarker;
-static float
-ph_clampf(float value, float min, float max)
-{
- if (value < min) return min;
- if (value > max) return max;
- return value;
-}
-
static int
ph_clampi(int value, int min, int max)
{
@@ -86,25 +78,6 @@ ph_item_def_index(const PhWorld *world, int item_id)
return -1;
}
-static void
-ph_camera_follow_player(PhWorld *world)
-{
- const PhEntity *player;
- float max_x;
- float max_y;
-
- player = ph_world_player(world);
- if (!player) return;
-
- max_x = (float)(world->area.width * PH_TILE_SIZE) - world->camera.viewport_w;
- max_y = (float)(world->area.height * PH_TILE_SIZE) - world->camera.viewport_h;
- if (max_x < 0.0f) max_x = 0.0f;
- if (max_y < 0.0f) max_y = 0.0f;
-
- world->camera.pos.x = ph_clampf(player->pos.x - world->camera.viewport_w * 0.5f, 0.0f, max_x);
- world->camera.pos.y = ph_clampf(player->pos.y - world->camera.viewport_h * 0.5f, 0.0f, max_y);
-}
-
static int
ph_position_blocked(const PhWorld *world, PhVec2 pos)
{
@@ -483,7 +456,7 @@ ph_world_update_actors(PhWorld *world, float dt)
int
ph_world_init(PhWorld *world, PhArea area, int area_id,
- PhWorldCatalog content, float viewport_w, float viewport_h)
+ PhWorldCatalog content)
{
if (content.entity_count < 0 || content.entity_count > PH_MAX_ENTITY_TYPES ||
content.item_count < 0 || content.item_count > PH_MAX_ITEM_TYPES ||
@@ -493,8 +466,6 @@ ph_world_init(PhWorld *world, PhArea area, int area_id,
world->area = area;
world->area_id = area_id;
world->content = content;
- world->camera.viewport_w = viewport_w;
- world->camera.viewport_h = viewport_h;
world->player_index = -1;
world->encounter_index = -1;
world->rng_state = 0x5048414eu;
@@ -517,7 +488,6 @@ ph_world_enter_area(PhWorld *world, PhArea area, int area_id, PhVec2 player_pos)
player->area_id = area_id;
player->pos = player->motion.target = player->behavior.home = player_pos;
player->motion.moving = 0;
- ph_camera_follow_player(world);
}
int
@@ -705,7 +675,6 @@ ph_world_set_player(PhWorld *world, int entity_index)
{
if (entity_index >= 0 && entity_index < world->entity_count) {
world->player_index = entity_index;
- ph_camera_follow_player(world);
}
}
@@ -991,7 +960,6 @@ ph_world_tick(PhWorld *world, PhInput input, float dt)
}
ph_world_update_actors(world, dt);
- ph_camera_follow_player(world);
}
int
diff --git a/src/engine/world.h b/src/engine/world.h
@@ -228,14 +228,7 @@ typedef struct {
} PhArea;
typedef struct {
- PhVec2 pos;
- float viewport_w;
- float viewport_h;
-} PhCamera;
-
-typedef struct {
PhArea area;
- PhCamera camera;
PhWorldCatalog content;
PhEntity entities[PH_MAX_ENTITIES];
PhGroundItem ground_items[PH_MAX_GROUND_ITEMS];
@@ -268,7 +261,7 @@ void ph_area_free(PhArea *area);
void ph_world_destroy(PhWorld *world);
int ph_world_init(PhWorld *world, PhArea area, int area_id,
- PhWorldCatalog content, float viewport_w, float viewport_h);
+ PhWorldCatalog content);
void ph_world_enter_area(PhWorld *world, PhArea area, int area_id,
PhVec2 player_pos);
int ph_world_spawn_entity(PhWorld *world, int type_id, PhVec2 pos,
diff --git a/src/examples/courier.c b/src/examples/courier.c
@@ -90,8 +90,7 @@ main(int argc, char **argv)
/* Runtime maps store tile catalog indices, not source symbols. */
for (i = 0; i < WIDTH * HEIGHT; ++i)
map[i] = map[i] == '#' ? 0 : map[i] == 'D' ? 2 : 1;
- if (ph_world_init(&world, area, 1, content, WIDTH * PH_TILE_SIZE,
- HEIGHT * PH_TILE_SIZE) < 0) return 1;
+ if (ph_world_init(&world, area, 1, content) < 0) return 1;
key = ph_world_spawn_entity(&world, COURIER,
(PhVec2){ PH_TILE_CENTER(1), PH_TILE_CENTER(1) }, 0, 1);
if (key < 0) goto fail;
diff --git a/src/game/main.c b/src/game/main.c
@@ -175,14 +175,12 @@ ph_run_game(void)
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
return 1;
}
- save_status = ph_save_load(PH_SAVE_PATH, &world, &ph_game_world, &spells,
- (float)PH_VIEW_W, (float)PH_VIEW_H);
+ save_status = ph_save_load(PH_SAVE_PATH, &world, &ph_game_world, &spells);
if (save_status < 0) {
fprintf(stderr, "save is invalid; starting a new game\n");
spells = ph_player_spellbook;
}
- if (save_status <= 0 && ph_world_start(&world, &ph_game_world,
- (float)PH_VIEW_W, (float)PH_VIEW_H) < 0) {
+ if (save_status <= 0 && ph_world_start(&world, &ph_game_world) < 0) {
SDL_Quit();
return 1;
}
@@ -232,8 +230,7 @@ ph_run_game(void)
if (request & PH_GAME_REQUEST_NEW) {
ph_world_destroy(&world);
spells = ph_player_spellbook;
- if (ph_world_start(&world, &ph_game_world,
- (float)PH_VIEW_W, (float)PH_VIEW_H) < 0) running = 0;
+ if (ph_world_start(&world, &ph_game_world) < 0) running = 0;
else {
remove(PH_SAVE_PATH);
context.menu = PH_MENU_NONE;
diff --git a/src/game/presentation.c b/src/game/presentation.c
@@ -713,6 +713,7 @@ ph_present_frame(PhRenderer *renderer,
const PhWorld *world = context->world;
const PhBattle *battle = context->battle;
PhGameMode game = *context->mode;
+ PhCamera camera = { .viewport_w = PH_VIEW_W, .viewport_h = PH_VIEW_H };
if (game == PH_GAME_BATTLE) {
ph_draw_battle(renderer, world, battle);
@@ -731,7 +732,8 @@ ph_present_frame(PhRenderer *renderer,
ph_render_color(renderer, (PhColor){ PH_CLEAR_COLOR });
ph_render_clear(renderer);
- ph_render_world(renderer, world);
+ ph_camera_follow_player(&camera, world);
+ ph_render_world(renderer, world, &camera);
if (context->menu == PH_MENU_CHARACTER) {
ph_draw_character_sheet(renderer, world, labels);
} else if (context->menu == PH_MENU_INVENTORY) {
diff --git a/src/tests/game.c b/src/tests/game.c
@@ -43,7 +43,7 @@ ph_timing_smoke(void)
PhGameContext context = { .world = &world, .mode = &mode };
uint64_t previous = 0;
- if (ph_world_init(&world, area, 1, catalog, 320, 128) < 0) return 1;
+ if (ph_world_init(&world, area, 1, catalog) < 0) return 1;
if (ph_world_spawn_entity(&world, 1, (PhVec2){ 24, 24 }, 0, 1) < 0 ||
ph_world_spawn_entity(&world, 2, (PhVec2){ 200, 88 }, 4, 1) < 0) return 1;
ph_world_set_player(&world, 0);
@@ -104,7 +104,7 @@ main(void)
if (!mkdtemp(directory)) return 1;
snprintf(save_path, sizeof(save_path), "%s/checkpoint.sav", directory);
snprintf(temp_path, sizeof(temp_path), "%s.tmp", save_path);
- CHECK(ph_world_start(&world, &ph_game_world, PH_VIEW_W, PH_VIEW_H) == 0);
+ CHECK(ph_world_start(&world, &ph_game_world) == 0);
player = &world.entities[world.player_index];
position = player->pos;
ph_game_update(&game, (PhInput){ .move_x = 1 }, 0.05f, save_path);
@@ -176,8 +176,7 @@ main(void)
world.encounter_index = enemy;
ph_game_update(&game, (PhInput){ 0 }, 0.0f, save_path);
CHECK(mode == PH_GAME_TRANSITION && world.combat_active);
- CHECK(ph_save_load(save_path, &loaded, &ph_game_world, &loaded_spells,
- PH_VIEW_W, PH_VIEW_H) == 1);
+ CHECK(ph_save_load(save_path, &loaded, &ph_game_world, &loaded_spells) == 1);
CHECK(!loaded.combat_active);
ph_game_update(&game, (PhInput){ 0 }, PH_BATTLE_TRANSITION_SECONDS, save_path);
CHECK(mode == PH_GAME_BATTLE);
diff --git a/src/tests/render.c b/src/tests/render.c
@@ -8,12 +8,51 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "config.h"
#if PH_USE_SDL
static int
+ph_camera_smoke(void)
+{
+ PhWorld world = { .area = { .width = 40, .height = 30 },
+ .player_index = 0, .entity_count = 1 };
+ PhWorld before;
+ PhCamera camera = { .viewport_w = 320, .viewport_h = 240 };
+ PhCamera other = { .viewport_w = 160, .viewport_h = 120 };
+
+ world.entities[0].active = 1;
+ world.entities[0].pos = (PhVec2){ 300, 220 };
+ memcpy(&before, &world, sizeof(world));
+ ph_camera_follow_player(&camera, &world);
+ ph_camera_follow_player(&other, &world);
+ if (camera.pos.x != 140 || camera.pos.y != 100 ||
+ other.pos.x != 220 || other.pos.y != 160 ||
+ memcmp(&before, &world, sizeof(world))) return 1;
+ world.entities[0].pos = (PhVec2){ 639, 479 };
+ ph_camera_follow_player(&camera, &world);
+ if (camera.pos.x != 320 || camera.pos.y != 240) return 1;
+ world.entities[0].pos = (PhVec2){ 8, 8 };
+ ph_camera_follow_player(&camera, &world);
+ if (camera.pos.x != 0 || camera.pos.y != 0) return 1;
+ world.entities[0].pos = (PhVec2){ 300, 220 };
+ camera.viewport_w = 800;
+ camera.viewport_h = 600;
+ ph_camera_follow_player(&camera, &world);
+ if (camera.pos.x != 0 || camera.pos.y != 0) return 1;
+ /* A smaller area must discard the previous area's scroll immediately. */
+ world.area.width = world.area.height = 4;
+ ph_camera_follow_player(&other, &world);
+ if (other.pos.x != 0 || other.pos.y != 0) return 1;
+ world.player_index = -1;
+ camera.pos = (PhVec2){ 100, 100 };
+ ph_camera_follow_player(&camera, &world);
+ return camera.pos.x != 0 || camera.pos.y != 0;
+}
+
+static int
ph_pixel_is(SDL_Surface *surface, int x, int y, PhColor color)
{
Uint8 r, g, b, a;
@@ -178,8 +217,11 @@ main(void)
}
result = ph_media_smoke(target, surface);
- if (ph_world_start(&world, &ph_game_world,
- (float)PH_VIEW_W, (float)PH_VIEW_H) < 0) {
+ if (ph_camera_smoke()) {
+ fprintf(stderr, "camera smoke test failed\n");
+ result = 1;
+ }
+ if (ph_world_start(&world, &ph_game_world) < 0) {
SDL_DestroyRenderer(target);
SDL_DestroySurface(surface);
SDL_Quit();
diff --git a/src/tests/smoke.c b/src/tests/smoke.c
@@ -63,7 +63,7 @@ ph_area_catalog_test(void)
int entity_count;
int item_count;
- if (ph_world_init(&world, area, 7, content, 32.0f, 32.0f) < 0 ||
+ if (ph_world_init(&world, area, 7, content) < 0 ||
ph_world_prepare_area(&world, &area, &catalog, 7, &player) < 0)
return 1;
if (player < 0 || world.entity_count != 2 || world.ground_item_count != 1 ||
@@ -126,9 +126,7 @@ ph_movement_test(int open, int blocked)
for (x = 0; x < area.width; ++x)
if (!x || !y || x == area.width - 1 || y == area.height - 1)
tiles[y * area.width + x] = (unsigned char)blocked;
- if (ph_world_init(&world, area, 1, content,
- (float)(area.width * PH_TILE_SIZE),
- (float)(area.height * PH_TILE_SIZE)) < 0 ||
+ if (ph_world_init(&world, area, 1, content) < 0 ||
(player_index = ph_world_spawn_entity(&world, 1, player_start, 0, 1)) < 0 ||
(mob_index = ph_world_spawn_entity(&world, 2, mob_start,
TERRITORY, 1)) < 0) return 1;
@@ -208,7 +206,7 @@ ph_area_state_scaling_test(void)
int i;
int result = 1;
- if (ph_world_init(&world, area, 1, content, 32.0f, 32.0f) < 0 ||
+ if (ph_world_init(&world, area, 1, content) < 0 ||
(player = ph_world_spawn_entity(&world, 1, (PhVec2){ 0 }, 0, 1)) < 0)
return 1;
ph_world_set_player(&world, player);
@@ -248,7 +246,7 @@ ph_flash_delay_test(void)
int cast;
int expected_next;
- if (ph_world_init(&world, area, 1, content, 32.0f, 32.0f) < 0 ||
+ if (ph_world_init(&world, area, 1, content) < 0 ||
(player = ph_world_spawn_entity(&world, 1, (PhVec2){ 0 }, 0, 1)) < 0 ||
(enemy = ph_world_spawn_entity(&world, 2, (PhVec2){ 16, 0 }, 0, 1)) < 0)
return 1;
@@ -337,9 +335,7 @@ ph_logic_test(int open, int blocked)
memset(tiles, blocked, sizeof(tiles));
tiles[ROW * area.width + LEFT_COL] = (unsigned char)open;
tiles[ROW * area.width + RIGHT_COL] = (unsigned char)open;
- if (ph_world_init(&world, area, 1, content,
- (float)(area.width * PH_TILE_SIZE),
- (float)(area.height * PH_TILE_SIZE)) < 0 ||
+ if (ph_world_init(&world, area, 1, content) < 0 ||
(player_index = ph_world_spawn_entity(&world, 1, player_start, 0, 1)) < 0 ||
(enemy_index = ph_world_spawn_entity(&world, 4, enemy_start, 0, 1)) < 0 ||
ph_world_drop_item(&world, 1, player_start, 1, 1) < 0 ||
@@ -366,7 +362,6 @@ ph_logic_test(int open, int blocked)
if (!player || (int)(player->pos.x / PH_TILE_SIZE) != RIGHT_COL ||
(int)(player->pos.y / PH_TILE_SIZE) != ROW ||
player->motion.facing_x != 0 || player->motion.facing_y != 1 ||
- world.camera.pos.x != 0.0f || world.camera.pos.y != 0.0f ||
ph_world_item_amount(&world, 1) != 0 ||
ph_world_item_amount(&world, 2) != 0 ||
ph_world_item_amount(&world, 3) != 1 || player->vitals.hp != 4 ||
@@ -469,7 +464,7 @@ ph_area_shop_test(void)
int i;
unsigned int events;
- if (ph_world_start(&world, &ph_game_world, 320.0f, 240.0f) < 0) return 1;
+ if (ph_world_start(&world, &ph_game_world) < 0) return 1;
player = &world.entities[world.player_index];
potion = ph_world_item_def(&world, PH_ITEM_HEALING_POTION);
ether = ph_world_item_def(&world, PH_ITEM_ETHER);
@@ -638,9 +633,8 @@ ph_save_test(void)
remove(path);
remove("obj/test-save.phsave.tmp");
- if (ph_save_load(path, &loaded, &ph_game_world, &loaded_spells,
- 320.0f, 240.0f) != 0 ||
- ph_world_start(&world, &ph_game_world, 320.0f, 240.0f) < 0) return 1;
+ if (ph_save_load(path, &loaded, &ph_game_world, &loaded_spells) != 0 ||
+ ph_world_start(&world, &ph_game_world) < 0) return 1;
player = &world.entities[world.player_index];
player->vitals.hp = 23;
player->xp = 91;
@@ -650,8 +644,7 @@ ph_save_test(void)
if (ph_enter_portal(&world, PH_AREA_STONEHOLLOW) != 1 ||
world.entity_count != 1) goto done_world;
if (ph_save_write(path, &world, &spells) < 0) goto done_world;
- if (ph_save_load(path, &loaded, &ph_game_world, &loaded_spells,
- 320.0f, 240.0f) != 1) {
+ if (ph_save_load(path, &loaded, &ph_game_world, &loaded_spells) != 1) {
fprintf(stderr, "save round trip failed to load\n");
goto done_world;
}
@@ -678,8 +671,7 @@ ph_save_test(void)
ph_battle_begin(&checkpoint_battle, &loaded, 1, loaded_spells);
--loaded.entities[1].vitals.hp;
if (ph_save_write(path, &loaded, &loaded_spells) != -1 ||
- ph_save_load(path, &checkpoint, &ph_game_world, &loaded_spells,
- 320.0f, 240.0f) != 1) goto done_loaded;
+ ph_save_load(path, &checkpoint, &ph_game_world, &loaded_spells) != 1) goto done_loaded;
if (checkpoint.entity_count != 2 ||
checkpoint.entities[1].vitals.hp != enemy_hp) {
ph_world_destroy(&checkpoint);
@@ -694,8 +686,7 @@ ph_save_test(void)
goto done_loaded;
}
if (fclose(corrupt) != 0) goto done_loaded;
- if (ph_save_load(path, &(PhWorld){ 0 }, &ph_game_world, &loaded_spells,
- 320.0f, 240.0f) != -1) goto done_loaded;
+ if (ph_save_load(path, &(PhWorld){ 0 }, &ph_game_world, &loaded_spells) != -1) goto done_loaded;
result = 0;
done_loaded: