Czech Technical University

Faculty of Electrical Engineering

 

X36TJC - Class Project

Project Name: Coolaaber

 

Author: Marek Handl

Date: February 2008

 

 

Goal:

The goal of the project was to create a simple computer game of pool (billiard). Main programming language shall be C++. The graphic part of the application is shall be displayed using OpenGL. GUI shall be created using Qt libraries. There was no intention to create any kind of artificial intelligence; the game shall be played only by humans. It was expected that collision detection and handling might be slightly complicated.

 

Achievements:

The application is in a state where it is possible to play a game. Simple game rules apply. The simulation engine is not perfect but shall be able to handle most of situation. It has been decided to concentrate on movements in 2D only as the third dimension proved to be very complex to add. Even in 2D a lot of equation needs to be solved to do the simulation. It took me unexpectedly tens of hours to even derive these 2D equations and to debug them and yet they are not perfect. To implement the other dimension would require other tens of hours, which I find inappropriate for a class project of this kind. The foundations of the program are ready for implementation of the third dimension, though. Collision detection and resolving should work in 3D, although it hasn’t been thoroughly tested. Main concern is the gravity, as it complicates the computation a lot. Therefore no gravity has been implemented and an assumption has been made, that all collisions would happen in one horizontal plane.

At the moment the application can resolve ball-ball collision as well as ball-cuboid collision. The cuboids collisions are working in general, it is easy to add any other cuboid in the game and the collision handling will work just fine.

It is possible to customize starting position of the game. By editing “game_setup.cfg” you can change positioning of balls and add additional cuboids to the game.

Due to complexity of the problem, graphic design of the application is therefore simple too. There are two possible views. The first one “overhead view” is stationary, looking at the table from above, whole table visible. The other one “white ball follow view” is dynamic – there is always the white ball in the center of screen and the view is looking in the direction of the cue. The second view is better for aiming.

 

Developing platform:

Intel Core2Duo

MS Windows Vista

Visual Studio C++ 2005 Express

Qt 4.3.0 with OpenGL

The project hasn’t been tested on any other system, but the code shall be platform independent.

 

User manual:

Start the application using Coolaaber.exe.

Hold down left mouse button and move your mouse from left to right to aim.

Press right mouse button to do the stroke. If balls moving, you can press the right button again to stop displaying animation and let the application compute the result as fast as possible – it will be displayed when ready.

Use the slider on the right to control how much energy is put into the stroke.

Look in upper right corner for information whose turn it is and who won.

You cannot do a stroke unless cue is visible.

You can use the Restart button anytime to start a new game.

Use the Change view button to switch between “overhead view” and “follow white ball view”.

Clicking on Quit button closes the application immediately.

Edit game_setup.cfg file to modify number of balls in the game, their positions, colors and to add additional cuboids in the game. See the inside of the file for format description.

 

List of files with description:

Ball.cpp

Ball object

Collision.cpp

Represents one collision (either ball-wall or ball-ball)

Collision resolving is implemented here

Coolaaber.cpp

Encapsulates the Qt gui

Cuboid.cpp

Box like object in a game – 6 walls, stationary

Collision detection implemented here

Cue.cpp

Just cue class

Direction.cpp

Mathematical vector with operators

Game.cpp

Central class – here is most of the logic implemented

Controls the flow of the game.

Finds collisions and handles them.

GameObject.cpp

Abstract class for objects in the game

GameSetup.cpp

Sets up the game – creates table and balls

Reads from configuration file

Glwidget.cpp

OpenGL widget – openGl setup, user input handling

Main.cpp

Main – just starts up the Qt application

Plane.cpp

Mathematical plane with operators

Point.cpp

Mathematical point with operators

Wall.cpp

One wall of a cuboid

WallPoints.cpp

Set of points – used to describe a wall

Globals.h

Constants, basic setup

Coolaaber.pro

Qt project file

Coolaaber.ui

Qt qui file – Qt generates a c++ .h file from it

 

See attached class diagram for more information about the class model.

 

Simple description how the program works:

Main.cpp calls Coolaaber class which creates gui and starts the application. Then all communication with the user goes through glwidget class, which has slots to receive user action signals and also controls the OpenGL widget (the whole animation).

Most of functionality is implemented in the Game class. It uses GameSetup class to create the world (the pool table and balls – they are read from the configuration file). Game class contains the game rules and controls almost everything (stroke, balls movement, ball-ball collision detection). Ball-wall collision detection is in Cuboid class. Collision handling is implemented in Collision class.

A lot of application settings can be changed in globals.h.

 

Some algorithms used:

 

Collision detection

Program uses iterative simulation. In each iteration, balls are moved according to their actual speed. Then collision detection takes place. When checking for collision with a cuboid a bounding sphere collision detection is done first. Only if this first test is positive a more sophisticated algorithm (listed below) is used. If there was collision, moment in time when the two objects touched is computed. All objects are moved back to this moment. It is checked for other collisions and if none is found the original collision is resolved. The balls finish their movements accordingly (based on the amount of time that was taken back).

 

Ball and Cuboid collision

- imagine walls of the cuboids are infinite planes

- compute distance of the ball from all the planes (positive if ball is in front of the wall with respect to the wall’s normal vector)

- if only one is positive and the distance is less than a diameter, there has been a collision with the wall (the wall plane will be used for computation)

- if two are positive … collision with the edge (compute a plane that is 45° to both of the walls and contains their intersection)

- if three are positive … collision with the corner (compute a plane that is 45° to all three walls and contains their intersection – the corner)

- do a rebound from the computed plane

- the resulting speed vector is initial vector mirrored with respect to plane’s normal, it needs to be change to negative as the last step

 

 

Ball and Ball collision

- once centers of two balls are closer than two radii, there must have been a collision

 

// segment connecting the two centers

X_Axis = (center2 - center1)

X_Axis.normalize();

// projections of speed vectors into connecting axis and perpendicular direction

U1x = X_Axis * (X_Axis dot U1)

U1y = U1 - U1x

U2x = -X_Axis * (-X_Axis dot U2)

U2y = U2 - U2x

// computation based upon momentum, weights of balls are considered too

V1x = ((U1x * M1) + (U2x * M2) - (U1x - U2x) * M2) / (M1 + M2)

V2x = ((U1x * M1) + (U2x * M2) - (U2x - U1x) * M1) / (M1 + M2)

// new speed vectors

V1 = V1x + U1y

V2 = V2x + U2y

 

Speed Attenuation

- each iteration the balls lose some of their speed (simulates friction)

- both x and y component of the speed are multiplied by a deceleration factor

- when a ball hits a wall loss of speed is determined by the wall deceleration factor

- when a ball hits another ball bounce deceleration factor is used

- when the balls were standing next to each other (and one had been hit) the bounce deceleration factor is ignored to grant proper energy transport