Beispiel #1
0
void			Game::moveMissiles()
{
	int		i;

	i = 0;
	while (i < _missileId)
	{
		_board.setMatriceValueAt(_missile[i].getPosX(), _missile[i].getPosY(), 0);
		switch(_missile[i].getDirection())
		{
		case RIGHT :
			_missile[i].goRight();
			break;
		case LEFT :
			_missile[i].goLeft();
			break;
		}
		if (_missile[i].getPosX() > _win.getW() || _missile[i].getPosX() < 0)
			deleteEntity(_missile[i]);
		else if (_missile[i].getPosY() > _win.getW() || _missile[i].getPosY() < 0)
			deleteEntity(_missile[i]);
		else if (!checkIfCollision(_missile[i]))
		{
			_board.setMatriceValueAt(_missile[i].getPosX(), _missile[i].getPosY(), &_missile[i]);
			i++;
		}
	}
}
Beispiel #2
0
void EntityManager::clear() {
    for (auto entityEntry : entityExistence) {
        deleteEntity(entityEntry.first);
    }

    entityExistence.clear();
}
Beispiel #3
0
void deleteActor(character *chr) {
	item *lodgedItem = getItemLodgedInActor(chr);
	
	if (chr == getPlayer()) {
		killPlayer();
	}

	deleteEntity(getWorld(), chr->entityId);
	
	if (lodgedItem) {
		lodgedItem->itemFlags ^= IS_LODGED;
		lodgedItem->lodgedInActor = NULL;
		lodgedItem->x = chr->x;
		lodgedItem->y = chr->y;
	}

	if (chr->itemLight) {
		deleteDynamicLight(chr->itemLight);
		chr->itemLight = NULL;
	}

	if (chr == CHARACTERS) {
		CHARACTERS = chr->next;
	} else {
		chr->prev->next = chr->next;

		if (chr->next) {
			chr->next->prev = chr->prev;
		}
	}

	free(chr);
}
Beispiel #4
0
void CGameEngine::cleanEntityToDelete()
{
	while(!m_entityToDelete.empty())
	{
		deleteEntity(m_entityToDelete.top());
		m_entityToDelete.pop();
	}
}
Beispiel #5
0
	void CObjectViewer::deleteEntities()
	{
		for (EIT eit = _Entities.begin(); eit != _Entities.end(); ++eit)
		{
			CEntity	&entity = (*eit).second;
			deleteEntity(entity);
		}
		_Entities.clear();
	}
Beispiel #6
0
void			Game::moveEnemies()
{
	int				i;

	i = 0;
	while (i < _enemyId)
	{
		deleteShip(_enemy[i]);
		_enemy[i].goLeft();
		if (_enemy[i].getPosX() < 0)
			_win.renderLose();
		if (_enemy[i].getPosY() > _win.getH() || _enemy[i].getPosY() < 0)
			deleteEntity(_enemy[i]);
		if (!checkIfCollision(_enemy[i]))
			drawShip(_enemy[i]);
		i++;
	}
}
void ProjectileCollideSystem::update()
{
    for(int subID = 0; subID < subscribedEntities[0].size(); subID++)
    {
        //Get projectile component
        Entity * projectileEnt = entities[subscribedEntities[0][subID]];
        ColliderComponent* projectileCollideComp = static_cast<ColliderComponent*>(projectileEnt->getComponent(ColliderComponent::getStaticID()));
        WorldComponent * projectileWorldComp = static_cast<WorldComponent*>(projectileEnt->getComponent(WorldComponent::getStaticID()));
        PhysicsComponent* projectilePhysicsComp = static_cast<PhysicsComponent*>(projectileEnt->getComponent(PhysicsComponent::getStaticID()));

        //Check projectile for collisions
        for(int i = 0; i < projectileCollideComp->collisionData.size(); i++)
        {
            std::shared_ptr<CollisionPair> collision = projectileCollideComp->collisionData[i];
            int projectilePairID = collision->getCollisionPairID(subscribedEntities[0][subID]);//Projectile's CollisionPairID
            int collidingPairID = collision->getOppositePairID(projectilePairID);//The Colliding Ent's CollisionPairID
            Entity * collidingEnt = entities[collision->getCollisionEntityID(collidingPairID)]; //The Colliding Entity

            //Check the type of the collided entity and perform action
            if(collidingEnt->hasComponent(TerrainComponent::getStaticID()))
            {
                deleteEntity(projectileEnt->entityID);
            }
            if(collidingEnt->hasComponent(PhysicsComponent::getStaticID()) && !collidingEnt->hasComponent(PlayerComponent::getStaticID()))
            {
                glm::vec2 col = collision->getMinimumTranslation(projectilePairID);
                PhysicsComponent* physicsComp = static_cast<PhysicsComponent*>(collidingEnt->getComponent(PhysicsComponent::getStaticID()));
                //Should 1. Be conserving energy
                //Should 2. Be making sure the velocity is transfered correctly
                //http://gafferongames.com/virtual-go/collision-response-and-coulomb-friction/
                float j = -(1+physicsComp->coefficientRestitution)*glm::dot(projectilePhysicsComp->velocity*projectilePhysicsComp->mass,glm::normalize(col)); //projectiles impulse
                float impulseMag = glm::max(j, 0.0f);
                //Logger()<<impulseMag<<std::endl;
                physicsComp->impulse(impulseMag*glm::normalize(-col));
                projectilePhysicsComp->impulse(impulseMag*glm::normalize(col));
            }
        }
    }
}
Beispiel #8
0
int				Game::checkIfCollision(AGameEntity & entity)
{
	AGameEntity		*result;

	result = _board.getMatriceValueAt(entity.getPosX(), entity.getPosY());
	if (!result)
		return 0;
	switch (result->getType())
	{
	case MISSILE:
		if (entity.getType() != MISSILE)
		{
			deleteEntity(*result);
			deleteEntity(entity);
			return 1;
		}
		break ;
	case ENEMY :
		if (entity.getType() == MISSILE)
		{
			if (static_cast<Missile &>(entity).getDirection() == RIGHT)
			{
				deleteEntity(*result);
				deleteEntity(entity);
				_win.incScore();
				return 1;
			}
			return 0;
			}
		else
			deleteEntity(*result);
		return 1;
	case PLAYER :
		if (static_cast<Missile &>(entity).getDirection() == RIGHT)
			return 0;
		loseHp(static_cast<Player &>(*result));
		deleteEntity(entity);
		return 1;
	case 0:
		return 0;
	}
	return 0;
}
int ClientInterface::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QMainWindow::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: sendMessage(); break;
        case 1: chat((*reinterpret_cast< CLID(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2])),(*reinterpret_cast< QString(*)>(_a[3])),(*reinterpret_cast< ENUM_TYPE(*)>(_a[4]))); break;
        case 2: changeServerInformations((*reinterpret_cast< ServerInformations(*)>(_a[1]))); break;
        case 3: changeClientID((*reinterpret_cast< CLID(*)>(_a[1]))); break;
        case 4: changeClientNickname((*reinterpret_cast< CLID(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 5: showError((*reinterpret_cast< ENUM_TYPE(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 6: changeGameMaster((*reinterpret_cast< CLID(*)>(_a[1]))); break;
        case 7: clientVoted((*reinterpret_cast< CLID(*)>(_a[1])),(*reinterpret_cast< CLID(*)>(_a[2]))); break;
        case 8: connectionEtablished(); break;
        case 9: connectionLost(); break;
        case 10: diceRolled((*reinterpret_cast< CLID(*)>(_a[1])),(*reinterpret_cast< quint16(*)>(_a[2])),(*reinterpret_cast< quint16(*)>(_a[3]))); break;
        case 11: sanctionned((*reinterpret_cast< CLID(*)>(_a[1])),(*reinterpret_cast< ENUM_TYPE(*)>(_a[2])),(*reinterpret_cast< QString(*)>(_a[3]))); break;
        case 12: rollDice(); break;
        case 13: rollSpecialDice(); break;
        case 14: serverName((*reinterpret_cast< QString(*)>(_a[1]))); break;
        case 15: motdChanged((*reinterpret_cast< QString(*)>(_a[1]))); break;
        case 16: gameLaunched(); break;
        case 17: setTitle(); break;
        case 18: playSound((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 19: updatePlayerList(); break;
        case 20: clientJoined((*reinterpret_cast< CLID(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 21: clientLeft((*reinterpret_cast< CLID(*)>(_a[1]))); break;
        case 22: updateGMLabel(); break;
        case 23: updateGMPanel(); break;
        case 24: { bool _r = addLanguage();
            if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; }  break;
        case 25: { bool _r = addLanguage((*reinterpret_cast< const QString(*)>(_a[1])),(*reinterpret_cast< const QString(*)>(_a[2])));
            if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; }  break;
        case 26: languageListMenu((*reinterpret_cast< const QPoint(*)>(_a[1]))); break;
        case 27: { bool _r = removeLanguage((*reinterpret_cast< const QString(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast< bool*>(_a[0]) = _r; }  break;
        case 28: removeLanguageMenu(); break;
        case 29: importLanguageList(); break;
        case 30: sendLanguageList(); break;
        case 31: { CLID _r = CLIDFromString((*reinterpret_cast< const QString(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast< CLID*>(_a[0]) = _r; }  break;
        case 32: switchConnectionState(); break;
        case 33: openSettings(); break;
        case 34: openSoundsGUI(); break;
        case 35: aboutUs(); break;
        case 36: aboutServer(); break;
        case 37: openMapEditor(); break;
        case 38: clearMapEditor(); break;
        case 39: mapFlare(); break;
        case 40: resetData(); break;
        case 41: setCSS((*reinterpret_cast< const QString(*)>(_a[1]))); break;
        case 42: setCSS(); break;
        case 43: setInterface((*reinterpret_cast< const QString(*)>(_a[1]))); break;
        case 44: setInterface(); break;
        case 45: playerListMenu((*reinterpret_cast< const QPoint(*)>(_a[1]))); break;
        case 46: actionKick(); break;
        case 47: actionBan(); break;
        case 48: actionVoteGM(); break;
        case 49: actionChangeGM(); break;
        case 50: refresh(); break;
        case 51: textChanged(); break;
        case 52: narrationChanged((*reinterpret_cast< QString(*)>(_a[1]))); break;
        case 53: syncSoundLibs((*reinterpret_cast< QList<SoundLibInformations>(*)>(_a[1]))); break;
        case 54: syncLanguagesList((*reinterpret_cast< QList<QPair<QString,QString> >(*)>(_a[1]))); break;
        case 55: syncDictionariesList((*reinterpret_cast< QStringList(*)>(_a[1]))); break;
        case 56: requestScriptDownload((*reinterpret_cast< QString(*)>(_a[1]))); break;
        case 57: sendScriptToServer((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 58: deleteScript((*reinterpret_cast< QString(*)>(_a[1]))); break;
        case 59: renameScript((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 60: makeEntity((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 61: deleteEntity((*reinterpret_cast< const QString(*)>(_a[1]))); break;
        case 62: injectCode((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 63: scriptToGMMsg((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 64: scriptToOwnerMsg((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 65: scriptActionMsg((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 66: scriptToPlayerMsg((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 67: scriptMsg((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 68: scriptError((*reinterpret_cast< QString(*)>(_a[1])),(*reinterpret_cast< QString(*)>(_a[2]))); break;
        case 69: sendMapToServer((*reinterpret_cast< const MapInformations*const(*)>(_a[1])),(*reinterpret_cast< const QMap<QString,RSID>(*)>(_a[2]))); break;
        case 70: addDictionnary(); break;
        case 71: saveGame(); break;
        case 72: loadGame(); break;
        case 73: VOIPRemoveClient(); break;
        case 74: VOIPAddClient(); break;
        case 75: VOIPClientVolume(); break;
        case 76: dataPerSecond((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
        default: ;
        }
        _id -= 77;
    }
    return _id;
}
Beispiel #10
0
INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
{
	GameWorldState *world =
	    GET_STATE_DATA(state, &state->persistentArena, GameWorldState);

	if (!common_isSet(world->flags, gameworldstateflags_init))
	{

#ifdef DENGINE_DEBUG
		{
			u8 *data = (u8 *)world;
			for (i32 i = 0; i < sizeof(GameWorldState); i++)
				ASSERT(data[i] == 0);
		}
#endif
		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);

		world->camera.min = V2(0, 0);
		world->camera.max = state->renderer.size;
		world->size       = state->renderer.size;

		world->entityListSize = 1024;
		world->entityList     = MEMORY_PUSH_ARRAY(&world->entityArena,
		                                      world->entityListSize, Entity);

		{ // Init null entity
			Entity *nullEntity = &world->entityList[world->entityIndex++];
			nullEntity->id     = world->entityIdCounter++;
		}

		{ // Init asteroid entities
			world->numAsteroids = 15;
		}

		{ // Init audio renderer
			world->numAudioRenderers = 8;
			world->audioRenderer     = MEMORY_PUSH_ARRAY(
			    &world->entityArena, world->numAudioRenderers, AudioRenderer);
		}

		{ // Global Collision Rules
			setCollisionRule(world, entitytype_ship, entitytype_asteroid_small,
			                 TRUE);
			setCollisionRule(world, entitytype_ship, entitytype_asteroid_medium,
			                 TRUE);
			setCollisionRule(world, entitytype_ship, entitytype_asteroid_large,
			                 TRUE);
			setCollisionRule(world, entitytype_bullet,
			                 entitytype_asteroid_small, TRUE);
			setCollisionRule(world, entitytype_bullet,
			                 entitytype_asteroid_medium, TRUE);
			setCollisionRule(world, entitytype_bullet,
			                 entitytype_asteroid_large, TRUE);
		}

		world->numStarP = 100;
		world->starPList =
		    MEMORY_PUSH_ARRAY(&world->entityArena, world->numStarP, v2);
		world->starMinOpacity = 0.25f;

		for (i32 i = 0; i < world->numStarP; i++)
		{
			i32 randX = rand() % (i32)world->size.x;
			i32 randY = rand() % (i32)world->size.y;

			world->starPList[i] = V2i(randX, randY);
		}

		world->flags |= gameworldstateflags_init;

		world->scoreMultiplier                = 5;
		world->scoreMultiplierBarTimer        = 0.0f;
		world->scoreMultiplierBarThresholdInS = 2.0f;
	}

	if (common_isSet(world->flags, gameworldstateflags_level_started))
	{
		Font *arial40 = asset_fontGet(&state->assetManager, "Arial", 40);

		Renderer *renderer = &state->renderer;

		/* Render scores onto screen */
		v2 stringP =
		    V2((renderer->size.w * 0.5f), renderer->size.h - arial40->size);
		char gamePointsString[COMMON_ITOA_MAX_BUFFER_32BIT] = {0};
		common_itoa(world->score, gamePointsString,
		            ARRAY_COUNT(gamePointsString));

		renderer_stringFixedCentered(renderer, &state->transientArena, arial40,
		                             gamePointsString, stringP, V2(0, 0), 0,
		                             V4(1.0f, 1.0f, 1.0f, 1.0f), 1, 0);

		/* Render multiplier accumulator bar onto screen */
		v2 stringDim = asset_fontStringDimInPixels(arial40, gamePointsString);
		v2 multiplierOutlineSize =
		    V2(renderer->size.w * 0.5f, stringDim.h * 0.25f);

		v2 multiplierOutlineP = V2(renderer->size.w * 0.5f, stringP.h);
		multiplierOutlineP.x -= (multiplierOutlineSize.w * 0.5f);
		multiplierOutlineP.y -= stringDim.h * 1.5f;

		renderer_rectFixedOutline(
		    renderer, multiplierOutlineP, multiplierOutlineSize, V2(0, 0), 2, 0,
		    NULL, V4(0.2f, 0.3f, 0.8f, 1.0f), 2, renderflag_no_texture);

		f32 progressNormalised = world->scoreMultiplierBarTimer /
		                         world->scoreMultiplierBarThresholdInS;
		renderer_rectFixed(renderer, multiplierOutlineP,
		                   V2(multiplierOutlineSize.w * progressNormalised,
		                      multiplierOutlineSize.h),
		                   V2(0, 0), 0, NULL, V4(0.2f, 0.3f, 0.8f, 1.0f), 1,
		                   renderflag_no_texture);

		/* Render multiplier counter hud onto screen */
		v2 multiplierHudP    = V2(0, 0.05f * renderer->size.h);
		v2 multiplierHudSize =
		    V2((arial40->maxSize.w * 3.5f), arial40->fontHeight * 1.2f);

		renderer_rectFixed(renderer, multiplierHudP, multiplierHudSize,
		                   V2(0, 0), 0, NULL, V4(1, 1, 1, 0.1f), 2,
		                   renderflag_no_texture);

		/* Render multiplier counter string to hud */
		char multiplierToString[COMMON_ITOA_MAX_BUFFER_32BIT + 1] = {0};
		common_itoa(world->scoreMultiplier, multiplierToString + 1,
		            ARRAY_COUNT(multiplierToString) - 1);
		multiplierToString[0] = 'x';

		v2 multiplierToStringP = multiplierHudP;
		multiplierToStringP =
		    v2_add(multiplierToStringP, v2_scale(multiplierHudSize, 0.5f));

		renderer_stringFixedCentered(
		    renderer, &state->transientArena, arial40, multiplierToString,
		    multiplierToStringP, V2(0, 0), 0, V4(1.0f, 1.0f, 1.0f, 1.0f), 3, 0);

		/* Process multiplier bar updates */
		if (!common_isSet(world->flags, gameworldstateflags_player_lost))
		{
			f32 barTimerPenalty = 1.0f;
			if (world->timeSinceLastShot < 1.5f)
			{
				barTimerPenalty = 0.1f;
			}

			world->scoreMultiplierBarTimer += (barTimerPenalty * dt);
			world->timeSinceLastShot += dt;

			if (world->scoreMultiplierBarTimer >
			    world->scoreMultiplierBarThresholdInS)
			{
				world->scoreMultiplierBarTimer = 0;
				world->scoreMultiplier++;

				if (world->scoreMultiplier > 9999)
					world->scoreMultiplier = 9999;
			}
		}
	}

	if (common_isSet(world->flags, gameworldstateflags_player_lost))
	{
		Font *arial40 = asset_fontGet(&state->assetManager, "Arial", 40);

		char *gameOver = "Game Over";
		v2 gameOverP = v2_scale(state->renderer.size, 0.5f);
		renderer_stringFixedCentered(
		    &state->renderer, &state->transientArena, arial40, "Game Over",
		    gameOverP, V2(0, 0), 0, V4(1, 1, 1, 1), 0, 0);

		v2 gameOverSize = asset_fontStringDimInPixels(arial40, gameOver);
		v2 replayP = V2(gameOverP.x, gameOverP.y - (gameOverSize.h * 1.2f));

		renderer_stringFixedCentered(
		    &state->renderer, &state->transientArena, arial40,
		    "Press enter to play again or backspace to return to menu", replayP,
		    V2(0, 0), 0, V4(1, 1, 1, 1), 0, 0);

		if (platform_queryKey(&state->input.keys[keycode_enter],
		                      readkeytype_one_shot, 0.0f))
		{
			// TODO(doyle): Extract score init default values to some game
			// definitions file
			world->score                          = 0;
			world->scoreMultiplier                = 5;
			world->scoreMultiplierBarTimer        = 0.0f;
			world->scoreMultiplierBarThresholdInS = 2.0f;

			addPlayer(world);

			world->flags ^= gameworldstateflags_player_lost;
		}
		else if (platform_queryKey(&state->input.keys[keycode_backspace],
		                           readkeytype_one_shot, 0.0f))
		{
			common_memset((u8 *)world, 0, sizeof(*world));
			state->currState = appstate_StartMenuState;
			return;
		}
	}

	for (u32 i = world->asteroidCounter; i < world->numAsteroids; i++)
		addAsteroid(world, (rand() % asteroidsize_count));

	Radians starRotation   = DEGREES_TO_RADIANS(45.0f);
	v2 starSize            = V2(2, 2);

	ASSERT(world->starMinOpacity >= 0.0f && world->starMinOpacity <= 1.0f);
	f32 opacityFadeRateInS = 0.5f;
	if (world->starFadeAway)
	{
		opacityFadeRateInS *= -1.0f;
	}

	if (world->starOpacity > 1.0f)
	{
		world->starOpacity = 1.0f;
		world->starFadeAway = TRUE;
	}
	else if (world->starOpacity < world->starMinOpacity)
	{
		world->starOpacity = world->starMinOpacity;
		world->starFadeAway = FALSE;
	}

	world->starOpacity += (opacityFadeRateInS * dt);
	DEBUG_PUSH_VAR("Star Opacity: %5.2f", world->starOpacity, "f32");

	for (i32 i = 0; i < world->numStarP; i++)
	{
		world->starPList[i] = v2_add(world->starPList[i], V2(4.0f * dt, 0));
		world->starPList[i] = wrapPAroundBounds(
		    world->starPList[i], math_rectCreate(V2(0, 0), world->size));

		renderer_rect(&state->renderer, world->camera, world->starPList[i],
		              starSize, V2(0, 0), starRotation, NULL,
		              V4(0.8f, 0.8f, 0.8f, world->starOpacity), 0,
		              renderflag_no_texture | renderflag_wireframe);
	}

#ifdef DENGINE_DEBUG
	if (platform_queryKey(&state->input.keys[keycode_left_square_bracket],
	                      readkeytype_repeat, 0.2f))
	{
		addAsteroid(world, (rand() % asteroidsize_count));
	}
#endif

	ASSERT(world->entityList[0].id == NULL_ENTITY_ID);
	for (i32 i = 1; i < world->entityIndex; i++)
	{
		Entity *entity = &world->entityList[i];
		ASSERT(entity->type != entitytype_invalid);

		v2 pivotPoint    = {0};
		f32 ddPSpeedInMs = 0;
		v2 ddP           = {0};
		if (entity->type == entitytype_ship)
		{
			if (platform_queryKey(&state->input.keys[keycode_up],
			                      readkeytype_repeat, 0.0f))
			{
				// TODO(doyle): Renderer creates upfacing triangles by default,
				// but we need to offset rotation so that our base "0 degrees"
				// is right facing for trig to work
				Radians rotation =
				    DEGREES_TO_RADIANS((entity->rotation + 90.0f));
				v2 direction = V2(math_cosf(rotation), math_sinf(rotation));
				ddP          = direction;

				AudioVorbis *thrust =
				    asset_vorbisGet(&state->assetManager, "thrust");
				AudioRenderer *audioRenderer =
				    getFreeAudioRenderer(world, thrust, 3);
				if (audioRenderer)
				{
					audio_vorbisPlay(&state->transientArena,
					                 &state->audioManager, audioRenderer,
					                 thrust, 1);
				}
			}

			if (platform_queryKey(&state->input.keys[keycode_space],
			                      readkeytype_one_shot, KEY_DELAY_NONE))
			{
				addBullet(world, entity);

				if (world->timeSinceLastShot >= 0)
				{
					world->timeSinceLastShot = 0;

					f32 multiplierPenalty    = -2.0f;
					world->timeSinceLastShot += multiplierPenalty;
				}

				AudioVorbis *fire =
				    asset_vorbisGet(&state->assetManager, "fire");
				AudioRenderer *audioRenderer =
				    getFreeAudioRenderer(world, fire, 2);
				if (audioRenderer)
				{
					// TODO(doyle): Atm transient arena is not used, this is
					// just to fill out the arguments
					audio_vorbisPlay(&state->transientArena,
					                 &state->audioManager, audioRenderer, fire,
					                 1);
				}
			}

			Degrees rotationsPerSecond = 180.0f;
			if (platform_queryKey(&state->input.keys[keycode_left],
			                      readkeytype_repeat, 0.0f))
			{
				entity->rotation += (rotationsPerSecond)*dt;
			}

			if (platform_queryKey(&state->input.keys[keycode_right],
			                      readkeytype_repeat, 0.0f))
			{
				entity->rotation -= (rotationsPerSecond)*dt;
			}
			entity->rotation = (f32)((i32)entity->rotation);

			ddPSpeedInMs = 25;
			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("Rotation: %5.2f", entity->rotation, "f32");

			DEBUG_PUSH_VAR("TimeSinceLastShot: %5.2f", world->timeSinceLastShot,
			               "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), 0, renderflag_no_texture);
		}
		else if (entity->type >= entitytype_asteroid_small &&
		         entity->type <= entitytype_asteroid_large)
		{

			i32 randValue = rand();

			// NOTE(doyle): If it is a new asteroid with no dp set, we need to
			// set a initial dp for it to move from.
			v2 localDp = {0};
			if ((i32)entity->dP.x == 0 && (i32)entity->dP.y == 0)
			{
				enum Direction direction = randValue % direction_count;
				switch (direction)
				{
				case direction_north:
				case direction_northwest:
				{
					localDp.x = 1.0f;
					localDp.y = 1.0f;
				}
				break;

				case direction_west:
				case direction_southwest:
				{
					localDp.x = -1.0f;
					localDp.y = -1.0f;
				}
				break;

				case direction_south:
				case direction_southeast:
				{
					localDp.x = 1.0f;
					localDp.y = -1.0f;
				}
				break;

				case direction_east:
				case direction_northeast:
				{
					localDp.x = 1.0f;
					localDp.y = 1.0f;
				}
				break;

				default:
				{
					ASSERT(INVALID_CODE_PATH);
				}
				break;
				}
			}
			// NOTE(doyle): Otherwise, if it has pre-existing dp, maintain our
			// direction by extrapolating from it's current dp
			else
			{
				if (entity->dP.x >= 0)
					localDp.x = 1.0f;
				else
					localDp.x = -1.0f;

				if (entity->dP.y >= 0)
					localDp.y = 1.0f;
				else
					localDp.y = -1.0f;
			}

			/*
			   NOTE(doyle): We compare current dP with the calculated dP. In the
			   event we want to artificially boost the asteroid, we set a higher
			   dP on creation, which will have a higher dP than the default dP
			   we calculate. So here we choose to keep it until it decays enough
			   that the default dP of the asteroid is accepted.
			 */
			v2 newDp     = v2_scale(localDp, world->pixelsPerMeter * 1.5f);
			f32 newDpSum = ABS(newDp.x) + ABS(newDp.y);
			f32 oldDpSum = ABS(entity->dP.x) + ABS(entity->dP.y);

			if (newDpSum > oldDpSum)
			{
				entity->dP = newDp;
			}
		}
		else if (entity->type == entitytype_bullet)
		{
			if (!math_rectContainsP(world->camera, entity->pos))
			{
				deleteEntity(world, i--);
				continue;
			}

			Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f));
			v2 localDp       = V2(math_cosf(rotation), math_sinf(rotation));
			entity->dP       = v2_scale(localDp, world->pixelsPerMeter * 5);
		}
		else if (entity->type == entitytype_particle)
		{
			f32 diff = entity->color.a - 0.1f;
			if (diff < 0.01f)
			{
				deleteEntity(world, i--);
				continue;
			}

			f32 divisor =
			    MAX(entity->particleInitDp.x, entity->particleInitDp.y);
			f32 maxDp = MAX(entity->dP.x, entity->dP.y);

			entity->color.a = maxDp / divisor;
		}

		entity->pos = wrapPAroundBounds(entity->pos,
		                                math_rectCreate(V2(0, 0), world->size));

		/* Loop entity around world */
		i32 collisionIndex = moveEntity(world, &state->transientArena, entity,
		                                i, ddP, dt, ddPSpeedInMs);

		v4 collideColor = {0};
		if (collisionIndex != -1)
		{
			ASSERT(collisionIndex < world->entityIndex);

			Entity *collideEntity = &world->entityList[collisionIndex];

			Entity *colliderA;
			Entity *colliderB;

			if (collideEntity->type < entity->type)
			{
				colliderA = collideEntity;
				colliderB = entity;
			}
			else
			{
				colliderA = entity;
				colliderB = collideEntity;
			}

			// Assumptions made that the collision detect system relies on
			ASSERT(entitytype_ship            < entitytype_asteroid_small);
			ASSERT(entitytype_asteroid_small  < entitytype_asteroid_medium);
			ASSERT(entitytype_asteroid_medium < entitytype_asteroid_large);
			ASSERT(entitytype_asteroid_large  < entitytype_bullet);
			ASSERT(entitytype_asteroid_small + 1 == entitytype_asteroid_medium);
			ASSERT(entitytype_asteroid_medium + 1 == entitytype_asteroid_large);

			if (colliderA->type >= entitytype_asteroid_small &&
			    colliderA->type <= entitytype_asteroid_large)
			{
				f32 numParticles = 4;
				if (colliderA->type == entitytype_asteroid_medium)
				{
					AsteroidSpec spec = {0};
					spec.pos          = colliderA->pos;
					spec.dP           = v2_scale(colliderA->dP, -2.0f);
					addAsteroidWithSpec(world, asteroidsize_small, &spec);

					numParticles = 8;
					world->score += (10 * world->scoreMultiplier);
				}
				else if (colliderA->type == entitytype_asteroid_large)
				{
					AsteroidSpec spec = {0};
					spec.pos          = colliderA->pos;
					spec.dP           = v2_scale(colliderA->dP, -4.0f);
					addAsteroidWithSpec(world, asteroidsize_medium, &spec);

					spec.dP = v2_perpendicular(spec.dP);
					addAsteroidWithSpec(world, asteroidsize_small, &spec);

					spec.dP = v2_perpendicular(colliderA->dP);
					addAsteroidWithSpec(world, asteroidsize_small, &spec);

					numParticles = 16;
					world->score += (20 * world->scoreMultiplier);
				}
				else
				{
					world->score += (5 * world->scoreMultiplier);
				}

				for (i32 i = 0; i < numParticles; i++)
				{
					{ // Add particles
						Entity *particle =
						    &world->entityList[world->entityIndex++];
						particle->id = world->entityIdCounter++;

						particle->pos  = colliderA->pos;
						particle->size = V2(4.0f, 4.0f);

						i32 randValue = rand();
						Radians rotation =
						    DEGREES_TO_RADIANS((randValue % 360));
						v2 randDirectionVec =
						    V2(math_cosf(rotation), math_sinf(rotation));

						i32 particleDpLimit = 8;
						f32 randDpMultiplier =
						    (f32)(randValue % particleDpLimit) + 1;

						v2 newDp = v2_scale(colliderA->dP, randDpMultiplier);
						newDp    = v2_hadamard(newDp, randDirectionVec);

						particle->dP             = newDp;
						particle->particleInitDp = newDp;

						particle->offset     = v2_scale(particle->size, -0.5f);
						particle->hitbox     = particle->size;
						particle->rotation   = 0;
						particle->renderMode = rendermode_polygon;

						if (!world->particleVertexCache)
						{
							world->particleVertexCache =
							    MEMORY_PUSH_ARRAY(&world->entityArena, 4, v2);
							world->particleVertexCache[0] =
							    V2(0, particle->size.h);
							world->particleVertexCache[1] = V2(0, 0);
							world->particleVertexCache[2] =
							    V2(particle->size.w, 0);
							world->particleVertexCache[3] = particle->size;
						}

						particle->vertexPoints    = world->particleVertexCache;
						particle->numVertexPoints = 4;

						particle->type  = entitytype_particle;
						particle->color = V4(1.0f, 0.0f, 0, 1.0f);
					}
				}

				ASSERT(colliderB->type == entitytype_bullet);

				deleteEntity(world, collisionIndex);
				deleteEntity(world, i--);
				world->asteroidCounter--;

				ASSERT(world->asteroidCounter >= 0);

				char *sound;
				i32 choice = rand() % 3;
				if (choice == 0)
				{
					sound = "bang_small";
				}
				else if (choice == 1)
				{
					sound = "bang_medium";
				}
				else
				{
					sound = "bang_large";
				}

				AudioVorbis *explode =
				    asset_vorbisGet(&state->assetManager, sound);
				AudioRenderer *audioRenderer =
				    getFreeAudioRenderer(world, explode, 3);
				if (audioRenderer)
				{
					audio_vorbisPlay(&state->transientArena,
					                 &state->audioManager, audioRenderer,
					                 explode, 1);
				}

				continue;
			}
			else if (colliderA->type == entitytype_ship)
			{
				if (colliderB->type >= entitytype_asteroid_small &&
				    colliderB->type <= entitytype_asteroid_large)
				{
					world->flags |= gameworldstateflags_player_lost;

					if (collideEntity->type == entitytype_ship)
					{
						deleteEntity(world, collisionIndex);
					}
					else
					{
						deleteEntity(world, i--);
					}

					AudioVorbis *explode =
					    asset_vorbisGet(&state->assetManager, "bang_large");
					AudioRenderer *audioRenderer =
					    getFreeAudioRenderer(world, explode, 3);
					if (audioRenderer)
					{
						audio_vorbisPlay(&state->transientArena,
						                 &state->audioManager, audioRenderer,
						                 explode, 1);
					}

					continue;
				}
			}
		}

		RenderFlags flags = renderflag_wireframe | renderflag_no_texture;
		renderer_entity(&state->renderer, &state->transientArena, world->camera,
		                entity, V2(0, 0), 0, collideColor, 0, flags);
	}

	for (i32 i = 0; i < world->numAudioRenderers; i++)
	{
		AudioRenderer *audioRenderer = &world->audioRenderer[i];
		audio_updateAndPlay(&state->transientArena, &state->audioManager,
		                    audioRenderer);
	}
}