mirror of
				https://github.com/Ed94/HandmadeHero.git
				synced 2025-10-30 22:40:55 -07:00 
			
		
		
		
	Day 39 complete
This commit is contained in:
		| @@ -33,7 +33,7 @@ Module build order: | ||||
|  | ||||
| ## Milestone | ||||
|  | ||||
| Day 38 : Basic Linear Bitmap Blending | ||||
| Day 39 : Basic Bitmap Rendering Cleanup | ||||
|  | ||||
| Features Done so far: | ||||
|  | ||||
| @@ -59,12 +59,16 @@ Features Done so far: | ||||
|   * Record & replay input. | ||||
|   * WIP : 2.5D Tile Map | ||||
|     * Virtualized into chunks | ||||
|     * Some basic collision detection & math (pre-math coverage by Casey) | ||||
|   * Bitmap file loading | ||||
|     * Compression mode 3 | ||||
|     * Linear alpha blending | ||||
|     * Basic rendering | ||||
|       * Linear alpha blending | ||||
|       * Anchored to center position | ||||
|  | ||||
| ## 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_y = round( pos_y ) + half_height; | ||||
|  | ||||
| 	s32 bmp_start_x = min_x < 0 ? min_x * -1 : 0; | ||||
| 	u32 bmp_start_y = min_y < 0 ? bitmap->height + min_y - 1 : bitmap->height - 1; | ||||
| 	s32 bmp_offset_x = min_x < 0 ? min_x * -1 : 0; | ||||
| 	u32 bmp_offset_y = min_y < 0 ? bitmap->height + min_y - 1 : bitmap->height - 1; | ||||
|  | ||||
| 	s32 buffer_width  = buffer->width; | ||||
| 	s32 buffer_height = buffer->height; | ||||
| @@ -268,12 +268,12 @@ void draw_bitmap( OffscreenBuffer* buffer | ||||
| 	u8*  dst_row = rcast(u8*, buffer->memory ) | ||||
| 	          + min_x * buffer->bytes_per_pixel | ||||
| 	          + 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 ) | ||||
| 	{ | ||||
| 		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 ) | ||||
| 		{ | ||||
| @@ -418,8 +418,8 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* | ||||
| 	state->x_offset = 0; | ||||
| 	state->y_offset = 0; | ||||
|  | ||||
| 	state->sample_wave_switch = false; | ||||
| 	state->wave_tone_hz = 60; | ||||
| 	state->sample_wave_switch    = false; | ||||
| 	state->wave_tone_hz          = 60; | ||||
| 	state->sample_wave_sine_time = 0.f; | ||||
|  | ||||
| 	state->renderer_paused = false; | ||||
| @@ -457,7 +457,7 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* | ||||
| 		//tile_map->chunks = & temp_chunk; | ||||
|  | ||||
| 		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; | ||||
|  | ||||
| 		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_y = +( tile_size_in_pixels * 0.25f) + scast(f32, back_buffer->height); | ||||
|  | ||||
| 		u32 tiles_per_screen_x = 17; | ||||
| 		u32 tiles_per_screen_y = 9; | ||||
| 		world->tiles_per_screen_x = 17; | ||||
| 		world->tiles_per_screen_y = 9; | ||||
|  | ||||
| 		u32 screen_x  = 0; | ||||
| 		u32 screen_y  = 0; | ||||
| @@ -518,23 +518,23 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* | ||||
| 				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; | ||||
| 					u32 abs_tile_y = screen_y * tiles_per_screen_y + tile_y; | ||||
| 					s32 abs_tile_x = screen_x * world->tiles_per_screen_x + tile_x; | ||||
| 					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_y = tile_y == (tiles_per_screen_y / 2); | ||||
| 					bool in_middle_x = tile_x == (world->tiles_per_screen_x / 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_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 )) | ||||
| 					{ | ||||
| @@ -615,19 +615,19 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* | ||||
|  | ||||
| 	// Personally made assets | ||||
| 	{ | ||||
| 		StrPath path_test_bg; | ||||
| 		StrPath path_test_bg {}; | ||||
| 		path_test_bg.concat( platform_api->path_content, str_ascii("test_background.bmp") ); | ||||
| 		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") ); | ||||
| 		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") ); | ||||
| 		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") ); | ||||
| 		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")); | ||||
| 		game_state->test_bg_hh = load_bmp( platform_api, path_test_bg_hh ); | ||||
|  | ||||
| 		StrPath path_hero_front_head; | ||||
| 		path_hero_front_head.concat( platform_api->path_content, str_ascii("offical/test/test_hero_front_head.bmp")); | ||||
| 		game_state->hero_front_head = load_bmp( platform_api, path_hero_front_head ); | ||||
| 	#define path_test "offical\\test\\" | ||||
| 		constexpr char const subpath_hero_front_head[] = path_test "test_hero_front_head.bmp"; | ||||
| 		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; | ||||
| 		path_hero_front_cape.concat( platform_api->path_content, str_ascii("offical/test/test_hero_front_cape.bmp")); | ||||
| 		game_state->hero_front_cape = load_bmp( platform_api, path_hero_front_cape ); | ||||
| 		constexpr char const subpath_hero_front_cape[] = path_test "test_hero_front_cape.bmp"; | ||||
| 		constexpr char const subpath_hero_back_cape [] = path_test "test_hero_back_cape.bmp"; | ||||
| 		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; | ||||
| 		path_hero_front_torso.concat( platform_api->path_content, str_ascii("offical/test/test_hero_front_torso.bmp")); | ||||
| 		game_state->hero_front_torso = load_bmp( platform_api, path_hero_front_torso ); | ||||
| 		constexpr char const subpath_hero_front_torso[] = path_test "test_hero_front_torso.bmp"; | ||||
| 		constexpr char const subpath_hero_back_torso [] = path_test "test_hero_back_torso.bmp"; | ||||
| 		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; | ||||
| 	player->position.tile_x     = 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_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 ); | ||||
| 	{ | ||||
| 		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; | ||||
| 		{ | ||||
| 			TileMapPosition test_pos = { | ||||
| 				new_player_pos_x, new_player_pos_y, | ||||
| 				player->position.tile_x, player->position.tile_y, player->position.tile_z | ||||
| 			                           new_player_pos_x, new_player_pos_y, | ||||
| 									   player->position.tile_x, player->position.tile_y, player->position.tile_z | ||||
| 			}; | ||||
| 			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 ) | ||||
| 		{ | ||||
|  | ||||
| 			TileMapPosition new_pos = { | ||||
| 				new_player_pos_x, new_player_pos_y, | ||||
| 				player->position.tile_x, player->position.tile_y, player->position.tile_z | ||||
| 			                          new_player_pos_x, new_player_pos_y, | ||||
| 									  player->position.tile_x, player->position.tile_y, player->position.tile_z | ||||
| 			}; | ||||
| 			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; | ||||
|  | ||||
| 			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 ) | ||||
| @@ -926,25 +998,46 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | ||||
| 			player->jump_time = 1.f; | ||||
| 			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 | ||||
| 		, 0.f, 0.f | ||||
| 		, scast(f32, back_buffer->width), scast(f32, back_buffer->height) | ||||
| 		, 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 | ||||
| 		, scast(f32, back_buffer->width) / 2.f, scast(f32, back_buffer->height) / 2.f | ||||
| 		, & game_state->test_bg_hh | ||||
| 	); | ||||
|  | ||||
| 	draw_bitmap( back_buffer | ||||
| 		, scast(f32, back_buffer->width) / 2.5f, scast(f32, back_buffer->height) / 2.5f | ||||
| 		, & game_state->hero_front_head | ||||
| 	); | ||||
|  | ||||
| // Scrolling | ||||
| // Screen Camera | ||||
| 	f32 screen_center_x = 0.5f * scast(f32, back_buffer->width); | ||||
| 	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 ) | ||||
| 		{ | ||||
| 			u32 col = player->position.tile_x + relative_col; | ||||
| 			u32 row = player->position.tile_y + relative_row; | ||||
| 			s32 col = game_state->camera_pos.tile_x + relative_col; | ||||
| 			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 }; | ||||
|  | ||||
| 			if ( tile_id > 1 || row == player->position.tile_y && col == player->position.tile_x ) | ||||
| //			if ( tile_id > 1 ) | ||||
| 			{ | ||||
| 				if ( tile_id == 2 ) | ||||
| 				{ | ||||
| @@ -986,8 +1080,8 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | ||||
| 					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_y = screen_center_y - scast(f32, relative_row) * tile_size_in_pixels + player->position.y * 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 + game_state->camera_pos.y * world->tile_meters_to_pixels; | ||||
|  | ||||
| 				f32 min_x = center_x - 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_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; | ||||
| 	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; | ||||
| 	TileMapPosition player_to_camera = subtract( player->position, game_state->camera_pos ); | ||||
|  | ||||
| 	f32 player_screen_pos_x = screen_center_x; | ||||
| 	f32 player_screen_pos_y = screen_center_y; | ||||
| 	f32 offcenter_amount_x  = player_to_camera.x + scast(f32, player_to_camera.tile_x) * world->tile_map->tile_size_in_meters; | ||||
| 	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 | ||||
| 	            , player_screen_pos_x, player_screen_pos_y | ||||
| 	            , & game_state->mojito_head ); | ||||
|  | ||||
| 	            , player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y) | ||||
| 	            , & 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 | ||||
| 	draw_rectangle( back_buffer | ||||
| 		, player_screen_pos_x - player_half_width * world->tile_meters_to_pixels, player_screen_pos_y - player->height * world->tile_meters_to_pixels | ||||
| 		, player_screen_pos_x + player_half_width * world->tile_meters_to_pixels, player_screen_pos_y | ||||
| 		, player_red, player_green, player_blue ); | ||||
| 	draw_bitmap( back_buffer | ||||
| 	            , player_ground_pos_x, player_ground_pos_y - 45.f | ||||
| 	            , & game_state->mojito_head ); | ||||
| #else | ||||
| 	draw_bitmap( back_buffer | ||||
| 	            , player_ground_pos_x, player_ground_pos_y - scast(f32, hero_bitmaps->align_y) | ||||
| 	            , & hero_bitmaps->head ); | ||||
| #endif | ||||
|  | ||||
| 	// Auto-Snapshot percent bar | ||||
|   | ||||
| @@ -177,6 +177,9 @@ struct World | ||||
|  | ||||
| 	f32 tile_meters_to_pixels; | ||||
| 	s32 tile_size_in_pixels; | ||||
| 	 | ||||
| 	s32 tiles_per_screen_x; | ||||
| 	s32 tiles_per_screen_y; | ||||
|  | ||||
| 	TileMap* tile_map; | ||||
| }; | ||||
|   | ||||
| @@ -4,9 +4,24 @@ | ||||
|  | ||||
| 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) | ||||
| 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_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" | ||||
| 	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; | ||||
|  | ||||
| 	assert( new_pos_coord >= -tile_size * 0.5f ); | ||||
| @@ -38,9 +53,9 @@ TileMapPosition recannonicalize_position( TileMap* tile_map, TileMapPosition pos | ||||
| } | ||||
|                                                                      | ||||
| 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( x < 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 | ||||
| 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_chunk != nullptr ); | ||||
| @@ -130,7 +145,7 @@ b32 TileMap_is_point_empty( TileMap* tile_map, TileMapPosition position ) | ||||
| } | ||||
|  | ||||
| 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 ); | ||||
| 	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 ) | ||||
| 	{ | ||||
| 		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 ) | ||||
| 		{ | ||||
|   | ||||
| @@ -11,9 +11,11 @@ | ||||
|  | ||||
| NS_ENGINE_BEGIN | ||||
|  | ||||
| // TODO(Ed) : I switch the tile coordinates to signed values, I'm clamping rn to force positive | ||||
|  | ||||
| struct TileChunk | ||||
| { | ||||
| 	u32* tiles; | ||||
| 	s32* tiles; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| @@ -21,14 +23,14 @@ struct TileChunk | ||||
| */ | ||||
| struct TileChunkPosition | ||||
| { | ||||
| 	u32 tile_chunk_x; | ||||
| 	u32 tile_chunk_y; | ||||
| 	u32 tile_chunk_z; | ||||
| 	s32 tile_chunk_x; | ||||
| 	s32 tile_chunk_y; | ||||
| 	s32 tile_chunk_z; | ||||
|  | ||||
| 	// "Chunk-relative (x, y) | ||||
|  | ||||
| 	u32 tile_x; | ||||
| 	u32 tile_y; | ||||
| 	s32 tile_x; | ||||
| 	s32 tile_y; | ||||
| }; | ||||
|  | ||||
| struct TileMap | ||||
| @@ -41,9 +43,9 @@ struct TileMap | ||||
| 	f32 tile_size_in_meters; | ||||
|  | ||||
| 	// TODO(Ed) : Real sparseness ? (not use the giant pointer array) | ||||
| 	u32 chunk_shift; | ||||
| 	u32 chunk_mask; | ||||
| 	u32 chunk_dimension; | ||||
| 	s32 chunk_shift; | ||||
| 	s32 chunk_mask; | ||||
| 	s32 chunk_dimension; | ||||
|  | ||||
| 	TileChunk* chunks; | ||||
| }; | ||||
| @@ -58,9 +60,9 @@ struct TileMapPosition | ||||
| 	// Fixed point tile locations. | ||||
| 	// High bits are the tile-chunk index, and the low bits are the tile index in the chunk. | ||||
|  | ||||
| 	u32 tile_x; | ||||
| 	u32 tile_y; | ||||
| 	u32 tile_z; | ||||
| 	s32 tile_x; | ||||
| 	s32 tile_y; | ||||
| 	s32 tile_z; | ||||
| }; | ||||
|  | ||||
| NS_ENGINE_END | ||||
|   | ||||
| @@ -91,21 +91,43 @@ struct PlayerActions | ||||
| 	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 | ||||
| { | ||||
| 	PlayerState player_state; | ||||
| 	 | ||||
|  | ||||
| 	using Bitmap = engine::Bitmap; | ||||
| 	 | ||||
|  | ||||
| 	Bitmap debug_bitmap; | ||||
| 	Bitmap test_bg; | ||||
| 	Bitmap mojito; | ||||
| 	Bitmap mojito_head; | ||||
| 	 | ||||
|  | ||||
| 	Bitmap test_bg_hh; | ||||
| 	Bitmap hero_front_head; | ||||
| 	Bitmap hero_front_cape; | ||||
| 	Bitmap hero_front_torso; | ||||
| 	 | ||||
| 	engine::TileMapPosition camera_pos; | ||||
|  | ||||
| 	EHeroBitmapsDirection hero_direction; | ||||
| 	HeroBitmaps hero_bitmaps[4]; | ||||
| }; | ||||
|  | ||||
| NS_HANDMADE_END | ||||
|   | ||||
		Reference in New Issue
	
	Block a user