Micro Machines

NameMicro Machines
Short DescriptionA game about racing in your boat to get the fastest time.
CategorySchool Project - Year 1
DateDec 2014 - Jan 2015 (~2 months)
LanguageC++

About

Micro Machines is a game I wrote in C++. It is the first complete game I worked on which featured menus, sound, music, AI, leaderboards, physics, multiple levels etc.

Programming

The main challenge in this game is that everything in the game had to be written manually. There was no code for buttons, rotating images, playing music etc. Besides making this game and making it fun, I had to write all of the underlying code. This includes the UI code, rendering, audio, but also the Quadtree system used to handle the collision between the boats and the bubbles.

Another piece of code I spend a significant amount of time on is the AI code in the game. The 3 enemies all had to find the quickest way around the track while going through all the white checkpoints. Another thing which had to be made sure is that not all of them would follow the exact same path because that would cause them to get stuck on each other. To accomplish these things, each level has an array of points the enemies must have gone past. Once they get within a certain distance, the point is passed. Every enemy would get a random offset to each point so they wouldn’t follow the exact same path. This is the code which handles all of that.

Enemy AI
void Enemy::control()
{
	//get new pos if needed
	if (atNewPos)
	{
		currentPos++;
		if (currentPos == Game::getInstance()->world->activeAIPositions.size())
			currentPos = 0;
 
		desiredPosition = Game::getInstance()->world->activeAIPositions[currentPos] + vec2(-20 + rand() % 40, -20 + rand() % 40);
		atNewPos = false;
	}
	else
	{
		//otherwise check distance
		float dX = position.x - desiredPosition.x;
		float dY = position.y - desiredPosition.y;
		float distance = dX * dX + dY * dY;
 
		if (distance < maxDistance)
		{
			atNewPos = true;
		}
	}
 
	vec2 distance = desiredPosition - position;
	normal = vec2(sin((angle - 90) * PI / 180.0), cos((angle - 90) * PI / 180.0) * -1);
	float dir = normal.x * distance.x + normal.y * distance.y;
 
	//turn
	if (dir > 0)
	{
		angle -= dAngle;
		boat->RotateImage(-dAngle);
	}
	if (dir < 0)
	{
		angle += dAngle;
		boat->RotateImage(dAngle);
	}
 
	velocity += vec2(acceleration * cos((angle - 90) * PI / 180.0), acceleration * sin((angle - 90) * PI / 180.0));
}

 

One of the most difficult parts of programming this game is the fact that there are hundreds of bubbles on screen which can all collide with each other. To make sure the game has playable performance, I created a Quadtree. The bubble then only checks collision for collidable entities which are nearby.

Bubble Collisions
void Bubble::checkCollisions()
{
	vector<Bubble*> bubbles = Game::getInstance()->world->getQuadTree()->getCollidables(position.x, position.y);

	for (int i = 0; i < bubbles.size(); i++)
	{
		int dX = position.x - bubbles[i]->getX();
		int dY = position.y - bubbles[i]->getY();

		int distance = dX * dX + dY * dY;

		if (distance > 0)
		{
			int combRadSquared = bubbles[i]->getRadius() + radius;
			combRadSquared *= combRadSquared;

			//are they colliding
			if (distance < combRadSquared)
			{
				Bubble* other = bubbles[i];

				vec2 collision = position - other->getPosition();

				distance = sqrtf(distance);
				float disDiff = radius + other->getRadius() - distance;

				collision /= distance;
				collision *= (disDiff / 2);
				
				//handle collision result
				if (canMove)
				{
					position += collision;
					if (!other->canMove || rand() % 4 == 0)
						prevPosition = position;
					shouldUpdate = true;
				}
				if (other->canMove)
				{
					other->position -= collision;
					if (!canMove || rand() % 4 == 0)
						other->prevPosition = other->position;
					other->shouldUpdate = true;
				}
			}
		}
	}
}

 

Screenshots & Downloads

  • The character select screen
    The character select screen
  • Mid-race
    Mid-race
  • The leaderboards showing the results
    The leaderboards showing the results
  • Another level
    Another level

 

The executable for Micro Machines can be downloaded here.