From 7e5187e35cb0df01a1da5d7eccd9ea765009c7e7 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 26 Jun 2021 16:36:40 +0900 Subject: [PATCH] DrawDungeon: 2D map improvements * Cells loaded from walk-data are half-transparent. * The player symbol is half-transparent when showing different floors. * Clear the texture before drawing a small map so that no garbage is left when the drawing is clipped. --- include/dungeon/map.h | 2 +- src/dungeon/dungeon.c | 6 +++--- src/dungeon/map.c | 29 ++++++++++++++++++----------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/include/dungeon/map.h b/include/dungeon/map.h index e8559f3..e54ac95 100644 --- a/include/dungeon/map.h +++ b/include/dungeon/map.h @@ -32,6 +32,6 @@ void dungeon_map_set_all_view(int surface, int flag); void dungeon_map_set_cg(int surface, int index, int sprite); void dungeon_map_set_small_map_floor(int surface, int floor); void dungeon_map_set_large_map_floor(int surface, int floor); -void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z); +void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool transparent); #endif /* SYSTEM4_DUNGEON_MAP_H */ diff --git a/src/dungeon/dungeon.c b/src/dungeon/dungeon.c index 3dcf193..50f81bf 100644 --- a/src/dungeon/dungeon.c +++ b/src/dungeon/dungeon.c @@ -294,7 +294,7 @@ static void neighbor_reveal(struct dungeon_context *ctx, int x, int y, int z) struct dgn_cell *cell = dgn_cell_at(ctx->dgn, x, y, z); if (cell->floor < 0) { cell->walked = 1; - dungeon_map_reveal(ctx, x, y, z); + dungeon_map_reveal(ctx, x, y, z, false); } } @@ -304,7 +304,7 @@ void dungeon_set_walked(int surface, int x, int y, int z, int flag) if (!ctx) return; dgn_cell_at(ctx->dgn, x, y, z)->walked = 1; - dungeon_map_reveal(ctx, x, y, z); + dungeon_map_reveal(ctx, x, y, z, false); if (ctx->version == DRAW_DUNGEON_1) { if (x > 0) neighbor_reveal(ctx, x - 1, y, z); @@ -399,7 +399,7 @@ bool dungeon_load_walk_data(int surface, int map, struct page **page) int nr_cells = dgn_nr_cells(ctx->dgn); for (struct dgn_cell *c = ctx->dgn->cells; c < ctx->dgn->cells + nr_cells; c++) { if (array->values[offset].i) - dungeon_map_reveal(ctx, c->x, c->y, c->z); + dungeon_map_reveal(ctx, c->x, c->y, c->z, true); c->walked = array->values[offset++].i; } diff --git a/src/dungeon/map.c b/src/dungeon/map.c index 6f52d1e..0ddcd1a 100644 --- a/src/dungeon/map.c +++ b/src/dungeon/map.c @@ -33,6 +33,8 @@ #define LMAP_WIDTH 32 #define LMAP_HEIGHT 32 +static const SDL_Color unenterable_cell_color = {182, 72, 0, 0}; + enum symbol_type { SYMBOL_PLAYER_NORTH = 0, SYMBOL_PLAYER_SOUTH = 1, @@ -118,11 +120,11 @@ void dungeon_map_init(struct dungeon_context *ctx) } } map->offset_x = (LMAP_WIDTH - (max_x - min_x + 1)) / 2 - min_x; - map->offset_y = (LMAP_HEIGHT - (max_y - min_y + 1) + 1) / 2 - min_y; + map->offset_y = (LMAP_HEIGHT - (max_y - min_y)) / 2 - min_y; // Initial draw for (uint32_t y = 0; y < dgn->size_y; y++) { - gfx_init_texture_rgba(&map->textures[y], LMAP_WIDTH * CS, LMAP_HEIGHT * CS, (SDL_Color){182, 72, 0, 0}); + gfx_init_texture_rgba(&map->textures[y], LMAP_WIDTH * CS, LMAP_HEIGHT * CS, unenterable_cell_color); for (uint32_t z = 0; z < dgn->size_z; z++) { for (uint32_t x = 0; x < dgn->size_x; x++) { dungeon_map_update_cell(ctx, x, y, z); @@ -131,13 +133,13 @@ void dungeon_map_init(struct dungeon_context *ctx) } } -void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z) +void dungeon_map_reveal(struct dungeon_context *ctx, int x, int y, int z, bool transparent) { if (!ctx->map) return; struct texture *dst = &ctx->map->textures[y]; Point pos = texture_pos(ctx, x, z); - gfx_fill_amap(dst, pos.x, pos.y, CS, CS, 255); + gfx_fill_amap(dst, pos.x, pos.y, CS, CS, transparent ? 128 : 255); } static void draw_hline(struct texture *dst, int x, int y, int w, SDL_Color col) @@ -150,11 +152,11 @@ static void draw_vline(struct texture *dst, int x, int y, int h, SDL_Color col) gfx_fill(dst, x, y, 1, h, col.r, col.g, col.b); } -static void draw_symbol(struct dungeon_context *ctx, struct texture *dst, int x, int y, int type) +static void draw_symbol(struct dungeon_map *map, struct texture *dst, int x, int y, int type) { - struct sact_sprite *sp = sact_get_sprite(ctx->map->symbol_sprites[type]); + struct sact_sprite *sp = sact_get_sprite(map->symbol_sprites[type]); if (!sp || sp->rect.w != CS - 2 || sp->rect.h != CS - 2) - VM_ERROR("Invalid map cg %d", ctx->map->symbol_sprites[type]); + VM_ERROR("Invalid map cg %d", map->symbol_sprites[type]); struct texture *src = sprite_get_texture(sp); gfx_copy(dst, x, y, src, 0, 0, src->w, src->h); } @@ -172,7 +174,7 @@ void dungeon_map_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y, if (cell->floor >= 0) gfx_fill(dst, x, y, CS, CS, 0, 0, 0); else - gfx_fill(dst, x, y, CS, CS, 182, 72, 0); + gfx_fill(dst, x, y, CS, CS, unenterable_cell_color.r, unenterable_cell_color.g, unenterable_cell_color.b); const SDL_Color wall_colors[2] = {{255, 255, 255, 255}, {255, 0, 0, 255}}; if (cell->north_wall >= 0) @@ -230,7 +232,7 @@ void dungeon_map_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y, symbol = SYMBOL_STAIRS_DOWN; if (symbol >= 0) - draw_symbol(ctx, dst, x + 1, y + 1, symbol); + draw_symbol(ctx->map, dst, x + 1, y + 1, symbol); } static int player_symbol(struct dungeon_context *ctx) @@ -268,9 +270,12 @@ void dungeon_map_draw(int surface, int sprite) int x = pos.x - (dst->w - CS) / 2; int y = pos.y - (dst->h - CS) / 2; + // Clear the texture so that no garbage is left if copy from `src` is clipped. + gfx_fill_with_alpha(dst, 0, 0, dst->w, dst->h, unenterable_cell_color.r, unenterable_cell_color.g, unenterable_cell_color.b, unenterable_cell_color.a); + gfx_copy_with_alpha_map(dst, 0, 0, src, x, y, dst->w, dst->h); - draw_symbol(ctx, dst, (dst->w - CS + 2) / 2, (dst->h - CS + 2) / 2, player_symbol(ctx)); + draw_symbol(ctx->map, dst, (dst->w - CS + 2) / 2, (dst->h - CS + 2) / 2, player_symbol(ctx)); if (ctx->map->all_visible) gfx_fill_amap(dst, 0, 0, dst->w, dst->h, 255); @@ -300,8 +305,10 @@ void dungeon_map_draw_lmap(int surface, int sprite) if (ctx->map->all_visible) gfx_fill_amap(dst, 0, 0, dst->w, dst->h, 255); + // Draw the player symbol. Point pos = texture_pos(ctx, player_x, player_z); - draw_symbol(ctx, dst, pos.x + 1, pos.y + 1, player_symbol(ctx)); + draw_symbol(ctx->map, dst, pos.x + 1, pos.y + 1, player_symbol(ctx)); + gfx_fill_amap(dst, pos.x + 1, pos.y + 1, CS - 2, CS - 2, level == player_y ? 255 : 128); } static void redraw_event_symbols(struct dungeon_context *ctx)