A Simple Game Loop for client-server game with collision

A forum to store posts deemed exceptionally wise and useful
Post Reply
mohaps
Posts: 248
Joined: Tue Jun 08, 2004 1:54 pm
Location: Shrewsbury MA
Contact:

A Simple Game Loop for client-server game with collision

Post by mohaps »

This is a simple game loop for reference in C/C++ like psuedo code for a client/server game architecture which uses collision detection. I wrote this for designing my multiplayer space combat game using ColDet library and Irrlicht... but i think the psuedocode is pretty generic...


Code: Select all

//
// this is the game main loop
//
void gameLoop()
{
	while(game->isRunning())
	{
		u32 deltaMillis = getElapsedTime();
		if(game->isServerOnly())
		{
			serverMain(deltaMillis);
		}
		else if(game->isClientOnly())
		{
			clientMain(deltaMillis);
		}
		else
		{
			mixedModeMain(deltaMillis);
		}
	}
}


//
//	Server Main Loop
//
void serverMain(u32 deltaMillis)
{
	//process the incoming server event queue
	processIncomingEvents();
	//run the server game
	runServerGame(deltaMillis);
	//send the server state update to clients
	sendUpdatesToClients();
}
//
// client main loop
//
void clientMain(u32 deltaMillis)
{

	//receive incoming server updates
	//and apply them
	processServerUpdates();
	//render the game
	render(deltaMillis);
	//process local input events
	//game generate devents and create updates
	runClientGame(deltaMillis);
	// generate updates and send to server
	sendUpdatesToServer();

}
// this is for a server with local client
// or a single player game
void mixedModeMain(u32 deltaMillis)
{
	serverMain(deltaMillis);
	clientMain(deltaMillis);
}

//this is your main loop for running the server game
void runServerGame(u32 deltaMillis)
{
	//run the bot clients
	runBots(deltaMillis);
	//apply the object transforms
	applyObjectTransforms(deltaMillis);
	//run collisions
	runCollisions();
	//process collisions
	processCollisions();

}
// this method applies the linear and angular velocities on the objects
// and stores them in the new transformation field
void applyObjectTransforms(u32 deltaMillis)
{
	for(int i = 0; i < objectCount; i++)
	{
		Object* obj = objects[i];
		obj->applyTransforms(deltaMillis);
	}
}
// this method processes the object with all other objects
// for possible collisions and creates a collision list
void runCollisions()
{
	for(int i = 0; i < objectCount; i++)
	{
		Object* obj = objects[i];
		array<Object> collisionCandidates = getProbableCollisionCandidates(obj);
		for(int j = 0; j < collisionCandidateCount; j++)
		{
			Object* testObj = collisionCandidates[j];
			if(obj->collide(testObj))
			{
				CollisionData *cdata = createCollisionData(testObj, obj->getDenyMask());
				obj->addCollision(cdata);
			}
		}
		//collision list is sorted in this order
		//  a) all ghost collisions first
		//  b) all collision points arranged in increasing order from the oldPosition
		obj->sortCollisionList();
	}

}
//
//	this method narrows down the list of available objects down to the
//	list of objects which could probably interact with this object
//
array<Object> getProbableCollisionCandidates(Object* obj, Mask denyMask)
{
	array<Object> candidates;
	Sphere sphere(obj->getPosition(), COLLISION_RADIUS);
	for(int i = 0; i < objectCount; i++)
	{
		Object* testObj = objects[i];

		if(testObj != obj)
		{
			f32 distance = distance(sphere->getCenter(),testObj->getPosition()) - testObj->getRadius();
			if(sphere.getRadius() >= distance)
			{
				//we check if the object should be allowed or denied outright
				if(denyMask->test(testObj->getMask()) )
				{
					candidates.push_back(testObj);
				}
			}
		}

	}

}
//
// this is where we actually process the collisions for each object
//
//
void processCollisions()
{
	for(int i = 0; i < objectCount; i++)
	{
		Object* obj = objects[i];
		if(obj->hasNoCollisions())
		{
			//object did not collide with any
			//thing so finalize the transformations
			obj->finalizeTransforms();
		}
		else
		{

			for(int j = 0; j < obj->getCollisionCount(); j++)
			{
				CollisionData *cdata = obj->getCollision[j];
				if(cdata->isGhostCollision())
				{
					//process a ghost collision like with a target or a trigger or a zone
					obj->processGhostCollision(cdata);
				}
				else if(cdata->isHardCollision())
				{
					//process a hard collision like hitting some world object (asteroid, missile)
					obj->processHardCollision(cdata);
				}
			}
			if(object->hasHardCollisions())
			{
				//if the object has a hard collision
				// revert to old position
				obj->revertToOldPosition();
			}

		}
		obj->clearCollisions();
	}
}
//create the collision data describing a single collision
//and its properties
CollisionData* createCollisionData(Object* obj,Object* testObj)
{
	CollisionData* cdata;
	if(testObj->isGhost())
	{
		cdata->setGhostCollision(true);
	}
	else
	{
		cdata->setHardCollision(false);
	}
	data->setCollidingObject(testObj);
	data->setCollidionTriangles(getCollidingTriangles(obj,testObj));
	data->setCollisionPoint(getCollisionPoint(obj,testObj));
	return data;

}
[/color]
---
Saurav Mohapatra
author, artist and bona fide geek

web: http://www.mohaps.com
email: mohaps AT gmail DOT com
Post Reply