Day 49 complete

This commit is contained in:
Edward R. Gonzalez 2024-01-01 02:53:15 -05:00
parent 2c3b6d9e66
commit 393f98a03d
6 changed files with 170 additions and 74 deletions

View File

@ -35,7 +35,7 @@ The final build order should have an additional game module: `handmade`, that wi
## Milestone ## Milestone
Day 48 : Line Segment Intersection Collisions Day 49 : Debugging Canonical Coordinatescl
Features Done so far: Features Done so far:

View File

@ -441,10 +441,7 @@ void player_init( hh::Player* player, hh::GameState* gs )
entity->kind = hh::EntityKind_Hero; entity->kind = hh::EntityKind_Hero;
entity->position.tile_x = 4; entity->position = gs->spawn_pos;
entity->position.tile_y = 4;
entity->position.rel_pos.x = 0.f;
entity->position.rel_pos.y = 0.f;
entity->velocity = {}; entity->velocity = {};
@ -569,7 +566,9 @@ void update_player( hh::Player* player, f32 delta_time, World* world, hh::GameSt
f32 player_half_width = entity->width / 2.f; f32 player_half_width = entity->width / 2.f;
f32 player_quarter_height = entity->height / 4.f; f32 player_quarter_height = entity->height / 4.f;
f32 move_accel = 36.f; // f32 move_accel = 36.f;
f32 move_accel = 200.f;
if ( actions->sprint ) if ( actions->sprint )
{ {
move_accel = 94.f; move_accel = 94.f;
@ -702,52 +701,91 @@ void update_player( hh::Player* player, f32 delta_time, World* world, hh::GameSt
} }
else else
{ {
TileMapPos new_pos = { TileMapPos new_pos = recannonicalize_position( tile_map, {
new_player_pos.x, new_player_pos.y, new_player_pos.x, new_player_pos.y,
old_pos.tile_x, old_pos.tile_y, old_pos.tile_z old_pos.tile_x, old_pos.tile_y, old_pos.tile_z
}; });
new_pos = recannonicalize_position( tile_map, new_pos ); TileMapPos best_position = old_pos;
f32 min_intersection_delta = 1.0f;
s32 min_tile_x = min( old_pos.tile_x, new_pos.tile_x ); if (0)
s32 min_tile_y = min( old_pos.tile_y, new_pos.tile_y );
s32 max_tile_x = max( old_pos.tile_x, new_pos.tile_x );
s32 max_tile_y = max( old_pos.tile_y, new_pos.tile_y );
TileMapPos best_position = old_pos;
f32 min_intersection_delta = 1.0f;
for ( s32 tile_y = min_tile_y; tile_y <= max_tile_y; ++ tile_y )
for ( s32 tile_x = min_tile_x; tile_x <= max_tile_x; ++ tile_x )
{ {
TileMapPos test_tile_pos = centered_tile_point( tile_x, tile_y, old_pos.tile_z ); s32 min_tile_x = min( old_pos.tile_x, new_pos.tile_x );
s32 tile_value = TileMap_get_tile_value( tile_map, test_tile_pos ); s32 min_tile_y = min( old_pos.tile_y, new_pos.tile_y );
if ( ! TileMap_is_tile_value_empty( tile_value ) )
s32 max_tile_x = max( old_pos.tile_x, new_pos.tile_x );
s32 max_tile_y = max( old_pos.tile_y, new_pos.tile_y );
for ( s32 tile_y = min_tile_y; tile_y <= max_tile_y; ++ tile_y )
for ( s32 tile_x = min_tile_x; tile_x <= max_tile_x; ++ tile_x )
{ {
Vec2 tile_xy_in_meters = Vec2 { tile_map->tile_side_in_meters, tile_map->tile_side_in_meters }; TileMapPos test_tile_pos = centered_tile_point( tile_x, tile_y, old_pos.tile_z );
s32 tile_value = TileMap_get_tile_value( tile_map, test_tile_pos );
if ( ! TileMap_is_tile_value_empty( tile_value ) )
{
Vec2 tile_xy_in_meters = Vec2 { tile_map->tile_side_in_meters, tile_map->tile_side_in_meters };
Vec2 min_corner = -0.5f * tile_xy_in_meters; Vec2 min_corner = -0.5f * tile_xy_in_meters;
Vec2 max_corner = 0.5f * tile_xy_in_meters; Vec2 max_corner = 0.5f * tile_xy_in_meters;
Vec2 rel_old_pos = subtract( old_pos, test_tile_pos ).rel_pos; Vec2 rel_old_pos = subtract( old_pos, test_tile_pos ).rel_pos;
Vec2 rel_old_pos_inv = { rel_old_pos.y, rel_old_pos.x }; Vec2 rel_old_pos_inv = { rel_old_pos.y, rel_old_pos.x };
Vec2 vel_inv = { entity->velocity.y, entity->velocity.x }; Vec2 vel_inv = { entity->velocity.y, entity->velocity.x };
test_wall( min_corner.x, rel_old_pos, min_corner.y, max_corner.y, entity->velocity, & min_intersection_delta ); test_wall( min_corner.x, rel_old_pos, min_corner.y, max_corner.y, entity->velocity, & min_intersection_delta );
test_wall( max_corner.x, rel_old_pos, min_corner.y, max_corner.y, entity->velocity, & min_intersection_delta ); test_wall( max_corner.x, rel_old_pos, min_corner.y, max_corner.y, entity->velocity, & min_intersection_delta );
test_wall( min_corner.y, rel_old_pos_inv, min_corner.x, max_corner.x, vel_inv, & min_intersection_delta ); test_wall( min_corner.y, rel_old_pos_inv, min_corner.x, max_corner.x, vel_inv, & min_intersection_delta );
test_wall( max_corner.y, rel_old_pos_inv, min_corner.x, max_corner.x, vel_inv, & min_intersection_delta ); test_wall( max_corner.y, rel_old_pos_inv, min_corner.x, max_corner.x, vel_inv, & min_intersection_delta );
}
}
}
else
{
s32 tile_delta_x = sign( new_pos.tile_x - old_pos.tile_x );
s32 tile_delta_y = sign( new_pos.tile_y - old_pos.tile_y );
for ( s32 tile_y = old_pos.tile_y; ; tile_y += tile_delta_y )
{
for ( s32 tile_x = old_pos.tile_x; ; tile_x += tile_delta_x )
{
TileMapPos test_tile_pos = centered_tile_point( tile_x, tile_y, old_pos.tile_z );
s32 tile_value = TileMap_get_tile_value( tile_map, test_tile_pos );
local_persist TileChunkPosition last_chunk = {};
TileChunkPosition curr_chunk = get_tile_chunk_position_for(tile_map, old_pos.tile_x, old_pos.tile_y, old_pos.tile_z );
if ( ! TileMap_is_tile_value_empty( tile_value ) )
{
Vec2 tile_xy_in_meters = Vec2 { tile_map->tile_side_in_meters, tile_map->tile_side_in_meters };
Vec2 min_corner = -0.5f * tile_xy_in_meters;
Vec2 max_corner = 0.5f * tile_xy_in_meters;
Vec2 rel_old_pos = subtract( old_pos, test_tile_pos ).rel_pos;
Vec2 rel_old_pos_inv = { rel_old_pos.y, rel_old_pos.x };
Vec2 vel_inv = { entity->velocity.y, entity->velocity.x };
test_wall( min_corner.x, rel_old_pos, min_corner.y, max_corner.y, entity->velocity, & min_intersection_delta );
test_wall( max_corner.x, rel_old_pos, min_corner.y, max_corner.y, entity->velocity, & min_intersection_delta );
test_wall( min_corner.y, rel_old_pos_inv, min_corner.x, max_corner.x, vel_inv, & min_intersection_delta );
test_wall( max_corner.y, rel_old_pos_inv, min_corner.x, max_corner.x, vel_inv, & min_intersection_delta );
}
if ( tile_x == new_pos.tile_x )
break;
}
if ( tile_y == new_pos.tile_y )
break;
} }
} }
new_player_pos = { old_pos.rel_pos.x, old_pos.rel_pos.y }; new_player_pos = { old_pos.rel_pos.x, old_pos.rel_pos.y };
new_player_pos += entity->velocity * min_intersection_delta; new_player_pos += entity->velocity * min_intersection_delta;
new_pos = recannonicalize_position( tile_map, {
new_pos = {
new_player_pos.x, new_player_pos.y, new_player_pos.x, new_player_pos.y,
old_pos.tile_x, old_pos.tile_y, old_pos.tile_z old_pos.tile_x, old_pos.tile_y, old_pos.tile_z
}; });
new_pos = recannonicalize_position( tile_map, new_pos );
entity->position = new_pos; entity->position = new_pos;
} }
@ -923,6 +961,9 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
state->game_memory.transient_size = memory->transient_size / Memory::game_memory_factor; state->game_memory.transient_size = memory->transient_size / Memory::game_memory_factor;
state->game_memory.transient = rcast(Byte*, memory->transient) + state->game_memory.transient_size; state->game_memory.transient = rcast(Byte*, memory->transient) + state->game_memory.transient_size;
hh::GameState* gs = rcast( hh::GameState*, state->game_memory.persistent );
assert( sizeof(hh::GameState) <= state->game_memory.persistent_size );
World* world; World* world;
// World setup // World setup
@ -965,8 +1006,8 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
world->tiles_per_screen_x = 17; world->tiles_per_screen_x = 17;
world->tiles_per_screen_y = 9; world->tiles_per_screen_y = 9;
u32 screen_x = 0; s32 screen_x = -10;
u32 screen_y = 0; s32 screen_y = -10;
u32 rng_index = 0; u32 rng_index = 0;
b32 door_left = false; b32 door_left = false;
@ -978,7 +1019,7 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
u32 abs_tile_z = 0; u32 abs_tile_z = 0;
for ( u32 screen_index = 0; screen_index < 100; ++ screen_index ) for ( u32 screen_index = 0; screen_index <= 100; ++ screen_index )
{ {
// TODO(Ed) : We need a proper RNG. // TODO(Ed) : We need a proper RNG.
assert( rng_index < array_count(RNG_Table) ) assert( rng_index < array_count(RNG_Table) )
@ -1015,6 +1056,9 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
door_top = true; door_top = true;
} }
local_persist TileChunkPosition last_chunk = {};
s32 chunk_index = 0;
for (s32 tile_y = 0; tile_y < world->tiles_per_screen_y; ++ tile_y ) for (s32 tile_y = 0; tile_y < world->tiles_per_screen_y; ++ tile_y )
{ {
for ( s32 tile_x = 0; tile_x < world->tiles_per_screen_x; ++ tile_x ) for ( s32 tile_x = 0; tile_x < world->tiles_per_screen_x; ++ tile_x )
@ -1022,6 +1066,12 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
s32 abs_tile_x = screen_x * world->tiles_per_screen_x + tile_x; s32 abs_tile_x = screen_x * world->tiles_per_screen_x + tile_x;
s32 abs_tile_y = screen_y * world->tiles_per_screen_y + tile_y; s32 abs_tile_y = screen_y * world->tiles_per_screen_y + tile_y;
do_once()
{
gs->spawn_pos.tile_x = abs_tile_x + 4;
gs->spawn_pos.tile_y = abs_tile_y + 4;
}
s32 tile_value = 1; s32 tile_value = 1;
b32 in_middle_x = tile_x == (world->tiles_per_screen_x / 2); b32 in_middle_x = tile_x == (world->tiles_per_screen_x / 2);
@ -1063,9 +1113,22 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
} }
} }
last_chunk = get_tile_chunk_position_for( tile_map, abs_tile_x, abs_tile_y, abs_tile_z );
chunk_index =
last_chunk.z * tile_map->tile_chunks_num_y * tile_map->tile_chunks_num_x
+ last_chunk.y * tile_map->tile_chunks_num_x
+ last_chunk.x;
// u32 tile_value = tile_x == tile_y && tile_y % 2 ? 1 : 0; // u32 tile_value = tile_x == tile_y && tile_y % 2 ? 1 : 0;
TileMap_set_tile_value( & state->world_arena, world->tile_map, abs_tile_x, abs_tile_y, abs_tile_z, tile_value ); TileMap_set_tile_value( & state->world_arena, world->tile_map, abs_tile_x, abs_tile_y, abs_tile_z, tile_value );
} }
s32 something = false;
something++;
if ( something )
{
something--;
}
} }
door_left = door_right; door_left = door_right;
@ -1107,9 +1170,6 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
} }
} }
hh::GameState* gs = rcast( hh::GameState*, state->game_memory.persistent );
assert( sizeof(hh::GameState) <= state->game_memory.persistent_size );
// Personally made assets // Personally made assets
{ {
StrPath path_test_bg {}; StrPath path_test_bg {};
@ -1198,9 +1258,6 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
using hh::FacingDirection_Front; using hh::FacingDirection_Front;
// gs->player_1 = {};
// gs->player_2 = {};
gs->camera_assigned_entity_id = gs->player_1.entity_id; gs->camera_assigned_entity_id = gs->player_1.entity_id;
} }
@ -1420,9 +1477,16 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
s32 tile_id = TileMap_get_tile_value( tile_map, col, row, gs->camera_pos.tile_z ); s32 tile_id = TileMap_get_tile_value( tile_map, col, row, gs->camera_pos.tile_z );
f32 color[3] = { 0.15f, 0.15f, 0.15f }; f32 color[3] = { 0.15f, 0.15f, 0.15f };
if ( tile_id > 1 || (entity_followed && row == entity_followed->position.tile_y && col == entity_followed->position.tile_x) ) if ( tile_id > 1 || tile_id == 0 || (entity_followed && row == entity_followed->position.tile_y && col == entity_followed->position.tile_x) )
// if ( tile_id > 1 ) // if ( tile_id > 1 )
{ {
if ( tile_id == 0 )
{
color[0] = 0.88f;
color[1] = 0.22f;
color[2] = 0.77f;
}
if ( tile_id == 2 ) if ( tile_id == 2 )
{ {
color[0] = 0.42f; color[0] = 0.42f;

View File

@ -7,7 +7,7 @@ NS_ENGINE_BEGIN
inline inline
TileMapPos subtract( TileMapPos pos_a, TileMapPos pos_b ) TileMapPos subtract( TileMapPos pos_a, TileMapPos pos_b )
{ {
TileMapPos result { TileMapPos result = {
pos_a.rel_pos - pos_b.rel_pos, pos_a.rel_pos - pos_b.rel_pos,
pos_a.tile_x - pos_b.tile_x, pos_a.tile_x - pos_b.tile_x,
@ -16,6 +16,7 @@ TileMapPos subtract( TileMapPos pos_a, TileMapPos pos_b )
// TODO(Ed) : Think about how to handle z... // TODO(Ed) : Think about how to handle z...
pos_a.tile_z - pos_b.tile_z pos_a.tile_z - pos_b.tile_z
}; };
return result; return result;
} }
@ -53,6 +54,13 @@ TileMapPos recannonicalize_position( TileMap* tile_map, TileMapPos pos )
return result; return result;
} }
inline
void offset( TileMap* tile_map, TileMapPos& map_pos, Vec2 rel_offset )
{
map_pos.rel_pos += rel_offset;
map_pos = recannonicalize_position( tile_map, map_pos);
}
inline inline
u32 TileChunk_get_tile_value( TileChunk* tile_chunk, TileMap* tile_map, s32 x, s32 y ) u32 TileChunk_get_tile_value( TileChunk* tile_chunk, TileMap* tile_map, s32 x, s32 y )
{ {
@ -77,18 +85,20 @@ void TileChunk_set_tile_value( TileChunk* tile_chunk, TileMap* tile_map, s32 x,
} }
inline inline
TileChunk* TileMap_get_chunk( TileMap* tile_map, s32 tile_chunk_x, s32 tile_chunk_y, s32 tile_chunk_z ) TileChunk* TileMap_get_chunk( TileMap* tile_map, TileChunkPosition chunk_pos )
{ {
TileChunk* chunk = nullptr; TileChunk* chunk = nullptr;
if ( tile_chunk_x >= 0 && tile_chunk_x < scast(s32, tile_map->tile_chunks_num_x) if ( chunk_pos.x >= 0 && chunk_pos.x < tile_map->tile_chunks_num_x
&& tile_chunk_y >= 0 && tile_chunk_y < scast(s32, tile_map->tile_chunks_num_y) && chunk_pos.y >= 0 && chunk_pos.y < tile_map->tile_chunks_num_y
&& tile_chunk_z >= 0 && tile_chunk_z < scast(s32, tile_map->tile_chunks_num_z) ) && chunk_pos.z >= 0 && chunk_pos.z < tile_map->tile_chunks_num_z )
{ {
chunk = & tile_map->chunks[ chunk = & tile_map->chunks[
tile_chunk_z * tile_map->tile_chunks_num_y * tile_map->tile_chunks_num_x chunk_pos.z * tile_map->tile_chunks_num_y * tile_map->tile_chunks_num_x
+ tile_chunk_y * tile_map->tile_chunks_num_x + chunk_pos.y * tile_map->tile_chunks_num_x
+ tile_chunk_x ]; + chunk_pos.x ];
return chunk;
} }
return chunk; return chunk;
@ -100,11 +110,24 @@ TileChunkPosition get_tile_chunk_position_for( TileMap* tile_map, s32 abs_tile_x
assert( tile_map != nullptr ); assert( tile_map != nullptr );
TileChunkPosition chunk_pos {}; TileChunkPosition chunk_pos {};
chunk_pos.tile_chunk_x = abs_tile_x >> tile_map->chunk_shift; chunk_pos.x = abs_tile_x >> tile_map->chunk_shift;
chunk_pos.tile_chunk_y = abs_tile_y >> tile_map->chunk_shift; chunk_pos.y = abs_tile_y >> tile_map->chunk_shift;
chunk_pos.tile_chunk_z = abs_tile_z; chunk_pos.z = abs_tile_z;
chunk_pos.tile_x = abs_tile_x & tile_map->chunk_mask;
chunk_pos.tile_y = abs_tile_y & tile_map->chunk_mask; // Correct negative values
s32 neg_mask = (1 << (sizeof(s32) * 8 - 1));
s32 is_neg_x = (chunk_pos.x & neg_mask) < 0;
s32 is_neg_y = (chunk_pos.y & neg_mask) < 0;
s32 offset_x = is_neg_x * tile_map->tile_chunks_num_x;
s32 offset_y = is_neg_y * tile_map->tile_chunks_num_y;
chunk_pos.x = offset_x + chunk_pos.x;
chunk_pos.y = offset_y + chunk_pos.y;
// chunk_pos.tile_x = (abs_tile_x * (-1 * is_neg_x)) & tile_map->chunk_mask;
// chunk_pos.tile_y = (abs_tile_y * (-1 * is_neg_y)) & tile_map->chunk_mask;
chunk_pos.tile_x = abs_tile_x & tile_map->chunk_mask;
chunk_pos.tile_y = abs_tile_y & tile_map->chunk_mask;
return chunk_pos; return chunk_pos;
} }
@ -117,7 +140,7 @@ u32 TileMap_get_tile_value( TileMap* tile_map, s32 tile_x, s32 tile_y, s32 tile_
s32 value = 0; s32 value = 0;
TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, tile_x, tile_y, tile_z ); TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, tile_x, tile_y, tile_z );
TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y, chunk_pos.tile_chunk_z ); TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos );
if ( chunk && chunk->tiles ) if ( chunk && chunk->tiles )
value = TileChunk_get_tile_value( chunk, tile_map, chunk_pos.tile_x, chunk_pos.tile_y ); value = TileChunk_get_tile_value( chunk, tile_map, chunk_pos.tile_x, chunk_pos.tile_y );
@ -155,7 +178,7 @@ internal
void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, s32 abs_tile_x, s32 abs_tile_y, s32 abs_tile_z, s32 value ) void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, s32 abs_tile_x, s32 abs_tile_y, s32 abs_tile_z, s32 value )
{ {
TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, abs_tile_x, abs_tile_y, abs_tile_z ); TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, abs_tile_x, abs_tile_y, abs_tile_z );
TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y, chunk_pos.tile_chunk_z ); TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos );
assert( chunk != nullptr ); assert( chunk != nullptr );

View File

@ -23,9 +23,9 @@ struct TileChunk
*/ */
struct TileChunkPosition struct TileChunkPosition
{ {
s32 tile_chunk_x; s32 x;
s32 tile_chunk_y; s32 y;
s32 tile_chunk_z; s32 z;
// "Chunk-relative (x, y) // "Chunk-relative (x, y)

View File

@ -150,6 +150,8 @@ struct GameState
Player player_1; Player player_1;
Player player_2; Player player_2;
engine::TileMapPos spawn_pos;
// PlayerState player_state; // PlayerState player_state;
// PlayerState player_state_2; // PlayerState player_state_2;

View File

@ -14,6 +14,13 @@ f32 abs( f32 value )
return result; return result;
} }
inline
s32 sign( s32 value )
{
s32 result = value >= 0 ? 1 : -1;
return result;
}
inline inline
f32 sqrt( f32 value ) f32 sqrt( f32 value )
{ {