Files
handmadehero/handmade_tile.c
T
2026-08-07 12:28:18 -07:00

251 lines
8.2 KiB
C

#include "handmade_tile.h"
#include <assert.h>
static struct tile_chunk *
get_tile_chunk(struct tile_map *tile_map,
unsigned int tile_chunk_x, unsigned int tile_chunk_y,
unsigned int tile_chunk_z)
{
struct tile_chunk *tile_chunk = NULL;
if((tile_chunk_x >= 0) && (tile_chunk_x < tile_map->tile_chunk_count_x) &&
(tile_chunk_y >= 0) && (tile_chunk_y < tile_map->tile_chunk_count_y) &&
(tile_chunk_z >= 0) && (tile_chunk_z < tile_map->tile_chunk_count_z))
{
tile_chunk =
&tile_map->tile_chunks[(tile_chunk_z * tile_map->tile_chunk_count_y *
tile_map->tile_chunk_count_x) +
(tile_chunk_y*tile_map->tile_chunk_count_x) + tile_chunk_x];
}
return tile_chunk;
}
static struct tile_chunk_position
get_chunk_position_for(struct tile_map *tile_map,
unsigned int abs_tile_x, unsigned int abs_tile_y,
unsigned int abs_tile_z)
{
struct tile_chunk_position result;
result.tile_chunk_x = abs_tile_x >> tile_map->chunk_shift;
result.tile_chunk_y = abs_tile_y >> tile_map->chunk_shift;
result.tile_chunk_z = abs_tile_z;
result.rel_tile_x = abs_tile_x & tile_map->chunk_mask;
result.rel_tile_y = abs_tile_y & tile_map->chunk_mask;
return result;
}
static unsigned int
get_tile_value_unchecked(struct tile_map *tile_map,
struct tile_chunk *tile_chunk,
unsigned int tile_x, unsigned int tile_y)
{
unsigned int tile_chunk_value;
assert(tile_chunk);
assert(tile_x < tile_map->chunk_dim);
assert(tile_y < tile_map->chunk_dim);
tile_chunk_value =
tile_chunk->tiles[tile_y * tile_map->chunk_dim + tile_x];
return tile_chunk_value;
}
static unsigned int
get_tile_chunk_value(struct tile_map *tile_map,
struct tile_chunk *tile_chunk,
unsigned int test_tile_x, unsigned int test_tile_y)
{
unsigned int tile_chunk_value = 0;
if(tile_chunk && tile_chunk->tiles) {
tile_chunk_value =
get_tile_value_unchecked(tile_map, tile_chunk,
test_tile_x, test_tile_y);
}
return tile_chunk_value;
}
static unsigned int
get_tile_value(struct tile_map *tile_map,
unsigned int abs_tile_x, unsigned int abs_tile_y,
unsigned int abs_tile_z)
{
struct tile_chunk_position chunk_pos =
get_chunk_position_for(tile_map, abs_tile_x, abs_tile_y, abs_tile_z);
struct tile_chunk *tile_chunk =
get_tile_chunk(tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y,
chunk_pos.tile_chunk_z);
unsigned int tile_chunk_value =
get_tile_chunk_value(tile_map, tile_chunk, chunk_pos.rel_tile_x,
chunk_pos.rel_tile_y);
return tile_chunk_value;
}
static int is_tile_value_empty(unsigned int tile_value)
{
int empty = ((tile_value == 1) || (tile_value == 3) || (tile_value == 4));
return empty;
}
static unsigned int get_tile_value_by_pos(struct tile_map *tile_map,
struct tile_map_position pos)
{
unsigned int tile_chunk_value =
get_tile_value(tile_map, pos.abs_tile_x,
pos.abs_tile_y, pos.abs_tile_z);
return tile_chunk_value;
}
static void set_tile_value_unchecked(struct tile_map *tile_map,
struct tile_chunk *tile_chunk,
unsigned int tile_x,
unsigned int tile_y,
unsigned int tile_value)
{
assert(tile_chunk);
assert(tile_x < tile_map->chunk_dim);
assert(tile_y < tile_map->chunk_dim);
tile_chunk->tiles[tile_y * tile_map->chunk_dim + tile_x] = tile_value;
}
static void set_tile_chunk_value(struct tile_map *tile_map,
struct tile_chunk *tile_chunk,
unsigned int test_tile_x,
unsigned int test_tile_y,
unsigned int tile_value)
{
if(tile_chunk && tile_chunk->tiles) {
set_tile_value_unchecked(tile_map, tile_chunk,
test_tile_x, test_tile_y,
tile_value);
}
}
static int is_tile_map_point_empty(struct tile_map *tile_map,
struct tile_map_position pos)
{
unsigned int tile_chunk_value;
int empty;
tile_chunk_value = get_tile_value_by_pos(tile_map, pos);
empty = is_tile_value_empty(tile_chunk_value);
return empty;
}
static void set_tile_value(struct memory_arena *arena,
struct tile_map *tile_map,
unsigned int abs_tile_x, unsigned int abs_tile_y,
unsigned int abs_tile_z, unsigned int tile_value)
{
struct tile_chunk_position chunk_pos;
struct tile_chunk *tile_chunk;
chunk_pos = get_chunk_position_for(tile_map,
abs_tile_x, abs_tile_y, abs_tile_z);
tile_chunk = get_tile_chunk(tile_map,
chunk_pos.tile_chunk_x,
chunk_pos.tile_chunk_y,
chunk_pos.tile_chunk_z);
assert(tile_chunk);
if(!tile_chunk->tiles) {
unsigned int tile_count, tile_index;
tile_count = tile_map->chunk_dim*tile_map->chunk_dim;
tile_chunk->tiles = PUSH_ARRAY(arena, tile_count, unsigned int);
for(tile_index = 0;
tile_index < tile_count;
tile_index++)
{
tile_chunk->tiles[tile_index] = 1;
}
}
set_tile_chunk_value(tile_map, tile_chunk, chunk_pos.rel_tile_x,
chunk_pos.rel_tile_y, tile_value);
}
/* TODO: Do these belong more in a "positioning" or "geometry" file? */
static void cannonicalize_coord(struct tile_map *tile_map,
unsigned int *tile,
float *tile_rel)
{
/* NOTE: The world is assumed to be toroidal topology. If you step off
* one end, you come back on the other.*/
int offset =
round_float_to_int(*tile_rel / tile_map->tile_side_in_meters);
*tile += offset;
*tile_rel -= (float)offset * tile_map->tile_side_in_meters;
assert(*tile_rel >= -0.5f*tile_map->tile_side_in_meters);
assert(*tile_rel <= 0.5f*tile_map->tile_side_in_meters);
}
static struct tile_map_position
recannonicalize_position(struct tile_map *tile_map,
struct tile_map_position pos)
{
struct tile_map_position result = pos;
cannonicalize_coord(tile_map, &result.abs_tile_x, &result.offset.x);
cannonicalize_coord(tile_map, &result.abs_tile_y, &result.offset.y);
return result;
}
static int are_on_same_tile(struct tile_map_position *a,
struct tile_map_position *b)
{
int result = ((a->abs_tile_x == b->abs_tile_x) &&
(a->abs_tile_y == b->abs_tile_y) &&
(a->abs_tile_z == b->abs_tile_z));
return result;
}
static struct tile_map_difference
subtract_in_float(struct tile_map *tile_map,
struct tile_map_position *a, struct tile_map_position *b)
{
struct tile_map_difference result;
struct v2 d_tile_xy;
float d_tile_z;
d_tile_xy.x = (float)a->abs_tile_x - (float)b->abs_tile_x;
d_tile_xy.y = (float)a->abs_tile_y - (float)b->abs_tile_y;
d_tile_z = (float)a->abs_tile_z - (float)b->abs_tile_z;
result.d_xy = v2_add(v2_multiply(tile_map->tile_side_in_meters,
d_tile_xy),
v2_subtract(a->offset, b->offset));
/* TODO: Incomplete . . . */
result.d_z = tile_map->tile_side_in_meters*d_tile_z;
return result;
}
static struct tile_map_position
centered_tile_point(unsigned int abs_tile_x, unsigned int abs_tile_y,
unsigned int abs_tile_z)
{
struct tile_map_position result;
memset(&result, 0, sizeof(result));
result.abs_tile_x = abs_tile_x;
result.abs_tile_y = abs_tile_y;
result.abs_tile_z = abs_tile_z;
return result;
}