DrawDungeon: Draw map in the center of target texture

This fixes an issue where the map is drawn outside of the target
texture's boundaries.
This commit is contained in:
kichikuou
2021-06-06 14:22:33 +09:00
parent 2ad6eba94f
commit 7f326527a0
+45 -9
View File
@@ -31,6 +31,8 @@
#endif
#define CS 12 // pixel size of a map cell
#define LMAP_WIDTH 32
#define LMAP_HEIGHT 32
enum symbol_type {
SYMBOL_PLAYER_NORTH = 0,
@@ -58,8 +60,17 @@ struct dungeon_map {
int large_map_floor;
bool all_visible;
int *walk_data;
int offset_x, offset_y;
};
static Point texture_pos(struct dungeon_context *ctx, int x, int z)
{
return (Point){
.x = (ctx->map->offset_x + x) * CS,
.y = (ctx->map->offset_y + ctx->dgn->size_z - z - 1) * CS
};
}
struct dungeon_map *dungeon_map_create(void)
{
struct dungeon_map *map = xcalloc(1, sizeof(struct dungeon_map));
@@ -85,8 +96,31 @@ void dungeon_map_init(struct dungeon_context *ctx)
map->textures = xcalloc(dgn->size_y, sizeof(struct texture));
map->nr_textures = dgn->size_y;
map->walk_data = xcalloc(dgn->size_x * dgn->size_y * dgn->size_z, sizeof(int));
// Calculate the bounding box on the XZ plane so that map is drawn in the
// center of the texture.
uint32_t min_x = dgn->size_x;
uint32_t min_y = dgn->size_z;
uint32_t max_x = 0;
uint32_t max_y = 0;
for (uint32_t y = 0; y < dgn->size_y; y++) {
gfx_init_texture_rgba(&map->textures[y], dgn->size_x * CS, dgn->size_z * CS, (SDL_Color){0, 0, 0, 0});
for (uint32_t z = 0; z < dgn->size_z; z++) {
uint32_t map_y = ctx->dgn->size_z - z - 1;
for (uint32_t x = 0; x < dgn->size_x; x++) {
if (dgn_cell_at(ctx->dgn, x, y, z)->floor < 0)
continue;
min_x = min(min_x, x);
min_y = min(min_y, map_y);
max_x = max(max_x, x);
max_y = max(max_y, map_y);
}
}
}
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;
// 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});
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);
@@ -99,9 +133,8 @@ static void reveal_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y, int d
{
ctx->map->walk_data[dgn_cell_index(ctx->dgn, dgn_x, dgn_y, dgn_z)] = 1;
struct texture *dst = &ctx->map->textures[dgn_y];
int x = dgn_x * CS;
int y = (ctx->dgn->size_z - dgn_z - 1) * CS;
gfx_fill_amap(dst, x, y, CS, CS, 255);
Point pos = texture_pos(ctx, dgn_x, dgn_z);
gfx_fill_amap(dst, pos.x, pos.y, CS, CS, 255);
}
static void draw_hline(struct texture *dst, int x, int y, int w, SDL_Color col)
@@ -127,8 +160,9 @@ void dungeon_map_update_cell(struct dungeon_context *ctx, int dgn_x, int dgn_y,
{
struct dgn_cell *cell = dgn_cell_at(ctx->dgn, dgn_x, dgn_y, dgn_z);
struct texture *dst = &ctx->map->textures[dgn_y];
int x = dgn_x * CS;
int y = (ctx->dgn->size_z - dgn_z - 1) * CS;
Point pos = texture_pos(ctx, dgn_x, dgn_z);
int x = pos.x;
int y = pos.y;
if (cell->floor >= 0)
gfx_fill(dst, x, y, CS, CS, 0, 0, 0);
@@ -225,8 +259,9 @@ void dungeon_map_draw(int surface, int sprite)
struct texture *src = &ctx->map->textures[level];
int x = player_x * CS - (dst->w - CS) / 2;
int y = (ctx->dgn->size_z - player_z - 1) * CS - (dst->h - CS) / 2;
Point pos = texture_pos(ctx, player_x, player_z);
int x = pos.x - (dst->w - CS) / 2;
int y = pos.y - (dst->h - CS) / 2;
gfx_copy_with_alpha_map(dst, 0, 0, src, x, y, dst->w, dst->h);
@@ -260,7 +295,8 @@ 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_symbol(ctx, dst, player_x * CS + 1, (ctx->dgn->size_z - player_z - 1) * CS + 1, player_symbol(ctx));
Point pos = texture_pos(ctx, player_x, player_z);
draw_symbol(ctx, dst, pos.x + 1, pos.y + 1, player_symbol(ctx));
}
void dungeon_map_set_all_view(int surface, int flag)