B Lab Exercise 2

The task in this exercise is to implement a 2D top-down billiard game, implementing a simplified set of the Straight Pool rules.23 For a realistic ball movement, detecting collisions and pocketing of balls, the physics engine dyn4j has to be used. Rendering is done with JavaFX, see Figures B.1 and B.2 for screenshots of the reference implementation with the initial and a progressed game state.

Screenshot of the Lab 2 reference implementation with initial game state before the first strike by Player 1.

Figure B.1: Screenshot of the Lab 2 reference implementation with initial game state before the first strike by Player 1.

Screenshot of the Lab 2 reference implementation with a progressed game state. Player 2 has just commited a foul: the white ball did not touch any object ball. Therefore Player 2 got subtracted one point and it is now the turn of Player 1 to strike.

Figure B.2: Screenshot of the Lab 2 reference implementation with a progressed game state. Player 2 has just commited a foul: the white ball did not touch any object ball. Therefore Player 2 got subtracted one point and it is now the turn of Player 1 to strike.

The learning experience in this exercise is to understand how to implement an interactive real-time game, which is very different from software you developed in the bachelor programme so far. Also you will learn how to connect a physics and rendering subsystem and how to build game logic on top of them, following object-oriented design principles you have learned in previous semesters.

B.1 Rules

In Straight Pool, players have to announce which ball they put into which pocket. If a player correctly puts the ball into the announced pocket, they receive a point and can continue. If a player pockets other balls beside the announced one, they will receive an additional point for each pocketed ball. If a player fails to pocket the announced ball correctly, it is the other players turn. For sake of simplicity in this exercise announcing is not necessary as it would complicate things substantially, however if a player does not pocket any ball, it is the next players turn. In Straight Pool, if only unnanounced balls fall, they are put back on the table. As announcing is not important in this exercise, this is irrelevant.

The balls have to be arranged in the well-known pyramid shape, with random order. In Straight Pool, if a ball is pocketed in an opening strike, this counts as a foul, however in our exercise we ignore this and they will count as normal points.

There are a number of fouls you have to implement:

  • It is a foul if any other ball than the white one is stroke by the cue.
  • It is a foul if the white ball is pocketed.
  • It is a foul if the white ball does not touch any object ball.

A foul results in adding a negative point (a negative score is therefore possible), switching of players, with the other player allowed to place the white ball wherever they want (free hand). In case more fouls are commited in one turn, only one negative point is awarded. For sake of simplicity in this exercise if the white ball is pocketed, it is put automatically back on the table in the spot where it was before the foul strike.

After the 14th ball is pocketed, the 14 balls are put back on the table with the top spot left free. The current player can then continue either by playing the 15th ball or any other balls in the rack. This continues forever.

B.2 Implementation

You don’t have to start from scratch. Please download the Code Skeleton which provides the following for you:

  • Gradle project with all necessary dependencies.
  • Setting up the JavaFX Application with a Canvas element and AnimationTimer.
  • Physical model of the table.
  • Physical model of the balls and placement of them on the table.
  • Rendering of the physical model of the table.
  • Rendering of the physical model of the balls.
  • A very clear (and oppinionated) structure with stub classes and interfaces, which give a lot of hints for the actual implementation.
  • Method stubs with TODOs where to put in code.

It is recommended that you first implement the game so that it just works. This will allow you to get accustomed with this new type of architecture, understand the physics engine and connect physics and rendering. Then refactor the code into a clean solution. The existing classes and interfaces should guide you. You are allowed to make any changes to the skeleton you wish to make.

What you have to implement:

  • The actual physics simulation using dyn4j. So far only the models have been set up for you, but no physical world is there, no collision and contact detection,… You have to set this up using dyn4j. Have a look at the documentation on http://www.dyn4j.org/ which explains the basic concepts very well. Also I strongly recommend to have a look at the dyn4j-samples https://github.com/dyn4j/dyn4j-samples to see examples in action with easy-to-understand code.
  • A concept of a cue for striking the balls. You will need to perform raycasting to dected hits and then apply force to the ball which was stroke. You also need to implement the rendering of the cue.
  • The game logic with the simplified rule set. As indicated by the existing interfaces you need to be able to detect the striking of a ball, the collision of balls, all objects resting or not, pocketing of a ball. You need to think how to achieve this with dyn4j - the key are the contact and step listener.
  • Feedback to the user: player score, next turn, fouls,…