mirror of
				https://github.com/Ed94/HandmadeHero.git
				synced 2025-10-31 06:50:54 -07:00 
			
		
		
		
	Day 46 complete
This commit is contained in:
		
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
								
							| @@ -21,28 +21,34 @@ Any code I do for this [series](https://handmadehero.org) will be here. | |||||||
|  |  | ||||||
| Building requires msvc or llvm's clang + lld, and powershell 7 | Building requires msvc or llvm's clang + lld, and powershell 7 | ||||||
|  |  | ||||||
| The build is done in two stages: | The build is done in the following stages (if clean build): | ||||||
|  |  | ||||||
| 1. Build and run metaprogram to scan and generate dependent code for the module being built. | 1. Build engine module | ||||||
| 2. Build the the runtime for the module. |     1. Build and run pre-build metaprogram: engine_gen.cpp | ||||||
|  |     2. Build engine module dll. | ||||||
|  |     3. Build and run post-build metaprogram to generate engine symbol constants. | ||||||
|  | 2. Build platform module | ||||||
|  |     1. Build and run pre-build metaprogram. | ||||||
|  |     2. Build platform module as executable | ||||||
|  |  | ||||||
| Module build order: | The final build order should have an additional game module: `handmade`, that will be dependent on the engine and platform modules. | ||||||
|  |  | ||||||
| 1. Engine |  | ||||||
| 2. Platform |  | ||||||
|  |  | ||||||
| ## Milestone | ## Milestone | ||||||
|  |  | ||||||
| Day 45 : Geometric vs. Temporal Movement Search | Day 46 : Basic Multiplayer Support | ||||||
|  |  | ||||||
| Features Done so far: | Features Done so far: | ||||||
|  |  | ||||||
| * Tailor made build system via powershell scripts | * Tailor made build system via powershell scripts | ||||||
|   * Supports building the repo with msvc or clang |   * Supports building the repo with msvc or clang | ||||||
|   * Will only build a module if it detects changes (md5 is cached) |   * Will only build a module if it detects changes (md5 is cached) | ||||||
|  |     * Check is rudimentary can cannot detect all changes (headers for the most part) | ||||||
|  |     * Any changes to target should require a clean rebuild. | ||||||
|   * Can stage codegen metaprograms to run before building the module |   * Can stage codegen metaprograms to run before building the module | ||||||
|     * Will automatically not run if app process is found (for engine module). |     * Will automatically not run if app process is found (for engine module). | ||||||
|  |     * Metaprogramming library used was self-made from scratch: gencpp | ||||||
|   * Can emit exported mangled symbols for the engine module for hot-reload with the platform module without needing to use C linkage symbols or a complex hot-reload library (Live++, etc). |   * Can emit exported mangled symbols for the engine module for hot-reload with the platform module without needing to use C linkage symbols or a complex hot-reload library (Live++, etc). | ||||||
|  |   * Project builds in less than 5 seconds. (Most of it is taken up by the metaprogramming library) | ||||||
| * Platform Layer: | * Platform Layer: | ||||||
|   * Block Memory allocation via VirtualAlloc for engine module |   * Block Memory allocation via VirtualAlloc for engine module | ||||||
|   * Memory mapped files for engine & game snapshots. |   * Memory mapped files for engine & game snapshots. | ||||||
| @@ -69,9 +75,14 @@ Features Done so far: | |||||||
|       * Linear alpha blending |       * Linear alpha blending | ||||||
|       * Anchored to center position |       * Anchored to center position | ||||||
|   * Experimental type sytem for physics vectors. |   * Experimental type sytem for physics vectors. | ||||||
|  |   * Basic local co-op support | ||||||
|  |     * Each player can be assigned a controller | ||||||
|  |     * So far only support for two players | ||||||
|  |   * Camera assignable to follow arbitary entity | ||||||
|  |  | ||||||
| ## Gallery | ## Gallery | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								docs/Day 045-6.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								docs/Day 045-6.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | # Day 45 | ||||||
|  |  | ||||||
|  | I had a long hiatus since the last time I updated this project: November 5th to December 29th!   | ||||||
|  | Coming back and making some headway again gave me some vitality. | ||||||
|  |  | ||||||
|  | # Day 46 | ||||||
|  |  | ||||||
|  | Took me quite a bit of time to get through this one. I wasn't a fan of the side-track at first to fix a bug by just straight up adding a feature, but it at least as completed in one session. I first implemented the input changes myself for the most part doing the minimal required to support 2 players. This route made more sense as the input setup used for this project has deviated a decent degree what Casey's implementation. I then got caught up and did the changes for entities and camera following. | ||||||
|  |  | ||||||
|  | Player's `ControllerState` is now a sort of assigned input tracker and the inputs are updated every frame to the latest polling. I keep track controller id for an xinput or dualsense pad and use that to determine assignment. What controllers are assigned depends on if a player has been assigned a controller yet. So its in order of first player 1 gets it when start is pressed then player 2. Keyboard & mouse is auto-assigned to player 1 (could change easily in the future). | ||||||
							
								
								
									
										
											BIN
										
									
								
								docs/imgs/handmade_win32_2023-12-30_01-52-23.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/imgs/handmade_win32_2023-12-30_01-52-23.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.6 MiB | 
| @@ -121,31 +121,25 @@ void input_poll_player_actions( hh::Player* player, b32 is_player_2 ) | |||||||
| 	{ | 	{ | ||||||
| 		DualsensePadState* pad = controller->ds_pad; | 		DualsensePadState* pad = controller->ds_pad; | ||||||
|  |  | ||||||
| 		actions->sprint |= pressed( pad->circle ); | 		actions->sprint |= pad->circle.ended_down; | ||||||
| 		actions->jump   |= pressed( pad->cross ); | 		actions->jump   |= pressed( pad->cross ); | ||||||
|  |  | ||||||
| 		actions->player_x_move_analog += pad->stick.left.X.end; | 		actions->player_x_move_analog += pad->stick.left.X.end; | ||||||
| 		actions->player_y_move_analog += pad->stick.left.Y.end; | 		actions->player_y_move_analog += pad->stick.left.Y.end; | ||||||
| 		 | 		 | ||||||
| 		if ( is_player_2 ) | 		actions->join |= pressed( pad->options ); | ||||||
| 		{ |  | ||||||
| 			actions->join |= pressed( pad->share ); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	if ( controller->xpad ) | 	if ( controller->xpad ) | ||||||
| 	{ | 	{ | ||||||
| 		XInputPadState* pad = controller->xpad; | 		XInputPadState* pad = controller->xpad; | ||||||
|  |  | ||||||
| 		actions->sprint |= pressed( pad->B ); | 		actions->sprint |= pad->B.ended_down; | ||||||
| 		actions->jump   |= pressed( pad->A ); | 		actions->jump   |= pressed( pad->A ); | ||||||
|  |  | ||||||
| 		actions->player_x_move_analog += pad->stick.left.X.end; | 		actions->player_x_move_analog += pad->stick.left.X.end; | ||||||
| 		actions->player_y_move_analog += pad->stick.left.Y.end; | 		actions->player_y_move_analog += pad->stick.left.Y.end; | ||||||
| 		 | 		 | ||||||
| 		if ( is_player_2 ) | 		actions->join |= pressed( pad->start ); | ||||||
| 		{ |  | ||||||
| 			actions->join |= pressed( pad->start ); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( controller->keyboard ) | 	if ( controller->keyboard ) | ||||||
| @@ -156,6 +150,8 @@ void input_poll_player_actions( hh::Player* player, b32 is_player_2 ) | |||||||
|  |  | ||||||
| 		actions->player_x_move_digital += keyboard->D.ended_down - keyboard->A.ended_down; | 		actions->player_x_move_digital += keyboard->D.ended_down - keyboard->A.ended_down; | ||||||
| 		actions->player_y_move_digital += keyboard->W.ended_down - keyboard->S.ended_down; | 		actions->player_y_move_digital += keyboard->W.ended_down - keyboard->S.ended_down; | ||||||
|  | 		 | ||||||
|  | 		actions->join |= pressed( keyboard->enter ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( controller->mouse ) | 	if ( controller->mouse ) | ||||||
| @@ -408,6 +404,7 @@ s32 get_entity( hh::GameState* gs ) | |||||||
| 		hh::Entity* entity = & gs->entities[ id ]; | 		hh::Entity* entity = & gs->entities[ id ]; | ||||||
| 		if ( ! entity->exists ) | 		if ( ! entity->exists ) | ||||||
| 		{ | 		{ | ||||||
|  | 			* entity = {}; | ||||||
| 			entity->exists = true; | 			entity->exists = true; | ||||||
| 			return id + 1; | 			return id + 1; | ||||||
| 		} | 		} | ||||||
| @@ -429,6 +426,8 @@ void player_init( hh::Player* player, hh::GameState* gs ) | |||||||
| 	 | 	 | ||||||
| 	hh::Entity* entity = get_entity( gs, entity_id ); | 	hh::Entity* entity = get_entity( gs, entity_id ); | ||||||
| 	 | 	 | ||||||
|  | 	entity->kind = hh::EntityKind_Hero; | ||||||
|  | 	 | ||||||
| 	entity->position.tile_x    = 4; | 	entity->position.tile_x    = 4; | ||||||
| 	entity->position.tile_y    = 4; | 	entity->position.tile_y    = 4; | ||||||
| 	entity->position.rel_pos.x = 0.f; | 	entity->position.rel_pos.x = 0.f; | ||||||
| @@ -442,18 +441,17 @@ void player_init( hh::Player* player, hh::GameState* gs ) | |||||||
| 	entity->height = 1.4f; | 	entity->height = 1.4f; | ||||||
| 	entity->width  = entity->height * 0.7f; | 	entity->width  = entity->height * 0.7f; | ||||||
| 	 | 	 | ||||||
| 	state->hero_direction = hh::HeroBitmaps_Front; | 	entity->facing_direction = hh::FacingDirection_Front; | ||||||
| 	 | 	 | ||||||
| 	player->entity_id = entity_id;  | 	player->entity_id = entity_id;  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Update mouse & keyboard states for player 1 | // TODO(Ed) : Make a menu down the line to allow the player to assign an input device to a player. | ||||||
| void update_player_controllers( hh::GameState* gs, InputState* input ) | void update_player_controllers( hh::GameState* gs, InputState* input ) | ||||||
| {	 | {	 | ||||||
| 	gs->player_1.controller.keyboard = input->keyboard; | 	gs->player_1.controller.keyboard = input->keyboard; | ||||||
| 	gs->player_1.controller.mouse    = input->mouse; | 	gs->player_1.controller.mouse    = input->mouse; | ||||||
|  |  | ||||||
| 	// Update controller states for the players |  | ||||||
| 	for ( s32 id = 1; id <= Max_Controllers; ++ id ) | 	for ( s32 id = 1; id <= Max_Controllers; ++ id ) | ||||||
| 	{ | 	{ | ||||||
| 		XInputPadState*    xpad   = input->xpads  [ id - 1 ]; | 		XInputPadState*    xpad   = input->xpads  [ id - 1 ]; | ||||||
| @@ -493,9 +491,6 @@ void update_player_controllers( hh::GameState* gs, InputState* input ) | |||||||
| 			{ | 			{ | ||||||
| 				gs->player_2.controller.xpad_id = id; | 				gs->player_2.controller.xpad_id = id; | ||||||
| 				gs->player_2.controller.xpad    = xpad; | 				gs->player_2.controller.xpad    = xpad; | ||||||
| 				do_once() { |  | ||||||
| 					player_init( & gs->player_2, gs ); |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| @@ -512,9 +507,6 @@ void update_player_controllers( hh::GameState* gs, InputState* input ) | |||||||
| 			{ | 			{ | ||||||
| 				gs->player_2.controller.ds_pad_id = id; | 				gs->player_2.controller.ds_pad_id = id; | ||||||
| 				gs->player_2.controller.ds_pad    = ds_pad; | 				gs->player_2.controller.ds_pad    = ds_pad; | ||||||
| 				do_once() { |  | ||||||
| 					player_init( & gs->player_2, gs ); |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	#undef can_assign | 	#undef can_assign | ||||||
| @@ -525,9 +517,17 @@ void update_player_controllers( hh::GameState* gs, InputState* input ) | |||||||
| internal | internal | ||||||
| void update_player( hh::Player* player, f32 delta_time, World* world, hh::GameState* gs ) | void update_player( hh::Player* player, f32 delta_time, World* world, hh::GameState* gs ) | ||||||
| { | { | ||||||
| 	hh::PlayerState*   state   = & player->state; |  | ||||||
| 	hh::Entity*        entity  = get_entity( gs, player->entity_id ); |  | ||||||
| 	hh::PlayerActions* actions = & player->actions; | 	hh::PlayerActions* actions = & player->actions; | ||||||
|  | 	if ( actions->join && ! player->entity_id ) {  | ||||||
|  | 		player_init( player, gs ); | ||||||
|  | 		gs->camera_assigned_entity_id = player->entity_id; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if ( ! player->entity_id ) | ||||||
|  | 		return; | ||||||
|  | 	 | ||||||
|  | 	hh::PlayerState* state  = & player->state; | ||||||
|  | 	hh::Entity*      entity = get_entity( gs, player->entity_id ); | ||||||
|  |  | ||||||
| 	TileMap* tile_map = world->tile_map; | 	TileMap* tile_map = world->tile_map; | ||||||
|  |  | ||||||
| @@ -715,27 +715,37 @@ void update_player( hh::Player* player, f32 delta_time, World* world, hh::GameSt | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	using hh::EHeroBitmapsDirection; | 	using hh::EFacingDirection; | ||||||
| 	using hh::HeroBitmaps_Front; | 	using hh::FacingDirection_Front; | ||||||
| 	using hh::HeroBitmaps_Back; | 	using hh::FacingDirection_Back; | ||||||
| 	using hh::HeroBitmaps_Left; | 	using hh::FacingDirection_Left; | ||||||
| 	using hh::HeroBitmaps_Right; | 	using hh::FacingDirection_Right; | ||||||
|  | 	 | ||||||
| 	if ( actions->player_y_move_digital > 0 || actions->player_y_move_analog > 0 ) | 	if ( is_nearly_zero( entity->move_velocity.x ) && is_nearly_zero( entity->move_velocity.y ) ) | ||||||
| 	{ | 	{ | ||||||
| 		state->hero_direction = HeroBitmaps_Back; | 		// Note(Ed): Leave facing directiona alone | ||||||
| 	} | 	} | ||||||
| 	if ( actions->player_y_move_digital < 0 || actions->player_y_move_analog < 0 ) | 	else if ( abs( entity->move_velocity.x ) > abs( entity->move_velocity.y ) ) | ||||||
| 	{ | 	{ | ||||||
| 		state->hero_direction = HeroBitmaps_Front; | 		if ( entity->move_velocity.x > 0 ) | ||||||
|  | 		{ | ||||||
|  | 			entity->facing_direction = FacingDirection_Right; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			entity->facing_direction = FacingDirection_Left; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	if ( actions->player_x_move_digital > 0 || actions->player_x_move_analog > 0 ) | 	else if ( abs( entity->move_velocity.x ) < abs( entity->move_velocity.y ) ) | ||||||
| 	{ | 	{ | ||||||
| 		state->hero_direction = HeroBitmaps_Right; | 		if ( entity->move_velocity.y >= 0 ) | ||||||
| 	} | 		{ | ||||||
| 	if ( actions->player_x_move_digital < 0 || actions->player_x_move_analog < 0 ) | 			entity->facing_direction = FacingDirection_Back; | ||||||
| 	{ | 		} | ||||||
| 		state->hero_direction = HeroBitmaps_Left; | 		else | ||||||
|  | 		{ | ||||||
|  | 			entity->facing_direction = FacingDirection_Front; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( state->jump_time > 0.f ) | 	if ( state->jump_time > 0.f ) | ||||||
| @@ -755,13 +765,10 @@ void update_player( hh::Player* player, f32 delta_time, World* world, hh::GameSt | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| void render_player( hh::Player* player, World* world, hh::GameState* gs, OffscreenBuffer* back_buffer ) | void render_player( hh::Entity* entity, World* world, hh::GameState* gs, OffscreenBuffer* back_buffer ) | ||||||
| { | { | ||||||
| 	Vec2 screen_center = get_screen_center( back_buffer ); | 	Vec2 screen_center = get_screen_center( back_buffer ); | ||||||
| 	 | 	 | ||||||
| 	hh::Entity*      entity = get_entity( gs, player->entity_id ); |  | ||||||
| 	hh::PlayerState* state  = & player->state; |  | ||||||
|  |  | ||||||
| 	f32 player_red   = 0.7f; | 	f32 player_red   = 0.7f; | ||||||
| 	f32 player_green = 0.7f; | 	f32 player_green = 0.7f; | ||||||
| 	f32 player_blue  = 0.3f; | 	f32 player_blue  = 0.3f; | ||||||
| @@ -779,7 +786,7 @@ void render_player( hh::Player* player, World* world, hh::GameState* gs, Offscre | |||||||
| 	}; | 	}; | ||||||
| 	Pos2 player_ground_pos = cast( Pos2, screen_center + player_to_screenspace * world->tile_meters_to_pixels ); | 	Pos2 player_ground_pos = cast( Pos2, screen_center + player_to_screenspace * world->tile_meters_to_pixels ); | ||||||
|  |  | ||||||
| 	hh::HeroBitmaps* hero_bitmaps = & gs->hero_bitmaps[state->hero_direction]; | 	hh::HeroBitmaps* hero_bitmaps = & gs->hero_bitmaps[entity->facing_direction]; | ||||||
|  |  | ||||||
| #if 1 | #if 1 | ||||||
| 	Vec2 player_collision_min { | 	Vec2 player_collision_min { | ||||||
| @@ -802,15 +809,19 @@ void render_player( hh::Player* player, World* world, hh::GameState* gs, Offscre | |||||||
| 	draw_bitmap( back_buffer | 	draw_bitmap( back_buffer | ||||||
| 		, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) } | 		, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) } | ||||||
| 		, & hero_bitmaps->cape ); | 		, & hero_bitmaps->cape ); | ||||||
| #if 1 |  | ||||||
| 	draw_bitmap( back_buffer | 	if ( entity == get_entity( gs, gs->player_1.entity_id ) ) | ||||||
| 		, { player_ground_pos.x, player_ground_pos.y - 125.f } | 	{ | ||||||
| 		, & gs->mojito_head ); | 		draw_bitmap( back_buffer | ||||||
| #else | 			, { player_ground_pos.x, player_ground_pos.y - 125.f } | ||||||
| 	draw_bitmap( back_buffer | 			, & gs->mojito_head ); | ||||||
| 		, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) } | 	} | ||||||
| 		, & hero_bitmaps->head ); | 	else | ||||||
| #endif | 	{ | ||||||
|  | 		draw_bitmap( back_buffer | ||||||
|  | 			, { player_ground_pos.x, player_ground_pos.y - scast(f32, hero_bitmaps->align_y) } | ||||||
|  | 			, & hero_bitmaps->head ); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| Engine_API | Engine_API | ||||||
| @@ -1097,36 +1108,36 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* | |||||||
| 			container = load_bmp( platform_api, path );                       \ | 			container = load_bmp( platform_api, path );                       \ | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		using hh::HeroBitmaps_Front; | 		using hh::FacingDirection_Front; | ||||||
| 		using hh::HeroBitmaps_Back; | 		using hh::FacingDirection_Back; | ||||||
| 		using hh::HeroBitmaps_Left; | 		using hh::FacingDirection_Left; | ||||||
| 		using hh::HeroBitmaps_Right; | 		using hh::FacingDirection_Right; | ||||||
|  |  | ||||||
| 		load_bmp_asset( subpath_hero_front_head, gs->hero_bitmaps[HeroBitmaps_Front].head ); | 		load_bmp_asset( subpath_hero_front_head, gs->hero_bitmaps[FacingDirection_Front].head ); | ||||||
| 		load_bmp_asset( subpath_hero_back_head,  gs->hero_bitmaps[HeroBitmaps_Back ].head ); | 		load_bmp_asset( subpath_hero_back_head,  gs->hero_bitmaps[FacingDirection_Back ].head ); | ||||||
| 		load_bmp_asset( subpath_hero_left_head,  gs->hero_bitmaps[HeroBitmaps_Left ].head ); | 		load_bmp_asset( subpath_hero_left_head,  gs->hero_bitmaps[FacingDirection_Left ].head ); | ||||||
| 		load_bmp_asset( subpath_hero_right_head, gs->hero_bitmaps[HeroBitmaps_Right].head ); | 		load_bmp_asset( subpath_hero_right_head, gs->hero_bitmaps[FacingDirection_Right].head ); | ||||||
|  |  | ||||||
| 		load_bmp_asset( subpath_hero_front_cape, gs->hero_bitmaps[HeroBitmaps_Front].cape ); | 		load_bmp_asset( subpath_hero_front_cape, gs->hero_bitmaps[FacingDirection_Front].cape ); | ||||||
| 		load_bmp_asset( subpath_hero_back_cape,  gs->hero_bitmaps[HeroBitmaps_Back ].cape ); | 		load_bmp_asset( subpath_hero_back_cape,  gs->hero_bitmaps[FacingDirection_Back ].cape ); | ||||||
| 		load_bmp_asset( subpath_hero_left_cape,  gs->hero_bitmaps[HeroBitmaps_Left ].cape ); | 		load_bmp_asset( subpath_hero_left_cape,  gs->hero_bitmaps[FacingDirection_Left ].cape ); | ||||||
| 		load_bmp_asset( subpath_hero_right_cape, gs->hero_bitmaps[HeroBitmaps_Right].cape ); | 		load_bmp_asset( subpath_hero_right_cape, gs->hero_bitmaps[FacingDirection_Right].cape ); | ||||||
|  |  | ||||||
| 		load_bmp_asset( subpath_hero_front_torso, gs->hero_bitmaps[HeroBitmaps_Front].torso ); | 		load_bmp_asset( subpath_hero_front_torso, gs->hero_bitmaps[FacingDirection_Front].torso ); | ||||||
| 		load_bmp_asset( subpath_hero_back_torso,  gs->hero_bitmaps[HeroBitmaps_Back ].torso ); | 		load_bmp_asset( subpath_hero_back_torso,  gs->hero_bitmaps[FacingDirection_Back ].torso ); | ||||||
| 		load_bmp_asset( subpath_hero_left_torso,  gs->hero_bitmaps[HeroBitmaps_Left ].torso ); | 		load_bmp_asset( subpath_hero_left_torso,  gs->hero_bitmaps[FacingDirection_Left ].torso ); | ||||||
| 		load_bmp_asset( subpath_hero_right_torso, gs->hero_bitmaps[HeroBitmaps_Right].torso ); | 		load_bmp_asset( subpath_hero_right_torso, gs->hero_bitmaps[FacingDirection_Right].torso ); | ||||||
|  |  | ||||||
| 		s32 align_x = 0; | 		s32 align_x = 0; | ||||||
| 		s32 align_y = 76; | 		s32 align_y = 76; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Front].align_x = align_x; | 		gs->hero_bitmaps[FacingDirection_Front].align_x = align_x; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Back ].align_x = align_x; | 		gs->hero_bitmaps[FacingDirection_Back ].align_x = align_x; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Left ].align_x = align_x; | 		gs->hero_bitmaps[FacingDirection_Left ].align_x = align_x; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Right].align_x = align_x; | 		gs->hero_bitmaps[FacingDirection_Right].align_x = align_x; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Front].align_y = align_y; | 		gs->hero_bitmaps[FacingDirection_Front].align_y = align_y; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Back ].align_y = align_y; | 		gs->hero_bitmaps[FacingDirection_Back ].align_y = align_y; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Left ].align_y = align_y; | 		gs->hero_bitmaps[FacingDirection_Left ].align_y = align_y; | ||||||
| 		gs->hero_bitmaps[HeroBitmaps_Right].align_y = align_y; | 		gs->hero_bitmaps[FacingDirection_Right].align_y = align_y; | ||||||
|  |  | ||||||
| 	#undef load_bmp_asset | 	#undef load_bmp_asset | ||||||
| 	} | 	} | ||||||
| @@ -1134,11 +1145,10 @@ void startup( OffscreenBuffer* back_buffer, Memory* memory, platform::ModuleAPI* | |||||||
| 	gs->camera_pos.tile_x = world->tiles_per_screen_x / 2; | 	gs->camera_pos.tile_x = world->tiles_per_screen_x / 2; | ||||||
| 	gs->camera_pos.tile_y = world->tiles_per_screen_y / 2; | 	gs->camera_pos.tile_y = world->tiles_per_screen_y / 2; | ||||||
| 	 | 	 | ||||||
| 	using hh::HeroBitmaps_Front; | 	using hh::FacingDirection_Front; | ||||||
|  |  | ||||||
| 	player_init( & gs->player_1, gs ); | //	gs->player_1 = {}; | ||||||
| //	player_init( & gs->player_2, gs ); | //	gs->player_2 = {}; | ||||||
| 	gs->player_2 = {}; |  | ||||||
|  |  | ||||||
| 	gs->camera_assigned_entity_id = gs->player_1.entity_id; | 	gs->camera_assigned_entity_id = gs->player_1.entity_id; | ||||||
| } | } | ||||||
| @@ -1298,21 +1308,17 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | |||||||
| 	update_player_controllers( gs, input ); | 	update_player_controllers( gs, input ); | ||||||
| 	 | 	 | ||||||
| 	input_poll_player_actions( & gs->player_1, 0 ); | 	input_poll_player_actions( & gs->player_1, 0 ); | ||||||
| 	 | 	input_poll_player_actions( & gs->player_2, 1 ); | ||||||
| 	if ( gs->player_2.controller.xpad || gs->player_2.controller.ds_pad ) |  | ||||||
| 		input_poll_player_actions( & gs->player_2, 1 ); |  | ||||||
|  |  | ||||||
| 	World*   world    = state->context.world; | 	World*   world    = state->context.world; | ||||||
| 	TileMap* tile_map = world->tile_map; | 	TileMap* tile_map = world->tile_map; | ||||||
|  |  | ||||||
| 	update_player( & gs->player_1, delta_time, world, gs ); | 	update_player( & gs->player_1, delta_time, world, gs ); | ||||||
| 	 | 	update_player( & gs->player_2, delta_time, world, gs ); | ||||||
| 	if ( gs->player_2.entity_id ) |  | ||||||
| 		update_player( & gs->player_2, delta_time, world, gs ); |  | ||||||
| 	 | 	 | ||||||
| 	// TODO(Ed) : Move to handmade module? | 	// TODO(Ed) : Move to handmade module? | ||||||
| 	// Camera Update | 	// Camera Update | ||||||
| 	// void update_camera( ... ) | 	if ( gs->camera_assigned_entity_id ) | ||||||
| 	{ | 	{ | ||||||
| 		hh::Entity* entity_followed = get_entity( gs, gs->camera_assigned_entity_id ); | 		hh::Entity* entity_followed = get_entity( gs, gs->camera_assigned_entity_id ); | ||||||
| 		TileMapPos player_to_camera = subtract( entity_followed->position, gs->camera_pos ); | 		TileMapPos player_to_camera = subtract( entity_followed->position, gs->camera_pos ); | ||||||
| @@ -1339,11 +1345,11 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | |||||||
| 	 | 	 | ||||||
| 	Vec2 screen_center = get_screen_center( back_buffer ); | 	Vec2 screen_center = get_screen_center( back_buffer ); | ||||||
| 	 | 	 | ||||||
| 	// Background & Tile Render relative to player 1's camera | 	// Background & Tile Render relative to assigned entity | ||||||
| 	// void render_bg_and_level( ... ) | 	// void render_bg_and_level( ... ) | ||||||
| 	{ | 	{ | ||||||
| 		hh::Entity* entity_followed = get_entity( gs, gs->camera_assigned_entity_id ); | 		hh::Entity* entity_followed = get_entity( gs, gs->camera_assigned_entity_id ); | ||||||
| 		 | 			 | ||||||
| 		draw_rectangle( back_buffer | 		draw_rectangle( back_buffer | ||||||
| 			, Zero(Vec2) | 			, Zero(Vec2) | ||||||
| 			, { scast(f32, back_buffer->width), scast(f32, back_buffer->height) } | 			, { scast(f32, back_buffer->width), scast(f32, back_buffer->height) } | ||||||
| @@ -1363,7 +1369,7 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | |||||||
| 				s32 tile_id  = TileMap_get_tile_value( tile_map, col, row, gs->camera_pos.tile_z ); | 				s32 tile_id  = TileMap_get_tile_value( tile_map, col, row, gs->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 == entity_followed->position.tile_y && col == entity_followed->position.tile_x) ) | 				if ( tile_id > 1 || (entity_followed && row == entity_followed->position.tile_y && col == entity_followed->position.tile_x) ) | ||||||
| //				if ( tile_id > 1 ) | //				if ( tile_id > 1 ) | ||||||
| 				{ | 				{ | ||||||
| 					if ( tile_id == 2 ) | 					if ( tile_id == 2 ) | ||||||
| @@ -1385,7 +1391,7 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | |||||||
| 						color[2] = 0.42f; | 						color[2] = 0.42f; | ||||||
| 					} | 					} | ||||||
| 	 | 	 | ||||||
| 					if ( row == entity_followed->position.tile_y && col == entity_followed->position.tile_x ) | 					if ( entity_followed && row == entity_followed->position.tile_y && col == entity_followed->position.tile_x ) | ||||||
| 					{ | 					{ | ||||||
| 						color[0] = 0.44f; | 						color[0] = 0.44f; | ||||||
| 						color[1] = 0.3f; | 						color[1] = 0.3f; | ||||||
| @@ -1427,11 +1433,22 @@ void update_and_render( f32 delta_time, InputState* input, OffscreenBuffer* back | |||||||
| 	} | 	} | ||||||
| 	#endif | 	#endif | ||||||
|  |  | ||||||
| 	// Player Rendering | 	// Render Entities | ||||||
| 	render_player( & gs->player_1, world, gs, back_buffer ); | 	{	 | ||||||
| 	 | 		s32         id     = array_count(gs->entities);  | ||||||
| 	if ( gs->player_2.entity_id ) | 		hh::Entity* entity = gs->entities;  | ||||||
| 		render_player( & gs->player_2, world, gs, back_buffer ); | 		for (; id; -- id, ++ entity ) | ||||||
|  | 		{ | ||||||
|  | 			if ( ! entity->exists ) | ||||||
|  | 				continue; | ||||||
|  | 			 | ||||||
|  | 			switch ( entity->kind ) | ||||||
|  | 			{ | ||||||
|  | 				case hh::EntityKind_Hero: | ||||||
|  | 					render_player( entity, world, gs, back_buffer ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	 | 	 | ||||||
| 	// Snapshot Visual Aid | 	// Snapshot Visual Aid | ||||||
| 	#if Build_Development | 	#if Build_Development | ||||||
|   | |||||||
| @@ -52,6 +52,7 @@ union KeyboardState | |||||||
| 		DigitalBtn L; | 		DigitalBtn L; | ||||||
| 		DigitalBtn escape; | 		DigitalBtn escape; | ||||||
| 		DigitalBtn backspace; | 		DigitalBtn backspace; | ||||||
|  | 		DigitalBtn enter; | ||||||
| 		DigitalBtn up; | 		DigitalBtn up; | ||||||
| 		DigitalBtn down; | 		DigitalBtn down; | ||||||
| 		DigitalBtn left; | 		DigitalBtn left; | ||||||
|   | |||||||
| @@ -72,12 +72,17 @@ struct ControllerState | |||||||
| 	engine::DualsensePadState* ds_pad; | 	engine::DualsensePadState* ds_pad; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum EHeroBitmapsDirection : u32 | enum EFacingDirection : u32 | ||||||
| { | { | ||||||
| 	HeroBitmaps_Front, | 	FacingDirection_Front, | ||||||
| 	HeroBitmaps_Back, | 	FacingDirection_Back, | ||||||
| 	HeroBitmaps_Left, | 	FacingDirection_Left, | ||||||
| 	HeroBitmaps_Right | 	FacingDirection_Right | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum EEntityKind : u32 | ||||||
|  | { | ||||||
|  | 	EntityKind_Hero, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct HeroBitmaps | struct HeroBitmaps | ||||||
| @@ -94,11 +99,15 @@ struct HeroBitmaps | |||||||
|  |  | ||||||
| struct Entity | struct Entity | ||||||
| { | { | ||||||
|  | 	EEntityKind kind; | ||||||
|  |  | ||||||
| 	b32 exists; | 	b32 exists; | ||||||
| 	 | 	 | ||||||
| 	f32 width; | 	f32 width; | ||||||
| 	f32 height; | 	f32 height; | ||||||
| 	 | 	 | ||||||
|  | 	EFacingDirection facing_direction; | ||||||
|  | 	 | ||||||
| 	engine::TileMapPos position; | 	engine::TileMapPos position; | ||||||
| 	Vel2               move_velocity; | 	Vel2               move_velocity; | ||||||
| }; | }; | ||||||
| @@ -107,8 +116,6 @@ struct PlayerState | |||||||
| { | { | ||||||
| 	b32 mid_jump; | 	b32 mid_jump; | ||||||
| 	f32 jump_time; | 	f32 jump_time; | ||||||
| 	 |  | ||||||
| 	EHeroBitmapsDirection hero_direction; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct PlayerActions | struct PlayerActions | ||||||
| @@ -129,9 +136,8 @@ struct Player | |||||||
| 	// So far just has an assigned controller. | 	// So far just has an assigned controller. | ||||||
| 	ControllerState controller; | 	ControllerState controller; | ||||||
| 	 | 	 | ||||||
| 	s32             entity_id; | 	s32         entity_id; | ||||||
| 	//Entity          entity; | 	PlayerState state; | ||||||
| 	PlayerState     state; |  | ||||||
| 	 | 	 | ||||||
| 	// TODO(Ed) : If the player ever gets different actions depending on a context, change it here. | 	// TODO(Ed) : If the player ever gets different actions depending on a context, change it here. | ||||||
| 	PlayerActions actions; | 	PlayerActions actions; | ||||||
|   | |||||||
| @@ -30,7 +30,6 @@ | |||||||
| 	}                      \ | 	}                      \ | ||||||
| 	while(0); | 	while(0); | ||||||
|  |  | ||||||
|  |  | ||||||
| #define array_count( array ) ( sizeof( array ) / sizeof( ( array )[0] ) ) | #define array_count( array ) ( sizeof( array ) / sizeof( ( array )[0] ) ) | ||||||
|  |  | ||||||
| // TODO(Ed) : Move to memory header eventually | // TODO(Ed) : Move to memory header eventually | ||||||
|   | |||||||
| @@ -86,6 +86,7 @@ poll_input( HWND window_handle, engine::InputState* input, u32 jsl_num_devices, | |||||||
| 		input_process_digital_btn( & old_keyboard->L,           & new_keyboard->L,           GetAsyncKeyState( 'L' ),       is_down ); | 		input_process_digital_btn( & old_keyboard->L,           & new_keyboard->L,           GetAsyncKeyState( 'L' ),       is_down ); | ||||||
| 		input_process_digital_btn( & old_keyboard->escape,      & new_keyboard->escape,      GetAsyncKeyState( VK_ESCAPE ), is_down ); | 		input_process_digital_btn( & old_keyboard->escape,      & new_keyboard->escape,      GetAsyncKeyState( VK_ESCAPE ), is_down ); | ||||||
| 		input_process_digital_btn( & old_keyboard->backspace,   & new_keyboard->backspace,   GetAsyncKeyState( VK_BACK ),   is_down ); | 		input_process_digital_btn( & old_keyboard->backspace,   & new_keyboard->backspace,   GetAsyncKeyState( VK_BACK ),   is_down ); | ||||||
|  | 		input_process_digital_btn( & old_keyboard->enter,       & new_keyboard->enter,       GetAsyncKeyState( VK_RETURN ), is_down ); | ||||||
| 		input_process_digital_btn( & old_keyboard->up,          & new_keyboard->up,          GetAsyncKeyState( VK_UP ),     is_down ); | 		input_process_digital_btn( & old_keyboard->up,          & new_keyboard->up,          GetAsyncKeyState( VK_UP ),     is_down ); | ||||||
| 		input_process_digital_btn( & old_keyboard->down,        & new_keyboard->down,        GetAsyncKeyState( VK_DOWN ),   is_down ); | 		input_process_digital_btn( & old_keyboard->down,        & new_keyboard->down,        GetAsyncKeyState( VK_DOWN ),   is_down ); | ||||||
| 		input_process_digital_btn( & old_keyboard->left,        & new_keyboard->left,        GetAsyncKeyState( VK_LEFT ),   is_down ); | 		input_process_digital_btn( & old_keyboard->left,        & new_keyboard->left,        GetAsyncKeyState( VK_LEFT ),   is_down ); | ||||||
|   | |||||||
| @@ -100,12 +100,13 @@ $stack_size = 1024 * 1024 * 4 | |||||||
|  |  | ||||||
| $compiler_args = @( | $compiler_args = @( | ||||||
| 	($flag_define + 'UNICODE'), | 	($flag_define + 'UNICODE'), | ||||||
| 	($flag_define + '_UNICODE') | 	($flag_define + '_UNICODE'), | ||||||
| 	( $flag_define + 'INTELLISENSE_DIRECTIVES=0'), | 	( $flag_define + 'INTELLISENSE_DIRECTIVES=0'), | ||||||
| 	# ($flag_set_stack_size + $stack_size) | 	# ($flag_set_stack_size + $stack_size) | ||||||
| 	$flag_wall | 	$flag_wall, | ||||||
| 	$flag_warnings_as_errors | 	$flag_warnings_as_errors, | ||||||
| 	$flag_optimize_intrinsics | 	$flag_optimize_intrinsics | ||||||
|  | 	#( $flag_language_standard + 'c++17' ) | ||||||
| ) | ) | ||||||
|  |  | ||||||
| if ( $dev ) { | if ( $dev ) { | ||||||
|   | |||||||
| @@ -105,6 +105,7 @@ if ( $vendor -match "clang" ) | |||||||
| 	$flag_include                      = '-I' | 	$flag_include                      = '-I' | ||||||
| 	$flag_section_data                 = '-fdata-sections' | 	$flag_section_data                 = '-fdata-sections' | ||||||
| 	$flag_section_functions            = '-ffunction-sections' | 	$flag_section_functions            = '-ffunction-sections' | ||||||
|  | 	$flag_langauge_standard            = '-std=' | ||||||
| 	$flag_library					   = '-l' | 	$flag_library					   = '-l' | ||||||
| 	$flag_library_path				   = '-L' | 	$flag_library_path				   = '-L' | ||||||
| 	$flag_linker                       = '-Wl,' | 	$flag_linker                       = '-Wl,' | ||||||
| @@ -247,6 +248,7 @@ if ( $vendor -match "msvc" ) | |||||||
| 	$flag_RTTI_disabled				 = '/GR-' | 	$flag_RTTI_disabled				 = '/GR-' | ||||||
| 	$flag_include                    = '/I' | 	$flag_include                    = '/I' | ||||||
| 	$flag_full_src_path              = '/FC' | 	$flag_full_src_path              = '/FC' | ||||||
|  | 	$flag_language_standard          = '/std:' | ||||||
| 	$flag_nologo                     = '/nologo' | 	$flag_nologo                     = '/nologo' | ||||||
| 	$flag_dll 				         = '/LD' | 	$flag_dll 				         = '/LD' | ||||||
| 	$flag_dll_debug 			     = '/LDd' | 	$flag_dll_debug 			     = '/LDd' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user