Add ability to shoot and delete entities
This commit is contained in:
		
							parent
							
								
									6069ed8415
								
							
						
					
					
						commit
						42ba86f05a
					
				
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										205
									
								
								src/Asteroid.c
									
									
									
									
									
								
							
							
						
						
									
										205
									
								
								src/Asteroid.c
									
									
									
									
									
								
							| @ -183,6 +183,8 @@ v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations, | |||||||
| 		result[i] = V2(((math_cosf(iterationAngle * i) + 1) * asteroidRadius), | 		result[i] = V2(((math_cosf(iterationAngle * i) + 1) * asteroidRadius), | ||||||
| 		               ((math_sinf(iterationAngle * i) + 1) * asteroidRadius)); | 		               ((math_sinf(iterationAngle * i) + 1) * asteroidRadius)); | ||||||
| 
 | 
 | ||||||
|  | 		ASSERT(result[i].x >= 0 && result[i].y >= 0); | ||||||
|  | 
 | ||||||
| #if 1 | #if 1 | ||||||
| 		f32 displacementDist   = 0.50f * asteroidRadius; | 		f32 displacementDist   = 0.50f * asteroidRadius; | ||||||
| 		i32 vertexDisplacement = | 		i32 vertexDisplacement = | ||||||
| @ -284,8 +286,9 @@ b32 checkEdgeProjectionOverlap(v2 *vertexList, i32 listSize, | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| b32 moveEntity(GameState *state, Entity *entity, i32 entityIndex, v2 ddP, | INTERNAL b32 moveEntity(World *world, MemoryArena_ *transientArena, | ||||||
|                f32 dt, f32 ddPSpeed) |                         Entity *entity, i32 entityIndex, v2 ddP, f32 dt, | ||||||
|  |                         f32 ddPSpeed) | ||||||
| { | { | ||||||
| 	ASSERT(ABS(ddP.x) <= 1.0f && ABS(ddP.y) <= 1.0f); | 	ASSERT(ABS(ddP.x) <= 1.0f && ABS(ddP.y) <= 1.0f); | ||||||
| 	/*
 | 	/*
 | ||||||
| @ -295,7 +298,7 @@ b32 moveEntity(GameState *state, Entity *entity, i32 entityIndex, v2 ddP, | |||||||
| 	    newPos = (a*t^2)/2 + oldVelocity*t + oldPos | 	    newPos = (a*t^2)/2 + oldVelocity*t + oldPos | ||||||
| 	*/ | 	*/ | ||||||
| 
 | 
 | ||||||
| 	ddP           = v2_scale(ddP, state->pixelsPerMeter * ddPSpeed); | 	ddP           = v2_scale(ddP, world->pixelsPerMeter * ddPSpeed); | ||||||
| 	v2 oldDp      = entity->dP; | 	v2 oldDp      = entity->dP; | ||||||
| 	v2 resistance = v2_scale(oldDp, 2.0f); | 	v2 resistance = v2_scale(oldDp, 2.0f); | ||||||
| 	ddP           = v2_sub(ddP, resistance); | 	ddP           = v2_sub(ddP, resistance); | ||||||
| @ -313,36 +316,37 @@ b32 moveEntity(GameState *state, Entity *entity, i32 entityIndex, v2 ddP, | |||||||
| 
 | 
 | ||||||
| 	// TODO(doyle): Collision for rects, (need to create vertex list for it)
 | 	// TODO(doyle): Collision for rects, (need to create vertex list for it)
 | ||||||
| #if 1 | #if 1 | ||||||
| 	if (entity->renderMode == rendermode_polygon && entity->collides) | 	for (i32 i = entityIndex + 1; i < world->entityIndex; i++) | ||||||
| 	{ | 	{ | ||||||
| 		for (i32 i = entityIndex + 1; i < state->entityIndex; i++) | 		Entity *checkEntity = &world->entityList[i]; | ||||||
| 		{ |  | ||||||
| 			Entity *checkEntity = &state->entityList[i]; |  | ||||||
| 		ASSERT(checkEntity->id != entity->id); | 		ASSERT(checkEntity->id != entity->id); | ||||||
| 
 | 
 | ||||||
| 			if (checkEntity->renderMode == rendermode_polygon && | 		if (world->collisionTable[entity->type][checkEntity->type]) | ||||||
| 			    checkEntity->collides) |  | ||||||
| 		{ | 		{ | ||||||
|  | 			ASSERT(entity->vertexPoints); | ||||||
|  | 			ASSERT(checkEntity->vertexPoints); | ||||||
|  | 
 | ||||||
| 			/* Create entity edge lists */ | 			/* Create entity edge lists */ | ||||||
| 				v2 *entityVertexListOffsetToP = | 			v2 *entityVertexListOffsetToP = entity_generateUpdatedVertexList( | ||||||
| 				    entity_createVertexList(&state->transientArena, entity); | 			    transientArena, entity); | ||||||
| 
 | 
 | ||||||
| 				v2 *checkEntityVertexListOffsetToP = entity_createVertexList( | 			v2 *checkEntityVertexListOffsetToP = | ||||||
| 				    &state->transientArena, checkEntity); | 			    entity_generateUpdatedVertexList(transientArena, | ||||||
|  | 			                                     checkEntity); | ||||||
| 
 | 
 | ||||||
| 				v2 *entityEdgeList = createNormalEdgeList( | 			v2 *entityEdgeList = createNormalEdgeList(transientArena, | ||||||
| 				    &state->transientArena, entityVertexListOffsetToP, | 			                                          entityVertexListOffsetToP, | ||||||
| 			                                          entity->numVertexPoints); | 			                                          entity->numVertexPoints); | ||||||
| 
 | 
 | ||||||
| 			v2 *checkEntityEdgeList = createNormalEdgeList( | 			v2 *checkEntityEdgeList = createNormalEdgeList( | ||||||
| 				    &state->transientArena, checkEntityVertexListOffsetToP, | 			    transientArena, checkEntityVertexListOffsetToP, | ||||||
| 			    checkEntity->numVertexPoints); | 			    checkEntity->numVertexPoints); | ||||||
| 
 | 
 | ||||||
| 			/* Combine both edge lists into one */ | 			/* Combine both edge lists into one */ | ||||||
| 			i32 totalNumEdges = | 			i32 totalNumEdges = | ||||||
| 			    checkEntity->numVertexPoints + entity->numVertexPoints; | 			    checkEntity->numVertexPoints + entity->numVertexPoints; | ||||||
| 				v2 *edgeList = memory_pushBytes(&state->transientArena, | 			v2 *edgeList = | ||||||
| 				                                totalNumEdges * sizeof(v2)); | 			    memory_pushBytes(transientArena, totalNumEdges * sizeof(v2)); | ||||||
| 			for (i32 i = 0; i < entity->numVertexPoints; i++) | 			for (i32 i = 0; i < entity->numVertexPoints; i++) | ||||||
| 			{ | 			{ | ||||||
| 				edgeList[i] = entityEdgeList[i]; | 				edgeList[i] = entityEdgeList[i]; | ||||||
| @ -350,8 +354,7 @@ b32 moveEntity(GameState *state, Entity *entity, i32 entityIndex, v2 ddP, | |||||||
| 
 | 
 | ||||||
| 			for (i32 i = 0; i < checkEntity->numVertexPoints; i++) | 			for (i32 i = 0; i < checkEntity->numVertexPoints; i++) | ||||||
| 			{ | 			{ | ||||||
| 					edgeList[i + entity->numVertexPoints] = | 				edgeList[i + entity->numVertexPoints] = checkEntityEdgeList[i]; | ||||||
| 					    checkEntityEdgeList[i]; |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (checkEdgeProjectionOverlap( | 			if (checkEdgeProjectionOverlap( | ||||||
| @ -363,11 +366,11 @@ b32 moveEntity(GameState *state, Entity *entity, i32 entityIndex, v2 ddP, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 			if (willCollide) { | 		if (willCollide) | ||||||
|  | 		{ | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
| @ -389,68 +392,106 @@ b32 moveEntity(GameState *state, Entity *entity, i32 entityIndex, v2 ddP, | |||||||
| 	return willCollide; | 	return willCollide; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| INTERNAL void addAsteroid(GameState *state, v2 windowSize) | INTERNAL void addAsteroid(World *world, v2 windowSize) | ||||||
| { | { | ||||||
| 	Entity *asteroid = &state->entityList[state->entityIndex]; | 	Entity *asteroid = &world->entityList[world->entityIndex++]; | ||||||
| 	asteroid->id     = state->entityIndex++; | 	asteroid->id     = world->entityIdCounter++; | ||||||
| 
 | 
 | ||||||
| 	i32 randValue = rand(); | 	i32 randValue = rand(); | ||||||
| 	i32 randX     = (randValue % (i32)windowSize.w); | 	i32 randX     = (randValue % (i32)windowSize.w); | ||||||
| 	i32 randY     = (randValue % (i32)windowSize.h); | 	i32 randY     = (randValue % (i32)windowSize.h); | ||||||
| 	asteroid->pos = V2i(randX, randY); | 	asteroid->pos = V2i(randX, randY); | ||||||
| 
 | 
 | ||||||
| 	asteroid->size       = V2(75.0f, 75.0f); | 	asteroid->size       = V2(100.0f, 100.0f); | ||||||
| 	asteroid->hitbox     = asteroid->size; | 	asteroid->hitbox     = asteroid->size; | ||||||
| 	asteroid->offset     = V2(asteroid->size.w * -0.5f, 0); | 	asteroid->offset     = v2_scale(asteroid->size, -0.5f); | ||||||
| 	asteroid->scale      = 1; |  | ||||||
| 	asteroid->rotation   = 45; |  | ||||||
| 	asteroid->type       = entitytype_asteroid; | 	asteroid->type       = entitytype_asteroid; | ||||||
| 	asteroid->direction  = direction_null; | 	asteroid->direction  = direction_null; | ||||||
| 	asteroid->renderMode = rendermode_polygon; | 	asteroid->renderMode = rendermode_polygon; | ||||||
| 
 | 
 | ||||||
| 	asteroid->numVertexPoints = 10; | 	asteroid->numVertexPoints = 10; | ||||||
| 	asteroid->vertexPoints    = createAsteroidVertexList( | 	asteroid->vertexPoints    = createAsteroidVertexList( | ||||||
| 	    &state->persistentArena, asteroid->numVertexPoints, | 	    &world->entityArena, asteroid->numVertexPoints, | ||||||
| 	    (i32)(asteroid->size.x * 0.5f)); | 	    (i32)(asteroid->size.w * 0.5f)); | ||||||
| 
 | 
 | ||||||
| 	asteroid->tex      = NULL; | 	asteroid->color = V4(0.0f, 0.5f, 0.5f, 1.0f); | ||||||
| 	asteroid->collides = TRUE; | } | ||||||
|  | 
 | ||||||
|  | INTERNAL void addBullet(World *world, Entity *shooter) | ||||||
|  | { | ||||||
|  | 	Entity *bullet = &world->entityList[world->entityIndex++]; | ||||||
|  | 	bullet->id     = world->entityIdCounter++; | ||||||
|  | 
 | ||||||
|  | 	bullet->offset     = v2_scale(bullet->size, -0.5f); | ||||||
|  | 	bullet->pos        = v2_add(shooter->pos, bullet->offset); | ||||||
|  | 	bullet->hitbox     = bullet->size; | ||||||
|  | 	bullet->size       = V2(2.0f, 20.0f); | ||||||
|  | 	bullet->rotation   = shooter->rotation; | ||||||
|  | 	bullet->renderMode = rendermode_quad; | ||||||
|  | 
 | ||||||
|  | 	// TODO(doyle): Figure out how to free this memory on entity delete. A free list?
 | ||||||
|  | 	bullet->vertexPoints = | ||||||
|  | 	    memory_pushBytes(&world->entityArena, sizeof(v2) * 4); | ||||||
|  | 	bullet->vertexPoints[0] = V2(0, bullet->size.h); | ||||||
|  | 	bullet->vertexPoints[1] = V2(0, 0); | ||||||
|  | 	bullet->vertexPoints[2] = V2(bullet->size.w, 0); | ||||||
|  | 	bullet->vertexPoints[3] = bullet->size; | ||||||
|  | 
 | ||||||
|  | 	bullet->numVertexPoints = 4; | ||||||
|  | 
 | ||||||
|  | 	bullet->type  = entitytype_bullet; | ||||||
|  | 	bullet->color = V4(1.0f, 1.0f, 0, 1.0f); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | INTERNAL void setCollisionRule(World *world, enum EntityType a, | ||||||
|  |                                enum EntityType b, b32 rule) | ||||||
|  | { | ||||||
|  | 	ASSERT(a <= entitytype_count); | ||||||
|  | 	ASSERT(b <= entitytype_count); | ||||||
|  | 	world->collisionTable[a][b] = rule; | ||||||
|  | 	world->collisionTable[b][a] = rule; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | ||||||
|                                   v2 windowSize, f32 dt) |                                   v2 windowSize, f32 dt) | ||||||
| { | { | ||||||
|  | 	MemoryIndex globalTransientArenaSize = | ||||||
|  | 	    (MemoryIndex)((f32)memory->transientSize * 0.5f); | ||||||
| 	memory_arenaInit(&state->transientArena, memory->transient, | 	memory_arenaInit(&state->transientArena, memory->transient, | ||||||
| 	                 memory->transientSize); | 	                 globalTransientArenaSize); | ||||||
| 
 | 
 | ||||||
|  | 	World *world = &state->world; | ||||||
| 	if (!state->init) | 	if (!state->init) | ||||||
| 	{ | 	{ | ||||||
| 		srand((u32)time(NULL)); | 		srand((u32)time(NULL)); | ||||||
| 		memory_arenaInit(&state->persistentArena, memory->persistent, |  | ||||||
| 		                 memory->persistentSize); |  | ||||||
| 		initAssetManager(state); | 		initAssetManager(state); | ||||||
| 		initRenderer(state, windowSize); | 		initRenderer(state, windowSize); | ||||||
| 
 | 
 | ||||||
| 		state->pixelsPerMeter = 70.0f; | 		world->pixelsPerMeter = 70.0f; | ||||||
|  | 
 | ||||||
|  | 		MemoryIndex entityArenaSize = | ||||||
|  | 		    (MemoryIndex)((f32)memory->transientSize * 0.5f); | ||||||
|  | 
 | ||||||
|  | 		u8 *arenaBase = state->transientArena.base + state->transientArena.size; | ||||||
|  | 		memory_arenaInit(&world->entityArena, arenaBase, entityArenaSize); | ||||||
| 
 | 
 | ||||||
| 		{ // Init asteroid entities
 | 		{ // Init asteroid entities
 | ||||||
| 			i32 numAsteroids = 15; | 			i32 numAsteroids = 15; | ||||||
| 			for (i32 i = 0; i < numAsteroids; i++) | 			for (i32 i = 0; i < numAsteroids; i++) | ||||||
| 				addAsteroid(state, windowSize); | 				addAsteroid(world, windowSize); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| #if 1 |  | ||||||
| 		{ // Init ship entity
 | 		{ // Init ship entity
 | ||||||
| 			Entity *ship     = &state->entityList[state->entityIndex]; | 			Entity *ship     = &world->entityList[world->entityIndex++]; | ||||||
| 			ship->id         = state->entityIndex++; | 			ship->id         = world->entityIdCounter++; | ||||||
| 			ship->pos        = V2(100, 100); | 			ship->pos        = V2(100, 100); | ||||||
| 			ship->size       = V2(25.0f, 50.0f); | 			ship->size       = V2(25.0f, 50.0f); | ||||||
| 			ship->hitbox     = ship->size; | 			ship->hitbox     = ship->size; | ||||||
| 			ship->offset     = v2_scale(ship->size, 0.5f); | 			ship->offset     = v2_scale(ship->size, -0.5f); | ||||||
| 
 | 
 | ||||||
| 			ship->numVertexPoints = 3; | 			ship->numVertexPoints = 3; | ||||||
| 			ship->vertexPoints    = memory_pushBytes( | 			ship->vertexPoints    = memory_pushBytes( | ||||||
| 			    &state->persistentArena, sizeof(v2) * ship->numVertexPoints); | 			    &world->entityArena, sizeof(v2) * ship->numVertexPoints); | ||||||
| 
 | 
 | ||||||
| 			v2 triangleBaseP  = V2(0, 0); | 			v2 triangleBaseP  = V2(0, 0); | ||||||
| 			v2 triangleTopP   = V2(ship->size.w * 0.5f, ship->size.h); | 			v2 triangleTopP   = V2(ship->size.w * 0.5f, ship->size.h); | ||||||
| @ -464,19 +505,21 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | |||||||
| 			ship->type       = entitytype_ship; | 			ship->type       = entitytype_ship; | ||||||
| 			ship->direction  = direction_null; | 			ship->direction  = direction_null; | ||||||
| 			ship->renderMode = rendermode_polygon; | 			ship->renderMode = rendermode_polygon; | ||||||
| 			ship->tex        = NULL; | 			ship->color      = V4(1.0f, 0.5f, 0.5f, 1.0f); | ||||||
| 			ship->collides   = TRUE; |  | ||||||
| 
 |  | ||||||
| 		} | 		} | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|  | 		{ // Global Collision Rules
 | ||||||
|  | 			setCollisionRule(world, entitytype_ship, entitytype_asteroid, TRUE); | ||||||
|  | 			setCollisionRule(world, entitytype_bullet, entitytype_asteroid, | ||||||
|  | 			                 TRUE); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		world->camera.min = V2(0, 0); | ||||||
|  | 		world->camera.max = state->renderer.size; | ||||||
|  | 		world->worldSize  = windowSize; | ||||||
| 
 | 
 | ||||||
| 		state->camera.min = V2(0, 0); |  | ||||||
| 		state->camera.max = state->renderer.size; |  | ||||||
| 		state->init       = TRUE; | 		state->init       = TRUE; | ||||||
| 
 | 
 | ||||||
| 		state->worldSize = windowSize; |  | ||||||
| 
 |  | ||||||
| 		debug_init(&state->persistentArena, windowSize, | 		debug_init(&state->persistentArena, windowSize, | ||||||
| 		           state->assetManager.font); | 		           state->assetManager.font); | ||||||
| 	} | 	} | ||||||
| @ -509,26 +552,26 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | |||||||
| 	if (getKeyStatus(&state->input.keys[keycode_left_square_bracket], | 	if (getKeyStatus(&state->input.keys[keycode_left_square_bracket], | ||||||
| 	                 readkeytype_repeat, 0.2f, dt)) | 	                 readkeytype_repeat, 0.2f, dt)) | ||||||
| 	{ | 	{ | ||||||
| 		addAsteroid(state, windowSize); | 		addAsteroid(world, windowSize); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i32 i = 0; i < state->entityIndex; i++) | 	for (i32 i = 0; i < world->entityIndex; i++) | ||||||
| 	{ | 	{ | ||||||
| 		Entity *entity = &state->entityList[i]; | 		Entity *entity = &world->entityList[i]; | ||||||
| 		ASSERT(entity->type != entitytype_invalid); | 		ASSERT(entity->type != entitytype_invalid); | ||||||
| 
 | 
 | ||||||
| 		v2 pivotPoint = {0}; | 		v2 pivotPoint = {0}; | ||||||
| 
 | 
 | ||||||
| 		// Loop entity around world
 | 		// Loop entity around world
 | ||||||
| 		if (entity->pos.y >= state->worldSize.h) | 		if (entity->pos.y >= world->worldSize.h) | ||||||
| 			entity->pos.y = 0; | 			entity->pos.y = 0; | ||||||
| 		else if (entity->pos.y < 0) | 		else if (entity->pos.y < 0) | ||||||
| 			entity->pos.y = state->worldSize.h; | 			entity->pos.y = world->worldSize.h; | ||||||
| 
 | 
 | ||||||
| 		if (entity->pos.x >= state->worldSize.w) | 		if (entity->pos.x >= world->worldSize.w) | ||||||
| 			entity->pos.x = 0; | 			entity->pos.x = 0; | ||||||
| 		else if (entity->pos.x < 0) | 		else if (entity->pos.x < 0) | ||||||
| 			entity->pos.x = state->worldSize.w; | 			entity->pos.x = world->worldSize.w; | ||||||
| 
 | 
 | ||||||
| 		f32 ddPSpeedInMs = 0; | 		f32 ddPSpeedInMs = 0; | ||||||
| 		v2 ddP           = {0}; | 		v2 ddP           = {0}; | ||||||
| @ -560,6 +603,12 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | |||||||
| 				entity->rotation -= (rotationsPerSecond) * dt; | 				entity->rotation -= (rotationsPerSecond) * dt; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			if (getKeyStatus(&state->input.keys[keycode_space], | ||||||
|  | 			                 readkeytype_delayedRepeat, 0.0f, dt)) | ||||||
|  | 			{ | ||||||
|  | 				addBullet(world, entity); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			if (ddP.x > 0.0f && ddP.y > 0.0f) | 			if (ddP.x > 0.0f && ddP.y > 0.0f) | ||||||
| 			{ | 			{ | ||||||
| 				// NOTE(doyle): Cheese it and pre-compute the vector for
 | 				// NOTE(doyle): Cheese it and pre-compute the vector for
 | ||||||
| @ -572,6 +621,11 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | |||||||
| 			DEBUG_PUSH_VAR("Pos: %5.2f, %5.2f", entity->pos, "v2"); | 			DEBUG_PUSH_VAR("Pos: %5.2f, %5.2f", entity->pos, "v2"); | ||||||
| 			DEBUG_PUSH_VAR("Velocity: %5.2f, %5.2f", entity->dP, "v2"); | 			DEBUG_PUSH_VAR("Velocity: %5.2f, %5.2f", entity->dP, "v2"); | ||||||
| 			DEBUG_PUSH_VAR("Rotation: %5.2f", entity->rotation, "f32"); | 			DEBUG_PUSH_VAR("Rotation: %5.2f", entity->rotation, "f32"); | ||||||
|  | 
 | ||||||
|  | 			renderer_rect(&state->renderer, world->camera, entity->pos, | ||||||
|  | 			              V2(5, 5), V2(0, 0), | ||||||
|  | 			              DEGREES_TO_RADIANS(entity->rotation), NULL, | ||||||
|  | 			              V4(1.0f, 1.0f, 1.0f, 1.0f), renderflag_no_texture); | ||||||
| 		} | 		} | ||||||
| 		else if (entity->type == entitytype_asteroid) | 		else if (entity->type == entitytype_asteroid) | ||||||
| 		{ | 		{ | ||||||
| @ -648,26 +702,43 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, | |||||||
| 			f32 dirOffset = ((randValue % 10) + 1) / 100.0f; | 			f32 dirOffset = ((randValue % 10) + 1) / 100.0f; | ||||||
| 			v2_scale(ddP, dirOffset); | 			v2_scale(ddP, dirOffset); | ||||||
| 
 | 
 | ||||||
| 			// NOTE(doyle): Make asteroids start and move at constant speed
 | 			// NOTE(doyle): Make asteroids start and move at constant speed by
 | ||||||
|  | 			// ensuring that dP is "refreshed" with non-decaying acceleration
 | ||||||
| 			ddPSpeedInMs = 1; | 			ddPSpeedInMs = 1; | ||||||
| 			entity->dP   = v2_scale(ddP, state->pixelsPerMeter * ddPSpeedInMs); | 			entity->dP   = v2_scale(ddP, world->pixelsPerMeter * ddPSpeedInMs); | ||||||
| 			entity->rotation += (60 * dt); | 			entity->rotation += (60 * dt); | ||||||
| #endif | #endif | ||||||
| 		} | 		} | ||||||
|  | 		else if (entity->type == entitytype_bullet) | ||||||
|  | 		{ | ||||||
|  | 			ddPSpeedInMs     = 5; | ||||||
|  | 			Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f)); | ||||||
|  | 			ddP              = V2(math_cosf(rotation), math_sinf(rotation)); | ||||||
|  | 			entity->dP = v2_scale(ddP, world->pixelsPerMeter * ddPSpeedInMs); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		b32 willCollide = moveEntity(state, entity, i, ddP, dt, ddPSpeedInMs); | 		b32 willCollide = moveEntity(world, &state->transientArena, entity, i, | ||||||
| 		v4 entityColor  = V4(1.0f, 1.0f, 1.0f, 1.0f); | 		                             ddP, dt, ddPSpeedInMs); | ||||||
| #if 1 | 		v4 collideColor = {0}; | ||||||
| 		if (willCollide) | 		if (willCollide) | ||||||
| 		{ | 		{ | ||||||
| 			entityColor = V4(1.0f, 1.0f, 0, 1.0f); | 			collideColor = V4(1.0f, 0, 0, 0.5f); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (entity->type == entitytype_bullet) | ||||||
|  | 		{ | ||||||
|  | 			if (!math_pointInRect(world->camera, entity->pos)) | ||||||
|  | 			{ | ||||||
|  | 				world->entityList[i] = world->entityList[--world->entityIndex]; | ||||||
|  | 				i--; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 		RenderFlags flags = renderflag_wireframe | renderflag_no_texture; | 		RenderFlags flags = renderflag_wireframe | renderflag_no_texture; | ||||||
| 		renderer_entity(&state->renderer, &state->transientArena, state->camera, | 		renderer_entity(&state->renderer, &state->transientArena, world->camera, | ||||||
| 		                entity, V2(0, 0), 0, | 		                entity, V2(0, 0), 0, | ||||||
| 		                entityColor, flags); | 		                collideColor, flags); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| #if 1 | #if 1 | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/Debug.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/Debug.c
									
									
									
									
									
								
							| @ -273,20 +273,28 @@ void debug_drawUi(GameState *state, f32 dt) | |||||||
| 	updateAndRenderDebugStack(&state->renderer, &state->transientArena, dt); | 	updateAndRenderDebugStack(&state->renderer, &state->transientArena, dt); | ||||||
| 	renderConsole(&state->renderer, &state->transientArena); | 	renderConsole(&state->renderer, &state->transientArena); | ||||||
| 
 | 
 | ||||||
|  | 	{ // Print Memory Arena Info
 | ||||||
|  | 		DEBUG_PUSH_STRING("== MEMORY ARENAS =="); | ||||||
| 		MemoryArena_ *transient = &state->transientArena; | 		MemoryArena_ *transient = &state->transientArena; | ||||||
| 		i32 transientSizeInKbs  = transient->size / 1024; | 		i32 transientSizeInKbs  = transient->size / 1024; | ||||||
| 		i32 transientUsedInKbs  = transient->used / 1024; | 		i32 transientUsedInKbs  = transient->used / 1024; | ||||||
| 		v2 transientUsage       = V2i(transientUsedInKbs, transientSizeInKbs); | 		v2 transientUsage       = V2i(transientUsedInKbs, transientSizeInKbs); | ||||||
| 	DEBUG_PUSH_VAR("Transient Size: %.0f", transient->size, "f32"); |  | ||||||
| 		DEBUG_PUSH_VAR("Transient Usage: %.0f/%.0f", transientUsage, "v2"); | 		DEBUG_PUSH_VAR("Transient Usage: %.0f/%.0f", transientUsage, "v2"); | ||||||
| 
 | 
 | ||||||
| 		MemoryArena_ *persistent = &state->persistentArena; | 		MemoryArena_ *persistent = &state->persistentArena; | ||||||
| 		i32 persistentSizeInKbs  = persistent->size / 1024; | 		i32 persistentSizeInKbs  = persistent->size / 1024; | ||||||
| 		i32 persistentUsedInKbs  = persistent->used / 1024; | 		i32 persistentUsedInKbs  = persistent->used / 1024; | ||||||
| 		v2 persistentUsage = V2i(persistentUsedInKbs, persistentSizeInKbs); | 		v2 persistentUsage = V2i(persistentUsedInKbs, persistentSizeInKbs); | ||||||
| 	DEBUG_PUSH_VAR("Permanent Size: %.0f", persistent->size, "f32"); |  | ||||||
| 		DEBUG_PUSH_VAR("Permanent Usage: %.0f/%.0f", persistentUsage, "v2"); | 		DEBUG_PUSH_VAR("Permanent Usage: %.0f/%.0f", persistentUsage, "v2"); | ||||||
| 
 | 
 | ||||||
|  | 		MemoryArena_ *entityArena = &state->world.entityArena; | ||||||
|  | 		i32 entitySizeInKbs       = entityArena->size / 1024; | ||||||
|  | 		i32 entityUsedInKbs       = entityArena->used / 1024; | ||||||
|  | 		v2 entityUsage            = V2i(entityUsedInKbs, entitySizeInKbs); | ||||||
|  | 		DEBUG_PUSH_VAR("Entity Usage: %.0f/%.0f", entityUsage, "v2"); | ||||||
|  | 		DEBUG_PUSH_STRING("== =="); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	DEBUG_PUSH_VAR("Num Vertex: %d", | 	DEBUG_PUSH_VAR("Num Vertex: %d", | ||||||
| 	               GLOBAL_debug.callCount[debugcount_numVertex], "i32"); | 	               GLOBAL_debug.callCount[debugcount_numVertex], "i32"); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -89,8 +89,12 @@ void entity_addAnim(AssetManager *const assetManager, Entity *const entity, | |||||||
| 	DEBUG_LOG("No more free entity animation slots"); | 	DEBUG_LOG("No more free entity animation slots"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity) | v2 *entity_generateUpdatedVertexList(MemoryArena_ *transientArena, | ||||||
|  |                                      Entity *entity) | ||||||
| { | { | ||||||
|  | 	ASSERT(entity->vertexPoints); | ||||||
|  | 	ASSERT(entity->numVertexPoints >= 3); | ||||||
|  | 
 | ||||||
| 	v2 *result = | 	v2 *result = | ||||||
| 	    memory_pushBytes(transientArena, entity->numVertexPoints * sizeof(v2)); | 	    memory_pushBytes(transientArena, entity->numVertexPoints * sizeof(v2)); | ||||||
| 
 | 
 | ||||||
| @ -98,9 +102,10 @@ v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity) | |||||||
| 	{ | 	{ | ||||||
| 		result[i] = v2_add(entity->vertexPoints[i], entity->offset); | 		result[i] = v2_add(entity->vertexPoints[i], entity->offset); | ||||||
| 		result[i] = v2_add(result[i], entity->pos); | 		result[i] = v2_add(result[i], entity->pos); | ||||||
|  | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	math_applyRotationToVertexes(result[0], entity->offset, | 	math_applyRotationToVertexes(entity->pos, V2(0 ,0), | ||||||
| 	                             DEGREES_TO_RADIANS(entity->rotation), result, | 	                             DEGREES_TO_RADIANS(entity->rotation), result, | ||||||
| 	                             entity->numVertexPoints); | 	                             entity->numVertexPoints); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -574,11 +574,15 @@ void renderer_entity(Renderer *renderer, MemoryArena_ *transientArena, | |||||||
| 		renderTex.texRect = texRect; | 		renderTex.texRect = texRect; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// TODO(doyle): Proper blending
 | ||||||
|  | 	v4 renderColor = color; | ||||||
|  | 	if (v4_equals(color, V4(0, 0, 0, 0))) renderColor = entity->color; | ||||||
|  | 
 | ||||||
| 	if (entity->renderMode == rendermode_quad) | 	if (entity->renderMode == rendermode_quad) | ||||||
| 	{ | 	{ | ||||||
| 		renderer_rect(renderer, camera, entity->pos, entity->size, | 		renderer_rect(renderer, camera, entity->pos, entity->size, | ||||||
| 		              v2_add(entity->offset, pivotPoint), totalRotation, | 		              v2_add(entity->offset, pivotPoint), totalRotation, | ||||||
| 		              &renderTex, color, flags); | 		              &renderTex, entity->color, flags); | ||||||
| 	} | 	} | ||||||
| 	else if (entity->renderMode == rendermode_polygon) | 	else if (entity->renderMode == rendermode_polygon) | ||||||
| 	{ | 	{ | ||||||
| @ -586,12 +590,12 @@ void renderer_entity(Renderer *renderer, MemoryArena_ *transientArena, | |||||||
| 		ASSERT(entity->vertexPoints); | 		ASSERT(entity->vertexPoints); | ||||||
| 
 | 
 | ||||||
| 		v2 *offsetVertexPoints = | 		v2 *offsetVertexPoints = | ||||||
| 		    entity_createVertexList(transientArena, entity); | 		    entity_generateUpdatedVertexList(transientArena, entity); | ||||||
| 
 | 
 | ||||||
| 		renderer_polygon(renderer, camera, offsetVertexPoints, | 		renderer_polygon(renderer, camera, offsetVertexPoints, | ||||||
| 		                 entity->numVertexPoints, | 		                 entity->numVertexPoints, | ||||||
| 		                 v2_add(entity->offset, pivotPoint), totalRotation, | 		                 v2_add(entity->offset, pivotPoint), totalRotation, | ||||||
| 		                 &renderTex, color, flags); | 		                 &renderTex, renderColor, flags); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
| @ -172,8 +172,13 @@ i32 main(void) | |||||||
| 	memory.transientSize = transientSize; | 	memory.transientSize = transientSize; | ||||||
| 	memory.transient     = PLATFORM_MEM_ALLOC_(NULL, transientSize, u8); | 	memory.transient     = PLATFORM_MEM_ALLOC_(NULL, transientSize, u8); | ||||||
| 
 | 
 | ||||||
| 	GameState gameState = {0}; | 	MemoryArena_ gameArena = {0}; | ||||||
| 	glfwSetWindowUserPointer(window, CAST(void *)(&gameState)); | 	memory_arenaInit(&gameArena, memory.persistent, memory.persistentSize); | ||||||
|  | 
 | ||||||
|  | 	GameState *gameState = MEMORY_PUSH_STRUCT(&gameArena, GameState); | ||||||
|  | 	gameState->persistentArena = gameArena; | ||||||
|  | 
 | ||||||
|  | 	glfwSetWindowUserPointer(window, CAST(void *)(gameState)); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 ******************* | 	 ******************* | ||||||
| @ -203,7 +208,7 @@ i32 main(void) | |||||||
| 		glClearColor(0.2f, 0.2f, 0.2f, 1.0f); | 		glClearColor(0.2f, 0.2f, 0.2f, 1.0f); | ||||||
| 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||||
| 
 | 
 | ||||||
| 		asteroid_gameUpdateAndRender(&gameState, &memory, windowSize, | 		asteroid_gameUpdateAndRender(gameState, &memory, windowSize, | ||||||
| 		                             secondsElapsed); | 		                             secondsElapsed); | ||||||
| 		GL_CHECK_ERROR(); | 		GL_CHECK_ERROR(); | ||||||
| 
 | 
 | ||||||
| @ -233,7 +238,7 @@ i32 main(void) | |||||||
| 			char textBuffer[256]; | 			char textBuffer[256]; | ||||||
| 			snprintf(textBuffer, ARRAY_COUNT(textBuffer), | 			snprintf(textBuffer, ARRAY_COUNT(textBuffer), | ||||||
| 			         "Dengine | %f ms/f | %f fps | Entity Count: %d", | 			         "Dengine | %f ms/f | %f fps | Entity Count: %d", | ||||||
| 			         msPerFrame, framesPerSecond, gameState.entityIndex); | 			         msPerFrame, framesPerSecond, gameState->world.entityIndex); | ||||||
| 
 | 
 | ||||||
| 			glfwSetWindowTitle(window, textBuffer); | 			glfwSetWindowTitle(window, textBuffer); | ||||||
| 			titleUpdateFrequencyInSeconds = 0.5f; | 			titleUpdateFrequencyInSeconds = 0.5f; | ||||||
|  | |||||||
| @ -8,23 +8,35 @@ | |||||||
| #include "Dengine/Platform.h" | #include "Dengine/Platform.h" | ||||||
| #include "Dengine/Renderer.h" | #include "Dengine/Renderer.h" | ||||||
| 
 | 
 | ||||||
|  | typedef struct World | ||||||
|  | { | ||||||
|  | 	MemoryArena_ entityArena; | ||||||
|  | 
 | ||||||
|  | 	v2 *entityVertexListCache[entitytype_count]; | ||||||
|  | 	Entity entityList[1024]; | ||||||
|  | 	i32 entityIndex; | ||||||
|  | 
 | ||||||
|  | 	u32 entityIdCounter; | ||||||
|  | 
 | ||||||
|  | 	f32 pixelsPerMeter; | ||||||
|  | 	v2 worldSize; | ||||||
|  | 	Rect camera; | ||||||
|  | 
 | ||||||
|  | 	// TODO(doyle): Ensure we change this if it gets too big
 | ||||||
|  | 	b32 collisionTable[entitytype_count][entitytype_count]; | ||||||
|  | } World; | ||||||
|  | 
 | ||||||
| typedef struct GameState { | typedef struct GameState { | ||||||
| 	b32 init; | 	b32 init; | ||||||
| 
 | 
 | ||||||
| 	Entity entityList[1024]; | 	World world; | ||||||
| 	i32 entityIndex; |  | ||||||
| 	f32 pixelsPerMeter; |  | ||||||
| 
 |  | ||||||
| 	v2 worldSize; |  | ||||||
| 
 |  | ||||||
| 	Rect camera; |  | ||||||
| 
 |  | ||||||
| 	AssetManager assetManager; | 	AssetManager assetManager; | ||||||
| 	KeyInput input; | 	KeyInput input; | ||||||
| 
 | 
 | ||||||
| 	MemoryArena_ transientArena; | 	MemoryArena_ transientArena; | ||||||
| 	MemoryArena_ persistentArena; | 	MemoryArena_ persistentArena; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 	Renderer renderer; | 	Renderer renderer; | ||||||
| } GameState; | } GameState; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -28,6 +28,7 @@ enum EntityType | |||||||
| 	entitytype_invalid, | 	entitytype_invalid, | ||||||
| 	entitytype_ship, | 	entitytype_ship, | ||||||
| 	entitytype_asteroid, | 	entitytype_asteroid, | ||||||
|  | 	entitytype_bullet, | ||||||
| 	entitytype_count, | 	entitytype_count, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -42,10 +43,7 @@ typedef struct EntityAnim | |||||||
| 
 | 
 | ||||||
| typedef struct Entity | typedef struct Entity | ||||||
| { | { | ||||||
| 	i32 id; | 	u32 id; | ||||||
| 
 |  | ||||||
| 	i32 childIds[8]; |  | ||||||
| 	i32 numChilds; |  | ||||||
| 
 | 
 | ||||||
| 	v2 pos; | 	v2 pos; | ||||||
| 	v2 dP; | 	v2 dP; | ||||||
| @ -53,11 +51,11 @@ typedef struct Entity | |||||||
| 	v2 hitbox; | 	v2 hitbox; | ||||||
| 	v2 size; | 	v2 size; | ||||||
| 
 | 
 | ||||||
| 	// NOTE(doyle): Offset from origin point to the entity's considered "center"
 | 	/*
 | ||||||
| 	// point, all operations work from this point, i.e. rotation, movement,
 | 	   NOTE(doyle): Offset is the vector to shift the polygons "origin" to the | ||||||
| 	// collision detection
 | 	   world origin. In our case this should strictly be negative as we have | ||||||
| 	// If this is a polygon, the offset should be from the 1st vertex point
 | 	   a requirement that all vertex points must be strictly positive. | ||||||
| 	// specified
 |    */ | ||||||
| 	v2 offset; | 	v2 offset; | ||||||
| 
 | 
 | ||||||
| 	enum RenderMode renderMode; | 	enum RenderMode renderMode; | ||||||
| @ -70,17 +68,11 @@ typedef struct Entity | |||||||
| 	enum EntityType type; | 	enum EntityType type; | ||||||
| 	enum Direction direction; | 	enum Direction direction; | ||||||
| 
 | 
 | ||||||
|  | 	v4 color; | ||||||
| 	Texture *tex; | 	Texture *tex; | ||||||
| 	b32 flipX; | 	b32 flipX; | ||||||
| 	b32 flipY; | 	b32 flipY; | ||||||
| 
 | 
 | ||||||
| 	// TODO(doyle): Two collision flags, we want certain entities to collide
 |  | ||||||
| 	// with certain types of entities only (i.e. projectile from hero to enemy,
 |  | ||||||
| 	// only collides with enemy). Having two flags is redundant, but! it does
 |  | ||||||
| 	// allow for early-exit in collision check if the entity doesn't collide at
 |  | ||||||
| 	// all
 |  | ||||||
| 	b32 collides; |  | ||||||
| 
 |  | ||||||
| 	EntityAnim animList[16]; | 	EntityAnim animList[16]; | ||||||
| 	i32 animListIndex; | 	i32 animListIndex; | ||||||
| 
 | 
 | ||||||
| @ -95,5 +87,6 @@ void entity_updateAnim(Entity *const entity, const f32 dt); | |||||||
| void entity_addAnim(AssetManager *const assetManager, Entity *const entity, | void entity_addAnim(AssetManager *const assetManager, Entity *const entity, | ||||||
|                     const char *const animName); |                     const char *const animName); | ||||||
| 
 | 
 | ||||||
| v2 *entity_createVertexList(MemoryArena_ *transientArena, Entity *entity); | v2 *entity_generateUpdatedVertexList(MemoryArena_ *transientArena, | ||||||
|  |                                      Entity *entity); | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -410,5 +410,23 @@ INTERNAL inline void math_applyRotationToVertexes(v2 pos, v2 pivotPoint, | |||||||
| 		vertexList[i] = newP; | 		vertexList[i] = newP; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | INTERNAL inline f32 math_lerp(f32 a, f32 t, f32 b) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	    Linear blend between two values. We having a starting point "a", and | ||||||
|  | 	    the distance to "b" is defined as (b - a). Then we can say | ||||||
|  | 
 | ||||||
|  | 	    a + t(b - a) | ||||||
|  | 
 | ||||||
|  | 	    As our linear blend fn. We start from "a" and choosing a t from 0->1 | ||||||
|  | 	    will vary the value of (b - a) towards b. If we expand this, this | ||||||
|  | 	    becomes | ||||||
|  | 
 | ||||||
|  | 	    a + (t * b) - (a * t) == (1 - t)a + t*b | ||||||
|  | 	*/ | ||||||
|  | 	f32 result = ((1 - t) * a) + (t * b); | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user