Greenfoot

From CompSciWiki
Jump to: navigation, search

COMP 1010 Home > Back to Extra Labs

Introduction

For this lab you are going to create a game using Greenfoot. Greenfoot is an interactive tool for building Java programs using a mixture of programming and interactivity. With Greenfoot, you are able to get a 2D graphic program up and running much faster than you would using regular Java. By completing this lab we hope you become more familiar with concepts such as objects and classes. Good luck!

Image by Graeme Peters

Step 0: Starting a New Scenario

Once you have Greenfoot open, the first thing you have to do is open a new scenario. To do this, follow these steps:

  1. Click on the "Scenario" menu tab at the top left of the window.
  2. Select "New..." from the list of options.
  3. Choose "Breakout" for your project name.
  4. Save project to either your own folder or the desktop so it is easy to find.
  5. Click "Create" to finish making your project.

Step 1: Making a New World

Now that you have a blank scenario open the next thing you have to do is add a new world for your game to exist in.

  1. Right click on the "World" button on the right side of the window.
  2. Select "New subclass..." from the list.
  3. Name this class "MyWorld"
  4. Select the image "bathroom-tile.jpg" from the "background" catagory. This will be the main background of your game.
  5. Click "Ok" to finish creating this class.
  6. Press the "Compile" button on the bottom right hand side.

Notice how nothing changed before you pressed the compile button? The compile button is like a save button, none of the changes you make will take effect until you compile your program.

Step 2: Creating The Paddle

Setting Up the Paddle Class

  1. First, right-click this-> PaddleV2.jpg image and select "Save As..." and save it in the folder where you created your Greenfoot program.
  2. On the right-hand side of your Greenfoot window, there are two boxes: One under "World classes" called "World" and another under "Actor classes" called "Actor". Right-Click "Actor" and select "New subclass..."
  3. Name your subclass Paddle by entering it into the New class name textbox.
  4. Now, for the image, click the "Import from file..." box in the bottom-left of this window. Find and select the PaddleV2.jpg file you just saved.
  5. Press OK on that window to close it and create the new subclass.

Moving the Paddle

Select the "Paddle" box, which is now located under the "Actor" box on the right-hand side, and select "new Paddle()". When you do this, you'll now see the image of the paddle following your mouse cursor. You can now place the paddle in the game screen by clicking anywhere within it. You can also do this by selecting the Paddle box, holding the shift key, and pressing anywhere in the game window,

Right now, if you click "Act" or "Run" on the game screen window after adding a paddle to it and press the left and right arrow keys, nothing happens. This isn't very game-like. We want our paddle to move around!

To do this, we need to add code to the Paddle class so it can control its own actions.

Right-click the "Paddle" box in the Actor classes box of the main window and select "Open editor", just like you did to change the code in MyWorld.

This opens up an editor with the following:

 ...

public class Paddle extends Actor
{
    /**
    * Act - do whatever the Paddle wants to do. This method is called whenever
    * the 'Act' or 'Run' button gets pressed in the environment.
    */
    public void act()
    {
        // Add your action code here
    }
} 

The comments in this code tell it all -- if you want your paddle to do anything, you have to add your code within the act() method. Change it so it looks like:

 public void act()
{
    if (Greenfoot.isKeyDown("left"))
    {
        setLocation(getX() - 3, getY());
    }
    else if (Greenfoot.isKeyDown("right"))
    {
        setLocation(getX() + 3, getY());
    }
} 

Let's break this code down:

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

This says that, when the user is pressing the "left" key, which is the left arrow on your keyboard, then do the code that is in it's block. The block:

 else if (Greenfoot.isKeyDown("right"))
{
    ...
} 

Does the exact same thing, except when the "right" key is pressed.

These two blocks contain:

 setLocation(getX() - 3, getY());
...
setLocation(getX() + 3, getY()); 

These both change the location of the Paddle object, except one has "getX() - 3" while the other has "getX() + 3". This means that one moves the Paddle to the left of it's current X position by 3 and the other to the right by 3. Try changing these values and even flipping them around to see how it changes your Paddle!

To test the changes, compile the code, press "Run" on the main window, and press your right and left keys. The paddle now moves!

Step 3: Creating a Bouncing Ball

To add a ball to your game you will need to create a new actor. Follow these steps:

  1. Right click on the "Actor" button
  2. Select "New subclass..." from the list of options.
  3. Name this class "Ball"
  4. Find and select the image "ball.png" from the "objects" catagory
  5. Press "Ok" to create the class.

Add a Ball to Your Game

Before you can add the ball to your game you must first write the constructor. Add the following code above the act() method in the "Ball" file.

 private boolean goLeft;
private boolean goUp;
private boolean gameOver;
    
public Ball()
{
    goLeft = true;   
    goUp = true;
    gameOver = false;
} 

The variables goLeft and goUp keep track of which direction the ball is in. A true value indicates that the ball is moving in that direction. This means that, when goUp is true, the ball is traveling upwards; when goUp is false, the ball is travelling downwards. After you compile your project you will be able to add a ball to your game by selecting "new Ball()" and placing the new ball onto your game screen like you did with the paddle earlier.

Make the Ball Move

To move the ball we are going to use the method setLocation(aNumber,aNumber) just like we did with the paddle. This time, however, we do not worry whether your are pressing the "left" or "right" arrow. Instead, the ball is just going to move on its own. Also, like we did with the paddle, we will set the location of the object based on its current location stored in getX() and getY(). This way, you can get the x and y coordinates of the object then add or subtract from these values to give them a moving effect.

Add the following code to the act() method within the "Ball" source file:

 if(gameOver == false)
{
    int changeX = 0;
    int changeY = 0;
            
    if(goUp == true)
    {
        changeY = changeY - 1;
    }
    else
    {
        changeY = changeY + 1;
    }
            
    if(goLeft == true)
    {
        changeX = changeX - 1;
    }
    else
    {
        changeX = changeX + 1;
    }
            
    setLocation(getX() + changeX, getY() + changeY);
} 

The above code checks which direction the ball is currently moving in and keeps the ball moving in that direction. This will make the ball move but as soon as it hits a wall it will stop. This is because, if it continues to add or subtract from its position, then it will be outside the bounds of the screen. To fix this and make the ball bounce off the walls, you will have to add methods to check if the ball is at a wall and, if it is, change the direction of the ball.

Check if the Ball Hits a Wall

We need to check if the ball is at a wall so we can switch it's direction. We use getX() and getY() to determine the ball's location. If getX() is less then 10, the ball is at the left side of the screen and if it is greater than the width of the screen minus 10 pixels of padding, it is at the right side of the screen.

Add the following code after the act() method in the "Ball" source file:

 public void checkSides()
{
    if(getX() <= 10)
    {
        goLeft = false;
    }
    else if(getX() >= getWorld().getWidth() - 10) // if
    {
        goLeft = true;
    }
} 

Like act(), checkSides() is also a method. There is difference between checkSides() and act(), however: because we manually made this method, Greenfoot will not use it until we tell it to like it does with the act() method, which Greenfoot uses implicitly. Since we know act() already runs code, we want to make sure that our checkSides code is also run. To do this, we must call it. Do this by putting checkSides() at the bottom of the act() function like:

 public void act() 
{
    if(gameOver == false)
    {
        int changeX = 0;
        int changeY = 0;
            
        if(goUp == true)
        {
            changeY = changeY - 1;
        }
        else
        {
            changeY = changeY + 1;
        }

        if(goLeft == true)
        {
            changeX = changeX - 1;
        }
        else
        {
            changeX = changeX + 1;
        }
            
        setLocation(getX() + changeX, getY() + changeY);
         
        checkSides();
    }
} 

Notice that the call to checkSides() is still in between the braces started up at the top of the act() method with the check

 if(gameOver == false) 

That's because we don't want to worry about whether or not the ball hits the sides when the game is already over.

This covers the side walls of the game. We also have to worry about what happens when the ball hits the top and bottom of the screen. Use this method:

 public void checkTopAndBottom()
{
    if(getY() < 5)
    {
        goUp = false;
    } 
    else if (getY() > getWorld().getHeight() - 5)
    {
        gameOver = true;
    }
} 

The top of the screen has a coordinate of 0 so if getY() is less than 5 we know the ball is at the top of the screen. When this happens, the Ball's goUp variable is set to false because it should now move downwards. The "else if" does something different; it says that, if the ball hits the bottom, then the game is over.

Remember: This method still needs to be called while the game is running, so make sure to put:

 checkTopAndBottom(); 

right underneath the call that you have in the act() method to checkSides().

The only thing left to check is whether or not the ball hits the paddle.

Add this method to the Ball class:

 public void checkObjectCollision()
{
    Actor paddle = getOneIntersectingObject(Paddle.class);
    if(paddle != null)
    {
       goUp = !goUp;
    }
} 

And also put the call to this method underneath the checkSides() and checkTopAndBottom() that we have already added. This snippet of code is telling us that if our ball ever happens to hit a paddle, then go in the opposite direction we are already going.

To test all of this, make sure to save your files, press the compile button, and add a ball and a paddle to the game screen. When you press "Run", you should see the ball bounce off the walls and your paddle, and stop when it hits the bottom of the screen.

Step 4: Creating The Bricks

To the complete the game we need bricks. This process is similar to when you were creating the paddle class. Follow these steps:

  1. Right click on the "Actor" tab on the right hand side of the main project screen.
  2. Select "New subclass..." from the list of options.
  3. Name this class Bricks.
  4. Select the "brick.png" image from the objects category.
  5. Press "Ok" when finished and compile your project.

You will not need to add any code to this class because all we do not need this object to move. All we need is the brick image.

Making Bricks Break

The main point of Breakout is for bricks to break when they are hit by a ball. To do this, we're going to add the following code in the Ball class's checkObjectCollision() method:

 Actor brick = getOneIntersectingObject(Brick.class);
if(brick != null)
{
    goUp = !goUp;
    getWorld().removeObject(brick);
} 

It looks similar to when a ball hits a paddle, in that its direction will reverse. However, there is an extra line of code here as well. It's telling the world to remove the brick that the ball has just hit.

Save, compile, add objects, and run your program to test it out!

Step 5: Adding All The Objects To Your Game

Now that you have made all the different objects for your game it is time to test them all out. To make the game work we need a ball, a paddle, and at least a couple bricks. The process of adding an object to the game is the same for all objects. As an example, follow these steps to add a paddle to your game:

  1. Right click "Paddle" tab on the right hand side.
  2. Select "new Paddle()" from the list of options.
  3. Now use the mouse to drag the paddle onto your game screen and click again to place it.
  4. Repeat these steps to add a ball and the bricks.

If you want to add a bunch of bricks to your game without having to add them individually, add the following code into the public MyWorld() method within the MyWorld source file:

 int x,y;
x = y = 20;
for(int i = 0; i < 195; i++){
     Bricks temp = new Bricks();
     addObject(temp,x,y);
     x+=40;
     if(x >= 600){
          x=20;
          y+=20;
     }
} 

This will add 195 blocks and arrange them in the appropriate order.

Full Example

If you were unable to get your game working the full example is available for download here.