Fix TileDef rendering at (0,0) and open editor with current level
Remove the (tex_x || tex_y) guard in tilemap_render_layer() that silently ignored TileDefs pointing to tileset position (0,0). The tile_def_count check alone is sufficient to distinguish defined from undefined tiles. Sync the editor palette to use TileDef tex coords when available, fixing the mismatch where the palette showed tiles by sequential grid position while the canvas used TileDef coordinates. Save all TileDef entries unconditionally to prevent round-trip data loss for tiles at position (0,0) with no flags. Track the active level file path so pressing E during gameplay opens the editor with that level loaded instead of a blank canvas.
This commit is contained in:
@@ -218,8 +218,7 @@ void tilemap_render_layer(const Tilemap *map, const uint16_t *layer,
|
||||
|
||||
/* Look up tile definition for source rect */
|
||||
SDL_Rect src;
|
||||
if (tile_id < map->tile_def_count &&
|
||||
(map->tile_defs[tile_id].tex_x || map->tile_defs[tile_id].tex_y)) {
|
||||
if (tile_id < map->tile_def_count) {
|
||||
src.x = map->tile_defs[tile_id].tex_x * TILE_SIZE;
|
||||
src.y = map->tile_defs[tile_id].tex_y * TILE_SIZE;
|
||||
} else {
|
||||
|
||||
@@ -489,12 +489,11 @@ static bool save_tilemap(const Tilemap *map, const char *path) {
|
||||
}
|
||||
if (map->exit_zone_count > 0) fprintf(f, "\n");
|
||||
|
||||
/* Tile definitions */
|
||||
/* Tile definitions — save all entries so flags and tex coords survive
|
||||
* round-trips, including tiles at position (0,0) with no flags. */
|
||||
for (int id = 1; id < map->tile_def_count; id++) {
|
||||
const TileDef *td = &map->tile_defs[id];
|
||||
if (td->flags || td->tex_x || td->tex_y) {
|
||||
fprintf(f, "TILEDEF %d %d %d %u\n", id, td->tex_x, td->tex_y, td->flags);
|
||||
}
|
||||
fprintf(f, "TILEDEF %d %d %d %u\n", id, td->tex_x, td->tex_y, td->flags);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
||||
@@ -1586,8 +1585,15 @@ void editor_render(Editor *ed, float interpolation) {
|
||||
if (draw_y + TILE_SIZE < pal_y_start ||
|
||||
draw_y > ent_section_y) continue;
|
||||
|
||||
int src_col = (id - 1) % ed->tileset_cols;
|
||||
int src_row = (id - 1) / ed->tileset_cols;
|
||||
/* Use TileDef tex coords when available, else grid position */
|
||||
int src_col, src_row;
|
||||
if (id < ed->map.tile_def_count) {
|
||||
src_col = ed->map.tile_defs[id].tex_x;
|
||||
src_row = ed->map.tile_defs[id].tex_y;
|
||||
} else {
|
||||
src_col = (id - 1) % ed->tileset_cols;
|
||||
src_row = (id - 1) / ed->tileset_cols;
|
||||
}
|
||||
SDL_Rect src = {
|
||||
src_col * TILE_SIZE, src_row * TILE_SIZE,
|
||||
TILE_SIZE, TILE_SIZE
|
||||
|
||||
21
src/main.c
21
src/main.c
@@ -29,6 +29,7 @@ static bool s_dump_lvl = false;
|
||||
static bool s_use_editor = false;
|
||||
static uint32_t s_gen_seed = 0;
|
||||
static char s_edit_path[256] = {0};
|
||||
static char s_level_path[ASSET_PATH_MAX] = {0}; /* path of active play-mode level */
|
||||
|
||||
/* Track whether we came from the editor (for returning after test play) */
|
||||
static bool s_testing_from_editor = false;
|
||||
@@ -46,6 +47,13 @@ static const char *theme_name(LevelTheme t) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Load a file-based level and remember its path for editor access. */
|
||||
static bool load_level_file(const char *path) {
|
||||
if (!level_load(&s_level, path)) return false;
|
||||
snprintf(s_level_path, sizeof(s_level_path), "%s", path);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void load_generated_level(void) {
|
||||
LevelGenConfig config = levelgen_default_config();
|
||||
config.seed = s_gen_seed;
|
||||
@@ -116,6 +124,7 @@ static void load_generated_level(void) {
|
||||
fprintf(stderr, "Failed to load generated level!\n");
|
||||
g_engine.running = false;
|
||||
}
|
||||
s_level_path[0] = '\0'; /* generated levels have no file path */
|
||||
}
|
||||
|
||||
static void load_station_level(void) {
|
||||
@@ -140,6 +149,7 @@ static void load_station_level(void) {
|
||||
fprintf(stderr, "Failed to load station level!\n");
|
||||
g_engine.running = false;
|
||||
}
|
||||
s_level_path[0] = '\0'; /* generated levels have no file path */
|
||||
}
|
||||
|
||||
/* ── Switch to editor mode ── */
|
||||
@@ -200,7 +210,7 @@ static void game_init(void) {
|
||||
} else if (s_use_procgen) {
|
||||
load_generated_level();
|
||||
} else {
|
||||
if (!level_load(&s_level, "assets/levels/moon01.lvl")) {
|
||||
if (!load_level_file("assets/levels/moon01.lvl")) {
|
||||
fprintf(stderr, "Failed to load level!\n");
|
||||
g_engine.running = false;
|
||||
}
|
||||
@@ -234,7 +244,8 @@ static void game_update(float dt) {
|
||||
|
||||
/* E key: enter editor from gameplay (not during test play) */
|
||||
if (!s_testing_from_editor && input_key_pressed(SDL_SCANCODE_E)) {
|
||||
/* Save current level path for potential re-editing */
|
||||
/* Load the current level file into the editor if available */
|
||||
snprintf(s_edit_path, sizeof(s_edit_path), "%s", s_level_path);
|
||||
level_free(&s_level);
|
||||
enter_editor();
|
||||
return;
|
||||
@@ -263,7 +274,7 @@ static void game_update(float dt) {
|
||||
printf("Level complete! (no next level)\n");
|
||||
/* Loop back to the beginning */
|
||||
level_free(&s_level);
|
||||
if (!level_load(&s_level, "assets/levels/moon01.lvl")) {
|
||||
if (!load_level_file("assets/levels/moon01.lvl")) {
|
||||
g_engine.running = false;
|
||||
}
|
||||
} else if (strcmp(target, "generate") == 0) {
|
||||
@@ -284,10 +295,10 @@ static void game_update(float dt) {
|
||||
char path[ASSET_PATH_MAX];
|
||||
snprintf(path, sizeof(path), "%s", target);
|
||||
level_free(&s_level);
|
||||
if (!level_load(&s_level, path)) {
|
||||
if (!load_level_file(path)) {
|
||||
fprintf(stderr, "Failed to load next level: %s\n", path);
|
||||
/* Fallback to moon01 */
|
||||
if (!level_load(&s_level, "assets/levels/moon01.lvl")) {
|
||||
if (!load_level_file("assets/levels/moon01.lvl")) {
|
||||
g_engine.running = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user