Growing the wave

7.8 Growing the wave

We have seen that the ProtonWave class has a method— initializeImages —that creates

30 images of different sizes and stores them in an array (Code 7.2). This array, named images , holds the smallest image at index 0, and the largest one at index 29 (see Figure 7.3). The images are created by loading a base image (wave.png) and then, in a loop, creating copies of this image and scaling them to different sizes.

Code 7.2 Initializing the

/ ** images for the

* Create the images for expanding the wave. proton wave

*/ public static void initializeImages() {

if(images == null ) {

GreenfootImage baseImage = new GreenfootImage( “wave.png” ); images = new GreenfootImage[NUMBER_IMAGES];

Chapter 7 | ■ Collision detection: Asteroids

Code 7.2 continued

int

i = 0;

Initializing the

while (i < NUMBER_IMAGES)

images for the

proton wave int size = (i+1) * (baseImage.getWidth() / NUMBER_IMAGES); images[i] = new GreenfootImage(baseImage); images[i].scale(size, size); i++;

Figure 7.3

GreenfootImage [] images

An array of images (some left out for space reasons)

This method uses the scale method from the GreenfootImage class to do the scaling. It also uses a while loop for the iteration. However, this is an example where a for loop, which we encountered at the beginning of this chapter, might be appropriate.

Exercise 7.48 Rewrite the initializeImages method to use a for loop instead of a while loop.

In practice, it is not very important which loop to use in this case. (We changed it here mainly to gain additional practice in writing for loops.) This is, however, a case where a for loop is a good choice, because we have a known number of iterations (the number of images) and we can make good use of the loop counter in calculating the image sizes. The advantage over the while loop is that the for loop brings all elements of the loop (initialization, condition, and increment) together in the header, so that we run less danger of forgetting one of its parts.

7.8 Growing the wave

The images field and the initializeImages method are static (they use the static keyword in their definition). As we have briefly mentioned in Chapter 7, this means that the images field is stored in the ProtonWave class, not in the individual instances. As a result, all objects that we shall create of this class can share this set of images, and we do not need to create

a separate set of images for each object. This is much more efficient than using a separate image set each time.

Copying and scaling these images takes a fairly long time (between a tenth of a second and half

a second on a current average computer). This does not may seem very much, but it is long enough to introduce a visible, annoying delay when we do it in the middle of playing a game. To solve this, the code of this method is enclosed in an if statement:

if (images == null ) {

This if statement ensures that the main part of this method (the body of the if statement) is executed only once. The first time, images will be null , and the method executes fully. This will initialize the images field to something other than null . From then on, the test of the if statement is all that will be executed, and the body will be skipped. The initializeImages method is actually called every time a proton wave is created (from the constructor), but only the very first time it is called, substantial work will be done. 1

Now that we have a fair idea of the code and the fields that already exist, we can finally get to work and make something happen.

What we want to do is the following:

We want to start the wave off with the smallest image.

At every act step, we want to grow the wave (show the next larger image).

After we have shown the largest image, the wave should disappear (be removed from the world).

The following exercises will achieve this.

Exercise 7.49 In the constructor of class ProtonWave, set the image to the smallest image. (You can use images[0] as the parameter to the setImage method.)

Exercise 7.50 Create an instance field named imageCount of type int, and initialize it to 0. We will use this field to count through the images. The current value is the index of the currently displayed image.

1 The method is actually called for the first time from the Space constructor, so it executes even before the first proton wave is created. This avoids a delay for the first proton wave as well. The call is included in

the proton wave constructor only as a safety feature: If this class is ever used in another project, and this method is not called in advance, all will still work.

| Chapter 7 ■ Collision detection: Asteroids

Exercise 7.51 Create a method stub for a new private method called grow. This method has no parameter and does not return a value.

Exercise 7.52 Call the grow method from your act method. (Even though it does not do anything at this stage.)

We’re almost there. The only thing left is to implement the grow method. The idea, roughly, is this:

show the image at index imageCount ; increment imageCount ;

We will also have to add an if statement that f irst checks whether imageCount has exceeded the number of images. In that case, we can remove the proton wave from the world and we’re done.

Exercise 7.53 Implement the grow method along the lines discussed above. Exercise 7.54 Test your proton wave. If you interactively create a proton wave and place

it into the world while the scenario is running, you should see the wave expansion effect.

Exercise 7.55 Add some sound. A sound file named proton.wav is included with the scenario—you can just play it. You can place the statement to play the sound into the con- structor of the proton wave.

Now that we have a functioning proton wave, we should equip our rocket to release it.

Exercise 7.56 In class Rocket, create a method stub named startProtonWave with- out parameters. Does it need to return anything?

Exercise 7.57 Implement this method: It should place a new proton wave object into the world, at the current coordinates of the rocket.

Exercise 7.58 Call this new method from the checkKeys method when the “z” key is pressed. Test.

Exercise 7.59 You will quickly notice that the proton wave can be released much too often now. For firing the bullets, a delay has been built into the Rocket class (using the gunReloadTime constant and the reloadDelayCount field). Study this code and imple- ment something similar for the proton wave. Try out different delay values until you find one that seems sensible.

7.9 Interacting with objects in range