Day 39 complete

This commit is contained in:
Edward R. Gonzalez 2023-10-21 22:21:53 -04:00
parent e721ee0536
commit 193b71ff92
9 changed files with 261 additions and 85 deletions

View File

@ -33,7 +33,7 @@ Module build order:
## Milestone ## Milestone
Day 38 : Basic Linear Bitmap Blending Day 39 : Basic Bitmap Rendering Cleanup
Features Done so far: Features Done so far:
@ -59,12 +59,16 @@ Features Done so far:
* Record & replay input. * Record & replay input.
* WIP : 2.5D Tile Map * WIP : 2.5D Tile Map
* Virtualized into chunks * Virtualized into chunks
* Some basic collision detection & math (pre-math coverage by Casey)
* Bitmap file loading * Bitmap file loading
* Compression mode 3 * Compression mode 3
* Linear alpha blending * Basic rendering
* Linear alpha blending
* Anchored to center position
## Gallery ## Gallery
![img](docs/imgs/handmade_win32_2023-10-21_22-18-47.gif)
![img](docs/imgs/handmade_win32_2023-10-21_02-16-43.png) ![img](docs/imgs/handmade_win32_2023-10-21_02-16-43.png)
![img](docs/imgs/handmade_win32_2023-10-20_23-14-37.png) ![img](docs/imgs/handmade_win32_2023-10-20_23-14-37.png)
![img](docs/imgs/Code_2023-10-20_21-57-06.png) ![img](docs/imgs/Code_2023-10-20_21-57-06.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 46 KiB

18
docs/Day 039.md Normal file
View File

@ -0,0 +1,18 @@
# Day 39
My `draw_bitmap` proc has been already setup to have the position specified
from the assumped position of the center of the image.
Its how I'm used to anchoring images by default so thats why I decided to go with it.
Casey however is using the corner however...
and then is doing some offset alignment based on what he sees for the coordinates on GIMP..
I decided to hand calibrate the alignment by eye. Since I already have it centered on X, the `align_x` could
stay zeroed for now and all I needed to do was align_y.
I also did not do the difference using a `tile_map_diff` like he did,
I just returned a tile_map_position and switch the map coodinates to be signed
(which tbh is fine I'll just adjust the math later when I need to).
I'm assuming it won't matter because the tile map setup we currently have is before he revamps the project with proper
vector math data structures, and he might switch to signed coordinates for them in the stream.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@ -249,8 +249,8 @@ void draw_bitmap( OffscreenBuffer* buffer
s32 max_x = round( pos_x ) + half_width; s32 max_x = round( pos_x ) + half_width;
s32 max_y = round( pos_y ) + half_height; s32 max_y = round( pos_y ) + half_height;
s32 bmp_start_x = min_x < 0 ? min_x * -1 : 0; s32 bmp_offset_x = min_x < 0 ? min_x * -1 : 0;
u32 bmp_start_y = min_y < 0 ? bitmap->height + min_y - 1 : bitmap->height - 1; u32 bmp_offset_y = min_y < 0 ? bitmap->height + min_y - 1 : bitmap->height - 1;
s32 buffer_width = buffer->width; s32 buffer_width = buffer->width;
s32 buffer_height = buffer->height; s32 buffer_height = buffer->height;
@ -268,12 +268,12 @@ void draw_bitmap( OffscreenBuffer* buffer
u8* dst_row = rcast(u8*, buffer->memory ) u8* dst_row = rcast(u8*, buffer->memory )
+ min_x * buffer->bytes_per_pixel + min_x * buffer->bytes_per_pixel
+ min_y * buffer->pitch; + min_y * buffer->pitch;
u32* src_row = bitmap->pixels + bitmap->width * (bitmap->height - 1); u32* src_row = bitmap->pixels + bitmap->width * bmp_offset_y;
for ( s32 y = min_y; y < max_y; ++ y ) for ( s32 y = min_y; y < max_y; ++ y )
{ {
u32* dst = rcast(u32*, dst_row); u32* dst = rcast(u32*, dst_row);
u32* src = src_row; u32* src = src_row + bmp_offset_x;
for ( s32 x = min_x; x < max_x; ++ x ) for ( s32 x = min_x; x < max_x; ++ x )
{ {
@ -418,8 +418,8 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
state->x_offset = 0; state->x_offset = 0;
state->y_offset = 0; state->y_offset = 0;
state->sample_wave_switch = false; state->sample_wave_switch = false;
state->wave_tone_hz = 60; state->wave_tone_hz = 60;
state->sample_wave_sine_time = 0.f; state->sample_wave_sine_time = 0.f;
state->renderer_paused = false; state->renderer_paused = false;
@ -457,7 +457,7 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
//tile_map->chunks = & temp_chunk; //tile_map->chunks = & temp_chunk;
tile_map->tile_size_in_meters = 1.4f; tile_map->tile_size_in_meters = 1.4f;
world->tile_size_in_pixels = 85; world->tile_size_in_pixels = 80;
world->tile_meters_to_pixels = scast(f32, world->tile_size_in_pixels) / tile_map->tile_size_in_meters; world->tile_meters_to_pixels = scast(f32, world->tile_size_in_pixels) / tile_map->tile_size_in_meters;
f32 tile_size_in_pixels = scast(f32, world->tile_size_in_pixels); f32 tile_size_in_pixels = scast(f32, world->tile_size_in_pixels);
@ -465,8 +465,8 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
world->tile_lower_left_x = -( tile_size_in_pixels * 0.5f); 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); world->tile_lower_left_y = +( tile_size_in_pixels * 0.25f) + scast(f32, back_buffer->height);
u32 tiles_per_screen_x = 17; world->tiles_per_screen_x = 17;
u32 tiles_per_screen_y = 9; world->tiles_per_screen_y = 9;
u32 screen_x = 0; u32 screen_x = 0;
u32 screen_y = 0; u32 screen_y = 0;
@ -518,23 +518,23 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
door_top = true; door_top = true;
} }
for (u32 tile_y = 0; tile_y < tiles_per_screen_y; ++ tile_y ) for (s32 tile_y = 0; tile_y < world->tiles_per_screen_y; ++ tile_y )
{ {
for ( u32 tile_x = 0; tile_x < tiles_per_screen_x; ++ tile_x ) for ( s32 tile_x = 0; tile_x < world->tiles_per_screen_x; ++ tile_x )
{ {
u32 abs_tile_x = screen_x * tiles_per_screen_x + tile_x; s32 abs_tile_x = screen_x * world->tiles_per_screen_x + tile_x;
u32 abs_tile_y = screen_y * tiles_per_screen_y + tile_y; s32 abs_tile_y = screen_y * world->tiles_per_screen_y + tile_y;
u32 tile_value = 1; s32 tile_value = 1;
bool in_middle_x = tile_x == (tiles_per_screen_x / 2); bool in_middle_x = tile_x == (world->tiles_per_screen_x / 2);
bool in_middle_y = tile_y == (tiles_per_screen_y / 2); bool in_middle_y = tile_y == (world->tiles_per_screen_y / 2);
bool on_right = tile_x == (tiles_per_screen_x - 1); bool on_right = tile_x == (world->tiles_per_screen_x - 1);
bool on_left = tile_x == 0; bool on_left = tile_x == 0;
bool on_bottom = tile_y == 0; bool on_bottom = tile_y == 0;
bool on_top = tile_y == (tiles_per_screen_y - 1); bool on_top = tile_y == (world->tiles_per_screen_y - 1);
if ( on_left && (! in_middle_y || ! door_left )) if ( on_left && (! in_middle_y || ! door_left ))
{ {
@ -615,19 +615,19 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
// Personally made assets // Personally made assets
{ {
StrPath path_test_bg; StrPath path_test_bg {};
path_test_bg.concat( platform_api->path_content, str_ascii("test_background.bmp") ); path_test_bg.concat( platform_api->path_content, str_ascii("test_background.bmp") );
game_state->test_bg = load_bmp( platform_api, path_test_bg ); game_state->test_bg = load_bmp( platform_api, path_test_bg );
StrPath path_mojito; StrPath path_mojito {};
path_mojito.concat( platform_api->path_content, str_ascii("mojito.bmp") ); path_mojito.concat( platform_api->path_content, str_ascii("mojito.bmp") );
game_state->mojito = load_bmp( platform_api, path_mojito ); game_state->mojito = load_bmp( platform_api, path_mojito );
StrPath path_mojito_head; StrPath path_mojito_head {};
path_mojito_head.concat( platform_api->path_content, str_ascii("mojito_head.bmp") ); path_mojito_head.concat( platform_api->path_content, str_ascii("mojito_head.bmp") );
game_state->mojito_head = load_bmp( platform_api, path_mojito_head ); game_state->mojito_head = load_bmp( platform_api, path_mojito_head );
StrPath path_debug_bitmap; StrPath path_debug_bitmap {};
path_debug_bitmap.concat( platform_api->path_content, str_ascii("debug_bitmap2.bmp") ); path_debug_bitmap.concat( platform_api->path_content, str_ascii("debug_bitmap2.bmp") );
game_state->debug_bitmap = load_bmp( platform_api, path_debug_bitmap ); game_state->debug_bitmap = load_bmp( platform_api, path_debug_bitmap );
} }
@ -638,19 +638,69 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI*
path_test_bg_hh.concat( platform_api->path_content, str_ascii("offical/test/test_background.bmp")); path_test_bg_hh.concat( platform_api->path_content, str_ascii("offical/test/test_background.bmp"));
game_state->test_bg_hh = load_bmp( platform_api, path_test_bg_hh ); game_state->test_bg_hh = load_bmp( platform_api, path_test_bg_hh );
StrPath path_hero_front_head; #define path_test "offical\\test\\"
path_hero_front_head.concat( platform_api->path_content, str_ascii("offical/test/test_hero_front_head.bmp")); constexpr char const subpath_hero_front_head[] = path_test "test_hero_front_head.bmp";
game_state->hero_front_head = load_bmp( platform_api, path_hero_front_head ); constexpr char const subpath_hero_back_head [] = path_test "test_hero_back_head.bmp";
constexpr char const subpath_hero_right_head[] = path_test "test_hero_right_head.bmp";
constexpr char const subpath_hero_left_head [] = path_test "test_hero_left_head.bmp";
StrPath path_hero_front_cape; constexpr char const subpath_hero_front_cape[] = path_test "test_hero_front_cape.bmp";
path_hero_front_cape.concat( platform_api->path_content, str_ascii("offical/test/test_hero_front_cape.bmp")); constexpr char const subpath_hero_back_cape [] = path_test "test_hero_back_cape.bmp";
game_state->hero_front_cape = load_bmp( platform_api, path_hero_front_cape ); constexpr char const subpath_hero_left_cape [] = path_test "test_hero_left_cape.bmp";
constexpr char const subpath_hero_right_cape[] = path_test "test_hero_right_cape.bmp";
StrPath path_hero_front_torso; constexpr char const subpath_hero_front_torso[] = path_test "test_hero_front_torso.bmp";
path_hero_front_torso.concat( platform_api->path_content, str_ascii("offical/test/test_hero_front_torso.bmp")); constexpr char const subpath_hero_back_torso [] = path_test "test_hero_back_torso.bmp";
game_state->hero_front_torso = load_bmp( platform_api, path_hero_front_torso ); constexpr char const subpath_hero_left_torso [] = path_test "test_hero_left_torso.bmp";
constexpr char const subpath_hero_right_torso[] = path_test "test_hero_right_torso.bmp";
#undef path_test
#define load_bmp_asset( sub_path, container ) \
{ \
StrPath path {}; \
path.concat( platform_api->path_content, str_ascii( sub_path ) ); \
container = load_bmp( platform_api, path ); \
}
using hh::HeroBitmaps_Front;
using hh::HeroBitmaps_Back;
using hh::HeroBitmaps_Left;
using hh::HeroBitmaps_Right;
load_bmp_asset( subpath_hero_front_head, game_state->hero_bitmaps[HeroBitmaps_Front].head );
load_bmp_asset( subpath_hero_back_head, game_state->hero_bitmaps[HeroBitmaps_Back ].head );
load_bmp_asset( subpath_hero_left_head, game_state->hero_bitmaps[HeroBitmaps_Left ].head );
load_bmp_asset( subpath_hero_right_head, game_state->hero_bitmaps[HeroBitmaps_Right].head );
load_bmp_asset( subpath_hero_front_cape, game_state->hero_bitmaps[HeroBitmaps_Front].cape );
load_bmp_asset( subpath_hero_back_cape, game_state->hero_bitmaps[HeroBitmaps_Back ].cape );
load_bmp_asset( subpath_hero_left_cape, game_state->hero_bitmaps[HeroBitmaps_Left ].cape );
load_bmp_asset( subpath_hero_right_cape, game_state->hero_bitmaps[HeroBitmaps_Right].cape );
load_bmp_asset( subpath_hero_front_torso, game_state->hero_bitmaps[HeroBitmaps_Front].torso );
load_bmp_asset( subpath_hero_back_torso, game_state->hero_bitmaps[HeroBitmaps_Back ].torso );
load_bmp_asset( subpath_hero_left_torso, game_state->hero_bitmaps[HeroBitmaps_Left ].torso );
load_bmp_asset( subpath_hero_right_torso, game_state->hero_bitmaps[HeroBitmaps_Right].torso );
s32 align_x = 0;
s32 align_y = 76;
game_state->hero_bitmaps[HeroBitmaps_Front].align_x = align_x;
game_state->hero_bitmaps[HeroBitmaps_Back ].align_x = align_x;
game_state->hero_bitmaps[HeroBitmaps_Left ].align_x = align_x;
game_state->hero_bitmaps[HeroBitmaps_Right].align_x = align_x;
game_state->hero_bitmaps[HeroBitmaps_Front].align_y = align_y;
game_state->hero_bitmaps[HeroBitmaps_Back ].align_y = align_y;
game_state->hero_bitmaps[HeroBitmaps_Left ].align_y = align_y;
game_state->hero_bitmaps[HeroBitmaps_Right].align_y = align_y;
#undef load_bmp_asset
game_state->hero_direction = HeroBitmaps_Front;
} }
game_state->camera_pos.tile_x = state->world->tiles_per_screen_x / 2;
game_state->camera_pos.tile_y = state->world->tiles_per_screen_y / 2;
hh::PlayerState* player = & game_state->player_state; hh::PlayerState* player = & game_state->player_state;
player->position.tile_x = 4; player->position.tile_x = 4;
player->position.tile_y = 4; player->position.tile_y = 4;
@ -822,6 +872,12 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
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;
using hh::EHeroBitmapsDirection;
using hh::HeroBitmaps_Front;
using hh::HeroBitmaps_Back;
using hh::HeroBitmaps_Left;
using hh::HeroBitmaps_Right;
input_poll_player_actions( input, & player_actions ); input_poll_player_actions( input, & player_actions );
{ {
f32 move_speed = 6.f; f32 move_speed = 6.f;
@ -848,8 +904,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
b32 valid_new_pos = true; b32 valid_new_pos = true;
{ {
TileMapPosition 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_z player->position.tile_x, player->position.tile_y, player->position.tile_z
}; };
test_pos = recannonicalize_position( tile_map, test_pos ); test_pos = recannonicalize_position( tile_map, test_pos );
@ -886,10 +942,9 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
if ( valid_new_pos ) if ( valid_new_pos )
{ {
TileMapPosition 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_z player->position.tile_x, player->position.tile_y, player->position.tile_z
}; };
new_pos = recannonicalize_position( tile_map, new_pos ); new_pos = recannonicalize_position( tile_map, new_pos );
@ -909,6 +964,23 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
} }
player->position = new_pos; player->position = new_pos;
if ( player_actions.player_y_move_digital > 0 || player_actions.player_y_move_analog > 0 )
{
game_state->hero_direction = HeroBitmaps_Back;
}
if ( player_actions.player_y_move_digital < 0 || player_actions.player_y_move_analog < 0 )
{
game_state->hero_direction = HeroBitmaps_Front;
}
if ( player_actions.player_x_move_digital > 0 || player_actions.player_x_move_analog > 0 )
{
game_state->hero_direction = HeroBitmaps_Right;
}
if ( player_actions.player_x_move_digital < 0 || player_actions.player_x_move_analog < 0 )
{
game_state->hero_direction = HeroBitmaps_Left;
}
} }
if ( player->jump_time > 0.f ) if ( player->jump_time > 0.f )
@ -926,25 +998,46 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
player->jump_time = 1.f; player->jump_time = 1.f;
player->mid_jump = true; player->mid_jump = true;
} }
TileMapPosition player_to_camera = subtract( player->position, game_state->camera_pos );
game_state->camera_pos.tile_z = player->position.tile_z;
if ( player_to_camera.tile_x > world->tiles_per_screen_x / 2 )
{
game_state->camera_pos.tile_x += world->tiles_per_screen_x;
}
if ( player_to_camera.tile_y > world->tiles_per_screen_y / 2 )
{
game_state->camera_pos.tile_y += world->tiles_per_screen_y;
}
if ( player_to_camera.tile_x < -world->tiles_per_screen_x / 2 )
{
game_state->camera_pos.tile_x -= world->tiles_per_screen_x;
}
if ( player_to_camera.tile_y < -world->tiles_per_screen_y / 2 )
{
game_state->camera_pos.tile_y -= world->tiles_per_screen_y;
}
} }
draw_rectangle( back_buffer draw_rectangle( back_buffer
, 0.f, 0.f , 0.f, 0.f
, scast(f32, back_buffer->width), scast(f32, back_buffer->height) , scast(f32, back_buffer->width), scast(f32, back_buffer->height)
, 1.f, 0.24f, 0.24f ); , 1.f, 0.24f, 0.24f );
draw_bitmap( back_buffer
, scast(f32, back_buffer->width) / 2.f, scast(f32, back_buffer->height) / 2.f
, & game_state->test_bg
);
draw_bitmap( back_buffer draw_bitmap( back_buffer
, scast(f32, back_buffer->width) / 2.f, scast(f32, back_buffer->height) / 2.f , scast(f32, back_buffer->width) / 2.f, scast(f32, back_buffer->height) / 2.f
, & game_state->test_bg_hh , & game_state->test_bg_hh
); );
draw_bitmap( back_buffer // Screen Camera
, scast(f32, back_buffer->width) / 2.5f, scast(f32, back_buffer->height) / 2.5f
, & game_state->hero_front_head
);
// Scrolling
f32 screen_center_x = 0.5f * scast(f32, back_buffer->width); f32 screen_center_x = 0.5f * scast(f32, back_buffer->width);
f32 screen_center_y = 0.5f * scast(f32, back_buffer->height); f32 screen_center_y = 0.5f * scast(f32, back_buffer->height);
@ -952,13 +1045,14 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
{ {
for ( s32 relative_col = -20; relative_col < +20; ++ relative_col ) for ( s32 relative_col = -20; relative_col < +20; ++ relative_col )
{ {
u32 col = player->position.tile_x + relative_col; s32 col = game_state->camera_pos.tile_x + relative_col;
u32 row = player->position.tile_y + relative_row; s32 row = game_state->camera_pos.tile_y + relative_row;
u32 tile_id = TileMap_get_tile_value( tile_map, col, row, player->position.tile_z ); s32 tile_id = TileMap_get_tile_value( tile_map, col, row, game_state->camera_pos.tile_z );
f32 color[3] = { 0.15f, 0.15f, 0.15f }; f32 color[3] = { 0.15f, 0.15f, 0.15f };
if ( tile_id > 1 || row == player->position.tile_y && col == player->position.tile_x ) if ( tile_id > 1 || row == player->position.tile_y && col == player->position.tile_x )
// if ( tile_id > 1 )
{ {
if ( tile_id == 2 ) if ( tile_id == 2 )
{ {
@ -986,8 +1080,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back
color[2] = 0.3f; color[2] = 0.3f;
} }
f32 center_x = screen_center_x + scast(f32, relative_col) * tile_size_in_pixels - player->position.x * world->tile_meters_to_pixels; f32 center_x = screen_center_x + scast(f32, relative_col) * tile_size_in_pixels - game_state->camera_pos.x * world->tile_meters_to_pixels;
f32 center_y = screen_center_y - scast(f32, relative_row) * tile_size_in_pixels + player->position.y * world->tile_meters_to_pixels; f32 center_y = screen_center_y - scast(f32, relative_row) * tile_size_in_pixels + game_state->camera_pos.y * world->tile_meters_to_pixels;
f32 min_x = center_x - tile_size_in_pixels * 0.5f; f32 min_x = center_x - tile_size_in_pixels * 0.5f;
f32 min_y = center_y - tile_size_in_pixels * 0.5f; f32 min_y = center_y - tile_size_in_pixels * 0.5f;
@ -1024,21 +1118,39 @@ 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 = screen_center_x + scast(f32, player->position.tile_x) * world->tile_meters_to_pixels + player->position.x * world->tile_meters_to_pixels; TileMapPosition player_to_camera = subtract( player->position, game_state->camera_pos );
f32 player_tile_y_offset = screen_center_y - scast(f32, player->position.tile_y) * world->tile_meters_to_pixels + player->position.y * world->tile_meters_to_pixels;
f32 player_screen_pos_x = screen_center_x; f32 offcenter_amount_x = player_to_camera.x + scast(f32, player_to_camera.tile_x) * world->tile_map->tile_size_in_meters;
f32 player_screen_pos_y = screen_center_y; f32 offcenter_amount_y = player_to_camera.y + scast(f32, player_to_camera.tile_y) * world->tile_map->tile_size_in_meters;
offcenter_amount_x *= world->tile_meters_to_pixels;
offcenter_amount_y *= world->tile_meters_to_pixels * -1;
f32 player_ground_pos_x = screen_center_x + offcenter_amount_x;
f32 player_ground_pos_y = screen_center_y + offcenter_amount_y;
hh::HeroBitmaps* hero_bitmaps = & game_state->hero_bitmaps[game_state->hero_direction];
#if 1
draw_rectangle( back_buffer
, player_ground_pos_x - player_half_width * world->tile_meters_to_pixels, player_ground_pos_y - player->height * world->tile_meters_to_pixels
, player_ground_pos_x + player_half_width * world->tile_meters_to_pixels, player_ground_pos_y
, player_red, player_green, player_blue );
#endif
draw_bitmap( back_buffer draw_bitmap( back_buffer
, player_screen_pos_x, player_screen_pos_y , player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y)
, & game_state->mojito_head ); , & hero_bitmaps->torso );
draw_bitmap( back_buffer
, player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y)
, & hero_bitmaps->cape );
#if 0 #if 0
draw_rectangle( back_buffer draw_bitmap( 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_ground_pos_x, player_ground_pos_y - 45.f
, player_screen_pos_x + player_half_width * world->tile_meters_to_pixels, player_screen_pos_y , & game_state->mojito_head );
, player_red, player_green, player_blue ); #else
draw_bitmap( back_buffer
, player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y)
, & hero_bitmaps->head );
#endif #endif
// Auto-Snapshot percent bar // Auto-Snapshot percent bar

View File

@ -177,6 +177,9 @@ struct World
f32 tile_meters_to_pixels; f32 tile_meters_to_pixels;
s32 tile_size_in_pixels; s32 tile_size_in_pixels;
s32 tiles_per_screen_x;
s32 tiles_per_screen_y;
TileMap* tile_map; TileMap* tile_map;
}; };

View File

@ -4,9 +4,24 @@
NS_ENGINE_BEGIN NS_ENGINE_BEGIN
inline
TileMapPosition subtract( TileMapPosition pos_a, TileMapPosition pos_b )
{
TileMapPosition result {
pos_a.x - pos_b.x,
pos_a.y - pos_b.y,
pos_a.tile_x - pos_b.tile_x,
pos_a.tile_y - pos_b.tile_y,
// TODO(Ed) : Think about how to handle z...
pos_a.tile_z - pos_b.tile_z
};
return result;
}
// TODO(Ed) : Consider moving (Casey wants to) // TODO(Ed) : Consider moving (Casey wants to)
inline inline
void cannonicalize_coord( TileMap* tile_map, u32* tile_coord, f32* pos_coord ) void cannonicalize_coord( TileMap* tile_map, s32* tile_coord, f32* pos_coord )
{ {
assert( tile_map != nullptr ); assert( tile_map != nullptr );
assert( tile_coord != nullptr ); assert( tile_coord != nullptr );
@ -15,7 +30,7 @@ void cannonicalize_coord( TileMap* tile_map, u32* tile_coord, f32* pos_coord )
// Note(Ed) : World is assumed to be a "torodial topology" // Note(Ed) : World is assumed to be a "torodial topology"
s32 offset = round( (* pos_coord) / tile_size ); s32 offset = round( (* pos_coord) / tile_size );
u32 new_tile_coord = (* tile_coord) + offset; s32 new_tile_coord = (* tile_coord) + offset;
f32 new_pos_coord = (* pos_coord) - scast(f32, offset) * tile_size; 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 );
@ -38,9 +53,9 @@ TileMapPosition recannonicalize_position( TileMap* tile_map, TileMapPosition pos
} }
inline inline
u32 TileChunk_get_tile_value( TileChunk* tile_chunk, TileMap* tile_map, u32 x, u32 y ) u32 TileChunk_get_tile_value( TileChunk* tile_chunk, TileMap* tile_map, s32 x, s32 y )
{ {
assert( tile_map != nullptr ); assert( tile_map != nullptr );
assert( tile_chunk != nullptr ); assert( tile_chunk != nullptr );
assert( x < tile_map->chunk_dimension ); assert( x < tile_map->chunk_dimension );
assert( y < tile_map->chunk_dimension ); assert( y < tile_map->chunk_dimension );
@ -50,7 +65,7 @@ u32 TileChunk_get_tile_value( TileChunk* tile_chunk, TileMap* tile_map, u32 x, u
} }
inline inline
void TileChunk_set_tile_value( TileChunk* tile_chunk, TileMap* tile_map, u32 x, u32 y, u32 value) void TileChunk_set_tile_value( TileChunk* tile_chunk, TileMap* tile_map, s32 x, s32 y, s32 value)
{ {
assert( tile_map != nullptr ); assert( tile_map != nullptr );
assert( tile_chunk != nullptr ); assert( tile_chunk != nullptr );
@ -130,7 +145,7 @@ b32 TileMap_is_point_empty( TileMap* tile_map, TileMapPosition position )
} }
internal internal
void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, u32 abs_tile_x, u32 abs_tile_y, u32 abs_tile_z, u32 value ) void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, s32 abs_tile_x, s32 abs_tile_y, s32 abs_tile_z, s32 value )
{ {
TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, abs_tile_x, abs_tile_y, abs_tile_z ); TileChunkPosition chunk_pos = get_tile_chunk_position_for( tile_map, abs_tile_x, abs_tile_y, abs_tile_z );
TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y, chunk_pos.tile_chunk_z ); TileChunk* chunk = TileMap_get_chunk( tile_map, chunk_pos.tile_chunk_x, chunk_pos.tile_chunk_y, chunk_pos.tile_chunk_z );
@ -140,7 +155,7 @@ void TileMap_set_tile_value( MemoryArena* arena, TileMap* tile_map, u32 abs_tile
if ( chunk->tiles == nullptr ) if ( chunk->tiles == nullptr )
{ {
ssize num_tiles = tile_map->chunk_dimension * tile_map->chunk_dimension; ssize num_tiles = tile_map->chunk_dimension * tile_map->chunk_dimension;
chunk->tiles = arena->push_array( u32, num_tiles ); chunk->tiles = arena->push_array( s32, num_tiles );
for ( ssize tile_index = 0; tile_index < num_tiles; ++ tile_index ) for ( ssize tile_index = 0; tile_index < num_tiles; ++ tile_index )
{ {

View File

@ -11,9 +11,11 @@
NS_ENGINE_BEGIN NS_ENGINE_BEGIN
// TODO(Ed) : I switch the tile coordinates to signed values, I'm clamping rn to force positive
struct TileChunk struct TileChunk
{ {
u32* tiles; s32* tiles;
}; };
/* /*
@ -21,14 +23,14 @@ struct TileChunk
*/ */
struct TileChunkPosition struct TileChunkPosition
{ {
u32 tile_chunk_x; s32 tile_chunk_x;
u32 tile_chunk_y; s32 tile_chunk_y;
u32 tile_chunk_z; s32 tile_chunk_z;
// "Chunk-relative (x, y) // "Chunk-relative (x, y)
u32 tile_x; s32 tile_x;
u32 tile_y; s32 tile_y;
}; };
struct TileMap struct TileMap
@ -41,9 +43,9 @@ struct TileMap
f32 tile_size_in_meters; f32 tile_size_in_meters;
// TODO(Ed) : Real sparseness ? (not use the giant pointer array) // TODO(Ed) : Real sparseness ? (not use the giant pointer array)
u32 chunk_shift; s32 chunk_shift;
u32 chunk_mask; s32 chunk_mask;
u32 chunk_dimension; s32 chunk_dimension;
TileChunk* chunks; TileChunk* chunks;
}; };
@ -58,9 +60,9 @@ struct TileMapPosition
// Fixed point tile locations. // Fixed point tile locations.
// High bits are the tile-chunk index, and the low bits are the tile index in the chunk. // High bits are the tile-chunk index, and the low bits are the tile index in the chunk.
u32 tile_x; s32 tile_x;
u32 tile_y; s32 tile_y;
u32 tile_z; s32 tile_z;
}; };
NS_ENGINE_END NS_ENGINE_END

View File

@ -91,21 +91,43 @@ struct PlayerActions
b32 jump; b32 jump;
}; };
enum EHeroBitmapsDirection : u32
{
HeroBitmaps_Front,
HeroBitmaps_Back,
HeroBitmaps_Left,
HeroBitmaps_Right
};
struct HeroBitmaps
{
using Bitmap = engine::Bitmap;
s32 align_x;
s32 align_y;
Bitmap head;
Bitmap cape;
Bitmap torso;
};
struct GameState struct GameState
{ {
PlayerState player_state; PlayerState player_state;
using Bitmap = engine::Bitmap; using Bitmap = engine::Bitmap;
Bitmap debug_bitmap; Bitmap debug_bitmap;
Bitmap test_bg; Bitmap test_bg;
Bitmap mojito; Bitmap mojito;
Bitmap mojito_head; Bitmap mojito_head;
Bitmap test_bg_hh; Bitmap test_bg_hh;
Bitmap hero_front_head;
Bitmap hero_front_cape; engine::TileMapPosition camera_pos;
Bitmap hero_front_torso;
EHeroBitmapsDirection hero_direction;
HeroBitmaps hero_bitmaps[4];
}; };
NS_HANDMADE_END NS_HANDMADE_END