mirror of
https://github.com/Ed94/HandmadeHero.git
synced 2024-12-22 06:14:45 -08:00
Day 34 complete!!!
This commit is contained in:
parent
7958fabd00
commit
a4f07c67d2
2
.vscode/bookmarks.json
vendored
2
.vscode/bookmarks.json
vendored
@ -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"
|
||||||
}
|
}
|
||||||
|
@ -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
6
docs/Day 034.md
Normal 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.
|
BIN
docs/imgs/handmade_win32_2023-10-11_23-39-57.gif
Normal file
BIN
docs/imgs/handmade_win32_2023-10-11_23-39-57.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 328 KiB |
@ -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"
|
||||||
|
|
||||||
|
@ -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,7 +131,8 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
|
|||||||
{
|
{
|
||||||
DualsensePadState* pad = controller->ds_pad;
|
DualsensePadState* pad = controller->ds_pad;
|
||||||
|
|
||||||
actions->jump |= pressed( pad->cross );
|
actions->sprint |= pressed( pad->circle );
|
||||||
|
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;
|
||||||
actions->player_y_move_analog += pad->stick.left.Y.end;
|
actions->player_y_move_analog += pad->stick.left.Y.end;
|
||||||
@ -130,7 +141,8 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
|
|||||||
{
|
{
|
||||||
XInputPadState* pad = controller->xpad;
|
XInputPadState* pad = controller->xpad;
|
||||||
|
|
||||||
actions->jump |= pressed( pad->A );
|
actions->sprint |= pressed( pad->B );
|
||||||
|
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;
|
||||||
actions->player_y_move_analog += pad->stick.left.Y.end;
|
actions->player_y_move_analog += pad->stick.left.Y.end;
|
||||||
@ -139,7 +151,8 @@ void input_poll_player_actions( InputState* input, hh::PlayerActions* actions )
|
|||||||
if ( controller->keyboard )
|
if ( controller->keyboard )
|
||||||
{
|
{
|
||||||
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,14 +690,17 @@ 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;
|
f32 min_x = center_x - tile_size_in_pixels * 0.5f;
|
||||||
|
f32 min_y = center_y - tile_size_in_pixels * 0.5f;
|
||||||
|
f32 max_x = center_x + tile_size_in_pixels * 0.5f;
|
||||||
|
f32 max_y = center_y + tile_size_in_pixels * 0.5f;
|
||||||
|
|
||||||
draw_rectangle( back_buffer
|
draw_rectangle( back_buffer
|
||||||
, min_x, max_y
|
, min_x, min_y
|
||||||
, max_x, min_y
|
, max_x, max_y
|
||||||
, color[0], color[1], color[2] );
|
, color[0], color[1], color[2] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -739,88 +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 = center_x + scast(f32, player->position.tile_x) * world.tile_meters_to_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 = center_y - scast(f32, player->position.tile_y) * world.tile_meters_to_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 = center_x + player->position.x * world.tile_meters_to_pixels;
|
f32 player_screen_pos_x = screen_center_x;
|
||||||
f32 player_screen_pos_y = center_y - 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;
|
// 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
|
|
||||||
|
|
||||||
// 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
|
|
||||||
, min_x, min_y
|
|
||||||
, max_x, max_y
|
|
||||||
//, min_x, max_y
|
|
||||||
//, max_x, min_y
|
|
||||||
, 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Player
|
|
||||||
f32 player_red = 0.7f;
|
|
||||||
f32 player_green = 0.7f;
|
|
||||||
f32 player_blue = 0.3f;
|
|
||||||
|
|
||||||
f32 player_tile_x_offset = scast(f32, player->position.tile_x * world.tile_size_in_pixels);
|
|
||||||
f32 player_tile_y_offset = -scast(f32, player->position.tile_y * world.tile_size_in_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_y = world.tile_lower_left_y + player_tile_y_offset - player->position.y * world.tile_meters_to_pixels;
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
// Auto-Snapshot percent bar
|
// Auto-Snapshot percent bar
|
||||||
if (1)
|
if (1)
|
||||||
|
@ -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
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
/*
|
|
||||||
This represents the API only accessible to the engine to fullfill for the game module.
|
|
||||||
*/
|
|
14
project/engine/engine_module.hpp
Normal file
14
project/engine/engine_module.hpp
Normal 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
|
@ -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
0
project/engine/input.cpp
Normal file
178
project/engine/input.hpp
Normal file
178
project/engine/input.hpp
Normal 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
131
project/engine/tile_map.cpp
Normal 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
|
65
project/engine/tile_map.hpp
Normal file
65
project/engine/tile_map.hpp
Normal 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
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 \
|
||||||
|
@ -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 );
|
||||||
|
4
project/platform/platform_module.hpp
Normal file
4
project/platform/platform_module.hpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define NS_PLATFORM_BEGIN namespace platform {
|
||||||
|
#define NS_PLATFORM_END }
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user