mirror of
				https://github.com/Ed94/HandmadeHero.git
				synced 2025-10-31 06:50:54 -07:00 
			
		
		
		
	Day 39 complete
This commit is contained in:
		| @@ -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 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 46 KiB | 
							
								
								
									
										18
									
								
								docs/Day 039.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								docs/Day 039.md
									
									
									
									
									
										Normal 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. | ||||||
							
								
								
									
										
											BIN
										
									
								
								docs/imgs/handmade_win32_2023-10-21_22-18-47.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/imgs/handmade_win32_2023-10-21_22-18-47.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.7 MiB | 
| @@ -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 | ||||||
|   | |||||||
| @@ -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; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -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 ) | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user