Painting stars

7.2 Painting stars

In all our previous scenarios, we used a fixed image as the background for the world. The image was stored in an image file in our file system.

In this scenario, we’d like to introduce a different technique to make background images: paint- ing them on the fly.

The Asteroid scenario does not use an image file for the background. A world that does not have

a background image assigned will, by default, get an automatically created background image that is filled with plain white.

Exercise 7.6 Investigate the constructor of the Space class in your scenario. Find the lines of code that create the black background.

Looking at the asteroids-1 scenario, we can see that the background is plain black. When we investigate the constructor of the Space class, we can find these three lines of code:

GreenfootImage background = getBackground(); background.setColor(Color.BLACK); background.fill();

Tip: Exercise 7.7 Remove these three lines from your class. You can do this by just com-

If you want to

menting them out. What do you observe? (Once done, put them back in.)

remove some code temporarily, it is easier to “comment it out”, rather than

The first line retrieves the current background image from the world. This is the automatically

deleting it. The

generated (white) image. We then have a reference to the world background stored in the

Greenfoot editor has a function to

background variable.

do this. Just select the lines in ques-

The background object that we have stored here is of class GreenfootImage —we have seen

tion, and invoke

this class before.

‘Comment’ (F8) or ‘Uncomment’ (F7) from the Edit menu.

Exercise 7.8 Look up the documentation for the class GreenfootImage. What is the name of the method used to draw a rectangle? What is the difference between drawOval and fillOval?

| Chapter 7 ■ Collision detection: Asteroids

The second line in the code fragment above sets the paint color to black. Doing this has no immediate effect (it does not change the color of the image). Instead, it determines the color that is used by all following drawing operations. The parameter is a constant from the Color class, which we encountered in the previous chapter.

Exercise 7.9 Look up the documentation of class Color again. (Do you remember which package it is in?) For how many colors does this class define constant fields?

The third line of the code fragment now fills our image with the chosen color. Note that we do not need to set this image again as the background of the world. When we got the image (using getBackground() ), we got a reference to the background image, and the same image still remains the world background. It is not removed from the world just because we now have a reference to it.

When we paint onto this image, we are painting directly onto the background of the world. Our task now is to draw some stars onto the background image.

Exercise 7.10 In class Space, create a new method named createStars. This method should have one parameter of type int, named number, to specify the number of stars it should create. It has no return value. The method body should—for now—be empty.

Exercise 7.11 Write a comment for the new method. (The comment should describe what the method does, and explain what the parameter is used for.)

Exercise 7.12 Insert a call to this new method into your Space constructor. 300 stars may be a good amount to start with (although you can later experiment with different numbers and choose something that you think looks good).

Exercise 7.13 Compile the class Space. At this stage, you should not see any effect (since our new method is empty), but the class should compile without problems.

Concept:

In the createStars method, we will now write code to paint some stars onto the background image. The exact amount of stars is specified in the method’s parameter.

The for loop is one of Java’s loop

We will use yet another loop to achieve this: the for loop.

constructs. It is especially good for

Previously, we have seen the while loop and the for-each loop. The for loop uses the same key-

iterating a fixed

word as the for-each loop ( for ), but has a different structure. It is

number of times. for (initialization; loop-condition; increment) {

loop-body ;

An example of this loop can be seen in the addAsteroids method in the Space class.

7.2 Painting stars

Exercise 7.14 Examine the addAsteroids method in class Space. What does it do? Exercise 7.15 Look at the for loop in that method. From the loop header, write down

the initialization part, the loop-condition, and the increment. (See the definition of the for loop above.)

The initialization part of a for loop is executed exactly once before the loop starts. Then the loop condition is checked: If it is true, the loop body is executed. Finally, after the loop body has been completely executed, the increment section from the loop header is executed. After this, the loop starts over: The condition is evaluated again and, if true, the loop runs again. This continues until the loop conditions returns false. The initialization is never executed again.

A for loop could quite easily be replaced by a while loop. A while loop equivalent of the for loop structure shown above is this:

initialization ; while (loop-condition) {

loop-body ; increment ;

The while loop structure shown here and the for loop structure shown above do exactly the same thing. The main difference is that, in the for loop, the initialization and the increment have been moved into the loop header. This places all elements that define the loop behavior in one place, and can make loops easier to read.

The for loop is especially practical if we know at the beginning of the loop already how often we want to execute the loop.

The for loop example found in the addAsteroids method reads

for ( int i = 0; i < count; i++) { int x = Greenfoot.getRandomNumber(getWidth()/2); int y = Greenfoot.getRandomNumber(getHeight()/2); addObject( new Asteroid(), x, y);

This shows a typical example of a for loop:

The initialization part declares and initializes a loop variable. This variable is often called i ,

and often initialized to 0 .

The loop condition checks whether our loop variable is still less than a given limit (here: count ). If it is, the loop will continue.

The increment section simply increments the loop variable. Different variations of the for loop are possible, but this example shows a very typical format.

| Chapter 7 ■ Collision detection: Asteroids

Exercise 7.16 In your Space class, rewrite the for loop in addAsteroids as a while loop. Make sure that it does the same as before.

Exercise 7.17 Rewrite this method again with a for loop, as it was before. Exercise 7.18 Implement the body of the createStars method that you created earlier.

This method should include the following:

Retrieve the world’s background image.

Use a for loop similar to the one in addAsteroids. The limit for the loop is given in the

method parameter.

In the body of the loop, generate random x and y coordinates. Set the color to white and

then paint a filled oval with a width and height of two pixels. Test! Do you see stars in your world? If all went well, you should.

Exercise 7.19 Create stars of random brightness. You can do this by creating a random number between 0 and 255 (the legal range for RGB values for colors) and creating a new Color object using the same random value for all three color components (red, green, and blue). Using the same value for all color components ensures that the resulting color is a shade of neutral gray. Use this new random color for painting the stars. Make sure to generate a new color for every new star.

These exercises are quite challenging. If you have trouble, you can look into the solution. An implementation of this is provided in the asteroids-2 version of this scenario. Alternatively, you can ignore this section for now, continue with the following tasks first, and come back to this later.