Day 34 complete!!!

This commit is contained in:
Edward R. Gonzalez 2023-10-11 17:52:13 -04:00
parent 7958fabd00
commit a4f07c67d2
25 changed files with 670 additions and 564 deletions

View File

@ -14,7 +14,7 @@
"label": "Static Data" "label": "Static Data"
}, },
{ {
"line": 1002, "line": 1001,
"column": 0, "column": 0,
"label": "Main Loop : End" "label": "Main Loop : End"
} }

View File

@ -57,10 +57,11 @@ Features Done so far:
* Allows for engine or game state to be restored even if a crash occurs to exact memory state it was before. * Allows for engine or game state to be restored even if a crash occurs to exact memory state it was before.
* Basic input abstraction into hard-coded actions (``EngineActions` & `PlayerActions`) * Basic input abstraction into hard-coded actions (``EngineActions` & `PlayerActions`)
* Record & replay input. * Record & replay input.
* (WIP) : 2D Tile Map setup * (WIP) : 2D Tile Map (Virtualized into chunks)
## Gallery ## Gallery
![img](docs/imgs/handmade_win32_2023-10-11_23-39-57.gif)
![img](docs/imgs/handmade_win32_2023-10-11_00-47-19.gif) ![img](docs/imgs/handmade_win32_2023-10-11_00-47-19.gif)
![img](docs/imgs/handmade_win32_2023-10-10_13-13-14.gif) ![img](docs/imgs/handmade_win32_2023-10-10_13-13-14.gif)
![img](docs/imgs/handmade_win32_2023-10-06_12-43-47.gif) ![img](docs/imgs/handmade_win32_2023-10-06_12-43-47.gif)

6
docs/Day 034.md Normal file
View File

@ -0,0 +1,6 @@
# Day 34
Casey decided to start offloading tile map definitions to separate files so I took the time to also cleanup some of the organization of the code.
I'm still keeping some cpp files directly included within engine.cpp and win32_platform.cpp for now (instead of their translation unit files). I'll problably wait till much later to offload them.
Making that first baby step for procedural gen, and proper tile_chunk memory felt pretty good after many vods of stumbling.

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

View File

@ -15,12 +15,16 @@
#undef do_once_end #undef do_once_end
using namespace gen; using namespace gen;
#include "platform/platform_module.hpp"
#include "platform/grime.hpp" #include "platform/grime.hpp"
#include "platform/macros.hpp" #include "platform/macros.hpp"
#include "platform/types.hpp" #include "platform/types.hpp"
#include "platform/strings.hpp" #include "platform/strings.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "engine/engine_module.hpp"
#include "engine/input.hpp"
#include "engine/tile_map.hpp"
#include "engine/engine.hpp" #include "engine/engine.hpp"
#include "engine/engine_to_platform_api.hpp" #include "engine/engine_to_platform_api.hpp"

View File

@ -1,7 +1,12 @@
#if INTELLISENSE_DIRECTIVES #if INTELLISENSE_DIRECTIVES
#include "engine.hpp" #include "engine.hpp"
#include "input.hpp"
#include "engine_to_platform_api.hpp" #include "engine_to_platform_api.hpp"
// TODO(Ed) : This needs to be moved out eventually
#include "handmade.hpp" #include "handmade.hpp"
#include "tile_map.cpp"
#endif #endif
NS_ENGINE_BEGIN NS_ENGINE_BEGIN
@ -43,6 +48,11 @@ struct EngineActions
struct EngineState struct EngineState
{ {
hh::Memory game_memory;
MemoryArena world_arena;
World* world;
f32 auto_snapshot_interval; f32 auto_snapshot_interval;
f32 auto_snapshot_timer; f32 auto_snapshot_timer;
@ -55,15 +65,15 @@ struct EngineState
f32 sample_wave_sine_time; f32 sample_wave_sine_time;
b32 sample_wave_switch; b32 sample_wave_switch;
hh::Memory game_memory;
}; };
NS_ENGINE_END NS_ENGINE_END
// TODO(Ed) : does this need to be here or can it be moved to handmade_engine.cpp?
#include "test_samples.cpp" #include "test_samples.cpp"
#if Build_Development #if Build_Development
// TODO(Ed) : Do a proper header/src pair for this
#include "state_and_replay.cpp" #include "state_and_replay.cpp"
// Build_Development // Build_Development
#endif #endif
@ -121,6 +131,7 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
{ {
DualsensePadState* pad = controller->ds_pad; DualsensePadState* pad = controller->ds_pad;
actions->sprint |= pressed( pad->circle );
actions->jump |= pressed( pad->cross ); actions->jump |= pressed( pad->cross );
actions->player_x_move_analog += pad->stick.left.X.end; actions->player_x_move_analog += pad->stick.left.X.end;
@ -130,6 +141,7 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
{ {
XInputPadState* pad = controller->xpad; XInputPadState* pad = controller->xpad;
actions->sprint |= pressed( pad->B );
actions->jump |= pressed( pad->A ); actions->jump |= pressed( pad->A );
actions->player_x_move_analog += pad->stick.left.X.end; actions->player_x_move_analog += pad->stick.left.X.end;
@ -140,6 +152,7 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
{ {
KeyboardState* keyboard = controller->keyboard; KeyboardState* keyboard = controller->keyboard;
actions->jump |= pressed( keyboard->space ); actions->jump |= pressed( keyboard->space );
actions->sprint |= keyboard->left_shift.ended_down;
actions->player_x_move_digital += keyboard->D.ended_down - keyboard->A.ended_down; actions->player_x_move_digital += keyboard->D.ended_down - keyboard->A.ended_down;
actions->player_y_move_digital += keyboard->W.ended_down - keyboard->S.ended_down; actions->player_y_move_digital += keyboard->W.ended_down - keyboard->S.ended_down;
@ -151,8 +164,8 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
} }
} }
internal void internal
output_sound( EngineState* state, AudioBuffer* sound_buffer, GetSoundSampleValueFn* get_sample_value ) void output_sound( EngineState* state, AudioBuffer* sound_buffer, GetSoundSampleValueFn* get_sample_value )
{ {
s16* sample_out = sound_buffer->samples; s16* sample_out = sound_buffer->samples;
for ( s32 sample_index = 0; sample_index < sound_buffer->num_samples; ++ sample_index ) for ( s32 sample_index = 0; sample_index < sound_buffer->num_samples; ++ sample_index )
@ -223,122 +236,55 @@ void draw_rectangle( OffscreenBuffer* buffer
} }
inline inline
void cannonicalize_coord( World* world, u32* tile_coord, f32* pos_coord ) void draw_debug_point(OffscreenBuffer* back_buffer, World* world, TileMapPosition pos, f32 red, f32 green, f32 blue)
{ {
f32 tile_size = scast(f32, world->tile_size_in_meters); TileMap* tile_map = world->tile_map;
// Note(Ed) : World is assumed to be a "torodial topology" draw_rectangle(back_buffer,
s32 offset = floor( (* pos_coord) / tile_size ); pos.x * tile_map->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * tile_map->tile_size_in_pixels),
u32 new_tile_coord = (* tile_coord) + offset; pos.y * tile_map->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * tile_map->tile_size_in_pixels),
f32 new_pos_coord = (* pos_coord) - scast(f32, offset) * tile_size; (pos.x + 0.1f) * tile_map->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * tile_map->tile_size_in_pixels),
(pos.y + 0.1f) * tile_map->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * tile_map->tile_size_in_pixels),
assert( new_pos_coord >= 0 ); red, green, blue);
assert( new_pos_coord <= tile_size );
(* tile_coord) = new_tile_coord;
(* pos_coord) = new_pos_coord;
} }
inline
WorldPosition recannonicalize_position( World* world, WorldPosition pos ) internal
void MemoryArena_init( MemoryArena* arena, ssize size, Byte* storage )
{ {
WorldPosition result = pos; arena->storage = storage;
cannonicalize_coord( world, & result.tile_x, & result.x ); arena->size = size;
cannonicalize_coord( world, & result.tile_y, & result.y ); arena->used = 0;
}
#define MemoryArena_push_struct( arena, type ) MemoryArena__push_struct<type>( arena )
template< typename Type > inline
Type* MemoryArena__push_struct( MemoryArena* arena )
{
assert( arena != nullptr );
ssize type_size = sizeof( Type );
assert( arena->used + type_size <= arena->size );
Type* result = rcast(Type*, arena->storage + arena->used);
arena->used += type_size;
return result; return result;
} }
inline #define MemoryArena_push_array( arena, type, num ) MemoryArena__push_array<type>( arena, num )
u32 TileChunk_tile_value( TileChunk* tile_chunk, World* world, u32 x, u32 y ) template< typename Type> inline
Type* MemoryArena__push_array( MemoryArena* arena, ssize num )
{ {
assert( world != nullptr ); assert( arena != nullptr );
assert( tile_chunk != nullptr );
assert( x < world->chunk_dimension );
assert( y < world->chunk_dimension );
u32 value = tile_chunk->tiles[ (y * world->chunk_dimension) + x ]; ssize mem_amount = sizeof( Type ) * num;
return value; assert( arena->used + mem_amount <= arena->size );
}
// TODO(Ed) : Review if this is needed anymore? Type* result = rcast(Type*, arena->storage + arena->used);
#if 0 arena->used += mem_amount;
inline
b32 TileChunk_is_tile_empty( TileChunk* tile_chunk, World* world, u32 tile_x, u32 tile_y )
{
//assert( tile_chunk != nullptr );
assert( world != nullptr );
// Assume space is occupied if there is bad data return result;
if ( tile_chunk == nullptr )
return false;
b32 is_empty = false;
u32 tile_value = TileChunk_tile_value( tile_chunk, world, tile_x, tile_y );
is_empty = tile_value == 0;
return is_empty;
}
#endif
inline
TileChunk* World_get_tile_chunk( World* world, s32 tile_chunk_x, s32 tile_chunk_y )
{
TileChunk* chunk = nullptr;
if ( tile_chunk_x >= 0 && tile_chunk_x < scast(s32, world->tile_chunks_num_x)
&& tile_chunk_y >= 0 && tile_chunk_y < scast(s32, world->tile_chunks_num_y) )
{
chunk = & world->tile_chunks[ tile_chunk_y * world->tile_chunks_num_x + tile_chunk_x ];
}
return chunk;
}
inline
TileChunkPosition get_tile_chunk_position_for( World* world, u32 abs_tile_x, u32 abs_tile_y )
{
TileChunkPosition chunk_pos {};
chunk_pos.tile_chunk_x = abs_tile_x >> world->chunk_shift;
chunk_pos.tile_chunk_y = abs_tile_y >> world->chunk_shift;
chunk_pos.tile_x = abs_tile_x & world->chunk_mask;
chunk_pos.tile_y = abs_tile_y & world->chunk_mask;
return chunk_pos;
}
internal // TODO(Ed) : Review if he keeps this crap.
u32 piggy_get_tile_value( World* world, u32 tile_x, u32 tile_y )
{
assert( world != nullptr );
u32 value = 0;
TileChunkPosition chunk_pos = get_tile_chunk_position_for( world, tile_x, tile_y );
TileChunk* chunk = World_get_tile_chunk( world, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y );
if ( chunk )
value = TileChunk_tile_value( chunk, world, chunk_pos.tile_x, chunk_pos.tile_y );
return value;
}
internal
b32 world_is_point_empty( World* world, WorldPosition position )
{
assert( world != nullptr );
u32 chunk_value = piggy_get_tile_value( world, position.tile_x, position.tile_y );
b32 is_empty = chunk_value == 0;
return is_empty;
}
inline
void draw_debug_point(OffscreenBuffer* back_buffer, World* world, WorldPosition pos, f32 red, f32 green, f32 blue)
{
draw_rectangle(back_buffer,
pos.x * world->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * world->tile_size_in_pixels),
pos.y * world->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * world->tile_size_in_pixels),
(pos.x + 0.1f) * world->tile_meters_to_pixels + world->tile_lower_left_x + scast(f32, pos.tile_x * world->tile_size_in_pixels),
(pos.y + 0.1f) * world->tile_meters_to_pixels + world->tile_lower_left_y + scast(f32, pos.tile_y * world->tile_size_in_pixels),
red, green, blue);
} }
Engine_API Engine_API
@ -348,7 +294,7 @@ void on_module_reload( Memory* memory, platform::ModuleAPI* platfom_api )
} }
Engine_API Engine_API
void startup( Memory* memory, platform::ModuleAPI* platform_api ) void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* platform_api )
{ {
#if Build_Development #if Build_Development
memory->active_snapshot_slot = 1; memory->active_snapshot_slot = 1;
@ -380,22 +326,88 @@ void startup( Memory* memory, platform::ModuleAPI* platform_api )
state->sample_wave_sine_time = 0.f; state->sample_wave_sine_time = 0.f;
state->renderer_paused = false; state->renderer_paused = false;
state->game_memory.persistent_size = memory->persistent_size / 2; state->game_memory.persistent_size = memory->persistent_size / Memory::game_memory_factor;
state->game_memory.persistent = rcast(Byte*, memory->persistent) + state->game_memory.persistent_size; state->game_memory.persistent = rcast(Byte*, memory->persistent) + state->game_memory.persistent_size;
state->game_memory.transient_size = memory->transient_size / 2; 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;
// World setup
{
ssize world_arena_size = memory->engine_persistent_size() - sizeof(EngineState);
Byte* world_arena_storage = memory->persistent + sizeof(EngineState);
MemoryArena_init( & state->world_arena, world_arena_size, world_arena_storage );
state->world = MemoryArena_push_struct( & state->world_arena, World);
World* world = state->world;
TileMap* tile_map = MemoryArena_push_struct( & state->world_arena, TileMap);
world->tile_map = tile_map;
tile_map->chunk_shift = 4;
tile_map->chunk_mask = (1 << tile_map->chunk_shift) - 1;
tile_map->chunk_dimension = (1 << tile_map->chunk_shift);
tile_map->tile_chunks_num_x = 128;
tile_map->tile_chunks_num_y = 128;
tile_map->chunks = MemoryArena_push_array( & state->world_arena, TileChunk, tile_map->tile_chunks_num_x * tile_map->tile_chunks_num_y );
for ( s32 y = 0; y < tile_map->tile_chunks_num_y; ++ y )
{
for ( s32 x = 0; x < tile_map->tile_chunks_num_x; ++ x )
{
ssize num_tiles = tile_map->chunk_dimension * tile_map->chunk_dimension;
tile_map->chunks[ (y * tile_map->tile_chunks_num_x) + x ].tiles = MemoryArena_push_array( & state->world_arena, u32, num_tiles );
}
}
//TileChunk temp_chunk;
//temp_chunk.tiles = rcast( u32*, & temp_tiles );
//tile_map->chunks = & temp_chunk;
tile_map->tile_size_in_meters = 1.4f;
tile_map->tile_size_in_pixels = 85;
tile_map->tile_meters_to_pixels = scast(f32, tile_map->tile_size_in_pixels) / tile_map->tile_size_in_meters;
f32 tile_size_in_pixels = scast(f32, tile_map->tile_size_in_pixels);
world->tile_lower_left_x = -( tile_size_in_pixels * 0.5f);
world->tile_lower_left_y = +( tile_size_in_pixels * 0.25f) + scast(f32, back_buffer->height);
u32 tiles_per_screen_x = 17;
u32 tiles_per_screen_y = 9;
for ( u32 screen_y = 0; screen_y < 32; ++ screen_y )
{
for ( u32 screen_x = 0; screen_x < 32; ++ screen_x )
{
for (u32 tile_y = 0; tile_y < tiles_per_screen_y; ++ tile_y )
{
for ( u32 tile_x = 0; tile_x < tiles_per_screen_x; ++ tile_x )
{
u32 abs_tile_x = screen_x * tiles_per_screen_x + tile_x;
u32 abs_tile_y = screen_y * tiles_per_screen_y + tile_y;
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, tile_value );
}
}
}
}
}
hh::GameState* game_state = rcast( hh::GameState*, state->game_memory.persistent ); hh::GameState* game_state = rcast( hh::GameState*, state->game_memory.persistent );
assert( sizeof(hh::GameState) <= state->game_memory.persistent_size ); assert( sizeof(hh::GameState) <= state->game_memory.persistent_size );
hh::PlayerState* player = & game_state->player_state; hh::PlayerState* player = & game_state->player_state;
player->position.tile_x = 3; player->position.tile_x = 4;
player->position.tile_y = 3; player->position.tile_y = 4;
player->position.x = 0.f; player->position.x = 0.f;
player->position.y = 0.f; player->position.y = 0.f;
player->mid_jump = false; player->mid_jump = false;
player->jump_time = 0.f; player->jump_time = 0.f;
player->height = 1.4f;
player->width = player->height * 0.7f;
} }
Engine_API Engine_API
@ -549,63 +561,21 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
f32 x_offset_f = scast(f32, state->x_offset); f32 x_offset_f = scast(f32, state->x_offset);
f32 y_offset_f = scast(f32, state->y_offset); f32 y_offset_f = scast(f32, state->y_offset);
constexpr s32 tile_map_num_x = 256; World* world = state->world;
constexpr s32 tile_map_num_y = 256; TileMap* tile_map = world->tile_map;
// tiles_XY
u32 temp_tiles [tile_map_num_y][tile_map_num_x] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};
World world;
world.chunk_shift = 8;
world.chunk_mask = (1 << world.chunk_shift) - 1;
world.chunk_dimension = 256;
world.tile_chunks_num_x = 1;
world.tile_chunks_num_y = 1;
TileChunk temp_chunk;
temp_chunk.tiles = rcast( u32*, & temp_tiles );
world.tile_chunks = & temp_chunk;
world.tile_size_in_meters = 1.4f;
world.tile_size_in_pixels = 85;
world.tile_meters_to_pixels = scast(f32, world.tile_size_in_pixels) / world.tile_size_in_meters;
f32 tile_size_in_pixels = scast(f32, world.tile_size_in_pixels);
f32 scale = 85;
world.tile_lower_left_x = -( tile_size_in_pixels * 0.5f);
world.tile_lower_left_y = +( tile_size_in_pixels * 0.25f) + scast(f32, back_buffer->height);
player->height = 1.4f;
player->width = player->height * 0.7f;
f32 tile_size_in_pixels = scast(f32, tile_map->tile_size_in_pixels);
f32 player_half_width = player->width / 2.f; f32 player_half_width = player->width / 2.f;
f32 player_quarter_height = player->height / 4.f; f32 player_quarter_height = player->height / 4.f;
input_poll_player_actions( input, & player_actions ); input_poll_player_actions( input, & player_actions );
{ {
f32 move_speed = 4.f; f32 move_speed = 2.f;
if ( player_actions.sprint )
{
move_speed = 6.f;
}
f32 new_player_pos_x = player->position.x; f32 new_player_pos_x = player->position.x;
f32 new_player_pos_y = player->position.y; f32 new_player_pos_y = player->position.y;
@ -623,53 +593,52 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
b32 valid_new_pos = true; b32 valid_new_pos = true;
{ {
WorldPosition test_pos = { TileMapPosition test_pos = {
new_player_pos_x, new_player_pos_y, new_player_pos_x, new_player_pos_y,
player->position.tile_x, player->position.tile_y player->position.tile_x, player->position.tile_y
}; };
test_pos = recannonicalize_position( & world, test_pos ); test_pos = recannonicalize_position( tile_map, test_pos );
// TODO(Ed) : Need a delta-function that auto-reconnonicalizes. // TODO(Ed) : Need a delta-function that auto-reconnonicalizes.
WorldPosition test_pos_nw { TileMapPosition test_pos_nw {
new_player_pos_x - player_half_width, new_player_pos_y - player_quarter_height, new_player_pos_x - player_half_width, new_player_pos_y + player_quarter_height,
player->position.tile_x, player->position.tile_y player->position.tile_x, player->position.tile_y
}; };
test_pos_nw = recannonicalize_position( & world, test_pos_nw ); test_pos_nw = recannonicalize_position( tile_map, test_pos_nw );
valid_new_pos &= world_is_point_empty( & world, test_pos_nw ); valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_nw );
WorldPosition test_pos_ne { TileMapPosition test_pos_ne {
new_player_pos_x + player_half_width, new_player_pos_y - player_quarter_height, new_player_pos_x + player_half_width, new_player_pos_y + player_quarter_height,
player->position.tile_x, player->position.tile_y player->position.tile_x, player->position.tile_y
}; };
test_pos_ne = recannonicalize_position( & world, test_pos_ne ); test_pos_ne = recannonicalize_position( tile_map, test_pos_ne );
valid_new_pos &= world_is_point_empty( & world, test_pos_ne ); valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_ne );
WorldPosition test_pos_sw { TileMapPosition test_pos_sw {
new_player_pos_x - player_half_width, new_player_pos_y, new_player_pos_x - player_half_width, new_player_pos_y,
player->position.tile_x, player->position.tile_y player->position.tile_x, player->position.tile_y
}; };
test_pos_sw = recannonicalize_position( & world, test_pos_sw ); test_pos_sw = recannonicalize_position( tile_map, test_pos_sw );
valid_new_pos &= world_is_point_empty( & world, test_pos_sw ); valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_sw );
WorldPosition test_pos_se { TileMapPosition test_pos_se {
new_player_pos_x + player_half_width, new_player_pos_y, new_player_pos_x + player_half_width, new_player_pos_y,
player->position.tile_x, player->position.tile_y player->position.tile_x, player->position.tile_y
}; };
test_pos_se = recannonicalize_position( & world, test_pos_se ); test_pos_se = recannonicalize_position( tile_map, test_pos_se );
valid_new_pos &= world_is_point_empty( & world, test_pos_se ); valid_new_pos &= TileMap_is_point_empty( tile_map, test_pos_se );
} }
if ( valid_new_pos ) if ( valid_new_pos )
{ {
WorldPosition new_pos = { TileMapPosition new_pos = {
new_player_pos_x, new_player_pos_y, new_player_pos_x, new_player_pos_y,
player->position.tile_x, player->position.tile_y player->position.tile_x, player->position.tile_y
}; };
player->position = recannonicalize_position( & world, new_pos ); player->position = recannonicalize_position( tile_map, new_pos );
} }
if ( player->jump_time > 0.f ) if ( player->jump_time > 0.f )
{ {
player->jump_time -= delta_time; player->jump_time -= delta_time;
@ -693,10 +662,9 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
, 1.f, 0.24f, 0.24f ); , 1.f, 0.24f, 0.24f );
// Scrolling shitshow // Scrolling
#if 1 f32 screen_center_x = 0.5f * scast(f32, back_buffer->width);
f32 center_x = 0.5f * scast(f32, back_buffer->width); f32 screen_center_y = 0.5f * scast(f32, back_buffer->height);
f32 center_y = 0.5f * scast(f32, back_buffer->height);
for ( s32 relative_row = -10; relative_row < +10; ++ relative_row ) for ( s32 relative_row = -10; relative_row < +10; ++ relative_row )
{ {
@ -705,7 +673,7 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
u32 col = player->position.tile_x + relative_col; u32 col = player->position.tile_x + relative_col;
u32 row = player->position.tile_y + relative_row; u32 row = player->position.tile_y + relative_row;
u32 tileID = piggy_get_tile_value( & world, col, row ); u32 tileID = TileMap_get_tile_value( tile_map, col, row );
f32 color[3] = { 0.15f, 0.15f, 0.15f }; f32 color[3] = { 0.15f, 0.15f, 0.15f };
if ( tileID == 1 ) if ( tileID == 1 )
@ -722,85 +690,18 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
color[2] = 0.3f; color[2] = 0.3f;
} }
f32 min_x = center_x + scast(f32, relative_col) * tile_size_in_pixels; f32 center_x = screen_center_x + scast(f32, relative_col) * tile_size_in_pixels - player->position.x * tile_map->tile_meters_to_pixels;
f32 min_y = center_y - scast(f32, relative_row) * tile_size_in_pixels; f32 center_y = screen_center_y - scast(f32, relative_row) * tile_size_in_pixels + player->position.y * tile_map->tile_meters_to_pixels;
f32 max_x = min_x + tile_size_in_pixels;
f32 max_y = min_y - tile_size_in_pixels;
draw_rectangle( back_buffer f32 min_x = center_x - tile_size_in_pixels * 0.5f;
, min_x, max_y f32 min_y = center_y - tile_size_in_pixels * 0.5f;
, max_x, min_y f32 max_x = center_x + tile_size_in_pixels * 0.5f;
, color[0], color[1], color[2] ); f32 max_y = center_y + tile_size_in_pixels * 0.5f;
}
}
// Player
f32 player_red = 0.7f;
f32 player_green = 0.7f;
f32 player_blue = 0.3f;
f32 player_tile_x_offset = center_x + scast(f32, player->position.tile_x) * world.tile_meters_to_pixels;
f32 player_tile_y_offset = center_y - scast(f32, player->position.tile_y) * world.tile_meters_to_pixels;
f32 player_screen_pos_x = center_x + player->position.x * world.tile_meters_to_pixels;
f32 player_screen_pos_y = center_y - player->position.y * world.tile_meters_to_pixels;
// player_min_x = player_tile_x_offset - player_half_width * world;
draw_rectangle( back_buffer
, player_screen_pos_x - player_half_width * world.tile_meters_to_pixels, player_screen_pos_y - player->height * world.tile_meters_to_pixels
, player_screen_pos_x + player_half_width * world.tile_meters_to_pixels, player_screen_pos_y
, player_red, player_green, player_blue );
#endif
// Non-scrolling screen
#if 0
// Draw TileChunk
for ( u32 row = 0; row < 9; ++ row )
{
for ( u32 col = 0; col < 16; ++ col )
{
u32 tileID = piggy_get_tile_value( & world, col, row );
f32 color[3] = { 0.15f, 0.15f, 0.15f };
if ( tileID == 1 )
{
color[0] = 0.22f;
color[1] = 0.22f;
color[2] = 0.22f;
}
if ( row == player->position.tile_y && col == player->position.tile_x )
{
color[0] = 0.44f;
color[1] = 0.3f;
color[2] = 0.3f;
}
#if 0
// Was able to flip Y properly but not get the center alignemnt with the world.tile_lower_left that I wanted..
f32 min_x = world.tile_lower_left_x + scast(f32, col) * tile_size_in_pixels;
f32 min_y = scast(f32, row) * tile_size_in_pixels;
f32 max_x = min_x + tile_size_in_pixels;
f32 max_y = min_y + tile_size_in_pixels;
draw_rectangle( back_buffer draw_rectangle( back_buffer
, min_x, min_y , min_x, min_y
, max_x, max_y , max_x, max_y
//, min_x, max_y
//, max_x, min_y
, color[0], color[1], color[2] ); , color[0], color[1], color[2] );
#else
f32 min_x = world.tile_lower_left_x + scast(f32, col) * tile_size_in_pixels;
f32 min_y = world.tile_lower_left_y - scast(f32, row) * tile_size_in_pixels;
f32 max_x = min_x + tile_size_in_pixels;
f32 max_y = min_y - tile_size_in_pixels;
draw_rectangle( back_buffer
, min_x, max_y
, max_x, min_y
, color[0], color[1], color[2] );
#endif
} }
} }
@ -809,18 +710,18 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
f32 player_green = 0.7f; f32 player_green = 0.7f;
f32 player_blue = 0.3f; f32 player_blue = 0.3f;
f32 player_tile_x_offset = scast(f32, player->position.tile_x * world.tile_size_in_pixels); f32 player_tile_x_offset = screen_center_x + scast(f32, player->position.tile_x) * tile_map->tile_meters_to_pixels + player->position.x * tile_map->tile_meters_to_pixels;
f32 player_tile_y_offset = -scast(f32, player->position.tile_y * world.tile_size_in_pixels); f32 player_tile_y_offset = screen_center_y - scast(f32, player->position.tile_y) * tile_map->tile_meters_to_pixels + player->position.y * tile_map->tile_meters_to_pixels;
f32 player_screen_pos_x = world.tile_lower_left_x + player_tile_x_offset + player->position.x * world.tile_meters_to_pixels; f32 player_screen_pos_x = screen_center_x;
f32 player_screen_pos_y = world.tile_lower_left_y + player_tile_y_offset - player->position.y * world.tile_meters_to_pixels; f32 player_screen_pos_y = screen_center_y;
// player_min_x = player_tile_x_offset - player_half_width * world;
draw_rectangle( back_buffer draw_rectangle( back_buffer
, player_screen_pos_x - player_half_width * world.tile_meters_to_pixels, player_screen_pos_y - player->height * world.tile_meters_to_pixels , player_screen_pos_x - player_half_width * tile_map->tile_meters_to_pixels, player_screen_pos_y - player->height * tile_map->tile_meters_to_pixels
, player_screen_pos_x + player_half_width * world.tile_meters_to_pixels, player_screen_pos_y , player_screen_pos_x + player_half_width * tile_map->tile_meters_to_pixels, player_screen_pos_y
, player_red, player_green, player_blue ); , player_red, player_green, player_blue );
#endif
// Auto-Snapshot percent bar // Auto-Snapshot percent bar
if (1) if (1)

View File

@ -6,25 +6,12 @@
#if INTELLISENSE_DIRECTIVES #if INTELLISENSE_DIRECTIVES
#include "platform/platform.hpp" #include "platform/platform.hpp"
#endif #include "engine_module.hpp"
#include "tile_map.hpp"
#define NS_ENGINE_BEGIN namespace engine {
#define NS_ENGINE_END }
#ifndef Engine_API
// The build system is reponsible for defining this API macro for exporting symbols.
# define Engine_API
#endif #endif
NS_ENGINE_BEGIN NS_ENGINE_BEGIN
enum ReplayMode : s32
{
ReplayMode_Off,
ReplayMode_Record,
ReplayMode_Playback
};
struct Clocks struct Clocks
{ {
// TODO(Ed) : Clock values... // TODO(Ed) : Clock values...
@ -45,23 +32,49 @@ struct MemorySnapshot
u64 age; u64 age;
}; };
enum ReplayMode : s32
{
ReplayMode_Off,
ReplayMode_Record,
ReplayMode_Playback
};
struct ReplayData
{
static constexpr
s32 Num_Snapshot_Slots = 3;
// Abuse RAM to store snapshots of the Engine or Game state.
MemorySnapshot snapshots[ Num_Snapshot_Slots ];
s32 active_snapshot_slot;
// Recording and playback info is the same for either engine or game.
ReplayMode replay_mode;
platform::File active_input_replay_file;
// Engine-wide recording & playback loop.
s32 engine_loop_active;
s32 game_loop_active;
};
struct Memory struct Memory
{ {
// All memory for the engine is required to be zero initialized. // All memory for the engine is required to be zero initialized.
// Wiped on shutdown // Wiped on shutdown
void* persistent; Byte* persistent;
u64 persistent_size; ssize persistent_size;
// Wiped on a per-frame basis // Wiped on a per-frame basis
// void* Frame; // void* Frame;
// u64 FrameSize; // u64 FrameSize;
// Wiped whenever the engine wants to? // Wiped whenever the engine wants to?
void* transient; Byte* transient;
u64 transient_size; ssize transient_size;
// TODO(Ed) : Move this crap to state & replay archive definitions? // TODO(Ed) : Move this to state & replay archive definitions?
#if Build_Development #if Build_Development
static constexpr static constexpr
s32 Num_Snapshot_Slots = 3; s32 Num_Snapshot_Slots = 3;
@ -77,14 +90,32 @@ struct Memory
// Engine-wide recording & playback loop. // Engine-wide recording & playback loop.
s32 engine_loop_active; s32 engine_loop_active;
s32 game_loop_active; s32 game_loop_active;
//ReplayData replay;
#endif #endif
u64 total_size() // The game will have 1/4 of persistent's memory available ot it.
static constexpr
ssize game_memory_factor = 4;
ssize engine_persistent_size()
{
return persistent_size - persistent_size / game_memory_factor;
}
ssize total_size()
{ {
return persistent_size + transient_size; return persistent_size + transient_size;
} }
}; };
struct MemoryArena
{
Byte* storage;
ssize size;
ssize used;
};
struct OffscreenBuffer struct OffscreenBuffer
{ {
void* memory; // Lets use directly mess with the "pixel's memory buffer" void* memory; // Lets use directly mess with the "pixel's memory buffer"
@ -103,238 +134,13 @@ struct AudioBuffer
s32 num_samples; s32 num_samples;
}; };
struct DigitalBtn
{
s32 half_transitions;
b32 ended_down;
};
struct AnalogAxis
{
f32 start;
f32 end;
f32 min;
f32 max;
// Platform doesn't provide this, we process in the engine layer.
f32 average;
};
struct AnalogStick
{
AnalogAxis X;
AnalogAxis Y;
};
union KeyboardState
{
DigitalBtn keys[12];
struct {
DigitalBtn _1;
DigitalBtn _2;
DigitalBtn _3;
DigitalBtn _4;
DigitalBtn Q;
DigitalBtn E;
DigitalBtn W;
DigitalBtn A;
DigitalBtn S;
DigitalBtn D;
DigitalBtn K;
DigitalBtn L;
DigitalBtn escape;
DigitalBtn backspace;
DigitalBtn up;
DigitalBtn down;
DigitalBtn left;
DigitalBtn right;
DigitalBtn space;
DigitalBtn pause;
DigitalBtn left_alt;
DigitalBtn right_alt;
DigitalBtn right_shift;
DigitalBtn left_shift;
};
};
struct MousesState
{
DigitalBtn left;
DigitalBtn middle;
DigitalBtn right;
AnalogAxis X;
AnalogAxis Y;
AnalogAxis vertical_wheel;
AnalogAxis horizontal_wheel;
};
struct XInputPadState
{
struct
{
AnalogStick left;
AnalogStick right;
} stick;
AnalogAxis left_trigger;
AnalogAxis right_trigger;
union {
DigitalBtn btns[14];
struct {
struct {
DigitalBtn up;
DigitalBtn down;
DigitalBtn left;
DigitalBtn right;
} dpad;
DigitalBtn A;
DigitalBtn B;
DigitalBtn X;
DigitalBtn Y;
DigitalBtn back;
DigitalBtn start;
DigitalBtn left_shoulder;
DigitalBtn right_shoulder;
};
};
};
struct DualsensePadState
{
struct
{
AnalogStick left;
AnalogStick right;
} stick;
AnalogAxis L2;
AnalogAxis R2;
union {
DigitalBtn btns[14];
struct {
struct {
DigitalBtn up;
DigitalBtn down;
DigitalBtn left;
DigitalBtn right;
} dpad;
DigitalBtn cross;
DigitalBtn circle;
DigitalBtn square;
DigitalBtn triangle;
DigitalBtn share;
DigitalBtn options;
DigitalBtn L1;
DigitalBtn R1;
};
};
};
struct ControllerState
{
KeyboardState* keyboard;
MousesState* mouse;
XInputPadState* xpad;
DualsensePadState* ds_pad;
};
struct ControllerStateSnapshot
{
KeyboardState keyboard;
MousesState mouse;
XInputPadState xpad;
DualsensePadState ds_pad;
};
struct InputState
{
ControllerState controllers[4];
};
struct InputStateSnapshot
{
ControllerStateSnapshot controllers[4];
};
using InputBindCallback = void( void* );
using InputBindCallback_DigitalBtn = void( engine::DigitalBtn* button );
using InputBindCallback_AnalogAxis = void( engine::AnalogAxis* axis );
using InputBindCallback_AnalogStick = void( engine::AnalogStick* stick );
struct InputMode
{
InputBindCallback* binds;
s32 num_binds;
};
void input_mode_pop( InputMode* mode );
void input_mode_pop( InputMode* mode );
#if 0
struct RecordedInput
{
s32 num;
InputState* stream;
};
#endif
struct TileChunk
{
u32* tiles;
};
struct World struct World
{ {
// TODO(Ed) : Remove // TODO(Ed) : Remove
f32 tile_lower_left_x; f32 tile_lower_left_x;
f32 tile_lower_left_y; f32 tile_lower_left_y;
TileMap* tile_map;
u32 chunk_shift;
u32 chunk_mask;
f32 tile_size_in_meters;
s32 tile_size_in_pixels;
f32 tile_meters_to_pixels;
u32 chunk_dimension;
// TODO(Ed) : Beginner's sparseness
s32 tile_chunks_num_x;
s32 tile_chunks_num_y;
TileChunk* tile_chunks;
};
/*
This is a "backend" transient datatype for handling lookup of tile data from "chunks" of tiles.
*/
struct TileChunkPosition
{
u32 tile_chunk_x;
u32 tile_chunk_y;
// "Chunk-relative (x, y)
u32 tile_x;
u32 tile_y;
};
struct WorldPosition
{
// TODO(Ed) : Should this be from the center of the tile?
f32 x;
f32 y;
// "World-relative (x, y), AKA: Absolute Position, etc
u32 tile_x;
u32 tile_y;
}; };
NS_ENGINE_END NS_ENGINE_END

View File

@ -1,3 +0,0 @@
/*
This represents the API only accessible to the engine to fullfill for the game module.
*/

View File

@ -0,0 +1,14 @@
/*
This header exists for base shared definitions across engine files.
For now what every file needs is at least the namespace macros.
*/
#pragma once
#define NS_ENGINE_BEGIN namespace engine {
#define NS_ENGINE_END }
#ifndef Engine_API
// The build system is reponsible for defining this API macro for exporting symbols.
# define Engine_API
#endif

View File

@ -2,11 +2,14 @@
This represents the API only accessible to the platform layer to fullfill for the engine layer. This represents the API only accessible to the platform layer to fullfill for the engine layer.
*/ */
#pragma once #pragma once
#if INTELLISENSE_DIRECTIVES
#include "engine_module.hpp"
#endif
NS_ENGINE_BEGIN NS_ENGINE_BEGIN
using OnModuleRelaodFn = void( Memory* memory, platform::ModuleAPI* platform_api ); using OnModuleRelaodFn = void( Memory* memory, platform::ModuleAPI* platform_api );
using StartupFn = void( Memory* memory, platform::ModuleAPI* platform_api ); using StartupFn = void( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* platform_api );
using ShutdownFn = void( Memory* memory, platform::ModuleAPI* platform_api ); using ShutdownFn = void( Memory* memory, platform::ModuleAPI* platform_api );
// Needs a contextual reference to four things: // Needs a contextual reference to four things:

0
project/engine/input.cpp Normal file
View File

178
project/engine/input.hpp Normal file
View File

@ -0,0 +1,178 @@
#pragma once
#if INTELLISENSE_DIRECTIVES
#include "platform/platform.hpp"
#include "engine_module.hpp"
#endif
NS_ENGINE_BEGIN
struct DigitalBtn
{
s32 half_transitions;
b32 ended_down;
};
struct AnalogAxis
{
f32 start;
f32 end;
f32 min;
f32 max;
// Platform doesn't provide this, we process in the engine layer.
f32 average;
};
struct AnalogStick
{
AnalogAxis X;
AnalogAxis Y;
};
union KeyboardState
{
DigitalBtn keys[12];
struct {
DigitalBtn _1;
DigitalBtn _2;
DigitalBtn _3;
DigitalBtn _4;
DigitalBtn Q;
DigitalBtn E;
DigitalBtn W;
DigitalBtn A;
DigitalBtn S;
DigitalBtn D;
DigitalBtn K;
DigitalBtn L;
DigitalBtn escape;
DigitalBtn backspace;
DigitalBtn up;
DigitalBtn down;
DigitalBtn left;
DigitalBtn right;
DigitalBtn space;
DigitalBtn pause;
DigitalBtn left_alt;
DigitalBtn right_alt;
DigitalBtn right_shift;
DigitalBtn left_shift;
};
};
struct MousesState
{
DigitalBtn left;
DigitalBtn middle;
DigitalBtn right;
AnalogAxis X;
AnalogAxis Y;
AnalogAxis vertical_wheel;
AnalogAxis horizontal_wheel;
};
struct XInputPadState
{
struct
{
AnalogStick left;
AnalogStick right;
} stick;
AnalogAxis left_trigger;
AnalogAxis right_trigger;
union {
DigitalBtn btns[14];
struct {
struct {
DigitalBtn up;
DigitalBtn down;
DigitalBtn left;
DigitalBtn right;
} dpad;
DigitalBtn A;
DigitalBtn B;
DigitalBtn X;
DigitalBtn Y;
DigitalBtn back;
DigitalBtn start;
DigitalBtn left_shoulder;
DigitalBtn right_shoulder;
};
};
};
struct DualsensePadState
{
struct
{
AnalogStick left;
AnalogStick right;
} stick;
AnalogAxis L2;
AnalogAxis R2;
union {
DigitalBtn btns[14];
struct {
struct {
DigitalBtn up;
DigitalBtn down;
DigitalBtn left;
DigitalBtn right;
} dpad;
DigitalBtn cross;
DigitalBtn circle;
DigitalBtn square;
DigitalBtn triangle;
DigitalBtn share;
DigitalBtn options;
DigitalBtn L1;
DigitalBtn R1;
};
};
};
struct ControllerState
{
KeyboardState* keyboard;
MousesState* mouse;
XInputPadState* xpad;
DualsensePadState* ds_pad;
};
struct ControllerStateSnapshot
{
KeyboardState keyboard;
MousesState mouse;
XInputPadState xpad;
DualsensePadState ds_pad;
};
struct InputState
{
ControllerState controllers[4];
};
struct InputStateSnapshot
{
ControllerStateSnapshot controllers[4];
};
using InputBindCallback = void( void* );
using InputBindCallback_DigitalBtn = void( engine::DigitalBtn* button );
using InputBindCallback_AnalogAxis = void( engine::AnalogAxis* axis );
using InputBindCallback_AnalogStick = void( engine::AnalogStick* stick );
struct InputMode
{
InputBindCallback* binds;
s32 num_binds;
};
NS_ENGINE_END

131
project/engine/tile_map.cpp Normal file
View File

@ -0,0 +1,131 @@
#if INTELLISENSE_DIRECTIVES
#include "tile_map.hpp"
#endif
NS_ENGINE_BEGIN
inline
void cannonicalize_coord( TileMap* tile_map, u32* tile_coord, f32* pos_coord )
{
assert( tile_map != nullptr );
assert( tile_coord != nullptr );
f32 tile_size = scast(f32, tile_map->tile_size_in_meters);
// Note(Ed) : World is assumed to be a "torodial topology"
s32 offset = round( (* pos_coord) / tile_size );
u32 new_tile_coord = (* tile_coord) + offset;
f32 new_pos_coord = (* pos_coord) - scast(f32, offset) * tile_size;
assert( new_pos_coord >= -tile_size * 0.5f );
assert( new_pos_coord <= tile_size * 0.5f );
(* tile_coord) = new_tile_coord;
(* pos_coord) = new_pos_coord;
}
inline
TileMapPosition recannonicalize_position( TileMap* tile_map, TileMapPosition pos )
{
assert( tile_map != nullptr );
TileMapPosition result = pos;
cannonicalize_coord( tile_map, & result.tile_x, & result.x );
cannonicalize_coord( tile_map, & result.tile_y, & result.y );
return result;
}
inline
u32 TileChunk_get_tile_value( TileChunk* tile_chunk, TileMap* tile_map, u32 x, u32 y )
{
assert( tile_map != nullptr );
assert( tile_chunk != nullptr );
assert( x < tile_map->chunk_dimension );
assert( y < tile_map->chunk_dimension );
u32 value = tile_chunk->tiles[ (y * tile_map->chunk_dimension) + x ];
return value;
}
inline
void TileChunk_set_tile_value( TileChunk* tile_chunk, TileMap* tile_map, u32 x, u32 y , u32 value)
{
assert( tile_map != nullptr );
assert( tile_chunk != nullptr );
assert( x < tile_map->chunk_dimension );
assert( y < tile_map->chunk_dimension );
tile_chunk->tiles[ (y * tile_map->chunk_dimension) + x ] = value;
}
inline
TileChunk* TileMap_get_chunk( TileMap* tile_map, s32 tile_chunk_x, s32 tile_chunk_y )
{
TileChunk* chunk = nullptr;
if ( tile_chunk_x >= 0 && tile_chunk_x < scast(s32, tile_map->tile_chunks_num_x)
&& tile_chunk_y >= 0 && tile_chunk_y < scast(s32, tile_map->tile_chunks_num_y) )
{
chunk = & tile_map->chunks[ tile_chunk_y * tile_map->tile_chunks_num_x + tile_chunk_x ];
}
return chunk;
}
inline
TileChunkPosition get_tile_chunk_position_for( TileMap* tile_map, u32 abs_tile_x, u32 abs_tile_y )
{
assert( tile_map != nullptr );
TileChunkPosition chunk_pos {};
chunk_pos.tile_chunk_x = abs_tile_x >> tile_map->chunk_shift;
chunk_pos.tile_chunk_y = abs_tile_y >> tile_map->chunk_shift;
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;
}
u32 TileMap_get_tile_value( TileMap* tile_map, u32 tile_x, u32 tile_y )
{
assert( tile_map != nullptr );
u32 value = 0;
TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, tile_x, tile_y );
TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y );
if ( chunk )
value = TileChunk_get_tile_value( chunk, tile_map, chunk_pos.tile_x, chunk_pos.tile_y );
return value;
}
internal
b32 TileMap_is_point_empty( TileMap* tile_map, TileMapPosition position )
{
assert( tile_map != nullptr );
u32 chunk_value = TileMap_get_tile_value( tile_map, position.tile_x, position.tile_y );
b32 is_empty = chunk_value == 0;
return is_empty;
}
internal
void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, u32 abs_tile_x, u32 abs_tile_y, u32 value )
{
TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, abs_tile_x, abs_tile_y );
TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y );
#if 0
if ( chunk == nullptr )
{
}
#else
assert( chunk != nullptr );
#endif
TileChunk_set_tile_value( chunk, tile_map, chunk_pos.tile_x, chunk_pos.tile_y, value );
}
NS_ENGINE_END

View File

@ -0,0 +1,65 @@
/*
*/
#pragma once
#if INTELLISENSE_DIRECTIVES
#include "platform/platform.hpp"
#include "engine_module.hpp"
#endif
NS_ENGINE_BEGIN
struct TileChunk
{
u32* tiles;
};
/*
This is a "backend" transient datatype for handling lookup of tile data from "chunks" of tiles.
*/
struct TileChunkPosition
{
u32 tile_chunk_x;
u32 tile_chunk_y;
// "Chunk-relative (x, y)
u32 tile_x;
u32 tile_y;
};
struct TileMap
{
// TODO(Ed) : Beginner's sparseness
s32 tile_chunks_num_x;
s32 tile_chunks_num_y;
s32 tile_size_in_pixels;
f32 tile_size_in_meters;
f32 tile_meters_to_pixels;
u32 chunk_shift;
u32 chunk_mask;
u32 chunk_dimension;
TileChunk* chunks;
};
struct TileMapPosition
{
// TODO(Ed) : Should this be from the center of the tile?
f32 x;
f32 y;
// "World-relative (x, y), AKA: Absolute Position
// Fixed point tile locations.
// High bits are the tile-chunk index, and the low bits are the tile index in the chunk.
u32 tile_x;
u32 tile_y;
};
NS_ENGINE_END

View File

@ -6,7 +6,7 @@ NS_ENGINE_BEGIN
constexpr constexpr
Str const symbol_on_module_load = str_ascii("?on_module_reload@engine@@YAXPEAUMemory@1@PEAUModuleAPI@platform@@@Z"); Str const symbol_on_module_load = str_ascii("?on_module_reload@engine@@YAXPEAUMemory@1@PEAUModuleAPI@platform@@@Z");
constexpr constexpr
Str const symbol_startup = str_ascii("?startup@engine@@YAXPEAUMemory@1@PEAUModuleAPI@platform@@@Z"); Str const symbol_startup = str_ascii("?startup@engine@@YAXPEAUOffscreenBuffer@1@PEAUMemory@1@PEAUModuleAPI@platform@@@Z");
constexpr constexpr
Str const symbol_shutdown = str_ascii("?shutdown@engine@@YAXPEAUMemory@1@PEAUModuleAPI@platform@@@Z"); Str const symbol_shutdown = str_ascii("?shutdown@engine@@YAXPEAUMemory@1@PEAUModuleAPI@platform@@@Z");
constexpr constexpr

View File

@ -13,15 +13,15 @@ struct Memory
// Subscection of engine memory for the game to use. // Subscection of engine memory for the game to use.
void* persistent; void* persistent;
u64 persistent_size; ssize persistent_size;
// void* Frame; // void* Frame;
// u64 FrameSize; // u64 FrameSize;
void* transient; void* transient;
u64 transient_size; ssize transient_size;
u64 total_size() ssize total_size()
{ {
return persistent_size + transient_size; return persistent_size + transient_size;
} }
@ -74,11 +74,7 @@ struct PlayerState
f32 width; f32 width;
f32 height; f32 height;
// TODO(Ed) : Should this be canonical position now? engine::TileMapPosition position;
//f32 pos_x;
//f32 pos_y;
engine::WorldPosition position;
b32 mid_jump; b32 mid_jump;
f32 jump_time; f32 jump_time;
@ -91,7 +87,8 @@ struct PlayerActions
f32 player_x_move_analog; f32 player_x_move_analog;
f32 player_y_move_analog; f32 player_y_move_analog;
b32 jump = false; b32 sprint;
b32 jump;
}; };
struct GameState struct GameState

View File

@ -7,6 +7,7 @@ Handmade Engine Translation Unit
#include <math.h> // TEMP #include <math.h> // TEMP
#include <stdio.h> // TEMP #include <stdio.h> // TEMP
#include "platform/platform_module.hpp"
#include "platform/grime.hpp" #include "platform/grime.hpp"
#include "platform/macros.hpp" #include "platform/macros.hpp"
#include "platform/generics.hpp" #include "platform/generics.hpp"
@ -17,10 +18,14 @@ Handmade Engine Translation Unit
#include "platform/context.hpp" #include "platform/context.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "engine_module.hpp"
#include "input.hpp"
#include "tile_map.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "engine_to_platform_api.hpp" #include "engine_to_platform_api.hpp"
// Game layer headers // Game layer headers
#include "handmade.hpp" #include "handmade.hpp"
#include "tile_map.cpp"
#include "engine.cpp" #include "engine.cpp"

View File

@ -7,6 +7,7 @@ Handmade Win32 Platform Translation Unit
#include <math.h> // TEMP #include <math.h> // TEMP
#include <stdio.h> // TEMP #include <stdio.h> // TEMP
#include "platform_module.hpp"
#include "grime.hpp" #include "grime.hpp"
#include "macros.hpp" #include "macros.hpp"
#include "generics.hpp" #include "generics.hpp"
@ -18,6 +19,9 @@ Handmade Win32 Platform Translation Unit
#include "platform.hpp" #include "platform.hpp"
// Engine layer headers // Engine layer headers
#include "engine/engine_module.hpp"
#include "engine/input.hpp"
#include "engine/tile_map.hpp"
#include "engine/engine.hpp" #include "engine/engine.hpp"
#include "engine/engine_to_platform_api.hpp" #include "engine/engine_to_platform_api.hpp"
#include "gen/engine_symbol_table.hpp" #include "gen/engine_symbol_table.hpp"

View File

@ -22,7 +22,7 @@ s32 floor( f32 value )
inline inline
s32 round( f32 value ) s32 round( f32 value )
{ {
s32 result = scast(s32, value + 0.5f); s32 result = scast(s32, roundf( value ));
return result; return result;
} }

View File

@ -15,16 +15,7 @@
#define rcast( type, value ) reinterpret_cast< type >( value ) #define rcast( type, value ) reinterpret_cast< type >( value )
#define scast( type, value ) static_cast< type >( value ) #define scast( type, value ) static_cast< type >( value )
#define do_once() \ #define do_once() for ( local_persist b32 once = true; once; once = false )
do \
{ \
local_persist \
bool done = false; \
if ( done ) \
return; \
done = true; \
} \
while(0)
#define do_once_start \ #define do_once_start \
do \ do \

View File

@ -10,9 +10,9 @@
#if INTELLISENSE_DIRECTIVES #if INTELLISENSE_DIRECTIVES
// TODO(Ed) : REMOVE THESE WHEN CASEY GETS TO THEM // TODO(Ed) : REMOVE THESE WHEN CASEY GETS TO THEM
#include <math.h> // TODO : Implement math ourselves
#include <stdio.h> // TODO : Implement output logging ourselves #include <stdio.h> // TODO : Implement output logging ourselves
#include "platform_module.hpp"
#include "grime.hpp" #include "grime.hpp"
#include "macros.hpp" #include "macros.hpp"
#include "generics.hpp" #include "generics.hpp"
@ -23,9 +23,6 @@
#include "context.hpp" #include "context.hpp"
#endif #endif
#define NS_PLATFORM_BEGIN namespace platform {
#define NS_PLATFORM_END }
NS_PLATFORM_BEGIN NS_PLATFORM_BEGIN
// On-Demand platform interface. // On-Demand platform interface.
@ -121,6 +118,8 @@ struct ModuleAPI
}; };
#if Build_Development #if Build_Development
// TODO(Ed): This can't be done this way, we need a separate interface for other modules to use this.
// (At least, we need to hookup the symbols statically or at runtime somehow, and right now the only thing that does is the module api passthrough via the Engine API)
void impl_congrats( char const* message ); void impl_congrats( char const* message );
bool impl_ensure( bool condition, char const* message ); bool impl_ensure( bool condition, char const* message );
void impl_fatal( char const* message ); void impl_fatal( char const* message );

View File

@ -0,0 +1,4 @@
#pragma once
#define NS_PLATFORM_BEGIN namespace platform {
#define NS_PLATFORM_END }

View File

@ -79,10 +79,10 @@ static_assert( sizeof( u16 ) == 2, "sizeof(u16) != 2" );
static_assert( sizeof( u32 ) == 4, "sizeof(u32) != 4" ); static_assert( sizeof( u32 ) == 4, "sizeof(u32) != 4" );
static_assert( sizeof( u64 ) == 8, "sizeof(u64) != 8" ); static_assert( sizeof( u64 ) == 8, "sizeof(u64) != 8" );
typedef size_t uw; typedef size_t usize;
typedef ptrdiff_t sw; typedef ptrdiff_t ssize;
static_assert( sizeof( uw ) == sizeof( sw ), "sizeof(uw) != sizeof(sw)" ); static_assert( sizeof( usize ) == sizeof( ssize ), "sizeof(usize) != sizeof(ssize)" );
#if defined( _WIN64 ) #if defined( _WIN64 )
typedef signed __int64 sptr; typedef signed __int64 sptr;

View File

@ -135,7 +135,6 @@ timing_get_wall_clock()
return clock; return clock;
} }
#pragma endregion Timing #pragma endregion Timing
NS_PLATFORM_END NS_PLATFORM_END
#include "win32_audio.cpp" #include "win32_audio.cpp"
@ -540,8 +539,8 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
void* base_address = 0; void* base_address = 0;
#endif #endif
engine_memory.persistent = VirtualAlloc( base_address, total_size , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write ); engine_memory.persistent = rcast( Byte*, VirtualAlloc( base_address, total_size , MEM_Commit_Zeroed | MEM_Reserve, Page_Read_Write ));
engine_memory.transient = rcast( u8*, engine_memory.persistent ) + engine_memory.persistent_size; engine_memory.transient = rcast( Byte*, engine_memory.persistent ) + engine_memory.persistent_size;
#if Build_Development #if Build_Development
// First slot is for restore // First slot is for restore
@ -794,7 +793,7 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
} }
} }
engine_api.startup( & engine_memory, & platform_api ); engine_api.startup( rcast(engine::OffscreenBuffer*, & Surface_Back_Buffer.memory), & engine_memory, & platform_api );
u64 last_frame_clock = timing_get_wall_clock(); u64 last_frame_clock = timing_get_wall_clock();
u64 last_frame_cycle = __rdtsc(); u64 last_frame_cycle = __rdtsc();

View File

@ -152,6 +152,7 @@ else {
$should_format_gen = $false $should_format_gen = $false
# TODO(Ed) : Support detecting codegen changes separate from the module's runtime builds (so that it can be rebuild only when necessary as well)
function build-engine function build-engine
{ {
$should_build = check-ModuleForChanges $path_engine $should_build = check-ModuleForChanges $path_engine