Day 30 complete

This commit is contained in:
Edward R. Gonzalez 2023-10-06 13:06:40 -04:00
parent a103054023
commit dcc14d154f
13 changed files with 303 additions and 122 deletions

3
.gitignore vendored
View File

@ -19,7 +19,8 @@ build
**/*.dll **/*.dll
**/*.exe **/*.exe
**/*.pdb **/*.pdb
**/*.exe **/*.exp
**/*.lib
**/*.hmi **/*.hmi
**/*.symbols **/*.symbols

View File

@ -6,11 +6,14 @@ Any code I do for this [series](https://handmadehero.org) will be here.
## Scripts ## Scripts
* `build.ps1` - Builds the project use `.\scripts\build msvc debug` or `.\scripts\build clang debug`. * `build.ps1` - Builds the project use `.\scripts\build msvc <args> <module>` or `.\scripts\build clang <args> <module>`
* `debug` adds debug symbols, etc
* `dev` for development builds. (automatically adds debug)
* `optimize` for optimized builds. * `optimize` for optimized builds.
* `dev` for development builds. ( Dev memory layout and code paths compiled ). * `verbose` gives more info on arguments passed to tools, etc.
* `module` is the module to build, can be any of `platform` or `engine` for this point in the codebase. (Eventually game will also be a separate module)
* `clean.ps1` - Cleans the project * `clean.ps1` - Cleans the project
* `update_deps.ps1` - Updates the project dependencies to their latest from their respective repos. (Not done automatically on build) * `update_deps.ps1` - Updates the project dependencies to their latest from their respective repos.
*Make sure to run `update_deps.ps1` before building for the first time.* *Make sure to run `update_deps.ps1` before building for the first time.*
@ -20,17 +23,45 @@ Building requires msvc or llvm's clang + lld, and powershell 7
The build is done in two stages: The build is done in two stages:
1. ~~Build and run metaprogram to scan and generate dependent code.~~ (Not needed yet) 1. Build and run metaprogram to scan and generate dependent code for the module being built.
2. Build the handmade hero runtime. 2. Build the the runtime for the module.
Module build order:
1. Engine
2. Platform
## Milestone ## Milestone
Day 028: Drawing a Tile Map Day 30 : Moving Between Tile Maps
Features Done so far:
* Tailor made build system via powershell scripts
* Supports building the repo with msvc or clang
* Can stage codegen metaprograms to run before building the module
* Will automatically not run if app process is found (for engine module).
* Can emit exported mangled symbols for the engine module for hot-reload with the platform module without needing to use C linkage symbols or a complex hot-reload library (Live++, etc).
* Platform Layer:
* Direct Sound audio
* Keyboard & Mouse Input via GetAsyncKeyState & Win32 window messagng
* XInput controller support
* Dualsense controller support via joyshock library
* Software rendering via Win32 GDI
* Instantaneous hot reload of engine module
* Block Memory allocation via VirtualAlloc for engine module
* Memory mapped files for engine & game snapshots.
* Engine Layer:
* Take & load snapshots of either the engine's or game's memory state.
* 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`)
* Record & replay input.
* (WIP) : 2D Tile Map setup
## Gallery ## Gallery
![img](docs/imgs/handmade_win32_2023-10-01_20-22-20.gif) ![img](docs/imgs/handmade_win32_2023-10-01_20-22-20.gif)
![img](docs/imgs/Code_2023-10-01_19-20-56.gif)
![img](docs/imgs/Code_2023-09-28_15-14-53.gif) ![img](docs/imgs/Code_2023-09-28_15-14-53.gif)
![img](https://files.catbox.moe/ruv97s.gif)
![img](https://files.catbox.moe/9zau4s.png) ![img](https://files.catbox.moe/9zau4s.png)
![img](https://files.catbox.moe/b7ifa8.png) ![img](https://files.catbox.moe/b7ifa8.png)

7
docs/Day 030.md Normal file
View File

@ -0,0 +1,7 @@
# Day 30
Tile map stuff is looking alright. Doing my best to not clean-up the code as Casey pleads in the vods.
I would have perferred if he didn't just do one tilemap at a time and instead I would have had the current tile map and surrounding loaded at the same time (He might do this in the future). Since were aren't constrained memory wise like the old machines, we could have those loaded as well and it would make the management of the tilemaps easier (possibly...).
Looking foward to when he introduces a proper vector space for the positioning.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -382,6 +382,13 @@ output_sound( EngineState* state, AudioBuffer* sound_buffer, GetSoundSampleValue
} }
} }
inline
s32 floor_f32_to_s32( f32 value )
{
// TODO : Casey wants to use an intrinsic
return scast(s32, floorf( value ));
}
inline inline
s32 round_f32_to_s32( f32 value ) s32 round_f32_to_s32( f32 value )
{ {
@ -472,7 +479,7 @@ void startup( Memory* memory, platform::ModuleAPI* platform_api )
EngineState* state = rcast( EngineState*, memory->persistent ); EngineState* state = rcast( EngineState*, memory->persistent );
assert( sizeof(EngineState) <= memory->persistent_size ); assert( sizeof(EngineState) <= memory->persistent_size );
state->auto_snapshot_interval = 10.f; state->auto_snapshot_interval = 60.f;
state->tone_volume = 1000; state->tone_volume = 1000;
@ -489,11 +496,13 @@ void startup( Memory* memory, platform::ModuleAPI* platform_api )
state->game_memory.transient_size = memory->transient_size / 2; state->game_memory.transient_size = memory->transient_size / 2;
state->game_memory.transient = rcast(Byte*, memory->transient) + state->game_memory.transient_size; state->game_memory.transient = rcast(Byte*, memory->transient) + state->game_memory.transient_size;
hh::PlayerState* player = rcast( hh::PlayerState*, state->game_memory.persistent ); hh::GameState* game_state = rcast( hh::GameState*, state->game_memory.persistent );
assert( sizeof(hh::PlayerState) <= state->game_memory.persistent_size ); assert( sizeof(hh::GameState) <= state->game_memory.persistent_size );
player->width = 50.f; game_state->tile_map_x = 0;
player->height = 100.f; game_state->tile_map_y = 0;
hh::PlayerState* player = & game_state->player_state;
player->pos_x = 920; player->pos_x = 920;
player->pos_y = 466; player->pos_y = 466;
player->mid_jump = false; player->mid_jump = false;
@ -506,45 +515,110 @@ void shutdown( Memory* memory, platform::ModuleAPI* platform_api )
} }
inline inline
u32 tilemap_tile_value( TileMap* tile_map, s32 x, s32 y ) CanonPosition get_cannonical_position( World* world, RawPosition raw_pos )
{ {
assert( x >= 0 && x < scast(s32, tile_map->num_x) ); s32 tile_map_x = raw_pos.tile_map_x;
assert( y >= 0 && y < scast(s32, tile_map->num_y) ); s32 tile_map_y = raw_pos.tile_map_y;
return tile_map->tiles[ (y * tile_map->num_x) + x ];
f32 pos_x = ( raw_pos.x - world->tile_upper_left_x );
f32 pos_y = ( raw_pos.y - world->tile_upper_left_y );
s32 tile_x = floor_f32_to_s32( pos_x / world->tile_width );
s32 tile_y = floor_f32_to_s32( pos_y / world->tile_height );
f32 tile_rel_x = pos_x - scast(f32, tile_x) * world->tile_width;
f32 tile_rel_y = pos_y - scast(f32, tile_y) * world->tile_height;
assert( tile_rel_x >= 0.f );
assert( tile_rel_y >= 0.f );
assert( tile_rel_x < world->tile_width );
assert( tile_rel_y < world->tile_height );
/*
The puprpose of this is to be able to detect if the point is outside of the tilemap,
and if so, roll the point over to an adjacent tilemap.
For example : If the point is at x = -1, then it is outside of the tilemap, and
should be rolled over to the tilemap to the left of the current tilemap.
*/
if ( tile_x < 0 )
{
tile_x += world->num_tiles_x;
-- tile_map_x;
}
if ( tile_y < 0 )
{
tile_y += world->num_tiles_y;
-- tile_map_y;
}
if ( tile_x >= world->num_tiles_x )
{
tile_x -= world->num_tiles_x;
++ tile_map_x;
}
if ( tile_y >= world->num_tiles_y )
{
tile_y -= world->num_tiles_y;
++ tile_map_y;
}
return { tile_rel_x, tile_rel_y, tile_map_x, tile_map_y, tile_x, tile_y };
} }
inline inline
b32 tilemap_is_pos_empty( TileMap* tile_map, f32 x, f32 y ) u32 tilemap_tile_value( TileMap* tile_map, World* world, s32 x, s32 y )
{ {
s32 tile_x = truncate_f32_to_s32(( x - scast(f32, tile_map->upper_left_X)) / scast(f32, tile_map->width) ); assert( tile_map != nullptr );
s32 tile_y = truncate_f32_to_s32(( y - scast(f32, tile_map->upper_left_Y)) / scast(f32, tile_map->height) ); assert( world != nullptr );
assert( x >= 0 && x < scast(s32, world->num_tiles_x) );
assert( y >= 0 && y < scast(s32, world->num_tiles_y) );
return tile_map->tiles[ (y * world->num_tiles_x) + x ];
}
inline
b32 tilemap_is_point_empty( TileMap* tile_map, World* world, s32 tile_x, s32 tile_y )
{
assert( tile_map != nullptr );
assert( world != nullptr );
// Assume space is occupied if there is bad data
if ( tile_map == nullptr )
return false;
b32 is_empty = false; b32 is_empty = false;
if ( tile_x >= 0 && tile_x < scast(s32, tile_map->num_x) if ( tile_x >= 0 && tile_x < world->num_tiles_x
&& tile_y >= 0 && tile_y < scast(s32, tile_map->num_y) ) && tile_y >= 0 && tile_y < world->num_tiles_y )
{ {
u32 tile_value = tilemap_tile_value( tile_map, tile_x, tile_y ); u32 tile_value = tilemap_tile_value( tile_map, world, tile_x, tile_y );
is_empty = tile_value == 0; is_empty = tile_value == 0;
} }
return is_empty; return is_empty;
} }
inline inline
TileMap* world_tilemap( World* world, s32 x, s32 y ) TileMap* world_get_tilemap( World* world, s32 tile_map_x, s32 tile_map_y )
{ {
assert( x >= 0 && x < world->tilemaps_num_x ); assert( tile_map_x >= 0 && tile_map_x < world->tilemaps_num_x );
assert( y >= 0 && y < world->tilemaps_num_y ); assert( tile_map_y >= 0 && tile_map_y < world->tilemaps_num_y );
return & world->tile_maps[ (y * world->tilemaps_num_x) + x ]; return & world->tile_maps[ (tile_map_y * world->tilemaps_num_x) + tile_map_x ];
} }
internal internal
b32 world_is_pos_empty( World* world, s32 tm_x, s32 tm_y, f32 x, f32 y ) b32 world_is_point_empty( World* world, RawPosition raw_pos )
{ {
return false; assert( world != nullptr );
b32 is_empty = false;
CanonPosition position = get_cannonical_position( world, raw_pos );
TileMap* tile_map = world_get_tilemap( world, position.tile_map_x, position.tile_map_y );
is_empty = tilemap_is_point_empty( tile_map, world, position.tile_x, position.tile_y );
return is_empty;
} }
Engine_API Engine_API
// TODO : I rather expose the back_buffer and sound_buffer using getters for access in any function.
void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back_buffer void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back_buffer
, Memory* memory, platform::ModuleAPI* platform_api, ThreadContext* thread ) , Memory* memory, platform::ModuleAPI* platform_api, ThreadContext* thread )
{ {
@ -684,11 +758,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
} }
#endif #endif
hh::PlayerState* player = rcast( hh::PlayerState*, state->game_memory.persistent ); hh::GameState* game_state = rcast( hh::GameState*, state->game_memory.persistent );
assert( sizeof(hh::PlayerState) <= state->game_memory.persistent_size ); hh::PlayerState* player = & game_state->player_state;
f32 half_width = player->width / 2.f;
f32 quater_height = player->height / 4.f;
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);
@ -696,70 +767,83 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
constexpr s32 tile_map_num_x = 16; constexpr s32 tile_map_num_x = 16;
constexpr s32 tile_map_num_y = 9; constexpr s32 tile_map_num_y = 9;
// tiles_XY
u32 tiles_00 [tile_map_num_y][tile_map_num_x] = { u32 tiles_00 [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, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 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, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
}; };
u32 tiles_10 [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, 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 },
{ 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, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};
u32 tiles_01 [tile_map_num_y][tile_map_num_x] = { u32 tiles_01 [tile_map_num_y][tile_map_num_x] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 0, 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, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 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, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
}; };
u32 tiles_10 [tile_map_num_y][tile_map_num_x] = { u32 tiles_11 [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, 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 },
{ 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 },
};
u32 tiles_11 [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, 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 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, { 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, 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 },
}; };
TileMap tile_maps[2][2] {}; TileMap tile_maps[2][2] {};
tile_maps[0][0].upper_left_X = 0;
tile_maps[0][0].upper_left_Y = 0;
tile_maps[0][0].width = 80;
tile_maps[0][0].height = 80;
tile_maps[0][0].num_x = tile_map_num_x;
tile_maps[0][0].num_y = tile_map_num_y;
tile_maps[0][0].tiles = rcast(u32*, tiles_00); tile_maps[0][0].tiles = rcast(u32*, tiles_00);
tile_maps[0][1].tiles = rcast(u32*, tiles_10);
tile_maps[0][1] = tile_maps[0][0]; tile_maps[1][0].tiles = rcast(u32*, tiles_01);
tile_maps[0][1].tiles = rcast(u32*, tiles_01);
tile_maps[1][0] = tile_maps[0][0];
tile_maps[1][0].tiles = rcast(u32*, tiles_10);
tile_maps[1][1] = tile_maps[0][0];
tile_maps[1][1].tiles = rcast(u32*, tiles_11); tile_maps[1][1].tiles = rcast(u32*, tiles_11);
s32 current_tile_map_id[2] = { 0, 0 }; World world;
TileMap* current_tile_map = & tile_maps[current_tile_map_id[0] ][current_tile_map_id[1] ]; world.num_tiles_x = tile_map_num_x;
world.num_tiles_y = tile_map_num_y;
f32 scale = 85;
world.tile_width = scale;
world.tile_height = scale * 1.05f;
world.tile_upper_left_x = -(world.tile_width * 0.5f);
world.tile_upper_left_y = -(world.tile_height * 0.5f);
world.tilemaps_num_x = 2;
world.tilemaps_num_y = 2;
world.tile_maps = rcast(TileMap*, tile_maps);
TileMap* current_tile_map = world_get_tilemap( & world, game_state->tile_map_x, game_state->tile_map_y );
assert( current_tile_map != nullptr );
player->width = world.tile_width * 0.75f;
player->height = world.tile_height;
f32 player_half_width = player->width / 2.f;
f32 player_quarter_height = player->height / 4.f;
input_poll_player_actions( input, & player_actions ); input_poll_player_actions( input, & player_actions );
{ {
@ -779,16 +863,35 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
} }
new_player_pos_y += sinf( player->jump_time * TAU ) * 200.f * delta_time; new_player_pos_y += sinf( player->jump_time * TAU ) * 200.f * delta_time;
b32 valid_new_pos = b32 valid_new_pos = true;
tilemap_is_pos_empty( current_tile_map, new_player_pos_x - half_width, new_player_pos_y - quater_height ) {
&& tilemap_is_pos_empty( current_tile_map, new_player_pos_x + half_width, new_player_pos_y - quater_height ) RawPosition test_pos = { new_player_pos_x - player_half_width, new_player_pos_y - player_quarter_height, game_state->tile_map_x, game_state->tile_map_y };
&& tilemap_is_pos_empty( current_tile_map, new_player_pos_x - half_width, new_player_pos_y )
&& tilemap_is_pos_empty( current_tile_map, new_player_pos_x + half_width, new_player_pos_y ); valid_new_pos &= world_is_point_empty( & world, test_pos );
test_pos.x = new_player_pos_x + player_half_width;
valid_new_pos &= world_is_point_empty( & world, test_pos );
test_pos.x = new_player_pos_x - player_half_width;
test_pos.y = new_player_pos_y;
valid_new_pos &= world_is_point_empty( & world, test_pos );
test_pos.x = new_player_pos_x + player_half_width;
valid_new_pos &= world_is_point_empty( & world, test_pos );
}
if ( valid_new_pos ) if ( valid_new_pos )
{ {
player->pos_x = new_player_pos_x; RawPosition raw_pos = { new_player_pos_x, new_player_pos_y, game_state->tile_map_x, game_state->tile_map_y };
player->pos_y = new_player_pos_y; CanonPosition canon_pos = get_cannonical_position( & world, raw_pos);
game_state->tile_map_x = canon_pos.tile_map_x;
game_state->tile_map_y = canon_pos.tile_map_y;
// current_tile_map = world_get_tilemap( & world, game_state->tile_map_x, game_state->tile_map_y );
player->pos_x = world.tile_upper_left_x + world.tile_width * scast(f32, canon_pos.tile_x) + canon_pos.x;
player->pos_y = world.tile_upper_left_y + world.tile_height * scast(f32, canon_pos.tile_y) + canon_pos.y;
} }
// player_tile_x // player_tile_x
@ -821,7 +924,7 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
{ {
for ( s32 col = 0; col < 16; ++ col ) for ( s32 col = 0; col < 16; ++ col )
{ {
u32 tileID = tilemap_tile_value( & tile_maps[0][0], col, row ); u32 tileID = tilemap_tile_value( current_tile_map, & world, col, row );
f32 grey[3] = { 0.15f, 0.15f, 0.15f }; f32 grey[3] = { 0.15f, 0.15f, 0.15f };
if ( tileID == 1 ) if ( tileID == 1 )
@ -831,10 +934,10 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
grey[2] = 0.22f; grey[2] = 0.22f;
} }
f32 min_x = current_tile_map->upper_left_X + scast(f32, col) * current_tile_map->width; f32 min_x = world.tile_upper_left_x + scast(f32, col) * world.tile_width;
f32 min_y = current_tile_map->upper_left_Y + scast(f32, row) * current_tile_map->height; f32 min_y = world.tile_upper_left_y + scast(f32, row) * world.tile_height;
f32 max_x = min_x + current_tile_map->width; f32 max_x = min_x + world.tile_width;
f32 max_y = min_y + current_tile_map->height; f32 max_y = min_y + world.tile_height;
draw_rectangle( back_buffer draw_rectangle( back_buffer
, min_x, min_y , min_x, min_y
@ -849,8 +952,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
f32 player_blue = 0.3f; f32 player_blue = 0.3f;
draw_rectangle( back_buffer draw_rectangle( back_buffer
, player->pos_x - half_width, player->pos_y - player->height , player->pos_x - player_half_width, player->pos_y - player->height
, player->pos_x + half_width, player->pos_y , player->pos_x + player_half_width, player->pos_y
, player_red, player_green, player_blue ); , player_red, player_green, player_blue );
// Auto-Snapshot percent bar // Auto-Snapshot percent bar

View File

@ -277,20 +277,20 @@ struct RecordedInput
struct TileMap struct TileMap
{ {
f32 upper_left_X;
f32 upper_left_Y;
f32 width;
f32 height;
s32 num_x;
s32 num_y;
u32* tiles; u32* tiles;
}; };
struct World struct World
{ {
f32 tile_upper_left_x;
f32 tile_upper_left_y;
f32 tile_width;
f32 tile_height;
s32 num_tiles_x; // Number of tiles on the x-axis for a tilemap.
s32 num_tiles_y; // Number of tiles on the y-axis for a tilemap.
// TODO(Ed) : Beginner's sparseness // TODO(Ed) : Beginner's sparseness
s32 tilemaps_num_x; s32 tilemaps_num_x;
s32 tilemaps_num_y; s32 tilemaps_num_y;
@ -298,4 +298,29 @@ struct World
TileMap* tile_maps; TileMap* tile_maps;
}; };
struct CanonPosition
{
// Note: Tile-Relative position
// TODO(Ed) : These are still in pixels
f32 x;
f32 y;
s32 tile_map_x;
s32 tile_map_y;
s32 tile_x;
s32 tile_y;
};
// TODO(Ed) : Is this necessary?
struct RawPosition
{
// Note: TileMap-Relative position
f32 x;
f32 y;
s32 tile_map_x;
s32 tile_map_y;
};
NS_ENGINE_END NS_ENGINE_END

View File

@ -73,6 +73,7 @@ struct PlayerState
f32 width; f32 width;
f32 height; f32 height;
// TODO(Ed) : Should this be canonical position now?
f32 pos_x; f32 pos_x;
f32 pos_y; f32 pos_y;
@ -90,4 +91,12 @@ struct PlayerActions
b32 jump = false; b32 jump = false;
}; };
struct GameState
{
s32 tile_map_x;
s32 tile_map_y;
PlayerState player_state;
};
NS_HANDMADE_END NS_HANDMADE_END

View File

@ -7,6 +7,7 @@
#pragma warning( disable: 5105 ) #pragma warning( disable: 5105 )
#pragma warning( disable: 4820 ) #pragma warning( disable: 4820 )
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h> #include <windows.h>
#include <xinput.h> #include <xinput.h>
#include <mmeapi.h> #include <mmeapi.h>

View File

@ -642,8 +642,8 @@ WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int sho
} }
window_handle = CreateWindowExW( window_handle = CreateWindowExW(
WS_EX_LAYERED | WS_EX_TOPMOST, // WS_EX_LAYERED | WS_EX_TOPMOST,
// WS_EX_LAYERED, WS_EX_LAYERED,
window_class.lpszClassName, window_class.lpszClassName,
L"Handmade Hero", L"Handmade Hero",
WS_Overlapped_Window | WS_Initially_Visible, WS_Overlapped_Window | WS_Initially_Visible,

View File

@ -1,6 +1,4 @@
if ( $CursorPosition ) { Clear-Host
Clear-Host
}
$target_arch = Join-Path $PSScriptRoot 'helpers/target_arch.psm1' $target_arch = Join-Path $PSScriptRoot 'helpers/target_arch.psm1'
$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1' $devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
@ -13,8 +11,6 @@ $path_build = Join-Path $path_root 'build'
Import-Module $target_arch Import-Module $target_arch
Import-Module $format_cpp Import-Module $format_cpp
Push-Location $path_root
#region Arguments #region Arguments
$vendor = $null $vendor = $null
$optimize = $null $optimize = $null
@ -49,6 +45,8 @@ if ( $args ) { $args | ForEach-Object {
. $config_toolchain . $config_toolchain
#region Building #region Building
write-host "Building HandmadeHero with $vendor"
$path_project = Join-Path $path_root 'project' $path_project = Join-Path $path_root 'project'
$path_data = Join-Path $path_root 'data' $path_data = Join-Path $path_root 'data'
$path_binaries = Join-Path $path_data 'binaries' $path_binaries = Join-Path $path_data 'binaries'
@ -140,7 +138,7 @@ function build-engine
$unit = Join-Path $path_project 'handmade_engine.cpp' $unit = Join-Path $path_project 'handmade_engine.cpp'
$dynamic_library = Join-Path $path_binaries 'handmade_engine.dll' $dynamic_library = Join-Path $path_binaries 'handmade_engine.dll'
build-simple $includes $compiler_args $linker_args $unit $dynamic_library build-simple $path_build $includes $compiler_args $linker_args $unit $dynamic_library
Remove-Item $path_pdb_lock -Force Remove-Item $path_pdb_lock -Force
@ -233,7 +231,7 @@ function build-engine
$unit = Join-Path $path_codegen 'engine_postbuild_gen.cpp' $unit = Join-Path $path_codegen 'engine_postbuild_gen.cpp'
$executable = Join-Path $path_build 'engine_postbuild_gen.exe' $executable = Join-Path $path_build 'engine_postbuild_gen.exe'
build-simple $includes $compiler_args $linker_args $unit $executable build-simple $path_build $includes $compiler_args $linker_args $unit $executable
Push-Location $path_build Push-Location $path_build
$time_taken = Measure-Command { $time_taken = Measure-Command {
@ -279,7 +277,7 @@ function build-platform
$unit = Join-Path $path_codegen 'platform_gen.cpp' $unit = Join-Path $path_codegen 'platform_gen.cpp'
$executable = Join-Path $path_build 'platform_gen.exe' $executable = Join-Path $path_build 'platform_gen.exe'
build-simple $includes $compiler_args $linker_args $unit $executable build-simple $path_build $includes $compiler_args $linker_args $unit $executable $path_build
Push-Location $path_platform Push-Location $path_platform
$time_taken = Measure-Command { $time_taken = Measure-Command {
@ -308,14 +306,14 @@ function build-platform
$lib_jsl, $lib_jsl,
$flag_link_win_subsystem_windows $flag_link_win_subsystem_windows,
$flag_link_optimize_references $flag_link_optimize_references
) )
$unit = Join-Path $path_project 'handmade_win32.cpp' $unit = Join-Path $path_project 'handmade_win32.cpp'
$executable = Join-Path $path_binaries 'handmade_win32.exe' $executable = Join-Path $path_binaries 'handmade_win32.exe'
build-simple $includes $compiler_args $linker_args $unit $executable build-simple $path_build $includes $compiler_args $linker_args $unit $executable
# if ( Test-Path $executable ) # if ( Test-Path $executable )
# { # {

Binary file not shown.

View File

@ -7,11 +7,9 @@ if ($IsWindows) {
if ( $vendor -eq $null ) { if ( $vendor -eq $null ) {
write-host "No vendor specified, assuming clang available" write-host "No vendor specified, assuming clang available"
$compiler = "clang" $vendor = "clang"
} }
write-host "Building HandmadeHero with $vendor"
if ( $dev ) { if ( $dev ) {
if ( $debug -eq $null ) { if ( $debug -eq $null ) {
$debug = $true $debug = $true
@ -133,6 +131,8 @@ if ( $vendor -match "clang" )
$flag_set_stack_size = '-stack=' $flag_set_stack_size = '-stack='
$flag_syntax_only = '-fsyntax-only' $flag_syntax_only = '-fsyntax-only'
$flag_target_arch = '-target' $flag_target_arch = '-target'
$flag_time_trace = '-ftime-trace'
$flag_verbose = '-v'
$flag_wall = '-Wall' $flag_wall = '-Wall'
$flag_warning = '-W' $flag_warning = '-W'
$flag_warnings_as_errors = '-Werror' $flag_warnings_as_errors = '-Werror'
@ -155,16 +155,15 @@ if ( $vendor -match "clang" )
# 'libucrt', # 'libucrt',
'libcmt' # For the C Runtime (Static Linkage) 'libcmt' # For the C Runtime (Static Linkage)
) )
function build-simple function build-simple
{ {
param( [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary ) param( [string]$path_output, [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary )
#Write-Host "build-simple: clang" #Write-Host "build-simple: clang"
$object = $unit -replace '\.cpp', '.obj' $object = $unit -replace '\.cpp', '.obj'
$map = $unit -replace '\.cpp', '.map' $map = $unit -replace '\.cpp', '.map'
$object = join-path $path_build (split-path $object -Leaf) $object = join-path $path_output (split-path $object -Leaf)
$map = join-path $path_build (split-path $map -Leaf) $map = join-path $path_output (split-path $map -Leaf)
# The PDB file has to also be time-stamped so that we can reload the DLL at runtime # The PDB file has to also be time-stamped so that we can reload the DLL at runtime
$pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb" $pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb"
@ -174,11 +173,15 @@ if ( $vendor -match "clang" )
$flag_exceptions_disabled, $flag_exceptions_disabled,
$flag_target_arch, $target_arch, $flag_target_arch, $target_arch,
$flag_wall, $flag_wall,
$flag_preprocess_on_intergrated, $flag_preprocess_non_intergrated,
# $flag_section_data, # $flag_section_data,
# $flag_section_functions, # $flag_section_functions,
( $flag_path_output + $object ) ( $flag_path_output + $object )
) )
if ( $verbose ) {
# $compiler_args += $flag_verbose
# $compiler_args += $flag_time_trace
}
if ( $optimize ) { if ( $optimize ) {
$compiler_args += $flag_optimize_fast $compiler_args += $flag_optimize_fast
} }
@ -278,13 +281,13 @@ if ( $vendor -match "msvc" )
# This works because this project uses a single unit to build # This works because this project uses a single unit to build
function build-simple function build-simple
{ {
param( [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary ) param( [string]$path_output, [array]$includes, [array]$compiler_args, [array]$linker_args, [string]$unit, [string]$binary )
#Write-Host "build-simple: msvc" #Write-Host "build-simple: msvc"
$object = $unit -replace '\.(cpp)$', '.obj' $object = $unit -replace '\.(cpp)$', '.obj'
$map = $unit -replace '\.(cpp)$', '.map' $map = $unit -replace '\.(cpp)$', '.map'
$object = join-path $path_build (split-path $object -Leaf) $object = join-path $path_output (split-path $object -Leaf)
$map = join-path $path_build (split-path $map -Leaf) $map = join-path $path_output (split-path $map -Leaf)
# The PDB file has to also be time-stamped so that we can reload the DLL at runtime # The PDB file has to also be time-stamped so that we can reload the DLL at runtime
$pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb" $pdb = $binary -replace '\.(exe|dll)$', "_$(get-random).pdb"
@ -297,10 +300,13 @@ if ( $vendor -match "msvc" )
$flag_RTTI_disabled, $flag_RTTI_disabled,
$flag_preprocess_conform, $flag_preprocess_conform,
$flag_full_src_path, $flag_full_src_path,
( $flag_path_interm + $path_build + '\' ), ( $flag_path_interm + $path_output + '\' ),
( $flag_path_output + $path_build + '\' ) ( $flag_path_output + $path_output + '\' )
) )
if ( $verbose ) {
}
if ( $optimize ) { if ( $optimize ) {
$compiler_args += $flag_optimize_fast $compiler_args += $flag_optimize_fast
} }
@ -312,7 +318,7 @@ if ( $vendor -match "msvc" )
{ {
$compiler_args += $flag_debug $compiler_args += $flag_debug
$compiler_args += ( $flag_define + 'Build_Debug=1' ) $compiler_args += ( $flag_define + 'Build_Debug=1' )
$compiler_args += ( $flag_path_debug + $path_build + '\' ) $compiler_args += ( $flag_path_debug + $path_output + '\' )
$compiler_args += $flag_link_win_rt_static_debug $compiler_args += $flag_link_win_rt_static_debug
if ( $optimize ) { if ( $optimize ) {

View File

@ -8,7 +8,7 @@ function format-cpp
Write-Host "Beginning format" Write-Host "Beginning format"
$formatParams = @( $formatParams = @(
'-i' # In-place '-i' # In-place
'-style=file:./scripts/.clang-format' '-style=file:.clang-format'
'-verbose' '-verbose'
) )