Flying forward

7.4 Flying forward

Our Rocket class is a subclass of the SmoothMover class, which we have already seen in the previous chapter. This means that it holds a movement vector that determines its movement, and that it has a move() method that makes it move according to this vector.

Our first step is to make use of this move() method.

Exercise 7.23 In the Rocket’s act method, add a call to the move() method (inherited from SmoothMover). Test. What do you observe?

Adding the call to move() to our act method is an important first step, but does not achieve much by itself. It causes the rocket to move according to its movement vector, but since we have not initiated any movement, this vector currently has length 0, so no movement takes place.

To change this, let us first introduce a small amount of automatic drift, so that the rocket starts off with some initial movement. This makes it more interesting to play, because it stops players from being able to just remain stationary for a long time.

Exercise 7.24 Add a small amount of initial movement to the rocket in its constructor. To do this, create a new vector with some arbitrary direction and a small length (I used 0.3 for my own version) and then use the SmoothMover’s addForce method with this vector as a parameter to add this force to the rocket. (Make sure to use an int as your first parameter in the Vector’s constructor, in order to use the correct constructor.)

Test. If all went well, the rocket should drift all by itself when the scenario starts. Don’t make this initial drift too fast. Experiment until you have a nice, slow initial movement.

Next, we want to add movement controls for the player. The plan is that pressing the “up” arrow key ignites the rocket’s booster and moves us forward.

| Chapter 7 ■ Collision detection: Asteroids

For the other keyboard input, we have used code of the following pattern:

if (Greenfoot.isKeyDown( "left" )) {

setRotation(getRotation() - 5);

For the movement forward, we need a slightly different pattern. The reason is that, for the rota- tion shown here, we need to act only if the key is being pressed.

The movement forward is different: When we press the “up” key to move, we want to change the rocket’s image to show the rocket engine firing. When we release the key, the image should return to the normal image. Thus, we need a code pattern along these lines:

when “up” key is pressed:

change image to show engine fire; add movement;

when up key is released:

change back to normal image;

Showing the images is quite easy. The scenario already contains two different rocket images for this: rocket.png and rocketWithThrust.png. Both images are loaded into fields toward the top of the Rocket class.

Since we need to react in both cases, when the “up” key is pressed and when it is not pressed, we will define and call a separate method to handle this functionality.

In checkKeys , we can insert the following method call:

ignite(Greenfoot.isKeyDown( "up" )); We can then write a method called ignite that does the following:

It receives a boolean parameter (say, boosterOn ) that indicates whether the booster should be on or off.

If the booster is on, it sets the image to rocketWithThrust.png and uses addForce to add a new vector. This vector should get its direction from the current rotation of the rocket ( getRotation() ) and have a small, constant length (say, 0.3).

If the booster is not on, set the image to rocket.png.

Exercise 7.25 Add the call to the ignite method to your checkKeys method, exactly as shown above.

Exercise 7.26 Define a method stub (a method with an empty body) for the ignite method. This method should have one boolean parameter, and a void return type. Make sure to write a comment. Test! The code should compile (but not do anything yet).

Exercise 7.27 Implement the body of the ignite method, as outlined in the bullet points above.

7.5 Colliding with asteroids

For the implementation of our ignite method, it is okay if the image gets set every time the method is called, even when it is not necessary (e.g., if the booster is off, and it was also off last time, we would not need to set the image again since it has not changed). Setting the image even when it is not strictly necessary has very little overhead and so avoiding it is not crucial.

Once you have completed these exercises, you have reached a stage where you can fly your rocket around and fire at asteroids.

A version of the project that implements the exercises presented so far in this chapter is provided as asteroids-2 in the book scenarios.