Blog Archives

Developing a pool game in Alice 2.2

Introduction

In this article I will describe the development of a pool game in Alice. Because the game is quite complicated I will describe the development in a number of stages.

Upon starting the development I decided to simplify things a bit. In particular I decided to work with only two balls – the cue ball and the one ball. This is always a good policy when developing code – start simple then build up. If I can develop code that works for two balls, then I can investigate whether it generalised to deal with many balls.

Stage 1: Ball Collision

The plan for the first stage of development was to implement collision detection between two balls. To do this I needed some way of moving the cue ball. Therefore the requirements for the first stage of development became:

  • The user shall be able to aim and move the cue ball
  • The program shall detect collision between the cue ball and the one ball and react in a suitable manner.

To represent the aiming of the cue ball I added a cue. The user is able to rotate the cue using while key is pressed events. In addition I added support for varying the power of the shot. Pressing the down arrow pulled the cue backwards and hence increased the power of the shot. Pressing the up arrow decreased the power of the shot.

Detecting collision between the cue ball and the one ball is fairly straightforward. To do this we use the cueball within threshold of  function to check whether the cueball and one ball are touching. This check is done within a when condition becomes true event, so that collision is continuously being monitored. For this stage I went with a simple reaction to collision – the cue ball moves backwards and the one ball moves forwards.

Initial setup for pool game

The code for the first stage is available for download at http://www.alice.org/community/showthread.php?p=44054#post44054

Stage 2: Bouncing off cushions

In this stage I planned to add boundary detection for the cushions of the pool table.  Furthermore I wanted to make the reaction of colliding balls more realistic, i.e. make them move at a realistic angle.

In order to implement boundary detection I need a way of defining the cushions of the pool table. As it happens the pool table is defined as a single object, so the cushions are not defined. In order to define the boundaries of the cushions I placed four dummy objects along the cushions. This is similar to the idea presented in the video below, however in this case I chose not to shrink the dummy objects.

The dummy objects on the side cushions were position such that the right hand direction markers were facing directly out from the side of the table. Similarly the dummy objects on the end cushions were position so that the forward direction markers were facing out from the table. This is illustrated in the following picture.

These dummy objects can then be used to detect collision with the cushions. For the side cushions a collision occurs when the ball is not to the left of the dummy object. For the end cushions, we test whether the ball is not behind the dummy object. These checks were placed in a function, which is then called within a method, reboundOffCushion,  which implements rebounding of balls off of the cushions. This method is called within a while world is running event, which continually checks for collisions. In this version of the code a ball that collides with a cushion is turned at an angle of 90 degrees.

Improved ball collision

The other main enhancement during this stage of development was to improve the collision between balls. In the first version the one ball travelled directly forwards, while the cue ball travelled backwards regardless of what angle the balls collided. To improve ball collision we turn each ball so that it is pointing towards the centre of the other ball. We then rotate each ball 180 degrees. Probably not perfect physics, but it does provide a reasonable effect, allowing the player to play straight shots as well as cut shots.

The code for this second stage is available for download at http://www.alice.org/community/showthread.php?p=44057#post44057

Tutorial: collision detection

Introduction

Collision detection is a common feature of many animation tools, so a question that sometimes is asked when students first start using Alice is “where is built-in support for collision detection?”. The short answer is that there isn’t any. Remember that Alice is a programming environment in which students can develop animations, as opposed to a purpose built animation tool.  However, because it is a programming environment, Alice gives programmers the ability to readily develop their own support for collision detection. This tutorial provides a description of how such collision detection support can be implemented.

The Alice World

The world for this tutorial consists of a Humvee van and a number of obstacles. Event handling methods and event handlers have already been implemented that allow the user to move the car around the world. For example the code for driving the Humvee forward is as follows. A “Do together” block is used to drive the move the car forward and at the same time rotate the wheels.

Code for driving Humvee forward

Setting up collision detection

To set up collision detection and collision avoidance we begin by adding a method, called collision, to the world object  that detects and reacts to collisions. We begin by setting this up for a single obstacle, in this case a building and then extend the code so that we can handle multiple obstacles.  To detect a collision we use the “is within threshold of” function from the humvee object. This is used as the conditional of an if-then-else statement. If the condition is true, then the humvee reacts to the collision by moving backwards a short distance.

When using the “is within threshold of” function, we need to bear in mind that the function is measuring the distance between the centre of the Humvee and the centre of the obstacle. A collision with the side of the obstacle will therefore occur when the distance between the centres is half of the obstacle width + half of the Humvee depth. This distance will when the Humvee is approaching from a different direction, e.g. from the front of the building (in which case we might use the half of the obstacle depth). For this tutorial we just use the above calculation, but we could include a more sophisticated check by determining which direction the Humvee is approaching the obstacle from using the “is in front of” and similar functions.

After developing the collision method, we create a “while world is running” event handler. This event handler will call the collision method, such that whenever a collision is detected the Humvee will react and move backwards.

Dealing with multiple obstacles

So far we can only handle a single obstacle. We could of course develop similar methods to handle the other obstacles, but the DRY (don’t repeat yourself) principle suggests we should find a better way of doing this. Rather than repeating the code for the other obstacles, what we will do is generalise the existing code to handle many obstacles. To do this we use an list variable to represent the collection of all obstacles and then use the “for all do together” construct to implement collision detection and avoidance within a single method.

Video Tutorial

The following video tutorial provides a step-by-step description of the development of the collision detection capabilities.