Exemple #1
0
void World::update(int ticks)
{
    removeDeadObjects(mRenderables);
    removeDeadObjects(mCollideables);

    mPlayer->update();
    if (!mPlayer->isAlive())
    {
        mPlayer->respawn(mSpawnPoint);
        mCollideables.push_back(mPlayer);
    }

    for (auto& obj : mCollideables)
    {
        obj->update();
        if (!obj->isStatic())
            obj->setVelocity(obj->getVelocity() + mGravity*(UPDATE_STEP.asSeconds()));
        if (obj->getPhysicsPosition().y > SCREEN_HEIGHT)
            obj->kill();
    }

    for (auto& obj : mRenderables)
    {
        if (obj->isParallaxable())
        {
            obj->setRenderPosition(obj->getRenderPosition() + sf::Vector2f(0.25f, 0.f));
            if (obj->getRenderPosition().x > SCREEN_WIDTH)
                obj->setRenderPosition(sf::Vector2f(-obj->getSpriteInfo().mHitBox.width, obj->getRenderPosition().y));
        }
    }

    // check collisions
    for (std::size_t x = 0; x < mCollideables.size(); x++)
    {
        for (std::size_t y = x+1; y < mCollideables.size(); y++)
        {
            auto dynamic = mCollideables[x];
            auto _static = mCollideables[y];

            if (!mCollideables[x]->isStatic())
                dynamic = mCollideables[x];
            else if (!mCollideables[y]->isStatic())
                dynamic = mCollideables[y];

            if (mCollideables[x]->isStatic())
                _static = mCollideables[x];
            else if (mCollideables[y]->isStatic())
                _static = mCollideables[y];

            if (dynamic != _static)
            {
                if (checkCollision(dynamic, _static) && dynamic->isCollisionActive() && _static->isCollisionActive())
                    resolveCollision(dynamic, _static);
            }
        }
    }

    mCamera.follow(sf::Vector2f(mPlayer->getRenderPosition().x, SCREEN_HEIGHT/2.f));
}
Exemple #2
0
void Figure::xMovement(vector<Figure*>& other, int deltaTicks) {
   int count = 0;

   p.x += v.x * deltaTicks / 1000.0;

   if (isCollided(other, count) && count != -1)
      resolveCollision(other[count], deltaTicks, XHAT);
   else if (p.x > lw - dim.w)
      p.x = lw - dim.w;
   else if (p.x < 0)
      p.x = 0;
}
void Sim::collide() {

	contact->circle = ball;

	for (int i = 0; i < 4; i++) {

		if (inside(red[i].position.x - 1000, red[i].position.x + 1000, ball->position.x)) {
			for (int j = 0; j < red[i].size; j++) {

				contact->axis = red[i];
				contact->player = j;

				if (AABBvsCircle(contact)) resolveCollision(contact);
			}
		}



		if (inside(blu[i].position.x - 1000, blu[i].position.x + 1000, ball->position.x)) {
			for (int j = 0; j < blu[i].size; j++) {

				contact->axis = blu[i];
				contact->player = j;

				if (AABBvsCircle(contact)) resolveCollision(contact);
			}
		}

	}

	contactboundary->circle = ball;
	for (int i = 0; i < 6; i++) {
		contactboundary->box = &boundary[i];

		if (boundaryVsCircle(contactboundary)) resolveCollisionBoundary(contactboundary);
	}

}
void PlayerFigure::xMovement(vector<Figure*>& other, int deltaTicks) {
   int count = 0;

   //x movement grabstate
   determineGrabX(deltaTicks);

   p.x += (v.x * deltaTicks / 1000.0) + grabVel.x;

   if (isCollided(other, count) && count != -1)
      resolveCollision(other[count], deltaTicks, XHAT);
   else if (p.x > lw - dim.w)
      p.x = lw - dim.w;
   else if (p.x < 0)
      p.x = 0;
}
Exemple #5
0
int main()
{
    printf("Enter Time Limit : ");
    scanf("%f",&TIME_LIMIT);
    int i, j;
    srand(time(NULL));
    Heap *heap;
    Ball **ball;
    Interaction *nextCollision;
    heap = initHeap();
    ball = (Ball **)malloc(PARTICLE_COUNT * sizeof(Ball *));
    gnuplotPipe = initPipe();
    for(i = 0; i < PARTICLE_COUNT; i++)
    {
        logFile[i] = initGraph(i);
        gnuplotGraphPipe[i] = initGraphPipe(i);
    }
    for(i = 0; i < PARTICLE_COUNT; i++)
    {
        ball[i] = initBallRandom(i);
        insertToHeap(heap, eventWallCollideX(heap, ball[i]));
        insertToHeap(heap, eventWallCollideY(heap, ball[i]));
        for(j = 0; j < i; j++)
            insertToHeap(heap, eventBallCollide(heap, ball[i], ball[j]));
    }
    while(sim_time < TIME_LIMIT)
    {
        nextCollision = getNextEvent(heap);
        simulateTo(ball, nextCollision->tstamp);
        printf("Collision at t=%lf\n", sim_time);
        resolveCollision(nextCollision);
        removeFromHeap(heap, nextCollision->interactee->id);
        scheduleEvent(ball, heap, nextCollision->interactee->id);
        if(nextCollision->interactor != NULL)
        {
            removeFromHeap(heap, nextCollision->interactor->id);
            scheduleEvent(ball, heap, nextCollision->interactor->id);
        }
    }
    fprintf(gnuplotPipe, "quit\n");
    saveGraph(ball);
    showGraph(ball);
    return 0;
}
void ParticleSystemSolver2::onAdvanceTimeStep(double timeStepInSeconds) {
    beginAdvanceTimeStep(timeStepInSeconds);

    Timer timer;
    accumulateForces(timeStepInSeconds);
    JET_INFO << "Accumulating forces took "
             << timer.durationInSeconds() << " seconds";

    timer.reset();
    timeIntegration(timeStepInSeconds);
    JET_INFO << "Time integration took "
             << timer.durationInSeconds() << " seconds";

    timer.reset();
    resolveCollision();
    JET_INFO << "Resolving collision took "
             << timer.durationInSeconds() << " seconds";

    endAdvanceTimeStep(timeStepInSeconds);
}
Exemple #7
0
void Figure::yMovement(vector<Figure*>& other, int deltaTicks) {
   int count = 0;

   //gravity considerations
   determineGravity();

   //jump action
   determineJump();

   //check if inAir is true
   checkIfInAir(other);

   //collision with boundaries or other Figures
   p.y += v.y * deltaTicks / 1000.0;

   if (isCollided(other, count) && count != -1) {

      resolveCollision(other[count], deltaTicks, YHAT);
   }
   else if (p.y > lh - dim.h)
      p.y = lh - dim.h;
}
void ParticleSystemSolver2::resolveCollision() {
    resolveCollision(
        _newPositions.accessor(),
        _newVelocities.accessor());
}
Exemple #9
0
    virtual void	stepSimulation(float deltaTime)
    {
		switch (m_tutorialIndex)
		{
			case TUT_VELOCITY:
			{
				tutorial1Update(deltaTime);
				float xPos = m_bodies[0]->m_worldPose.m_position.x;
				float xVel = m_bodies[0]->m_linearVelocity.x;
				m_timeSeriesCanvas0->insertDataAtCurrentTime(xPos,0,true);
				m_timeSeriesCanvas0->insertDataAtCurrentTime(xVel,1,true);
				break;
			}
			case TUT_ACCELERATION:
			{
				tutorial2Update(deltaTime);
				float yPos = m_bodies[0]->m_worldPose.m_position.y;
				float yVel = m_bodies[0]->m_linearVelocity.y;
				m_timeSeriesCanvas1->insertDataAtCurrentTime(yPos,0,true);
				m_timeSeriesCanvas1->insertDataAtCurrentTime(yVel,1,true);
				
				break;
			}
			case TUT_COLLISION:
			{
				m_contactPoints.clear();
				LWContactPoint contactPoint;
				tutorialCollisionUpdate(deltaTime, contactPoint);
				m_contactPoints.push_back(contactPoint);
				m_timeSeriesCanvas1->insertDataAtCurrentTime(contactPoint.m_distance,0,true);
				
				break;
			}
			case TUT_SOLVE_CONTACT_CONSTRAINT:
			{
				m_contactPoints.clear();
				LWContactPoint contactPoint;
				tutorialSolveContactConstraintUpdate(deltaTime, contactPoint);
				m_contactPoints.push_back(contactPoint);
				if (contactPoint.m_distance<0)
				{
					m_bodies[0]->computeInvInertiaTensorWorld();
					m_bodies[1]->computeInvInertiaTensorWorld();
					
					b3Scalar appliedImpulse = resolveCollision(*m_bodies[0],
									 *m_bodies[1],
									 contactPoint
									 );
				
					m_timeSeriesCanvas1->insertDataAtCurrentTime(appliedImpulse,1,true);
					
				} else
				{
					m_timeSeriesCanvas1->insertDataAtCurrentTime(0.,1,true);
				}
				m_timeSeriesCanvas1->insertDataAtCurrentTime(contactPoint.m_distance,0,true);
				
				break;
			}

			default:
			{
			}
			
		};
		
		
		if (m_timeSeriesCanvas0)
			m_timeSeriesCanvas0->nextTick();
		
		if (m_timeSeriesCanvas1)
			m_timeSeriesCanvas1->nextTick();

		
		for (int i=0;i<m_bodies.size();i++)
		{
			
			m_bodies[i]->integrateAcceleration(deltaTime);
			m_bodies[i]->integrateVelocity(deltaTime);
			
			m_app->m_renderer->writeSingleInstanceTransformToCPU(m_bodies[i]->m_worldPose.m_position, m_bodies[i]->m_worldPose.m_orientation, m_bodies[i]->m_graphicsIndex);
		}

		
		 m_app->m_renderer->writeTransforms();
    }
    void StdChoreographer::update(double dt)
    {
        _dt = dt;

        if(_dt == 0)
        {
            // No time elapsed,
            // no need to update
            return;
        }

        if(_dt > _maxHandledDeltaTime)
        {
            // To much time elpased,
            // would make the simulation unstable
            return;
        }

        size_t nbCircles = _circles.size();
        size_t nbPolygons = _polygons.size();

        // Update positions of all shapes
        for(size_t i=0; i<_circles.size(); ++i)
        {
            updateShape(_circles[i]);
        }
        for(size_t i=0; i<_polygons.size(); ++i)
        {
            updateShape(_polygons[i]);
        }


        // Resolve collisions of dynamic shapes
        // Order is important;
        // A shape should never trigger a resolveXY() with a preceding shape :
        //  * Circles precede Polygons
        //  * Lower indices precede higher indices
        std::vector< std::shared_ptr<StdCollisionReport> > collisionReports;
        std::shared_ptr<StdCollisionReport> report;

        for(size_t master=0; master < nbCircles; ++master)
        {
            shared_ptr<Circle>& masterCircle = _circles[master];

            if(masterCircle->bodyType() == EBodyType::DYNAMIC)
            {
                for(size_t slave = 0; slave < nbCircles; ++slave)
                {
                    const std::shared_ptr<Circle>& slaveCircle = _circles[slave];
                    if(slaveCircle->bodyType() != EBodyType::GRAPHIC &&
                       (slaveCircle->bodyType() == EBodyType::KINEMATIC ||
                        master < slave))
                    {
                        report = detectCircleCircle(masterCircle, slaveCircle);
                        if(report->areColliding)
                            collisionReports.push_back(report);
                    }
                }

                for(size_t slave = 0; slave < nbPolygons; ++slave)
                {
                    const std::shared_ptr<Polygon>& slavePolygon = _polygons[slave];
                    if(slavePolygon->bodyType() != EBodyType::GRAPHIC)
                    {
                        report = detectCirclePolygon(masterCircle, slavePolygon);
                        if(report->areColliding)
                            collisionReports.push_back(report);
                    }
                }
            }
        }

        for(size_t master=0; master < nbPolygons; ++master)
        {
            shared_ptr<Polygon>& masterPolygon = _polygons[master];

            if(masterPolygon->bodyType() == EBodyType::DYNAMIC)
            {
                for(size_t slave = 0; slave < nbCircles; ++slave)
                {
                    const std::shared_ptr<Circle>& slaveCircle = _circles[slave];
                    if(slaveCircle->bodyType() == EBodyType::KINEMATIC)
                    {
                        report = detectCirclePolygon(slaveCircle, masterPolygon);
                        if(report->areColliding)
                            collisionReports.push_back(report);
                    }
                }

                for(size_t slave = 0; slave < nbPolygons; ++slave)
                {
                    const std::shared_ptr<Polygon>& slavePolygon = _polygons[slave];
                    if(slavePolygon->bodyType() != EBodyType::GRAPHIC &&
                       (slavePolygon->bodyType() == EBodyType::KINEMATIC ||
                        master < slave))
                    {
                        report = detectPolygonPolygon(masterPolygon, slavePolygon);
                        if(report->areColliding)
                            collisionReports.push_back(report);
                    }
                }
            }
        }


        // Resolve found collisions
        int nbReports = static_cast<int>(collisionReports.size());
        for(int i=0; i < nbReports; ++i)
        {
            moveApart(collisionReports[i]);
            resolveCollision(collisionReports[i]);
        }
    }
Exemple #11
0
void Physics::update(Game *game)
{
	// REMEMBER, AT THIS POINT, ALL PLAYER INPUT AND AI
	// HAVE ALREADY BEEN PROCESSED AND BOT AND PLAYER
	// STATES, VELOCITIES, AND ACCELERATIONS HAVE ALREADY
	// BEEN UPDATED. NOW WE HAVE TO PROCESS THE PHYSICS
	// OF ALL THESE OBJECTS INTERACTING WITH EACH OTHER
	// AND THE STATIC GAME WORLD. THIS MEANS WE NEED TO
	// DETECT AND RESOLVE COLLISIONS IN THE ORDER THAT
	// THEY WILL HAPPEN, AND WITH EACH COLLISION, EXECUTE
	// ANY GAMEPLAY RESPONSE CODE, UPDATE VELOCITIES, AND
	// IN THE END, UPDATE POSITIONS

	// FIRST, YOU SHOULD START BY ADDING ACCELERATION TO ALL 
	// VELOCITIES, WHICH INCLUDES GRAVITY, NOTE THE EXAMPLE
	// BELOW DOES NOT DO THAT


	// FOR NOW, WE'LL JUST ADD THE VELOCITIES TO THE
	// POSITIONS, WHICH MEANS WE'RE NOT APPLYING GRAVITY OR
	// ACCELERATION AND WE ARE NOT DOING ANY COLLISION 
	// DETECTION OR RESPONSE
	float timer = 0;

	GameStateManager *gsm = game->getGSM();
	SpriteManager *sm = gsm->getSpriteManager();
	World *w = gsm->getWorld();
	GameRules* gR = game->getGameRules();
	vector<WorldLayer*> *layers = w->getLayers();

	AnimatedSprite *player;
	PhysicalProperties *pp;
	TiledLayer *tL;
	list<Collision*> collisions;
	
	//finding TileLayer
	for(unsigned int i = 0; i < layers->size(); i++)
	{
		WorldLayer *currentLayer = (*layers)[i];
		if(currentLayer->hasCollidableTiles() == true)
		{
			tL = dynamic_cast<TiledLayer*>(currentLayer);
			if(tL != 0)
			{
				i = layers->size();
			}//end if
		}//end if
	}


	player = sm->getPlayer();
	pp = player->getPhysicalProperties();

	//UPDATING ALL VELOCITIES AND DOING TILE COLLISION
	pp->incVelocity(this,pp->getAccelerationX(), pp->getAccelerationY() + gravity); 
	collideTestWithTiles(player, tL, &collisions);

	list<Bot*>::iterator botIterator = sm->getBotsIterator();
	while (botIterator != sm->getEndOfBotsIterator())
	{			
		Bot *bot = (*botIterator);
		pp = bot->getPhysicalProperties();
		pp->incVelocity(this, pp->getAccelerationX(), pp->getAccelerationY());
		if(pp->isGravAffected() == true)
			pp->incVelocity(this, 0, gravity);
		collideTestWithTiles(bot, tL, &collisions);
		botIterator++;
	}

	//HERE, COLLIDE SPRITES WITH OTHER SPRITES
	collideTestWithSprites(game, player, &collisions);
	botIterator = sm->getBotsIterator();
	while (botIterator != sm->getEndOfBotsIterator())
	{			
		Bot *bot = (*botIterator);
		if(bot->isCurrentlyCollidable() == true);
			collideTestWithSprites(game, bot, &collisions);
		botIterator++;
	}

	//SORT COLLISIONS
	collisions.sort(compare_collisionTime);

	//RESOLVING ALL THE COLLISIONS
	while(collisions.empty() == false)
	{
		Collision* currentCollision = collisions.front();
		collisions.pop_front();
		float colTime = currentCollision->getTOC();
		CollidableObject* co1 = currentCollision->getCO1();
		CollidableObject* co2 = currentCollision->getCO2();

		if(colTime >= 0 && colTime <= 1)
		{
			
			pp = co1->getPhysicalProperties();
			//pp->setVelocity(pp->getVelocityX()*9.99f,pp->getVelocityY()*9.99f);
			pp = co2->getPhysicalProperties();
			//pp->setVelocity(pp->getVelocityX()*9.99f,pp->getVelocityY()*9.99f);

			pp = player->getPhysicalProperties();
			pp->setPosition(pp->getX() + (pp->getVelocityX()*(colTime-timer)),pp->getY() + (pp->getVelocityY()*(colTime-timer)));
			botIterator = sm->getBotsIterator();
			while (botIterator != sm->getEndOfBotsIterator())
			{			
				Bot *bot = (*botIterator);
				pp = bot->getPhysicalProperties();
				pp->setPosition(pp->getX() + (pp->getVelocityX()*(colTime-timer)), pp->getY() + (pp->getVelocityY()*(colTime-timer)));
				botIterator++;
			}

			gsm->updateViewport(game, colTime-timer);

			resolveCollision(game, currentCollision);
			gR->gameSpecificResolve(game, currentCollision);
			
			boolean deleteLast = false;
			list<Collision*>::iterator cIterator = collisions.begin();
			list<Collision*>::iterator lastIterator;
			while(cIterator != collisions.end())
			{
				if(deleteLast == true)
				{
					collisions.erase(lastIterator);
				}
				deleteLast = false;
				Collision* check = (*cIterator);
				if(check->contains(co1) || check->contains(co2))
				{
					CollidableObject* checkStatic = check->getCO2();
					if(checkStatic->isStaticObject())
					{
						coStackCounter ++;
						coStack[coStackCounter] = checkStatic;
					}

					collisionStackCounter ++;
					collisionStack[collisionStackCounter] = check;

					lastIterator = cIterator;
					deleteLast = true;
				}
				else
				{
					//check->calculateTimes();
				}

				cIterator++;
			}

			if(deleteLast == true)
			{
				collisions.erase(lastIterator);
			}

			collideTestWithTiles(co1, tL, &collisions);
			collideTestWithSprites(game, co1, &collisions);

			if(co2->isStaticObject() == false)
			{
				collideTestWithTiles(co2, tL, &collisions);
				collideTestWithSprites(game, co2, &collisions);
			}

			collisions.sort(compare_collisionTime);

			timer += (colTime-timer);
		}//end if


		if(co2->isStaticObject() == true)
		{
			coStackCounter ++;
			coStack[coStackCounter] = co2;
		}

		collisionStackCounter ++;
		collisionStack[collisionStackCounter] = currentCollision;
	
	}
	
	if(timer < 1)
	{
		gsm->updateViewport(game, 1-timer);
		pp = player->getPhysicalProperties();
		pp->setPosition(pp->getX() + (pp->getVelocityX()*(1-timer)),pp->getY() + (pp->getVelocityY()*(1-timer)));
		//pp->setVelocity(0.0f, pp->getVelocityY());
		botIterator = sm->getBotsIterator();
		while (botIterator != sm->getEndOfBotsIterator())
		{			
			Bot *bot = (*botIterator);
			pp = bot->getPhysicalProperties();
			pp->setPosition(pp->getX() + (pp->getVelocityX()*(1-timer)), pp->getY() + (pp->getVelocityY()*(1-timer)));
			botIterator++;
		}
		gsm->updateViewport(game, 1-timer);
	}
	
	pp = player->getPhysicalProperties();
	if(pp->getX() < 0)
	{
		pp->setX(0);
	}
	if(pp->getY() < 0)
	{
		pp->setY(0);
	}
	//pp->setVelocity(0.0f, pp->getVelocityY());
	/*pp->setPosition(pp->getX() + pp->getVelocityX(), pp->getY() + pp->getVelocityY());

	// FOR NOW THE PLAYER IS DIRECTLY CONTROLLED BY THE KEYBOARD,
	// SO WE'LL NEED TO TURN OFF ANY VELOCITY APPLIED BY INPUT
	// SO THE NEXT FRAME IT DOESN'T GET ADDED
	pp->setVelocity(0.0f, pp->getVelocityY());

	// AND NOW MOVE ALL THE BOTS
	list<Bot*>::iterator botIterator = sm->getBotsIterator();
	while (botIterator != sm->getEndOfBotsIterator())
	{			
		Bot *bot = (*botIterator);
		pp = bot->getPhysicalProperties();
		pp->setPosition(pp->getX() + pp->getVelocityX(), pp->getY() + pp->getVelocityY());
		botIterator++;
	}*/

	
}
void GameStatePlayUpdate(void)
{
    if (AEInputCheckTriggered(DIK_J))
        SendJoinMessage();

    MsgInput inputMsg;
    if(ProcInput(inputMsg))
    {
        strcpy(inputMsg.data_.username_.name_, client.config_.username_.c_str());
        NetworkMessage netMsg;
        netMsg << inputMsg;
        netMsg.receiverAddress_ = client.remoteAddr_;
        try
        {
            printf("\nSending INPUT message... Input Count = %d\n", inputMsg.data_.key_info_count_);
            client.udpSock_.Send(netMsg);
        }
        catch(iSocket::SockErr& e)
        {
            e.Print();
        }
    }

    char buffer[1000] = { 0 };
    sprintf(buffer, "TIME LEFT: %.2f", time);
    AEGfxPrint(300, 10, 0xFFFFFFFF, buffer);
    sprintf(buffer, "Round: %u", round);
    AEGfxPrint(350, 30, 0xFFFFFFFF, buffer);

    unsigned yPos = 10;
    unsigned xPos = 10;
    for(std::vector<ResultStatus>::iterator it = results.begin(); it != results.end(); ++it)
    {
        sprintf(buffer, "%s:    Score: %u", it->name_.name_, it->score_);
        AEGfxPrint(xPos, yPos, 0xFFFFFFFF, buffer);
        yPos += ROW_HEIGHT;
    }

    client.udpSock_.Resend();

    // check for messages from server
    NetworkMessage netMsg;
    if(client.udpSock_.Receive(netMsg))
        ProcMessage(netMsg);
#if 0
    // ===============
    // update physics
    // ===============

    for (u32 i = 0; i < GAME_OBJ_INST_NUM_MAX; i++)
    {
        GameObjInst* pInst = sGameObjInstList + i;

        // skip non-active object
        if ((pInst->flag & FLAG_ACTIVE) == 0)
            continue;

        // update the position
        AEVec2ScaleAdd(&pInst->posCurr, &pInst->velCurr, &pInst->posCurr, (f32)(gAEFrameTime));
    }

    // ===============
    // update objects
    // ===============

    for (u32 i = 0; i < GAME_OBJ_INST_NUM_MAX; i++)
    {
        GameObjInst* pInst = sGameObjInstList + i;

        // skip non-active object
        if ((pInst->flag & FLAG_ACTIVE) == 0)
            continue;

        // check if the object is a ship
        if (pInst->pObject->type == TYPE_SHIP)
        {
            // warp the ship from one end of the screen to the other
            pInst->posCurr.x = AEWrap(pInst->posCurr.x, gAEWinMinX - SHIP_SIZE, gAEWinMaxX + SHIP_SIZE);
            pInst->posCurr.y = AEWrap(pInst->posCurr.y, gAEWinMinY - SHIP_SIZE, gAEWinMaxY + SHIP_SIZE);
        }
        // check if the object is an asteroid
        else if (pInst->pObject->type == TYPE_ASTEROID)
        {
            AEVec2 u;
            f32    uLen;

            // warp the asteroid from one end of the screen to the other
            pInst->posCurr.x = AEWrap(pInst->posCurr.x, gAEWinMinX - AST_SIZE_MAX, gAEWinMaxX + AST_SIZE_MAX);
            pInst->posCurr.y = AEWrap(pInst->posCurr.y, gAEWinMinY - AST_SIZE_MAX, gAEWinMaxY + AST_SIZE_MAX);

            // pull the asteroid toward the ship a little bit
            if (spShip)
            {
                // apply acceleration propotional to the distance from the asteroid to the ship
                AEVec2Sub	(&u, &spShip->posCurr, &pInst->posCurr);
                AEVec2Scale	(&u, &u, AST_TO_SHIP_ACC * (f32)(gAEFrameTime));
                AEVec2Add	(&pInst->velCurr, &pInst->velCurr, &u);
            }

            // if the asterid velocity is more than its maximum velocity, reduce its speed
            if ((uLen = AEVec2Length(&pInst->velCurr)) > (AST_VEL_MAX * 2.0f))
            {
                AEVec2Scale	(&u, &pInst->velCurr, (1.0f / uLen) * (AST_VEL_MAX * 2.0f - uLen) * pow(AST_VEL_DAMP, (f32)(gAEFrameTime)));
                AEVec2Add	(&pInst->velCurr, &pInst->velCurr, &u);
            }
        }
        // check if the object is a bullet
        else if (pInst->pObject->type == TYPE_BULLET)
        {
            // kill the bullet if it gets out of the screen
            if (!AEInRange(pInst->posCurr.x, gAEWinMinX - AST_SIZE_MAX, gAEWinMaxX + AST_SIZE_MAX) || 
                !AEInRange(pInst->posCurr.y, gAEWinMinY - AST_SIZE_MAX, gAEWinMaxY + AST_SIZE_MAX))
                gameObjInstDestroy(pInst);
        }
        // check if the object is a bomb
        else if (pInst->pObject->type == TYPE_BOMB)
        {
            // adjust the life counter
            pInst->life -= (f32)(gAEFrameTime) / BOMB_LIFE;

            if (pInst->life < 0.0f)
            {
                gameObjInstDestroy(pInst);
            }
            else
            {
                f32    radius = 1.0f - pInst->life;
                AEVec2 u;

                pInst->dirCurr += 2.0f * PI * (f32)(gAEFrameTime);

                radius =   1.0f - radius;
                radius *=  radius;
                radius *=  radius;
                radius *=  radius;
                radius *=  radius;
                radius =   (1.0f - radius) * BOMB_RADIUS;

                // generate the particle ring
                for (u32 j = 0; j < 10; j++)
                {
                    //f32 dir = AERandFloat() * 2.0f * PI;
                    f32 dir = (j / 9.0f) * 2.0f * PI + pInst->life * 1.5f * 2.0f * PI;

                    u.x = AECos(dir) * radius + pInst->posCurr.x;
                    u.y = AESin(dir) * radius + pInst->posCurr.y;

                    //sparkCreate(PTCL_EXHAUST, &u, 1, dir + 0.8f * PI, dir + 0.9f * PI);
                    sparkCreate(PTCL_EXHAUST, &u, 1, dir + 0.40f * PI, dir + 0.60f * PI);
                }
            }
        }
        // check if the object is a missile
        else if (pInst->pObject->type == TYPE_MISSILE)
        {
            // adjust the life counter
            pInst->life -= (f32)(gAEFrameTime) / MISSILE_LIFE;

            if (pInst->life < 0.0f)
            {
                gameObjInstDestroy(pInst);
            }
            else
            {
                AEVec2 dir;

                if (pInst->pUserData == 0)
                {
                    pInst->pUserData = missileAcquireTarget(pInst);
                }
                else
                {
                    GameObjInst* pTarget = (GameObjInst*)(pInst->pUserData);

                    // if the target is no longer valid, reacquire
                    if (((pTarget->flag & FLAG_ACTIVE) == 0) || (pTarget->pObject->type != TYPE_ASTEROID))
                        pInst->pUserData = missileAcquireTarget(pInst);
                }

                if (pInst->pUserData)
                {
                    GameObjInst* pTarget = (GameObjInst*)(pInst->pUserData);
                    AEVec2 u;
                    f32    uLen;

                    // get the vector from the missile to the target and its length
                    AEVec2Sub(&u, &pTarget->posCurr, &pInst->posCurr);
                    uLen = AEVec2Length(&u);

                    // if the missile is 'close' to target, do nothing
                    if (uLen > 0.1f)
                    {
                        // normalize the vector from the missile to the target
                        AEVec2Scale(&u, &u, 1.0f / uLen);

                        // calculate the missile direction vector
                        AEVec2Set(&dir, AECos(pInst->dirCurr), AESin(pInst->dirCurr));

                        // calculate the cos and sin of the angle between the target 
                        // vector and the missile direction vector
                        f32 cosAngle = AEVec2DotProduct(&dir, &u), 
                            sinAngle = AEVec2CrossProductMag(&dir, &u), 
                            rotAngle;

                        // calculate how much to rotate the missile
                        if (cosAngle < AECos(MISSILE_TURN_SPEED * (f32)(gAEFrameTime)))
                            rotAngle = MISSILE_TURN_SPEED * (f32)(gAEFrameTime);
                        else
                            rotAngle = AEACos(AEClamp(cosAngle, -1.0f, 1.0f));

                        // rotate to the left if sine of the angle is positive and vice versa
                        pInst->dirCurr += (sinAngle > 0.0f) ? rotAngle : -rotAngle;
                    }
                }

                // adjust the missile velocity
                AEVec2Set  (&dir, AECos(pInst->dirCurr), AESin(pInst->dirCurr));
                AEVec2Scale(&dir, &dir, MISSILE_ACCEL * (f32)(gAEFrameTime));
                AEVec2Add  (&pInst->velCurr, &pInst->velCurr, &dir);
                AEVec2Scale(&pInst->velCurr, &pInst->velCurr, pow(MISSILE_DAMP, (f32)(gAEFrameTime)));

                sparkCreate(PTCL_EXHAUST, &pInst->posCurr, 1, pInst->dirCurr + 0.8f * PI, pInst->dirCurr + 1.2f * PI);
            }
        }
        // check if the object is a particle
        else if ((TYPE_PTCL_WHITE <= pInst->pObject->type) && (pInst->pObject->type <= TYPE_PTCL_RED))
        {
            pInst->scale   *= pow(PTCL_SCALE_DAMP, (f32)(gAEFrameTime));
            pInst->dirCurr += 0.1f;
            AEVec2Scale(&pInst->velCurr, &pInst->velCurr, pow(PTCL_VEL_DAMP, (f32)(gAEFrameTime)));

            if (pInst->scale < PTCL_SCALE_DAMP)
                gameObjInstDestroy(pInst);
        }
    }

    // ====================
    // check for collision
    // ====================

    for (u32 i = 0; i < GAME_OBJ_INST_NUM_MAX; i++)
    {
        GameObjInst* pSrc = sGameObjInstList + i;

        // skip non-active object
        if ((pSrc->flag & FLAG_ACTIVE) == 0)
            continue;

        if ((pSrc->pObject->type == TYPE_BULLET) || (pSrc->pObject->type == TYPE_MISSILE))
        {
            for (u32 j = 0; j < GAME_OBJ_INST_NUM_MAX; j++)
            {
                GameObjInst* pDst = sGameObjInstList + j;

                // skip no-active and non-asteroid object
                if (((pDst->flag & FLAG_ACTIVE) == 0) || (pDst->pObject->type != TYPE_ASTEROID))
                    continue;

                if (AETestPointToRect(&pSrc->posCurr, &pDst->posCurr, pDst->scale, pDst->scale) == false)
                    continue;

                if (pDst->scale < AST_SIZE_MIN)
                {
                    sparkCreate(PTCL_EXPLOSION_M, &pDst->posCurr, (u32)(pDst->scale * 10), pSrc->dirCurr - 0.05f * PI, pSrc->dirCurr + 0.05f * PI, pDst->scale);
                    sScore++;

                    if ((sScore % AST_SPECIAL_RATIO) == 0)
                        sSpecialCtr++;
                    if ((sScore % AST_SHIP_RATIO) == 0)
                        sShipCtr++;
                    if (sScore == sAstNum * 5)
                        sAstNum = (sAstNum < AST_NUM_MAX) ? (sAstNum * 2) : sAstNum;

                    // destroy the asteroid
                    gameObjInstDestroy(pDst);
                }
                else
                {
                    sparkCreate(PTCL_EXPLOSION_S, &pSrc->posCurr, 10, pSrc->dirCurr + 0.9f * PI, pSrc->dirCurr + 1.1f * PI);

                    // impart some of the bullet/missile velocity to the asteroid
                    AEVec2Scale(&pSrc->velCurr, &pSrc->velCurr, 0.01f * (1.0f - pDst->scale / AST_SIZE_MAX));
                    AEVec2Add  (&pDst->velCurr, &pDst->velCurr, &pSrc->velCurr);

                    // split the asteroid to 4
                    if ((pSrc->pObject->type == TYPE_MISSILE) || ((pDst->life -= 1.0f) < 0.0f))
                        astCreate(pDst);
                }

                // destroy the bullet
                gameObjInstDestroy(pSrc);

                break;
            }
        }
        else if (TYPE_BOMB == pSrc->pObject->type)
        {
            f32 radius = 1.0f - pSrc->life;

            pSrc->dirCurr += 2.0f * PI * (f32)(gAEFrameTime);

            radius =   1.0f - radius;
            radius *=  radius;
            radius *=  radius;
            radius *=  radius;
            radius *=  radius;
            radius *=  radius;
            radius =   (1.0f - radius) * BOMB_RADIUS;

            // check collision
            for (u32 j = 0; j < GAME_OBJ_INST_NUM_MAX; j++)
            {
                GameObjInst* pDst = sGameObjInstList + j;

                if (((pDst->flag & FLAG_ACTIVE) == 0) || (pDst->pObject->type != TYPE_ASTEROID))
                    continue;

                if (AECalcDistPointToRect(&pSrc->posCurr, &pDst->posCurr, pDst->scale, pDst->scale) > radius)
                    continue;

                if (pDst->scale < AST_SIZE_MIN)
                {
                    f32 dir = atan2f(pDst->posCurr.y - pSrc->posCurr.y, pDst->posCurr.x - pSrc->posCurr.x);

                    gameObjInstDestroy(pDst);
                    sparkCreate(PTCL_EXPLOSION_M, &pDst->posCurr, 20, dir + 0.4f * PI, dir + 0.45f * PI);
                    sScore++;

                    if ((sScore % AST_SPECIAL_RATIO) == 0)
                        sSpecialCtr++;
                    if ((sScore % AST_SHIP_RATIO) == 0)
                        sShipCtr++;
                    if (sScore == sAstNum * 5)
                        sAstNum = (sAstNum < AST_NUM_MAX) ? (sAstNum * 2) : sAstNum;
                }
                else
                {
                    // split the asteroid to 4
                    astCreate(pDst);
                }
            }
        }
        else if (pSrc->pObject->type == TYPE_ASTEROID)
        {
            for (u32 j = 0; j < GAME_OBJ_INST_NUM_MAX; j++)
            {
                GameObjInst* pDst = sGameObjInstList + j;
                f32          d;
                AEVec2       nrm, u;

                // skip no-active and non-asteroid object
                if ((pSrc == pDst) || ((pDst->flag & FLAG_ACTIVE) == 0)  || (pDst->pObject->type != TYPE_ASTEROID))
                    continue;

                // check if the object rectangle overlap
                d = AECalcDistRectToRect(
                    &pSrc->posCurr, pSrc->scale, pSrc->scale, 
                    &pDst->posCurr, pDst->scale, pDst->scale, 
                    &nrm);

                if (d >= 0.0f)
                    continue;

                // adjust object position so that they do not overlap
                AEVec2Scale	(&u, &nrm, d * 0.25f);
                AEVec2Sub	(&pSrc->posCurr, &pSrc->posCurr, &u);
                AEVec2Add	(&pDst->posCurr, &pDst->posCurr, &u);

                // calculate new object velocities
                resolveCollision(pSrc, pDst, &nrm);
            }
        }
        else if (pSrc->pObject->type == TYPE_SHIP)
        {
            for (u32 j = 0; j < GAME_OBJ_INST_NUM_MAX; j++)
            {
                GameObjInst* pDst = sGameObjInstList + j;

                // skip no-active and non-asteroid object
                if ((pSrc == pDst) || ((pDst->flag & FLAG_ACTIVE) == 0) || (pDst->pObject->type != TYPE_ASTEROID))
                    continue;

                // check if the object rectangle overlap
                if (AETestRectToRect(
                    &pSrc->posCurr, pSrc->scale, pSrc->scale, 
                    &pDst->posCurr, pDst->scale, pDst->scale) == false)
                    continue;

                // create the big explosion
                sparkCreate(PTCL_EXPLOSION_L, &pSrc->posCurr, 100, 0.0f, 2.0f * PI);

                // reset the ship position and direction
                AEVec2Zero(&spShip->posCurr);
                AEVec2Zero(&spShip->velCurr);
                spShip->dirCurr = 0.0f;

                sSpecialCtr = SHIP_SPECIAL_NUM;

                // destroy all asteroid near the ship so that you do not die as soon as the ship reappear
                for (u32 j = 0; j < GAME_OBJ_INST_NUM_MAX; j++)
                {
                    GameObjInst* pInst = sGameObjInstList + j;
                    AEVec2		 u;

                    // skip no-active and non-asteroid object
                    if (((pInst->flag & FLAG_ACTIVE) == 0) || (pInst->pObject->type != TYPE_ASTEROID))
                        continue;

                    AEVec2Sub(&u, &pInst->posCurr, &spShip->posCurr);

                    if (AEVec2Length(&u) < (spShip->scale * 10.0f))
                    {
                        sparkCreate		  (PTCL_EXPLOSION_M, &pInst->posCurr, 10, -PI, PI);
                        gameObjInstDestroy(pInst);
                    }
                }

                // reduce the ship counter
                sShipCtr--;

                // if counter is less than 0, game over
                if (sShipCtr < 0)
                {
                    sGameStateChangeCtr = 2.0;
                    gameObjInstDestroy(spShip);
                    spShip = 0;
                }

                break;
            }
        }
    }
#endif
    // =====================================
    // calculate the matrix for all objects
    // =====================================

    for (u32 i = 0; i < GAME_OBJ_INST_NUM_MAX; i++)
    {
        GameObjInst* pInst = sGameObjInstList + i;
        AEMtx33		 m;

        // skip non-active object
        if ((pInst->flag & FLAG_ACTIVE) == 0)
            continue;

        AEMtx33Scale		(&pInst->transform, pInst->scale,     pInst->scale);
        AEMtx33Rot			(&m,                pInst->dirCurr);
        AEMtx33Concat		(&pInst->transform, &m,               &pInst->transform);
        AEMtx33Trans		(&m,                pInst->posCurr.x, pInst->posCurr.y);
        AEMtx33Concat		(&pInst->transform, &m,               &pInst->transform);
    }
}
Exemple #13
0
/**
 * Steps the world.
 *
 * This function is not complete, may need some rework.
 */
void DYN_stepWorld(DYN_Context *context)
{
    int i, j;
    double remainingTime = 1;
    double nearestPoints[6];
    int stuckCtr = 0;

    if (simStopped) return;

    while (remainingTime > 0)
    {
        char wasCollision = 0;
        // STEP 1: Moving bodies
        for (i = 0; i < context->bodyCount; i++)
        {
            moveBody(&context->bodies[i], remainingTime);
        }
        // STEP 2: Collision detection
        for (i = 0; i < context->bodyCount; i++)
        {
            context->bodies[i].colliding = 0;
            context->bodies[i].inContact = 0;
        }
        for (i = 0; i < context->bodyCount; i++)
        {
            for (j = i + 1; j < context->bodyCount; j++)
            {
                double nearestPoints[6];
                int tmp[2];
                tmp[0] = i;
                tmp[1] = j;

                if (AVL_find(&context->ncPairIndex, tmp))
                {
                    continue;
                }

                if (COL_collide(&context->bodies[i], &context->bodies[j], nearestPoints, 0))
                {
                    addCollidingPair(context, i, j);
                    wasCollision = 1;
                }
            }
        }
        if (wasCollision)
        {
            double currentImpulseVector[3];
            double currentCollisionPoint[3];
            double minTime = 1;
            int earlyAIndex = -1, earlyBIndex = -1;
            // There was collision
            // STEP 3: Find earliest collision
            int i;
            int cpCount = DYNA_getLength(&context->collidingPairs);
            int (*collidingPairs)[2] = DYNA_getStorage(&context->collidingPairs);
            // Find the earliest collision.
            assert(cpCount);
            for (i = 0; i < cpCount; i++)
            {
                DYN_Body *a = &context->bodies[collidingPairs[i][0]];
                DYN_Body *b = &context->bodies[collidingPairs[i][1]];
                double lower = 0;
                double upper = remainingTime;
                int stuckCtr2 = 0;
                char nearestSet = 0;

                for(;;stuckCtr2++)
                {
                    double middle = (lower + upper) * 0.5;

                    revertMovement(a);
                    revertMovement(b);
                    moveBody(a, middle);
                    moveBody(b, middle);
                    if (COL_collide(a, b, nearestPoints, 0))
                    {
                        upper = middle;
                    }
                    else
                    {
                        nearestSet = 1;
                        lower = middle;
                    }
                    assert(lower != upper);
                    if (nearestSet)
                    {
                        double tmp[3];
                        ALG_getPointToPointVector(tmp, nearestPoints, &nearestPoints[3]);
                        if ((ALG_dotProduct(tmp, tmp) < 1e-6) || (fabs(upper-lower) < 1e-6))
                        {
                            // The two bodies are near each other.
                            if (middle <= minTime)
                            {
                                minTime = middle;
                                earlyAIndex = collidingPairs[i][0];
                                earlyBIndex = collidingPairs[i][1];
                                memcpy(currentImpulseVector, tmp, sizeof(currentImpulseVector));
                                memcpy(currentCollisionPoint, nearestPoints, sizeof(currentCollisionPoint));
                            }
                            break;
                        }
                    }
                }
            }
            {
                DYN_Body *a = &context->bodies[earlyAIndex];
                DYN_Body *b = &context->bodies[earlyBIndex];
                fprintf(DYN_log, "Collision!\n");
                fprintf(DYN_log, "Body index A: %d\n", earlyAIndex);
                fprintf(DYN_log, "Body index B: %d\n", earlyBIndex);
                fprintf(DYN_log, "Velocity A [%g, %g, %g] %g\n", a->velocity[0], a->velocity[1], a->velocity[2], ALG_getVectorLength(a->velocity));
                fprintf(DYN_log, "Velocity B [%g, %g, %g] %g\n", b->velocity[0], b->velocity[1], b->velocity[2], ALG_getVectorLength(b->velocity));
                fprintf(DYN_log, "Collision point [%g, %g, %g]\n", currentCollisionPoint[0], currentCollisionPoint[1], currentCollisionPoint[2]);
                fprintf(
                    DYN_log,
                    "Impulse vector [%g, %g, %g] %g\n",
                    currentImpulseVector[0],
                    currentImpulseVector[1],
                    currentImpulseVector[2],
                    ALG_getVectorLength(currentImpulseVector)
                );
                fprintf(DYN_log, "Elapsed time: %g\n", context->elapsedTime + context->timeStep * (1 - remainingTime));
            }
            // Revert and move all bodies to the collision moment.
            for (i = 0; i < context->bodyCount; i++)
            {
                DYN_Body *current = &context->bodies[i];
                revertMovement(current);
                moveBody(current, minTime);
            }
            assert(earlyAIndex >= 0);
            assert(earlyBIndex >= 0);
            // Resolve the collision
            {
                CollisionResult result = resolveCollision(
                    context,
                    &context->bodies[earlyAIndex],
                    &context->bodies[earlyBIndex],
                    currentCollisionPoint,
                    currentImpulseVector
                );
                if (result == DYN_STICKEDTOGETHER)
                {
                    addNonCollidingPair(context, earlyAIndex, earlyBIndex);
                    context->bodies[earlyAIndex].inContact = 1;
                    context->bodies[earlyBIndex].inContact = 1;
                }
            }
            memcpy(DYN_lastCollisionPoint, currentCollisionPoint, sizeof(DYN_lastCollisionPoint));
            memcpy(DYN_lastImpulse, currentImpulseVector, sizeof(DYN_lastImpulse));
            fprintf(DYN_log, "==============================\n");
            //
            clearCollidingPairs(context);
            // Continue the simulation
            remainingTime -= minTime;
        }
        else
        {
            // No collision, step finished
            break;
        }
        stuckCtr++;
        if (stuckCtr >= 100)
        {
            simStopped = 1;
            return;
        }
    }
    // STEP 4: repelling non-colliding pairs
    {
        int i;
        int n = DYNA_getLength(&context->nonCollidingPairs);
        int (*ncPairs)[2] = (int (*)[2])DYNA_getStorage(&context->nonCollidingPairs);
        double lastSimplex[12];

        for (i = 0; i < n; i++)
        {
            DYN_Body *a = &context->bodies[ncPairs[i][0]];
            DYN_Body *b = &context->bodies[ncPairs[i][1]];

            if (COL_collide(a, b, 0, lastSimplex))
            {
                double penetrationVector[3];
                fprintf(DYN_log, "Sticked and colliding after timestep!\n");
                COL_getPenetrationVector(a, b, lastSimplex, penetrationVector);
                fprintf(
                    DYN_log,
                    "Penetration vector was: [%g, %g, %g]\n",
                    penetrationVector[0],
                    penetrationVector[1],
                    penetrationVector[2]
                );
                {
                    // push it out from the body and a little.
                    double penetrationVectorLength = ALG_getVectorLength(penetrationVector);
                    double scaleFactor = (penetrationVectorLength + 0.01) / penetrationVectorLength;
                    ALG_scale(penetrationVector, scaleFactor);
                }
                ALG_translate(b->position, penetrationVector);
                fprintf(DYN_log, "==============================\n");
                a->colliding = a->inContact = 0;
                b->colliding = a->inContact = 0;
                {
                    // Body b may collide with other bodies. Translate those bodies as well.
                    DYNA_Array tmp;
                    int j;

                    DYNA_initialize(&tmp, sizeof(DYN_Body*));
                    DYNA_add(&tmp, b);
                    for (j = 0; j < DYNA_getLength(&tmp); j++)
                    {
                        DYN_Body **storage = DYNA_getStorage(&tmp);
                        DYN_Body *current = storage[j];

                        int k = 0;
                        for (k = 0; k < context->bodyCount; k++)
                        {
                            DYN_Body *other = &context->bodies[k];

                            if (other == current) continue;

                            if (COL_collide(current, other, 0, 0))
                            {
                                ALG_translate(other->position, penetrationVector);
                                current->colliding = 0;
                                other->colliding = 0;
                                DYNA_add(&tmp, other);
                            }
                        }
                    }
                    DYNA_deinitialize(&tmp);
                }
            }
        }
    }
    clearNonCollidingPairs(context);
    context->elapsedTime += context->timeStep;
}