virtual void RequestPositionUpdate( IGameObject* pGameObject, const AUVec3f& desiredPosition, float frameDelta )
	{
		AUVec3f pos = desiredPosition;

		ApplyGameAreaRepulsionField( pGameObject, pos, frameDelta );
		ApplyTeamRepulsionFields( pGameObject, pos, frameDelta );
		
		CheckForCollisions( pGameObject, pos, frameDelta );

		pGameObject->GetEntity()->SetPosition(pos);
	}
Ejemplo n.º 2
0
bool CustomPhysicsEngine::Update() {
	for (unsigned int actorIndex = 0; 
		actorIndex < actors.size(); 
		++actorIndex) {
		actors[actorIndex]->PhysicsUpdate(Time::deltaTime > 0.033f ? 0.033f : Time::deltaTime);
	}

	if (collisionEnabled) {
		CheckForCollisions();
	}

	return true;
}
Ejemplo n.º 3
0
void JelloMesh::Update(double dt, const World& world, const vec3& externalForces)
{
    m_externalForces = externalForces;

	CheckForCollisions(m_vparticles, world);
	ComputeForces(m_vparticles);
	ResolveContacts(m_vparticles);
	ResolveCollisions(m_vparticles);

    switch (m_integrationType)
    {
    case EULER: EulerIntegrate(dt); break;
    case MIDPOINT: MidPointIntegrate(dt); break;
    case RK4: RK4Integrate(dt); break;
    }
}
Ejemplo n.º 4
0
char
PongGameLoop(void)
{
    unsigned long dt;
    unsigned long thisTime;
    thisTime = GLIB_GetGameMillis();
    dt = thisTime - g_lastTime;
    g_lastTime = thisTime;

    if (GetBitUInt8(&g_pongState, PONG_PLAYING))
    {
        UpdateBall(&g_pongBall, dt);
        UpdatePlayerPaddle(&g_player, dt);
        UpdateCompPaddle(&g_comp, dt);
        HandleInput();
        CheckForCollisions();
    }
    RenderPong(dt);

    return 1;
}
Ejemplo n.º 5
0
// ----------------------------------------------------------------------------
//  Name: UpdateGameScreen
//
//  Desc: Updates the game. Processes ball and paddle movement as well as
//        collisions and key presses.
// ----------------------------------------------------------------------------
GameState CGame::UpdateGameScreen( FLOAT fElapsedTime )
{
	FLOAT x, y;
	BOOL l, r;
	D3DVECTOR d;
	GameState NextState = GameScreen;

	// Go back to the title screen if escape is pressed.
	if( m_bEscape && !m_pInput->KeyDown( DIK_ESCAPE ) )
	{
		NextState = TitleScreen;

		m_bEscape = FALSE;
	}
	else if( !m_bEscape && m_pInput->KeyDown( DIK_ESCAPE ) )
	{
		m_bEscape = TRUE;
	}

	// Get the deltas for how much the mouse moved and what buttons were
	// pressed.
	m_pInput->GetMouse( &l, &r, &x, &y );

	// Position the paddle.
	m_vPaddlePos.x += (x * 0.1f * fElapsedTime);

	// Make sure the paddle cannot be moved outside of the game boundaries.
	// TODO: Refactor this so that magic numbers are NOT used.
	if( (m_vPaddlePos.x - 0.15f) <= (-0.9f) ) m_vPaddlePos.x = -0.75f;
	if( (m_vPaddlePos.x + 0.15f) >= (0.9f) ) m_vPaddlePos.x = 0.75f;

	m_pPaddle->SetPosition( m_vPaddlePos.x, m_vPaddlePos.y, m_vPaddlePos.z );

	// Position the ball.
	CheckForCollisions( fElapsedTime );

	// Bounce the ball off the sides of the walls.
	// TODO: Refactor this so that magic numbers are NOT used.
	if( (m_vBallPos.x + 0.03f) >= (0.99f) )
	{
		m_vBallVel.x = -m_vBallVel.x;
		m_vBallPos.x = 0.95f;
	}
	if( (m_vBallPos.x - 0.03f) <= (-1.0f) )
	{
		m_vBallVel.x = -m_vBallVel.x;
		m_vBallPos.x = -0.96f;
	}
	
	if( (m_vBallPos.y + 0.03f) >= (1.0f) )
	{
		m_vBallVel.y = -m_vBallVel.y;
		m_vBallPos.y = 0.96f;
	}
	if( (m_vBallPos.y - 0.03f) <= (-1.0f) )
	{
		m_vBallVel.y = -m_vBallVel.y;
		m_vBallPos.y = -0.96f;
	}

	// Find out how the ball bounces off the paddle.
	d.x = m_vPaddlePos.x - m_vBallPos.x;
	d.y = m_vPaddlePos.y - m_vBallPos.y;
	d.z = m_vPaddlePos.z - m_vBallPos.z;

	d = VecNormalize( d );

	d.x = m_vBallPos.x + (d.x * 0.03);
	d.y = m_vBallPos.y + (d.y * 0.03);
	d.z = m_vBallPos.z + (d.z * 0.03);

	// TODO: Refactor so that magic numbers are NOT used.
	if( (d.y <= (m_vPaddlePos.y + 0.02f)) && (d.x >= (m_vPaddlePos.x - 0.25f)) && (d.x <= (m_vPaddlePos.x + 0.25f)) )
	{
		m_vBallVel.y = -m_vBallVel.y;
		m_vBallPos.y = m_vPaddlePos.y + 0.051f;
	}
	
	if( (m_vBallPos.y < (m_vPaddlePos.y - 0.2f)) )
	{
		NextState = TitleScreen;
	}

	m_pBall->SetPosition( m_vBallPos.x, m_vBallPos.y, m_vBallPos.z );

	// Make sure the camera is oriented just right.
	m_pCamera->Position( 0.0f, 0.0f, -2.5f );

	m_pDevice->SetTransform( D3DTS_VIEW, &m_pCamera->GetViewMatrix() );

	// End the game if all the bricks have been destroyed.
	if( !m_dwTotalBricks ) NextState = TitleScreen;

	m_fSecondCount += fElapsedTime;
	m_dwNewFPS++;

	if( m_fSecondCount >= 1.0f )
	{
		// Calculate an FPS. Deprecated.
		m_dwOldFPS = m_dwNewFPS;
		m_dwNewFPS = 0;

		// Increase the ball start timer.
		m_dwBallTimer++;

		m_fSecondCount = 0.0f;
	}

	if( m_dwBallTimer == 2 )
	{
		// If 3 seconds have passed, then start the ball moving.
		m_vBallVel.x = 0.7f;
		m_vBallVel.y = 0.6f;
	}

	return NextState;
}
void CPhysEnv::Simulate(float DeltaTime, BOOL running)
{
    float		CurrentTime = 0.0f;
    float		TargetTime = DeltaTime;
	tParticle	*tempSys;
	int			collisionState;

    while(CurrentTime < DeltaTime)
    {
		if (running)
		{
			ComputeForces(m_CurrentSys);

			// IN ORDER TO MAKE THINGS RUN FASTER, I HAVE THIS LITTLE TRICK
			// IF THE SYSTEM IS DOING A BINARY SEARCH FOR THE COLLISION POINT,
			// I FORCE EULER'S METHOD ON IT. OTHERWISE, LET THE USER CHOOSE.
			// THIS DOESN'T SEEM TO EFFECT STABILITY EITHER WAY
			if (m_CollisionRootFinding)
			{
				EulerIntegrate(TargetTime-CurrentTime);
			}
			else
			{
				switch (m_IntegratorType)
				{
				case EULER_INTEGRATOR:
					EulerIntegrate(TargetTime-CurrentTime);
					break;
				case MIDPOINT_INTEGRATOR:
					MidPointIntegrate(TargetTime-CurrentTime);
					break;
				case HEUN_INTEGRATOR:
					HeunIntegrate(TargetTime-CurrentTime);
					break;
				case RK4_INTEGRATOR:
					RK4Integrate(TargetTime-CurrentTime);
					break;
				case RK4_ADAPTIVE_INTEGRATOR:
					RK4AdaptiveIntegrate(TargetTime-CurrentTime);
					break;
				case FEHLBERG:
					FehlbergIntegrate(TargetTime-CurrentTime);
					break;
				}
			}
		}

		collisionState = CheckForCollisions(m_TargetSys);

        if(collisionState == PENETRATING)
        {
			// TELL THE SYSTEM I AM LOOKING FOR A COLLISION SO IT WILL USE EULER
			m_CollisionRootFinding = TRUE;
            // we simulated too far, so subdivide time and try again
            TargetTime = (CurrentTime + TargetTime) / 2.0f;

            // blow up if we aren't moving forward each step, which is
            // probably caused by interpenetration at the frame start
            assert(fabs(TargetTime - CurrentTime) > EPSILON);
        }
        else
        {
            // either colliding or clear
            if(collisionState == COLLIDING)
            {
                int Counter = 0;
                do
                {
                    ResolveCollisions(m_TargetSys);
                    Counter++;
                } while((CheckForCollisions(m_TargetSys) ==
                            COLLIDING) && (Counter < 100));

                assert(Counter < 100);
				m_CollisionRootFinding = FALSE;  // FOUND THE COLLISION POINT
            }

            // we made a successful step, so swap configurations
            // to "save" the data for the next step
            
			CurrentTime = TargetTime;
			TargetTime = DeltaTime;

			// SWAP MY TWO PARTICLE SYSTEM BUFFERS SO I CAN DO IT AGAIN
			tempSys = m_CurrentSys;
			m_CurrentSys = m_TargetSys;
			m_TargetSys = tempSys;
        }
    }
}
Ejemplo n.º 7
0
void	UpdateSimulation(void)
{
	double	dt = _TIMESTEP;
	int		i;
	double f, dl;
	Vector pt1, pt2;
	int j;
	Vector r;
	Vector F;
	Vector v1, v2, vr;

	if (FrameCounter >= _RENDER_FRAME_COUNT)
	{
		ClearBackBuffer();
		DrawLine(0, _WINHEIGHT - _GROUND_PLANE, _WINWIDTH, _WINHEIGHT - _GROUND_PLANE, 3, RGB(0, 0, 0));
		DrawObstacles();

	}

	for (i = 0; i < _NUM_OBJECTS; i++)
	{
		Objects[i].vSprings.x = 0;
		Objects[i].vSprings.y = 0;
		Objects[i].vSprings.z = 0;
	}


	for (i = 0; i < _NUM_SPRINGS; i++)
	{
		j = Springs[i].End1;
		pt1 = Objects[j].vPosition;
		v1 = Objects[j].vVelocity;

		j = Springs[i].End2;
		pt2 = Objects[j].vPosition;
		v2 = Objects[j].vVelocity;

		vr = v2 - v1; 
		r = pt2 - pt1;
		dl = r.Magnitude() - Springs[i].InitialLength;
		f = Springs[i].k* dl;
		r.Normalize();

		F = (r*f) + (Springs[i].d*(vr*r))*r;
		j = Springs[i].End1;

		if (Objects[j].bLocked == false)
			Objects[j].vSprings += F;

		j = Springs[i].End2;
		if (Objects[j].bLocked == false)
			Objects[j].vSprings -= F;
	}

	for (i = 0; i < _NUM_OBJECTS; i++)
	{
		Objects[i].bCollision = CheckForCollisions(&(Objects[i]));
		Objects[i].CalcLoads();
		Objects[i].UpdateBodyEuler(dt);

		if (FrameCounter >= _RENDER_FRAME_COUNT)
		{
			Objects[i].Draw();

			if (i < _NUM_OBJECTS - 1)
				Objects[i].DrawObjectLine(Objects[i + 1].vPosition);
		}

		if (Objects[i].vPosition.x > _WINWIDTH) Objects[i].vPosition.x = 0;
		if (Objects[i].vPosition.x < 0) Objects[i].vPosition.x = _WINWIDTH;
		if (Objects[i].vPosition.y < 0) Objects[i].vPosition.y = _WINHEIGHT;
	} 

	if (FrameCounter >= _RENDER_FRAME_COUNT) {
		CopyBackBufferToWindow();
		FrameCounter = 0;
	}
	else
		FrameCounter++;
}
Ejemplo n.º 8
0
/*
================
idPhysics_RigidBody::Evaluate

  Evaluate the impulse based rigid body physics.
  When a collision occurs an impulse is applied at the moment of impact but
  the remaining time after the collision is ignored.
================
*/
bool idPhysics_RigidBody::Evaluate( int timeStepMSec, int endTimeMSec ) {
	rigidBodyPState_t next;
	idAngles angles;
	trace_t collision;
	idVec3 impulse;
	idEntity *ent;
	idVec3 oldOrigin, masterOrigin;
	idMat3 oldAxis, masterAxis;
	float timeStep;
	bool collided, cameToRest = false;

	timeStep = MS2SEC( timeStepMSec );
	current.lastTimeStep = timeStep;

	if ( hasMaster ) {
		oldOrigin = current.i.position;
		oldAxis = current.i.orientation;
		self->GetMasterPosition( masterOrigin, masterAxis );
		current.i.position = masterOrigin + current.localOrigin * masterAxis;
		if ( isOrientated ) {
			current.i.orientation = current.localAxis * masterAxis;
		}
		else {
			current.i.orientation = current.localAxis;
		}
		clipModel->Link( gameLocal.clip, self, clipModel->GetId(), current.i.position, current.i.orientation );
		current.i.linearMomentum = mass * ( ( current.i.position - oldOrigin ) / timeStep );
		current.i.angularMomentum = inertiaTensor * ( ( current.i.orientation * oldAxis.Transpose() ).ToAngularVelocity() / timeStep );
		current.externalForce.Zero();
		current.externalTorque.Zero();

		return ( current.i.position != oldOrigin || current.i.orientation != oldAxis );
	}

	// if the body is at rest
	if ( current.atRest >= 0 || timeStep <= 0.0f ) {
		DebugDraw();
		return false;
	}

	// if putting the body to rest
	if ( dropToFloor ) {
		DropToFloorAndRest();
		current.externalForce.Zero();
		current.externalTorque.Zero();
		return true;
	}

#ifdef RB_TIMINGS
	timer_total.Start();
#endif

	// move the rigid body velocity into the frame of a pusher
//	current.i.linearMomentum -= current.pushVelocity.SubVec3( 0 ) * mass;
//	current.i.angularMomentum -= current.pushVelocity.SubVec3( 1 ) * inertiaTensor;

	clipModel->Unlink();

	next = current;

	// calculate next position and orientation
	Integrate( timeStep, next );

#ifdef RB_TIMINGS
	timer_collision.Start();
#endif

	// check for collisions from the current to the next state
	collided = CheckForCollisions( timeStep, next, collision );

#ifdef RB_TIMINGS
	timer_collision.Stop();
#endif

	// set the new state
	current = next;

	if ( collided ) {
		// apply collision impulse
		if ( CollisionImpulse( collision, impulse ) ) {
			current.atRest = gameLocal.time;
		}
	}

	// update the position of the clip model
	clipModel->Link( gameLocal.clip, self, clipModel->GetId(), current.i.position, current.i.orientation );

	DebugDraw();

	if ( !noContact ) {

#ifdef RB_TIMINGS
		timer_collision.Start();
#endif
		// get contacts
		EvaluateContacts();

#ifdef RB_TIMINGS
		timer_collision.Stop();
#endif

		// check if the body has come to rest
		if ( TestIfAtRest() ) {
			// put to rest
			Rest();
			cameToRest = true;
		}  else {
			// apply contact friction
			ContactFriction( timeStep );
		}
	}

	if ( current.atRest < 0 ) {
		ActivateContactEntities();
	}

	if ( collided ) {
		// if the rigid body didn't come to rest or the other entity is not at rest
		ent = gameLocal.entities[collision.c.entityNum];
		if ( ent && ( !cameToRest || !ent->IsAtRest() ) ) {
			// apply impact to other entity
			ent->ApplyImpulse( self, collision.c.id, collision.c.point, -impulse );
		}
	}

	// move the rigid body velocity back into the world frame
//	current.i.linearMomentum += current.pushVelocity.SubVec3( 0 ) * mass;
//	current.i.angularMomentum += current.pushVelocity.SubVec3( 1 ) * inertiaTensor;
	current.pushVelocity.Zero();

	current.lastTimeStep = timeStep;
	current.externalForce.Zero();
	current.externalTorque.Zero();

	if ( IsOutsideWorld() ) {
		gameLocal.Warning( "rigid body moved outside world bounds for entity '%s' type '%s' at (%s)",
					self->name.c_str(), self->GetType()->classname, current.i.position.ToString(0) );
		Rest();
	}

#ifdef RB_TIMINGS
	timer_total.Stop();

	if ( rb_showTimings->integer == 1 ) {
		gameLocal.Printf( "%12s: t %u cd %u\n",
						self->name.c_str(),
						timer_total.Milliseconds(), timer_collision.Milliseconds() );
		lastTimerReset = 0;
	}
	else if ( rb_showTimings->integer == 2 ) {
		numRigidBodies++;
		if ( endTimeMSec > lastTimerReset ) {
			gameLocal.Printf( "rb %d: t %u cd %u\n",
							numRigidBodies,
							timer_total.Milliseconds(), timer_collision.Milliseconds() );
		}
	}
	if ( endTimeMSec > lastTimerReset ) {
		lastTimerReset = endTimeMSec;
		numRigidBodies = 0;
		timer_total.Clear();
		timer_collision.Clear();
	}
#endif

	return true;
}
Ejemplo n.º 9
0
//-----------------------------------------------------------------------------
// Purpose: Main frame function, updates the state of the world and performs rendering
//-----------------------------------------------------------------------------
void CSpaceWarServer::RunFrame()
{
	// Run any Steam Game Server API callbacks
	SteamGameServer_RunCallbacks();

	// Update our server details
	SendUpdatedServerDetailsToSteam();

	// Timeout stale player connections, also update player count data
	uint32 uPlayerCount = 0;
	for( uint32 i=0; i < MAX_PLAYERS_PER_SERVER; ++i )
	{
		// If there is no ship, skip
		if ( !m_rgClientData[i].m_bActive )
			continue;

		if ( m_pGameEngine->GetGameTickCount() - m_rgClientData[i].m_ulTickCountLastData > SERVER_TIMEOUT_MILLISECONDS )
		{
			OutputDebugString( "Timing out player connection\n" );
			RemovePlayerFromServer( i );
		}
		else
		{
			++uPlayerCount;
		}
	}
	m_uPlayerCount = uPlayerCount;

	switch ( m_eGameState )
	{
	case k_EServerWaitingForPlayers:
		// Wait a few seconds (so everyone can join if a lobby just started this server)
		if ( m_pGameEngine->GetGameTickCount() - m_ulStateTransitionTime >= MILLISECONDS_BETWEEN_ROUNDS )
		{
			// Just keep waiting until at least one ship is active
			for( uint32 i = 0; i < MAX_PLAYERS_PER_SERVER; ++i )
			{
				if ( m_rgClientData[i].m_bActive )
				{
					// Transition to active
					OutputDebugString( "Server going active after waiting for players\n" );
					SetGameState( k_EServerActive );
				}
			}
		}
		break;
	case k_EServerDraw:
	case k_EServerWinner:
		// Update all the entities...
		m_pSun->RunFrame();
		for( uint32 i=0; i<MAX_PLAYERS_PER_SERVER; ++i )
		{
			if ( m_rgpShips[i] )
				m_rgpShips[i]->RunFrame();
		}

		// NOTE: no collision detection, because the round is really over, objects are now invulnerable

		// After 5 seconds start the next round
		if ( m_pGameEngine->GetGameTickCount() - m_ulStateTransitionTime >= MILLISECONDS_BETWEEN_ROUNDS )
		{
			ResetPlayerShips();
			SetGameState( k_EServerActive );
		}

		break;

	case k_EServerActive:
		// Update all the entities...
		m_pSun->RunFrame();
		for( uint32 i=0; i<MAX_PLAYERS_PER_SERVER; ++i )
		{
			if ( m_rgpShips[i] )
				m_rgpShips[i]->RunFrame();
		}

		// Check for collisions which could lead to a winner this round
		CheckForCollisions();

		break;
	case k_EServerExiting:
		break;
	default:
		OutputDebugString( "Unhandled game state in CSpaceWarServer::RunFrame\n" );
	}

	// Send client updates (will internal limit itself to the tick rate desired)
	SendUpdateDataToAllClients();
}