Chapter 1 - Moving a Sprite in Greenfoot: Redhood1 and Redhood2
A class is a collection of code that specifies what an object of that class type will look like and what it can do. You can think of a class as a cookie cutter, or a template. For example, when growing up you might have a pumpkin cookie cutter that you used at Halloween. You would use the cutter to make many instances of cookies. The shape of the cutter determines the shape of the cookie. Likewise, in computer programming, the stuff in the class declaration will determine with the object can do. Class definitions can contain member data and methods. The littleRedRight class specifies three methods. A method is a chunk of code that does something. In the case of littleRedRight the three methods are: act(), canMoveRightOne(), and moveRightOne(). When an object of type littleRedRight is created, that object can call those three methods.
The function of the three methods belonging to the littleRedRight class are:
Later we will explain in more detail exactly how the canMoveRightOne() and moveRightOne() methods work, but for now we will just use them.
Lets look at the code in the act method:
public void act()
{
if ( canMoveRightOne() )
{
moveRightOne(); // move one location to the right
}
else
{
Greenfoot.stopSimulation();
}
}
The first line declares the method and calls it act. The act method has a special meaning in Greenfoot: it is the class method that is called each "tick" of the game. Note the "{" and "}" on the second and last line of the method. The curly braces are used to delimit the code that belongs to the act() method. In general, a open/close pair of curly brackets enclose one or more statements. This group of one or more statements is called a statement block.
Now consider the code between the two open/close curly braces. The first statement is an if statement.
if ( expression )
{
do something
}
else
{
do something else
}
The if statement first evaluates the expression inside of the parenthesis ( ), if that expression evaluates to true, then the first statement block is executed. If on the other hand the expression evaluates to false, then the second statement block, the one following the else, is executed.
if ( canMoveRightOne() )
{
System.out.println("Moving one space") ;
moveRightOne();
}
else
{
System.out.println("Done moving") ;
Greenfoot.stopSimulation();
}
Now compile by clicking on the "compile" button in the top left menu bar of the code window. Now run the code by putting a littleRedRight object in the world and clicking run.
This example teaches three lessons:
- How to modify the code and compile it
- How to create written output using System.out.println(" text here ")
- An illustration of the concept that statement blocks can have multiple lines of code within them.
----------- End Exercise 1 ------------------------
----------- Begin Exercise 2 ------------------------
Click on the reset button and put a littleRedRight object into the world. Once in the world, right-click (CTRL+click on a mac) on the littleRedSprite. In the pop-up menu you will see the three method names. If you click on one of the method names it executes that method. Try out the various methods, see the effect, and look at the code.
----------- End Exercise 2 ------------------------
Now click on the "reset" button and then put two objects in the world, one of class littleRedRight() and one of littleRedRightVelocity(). Line them up vertically so they are starting from the same x-position. Click Run. You will see that the littleRedRightVelocity object moves twice as fast.
Open up the code for littleRedRightVelocity. First thing to notice is the following line that precedes the act() method:
int xVelocity = 2 ;
This is how we declare a data member. Members are data values that belong to the object.
As an analogy consider a kitchen oven. The oven might have methods such as openDoor(), setTemperature(), and turnOff(). The oven data member might be the currentInternalTemperature. Then, the method setTemperature() would look at the oven's currentInternalTemperature and if the desired temperature is higher turn on the fire, and, if lower, turn off the fire.
In general objects have both methods and members.
----------- Start Exercise 3 ------------------------
Modify the littleRedRightVelocity() class so that it moves twice as fast again. Hint: modify the xVelocity data member. Compile and run to verify you succeeded.
----------- End Exercise 3 ------------------------
Next, try out the last class in the Redhood1 scenario. Create an instance of the littleRedBackForth() class and place it in the world, then click the run botton. Sure enough, little red goes back and forth. Look at the code. The method canMoveX() has been modified to check the boundaries at both the left and right edges. In the act() method, if the canMoveX() method returns "false", then the xVelocity is negated. This is accomplished with the statement:
xVelocity = -1 * xVelocity ;
Now open the RedHood2 scenario. Again, click on Scenario->open and browse to RedHood2. Once open create an instance of the LittleRedRandom() class and put it in the world. Then click on the run button. As you see little red is now moving in both dimensions. Double click on the LittleRedRandom class to open the code. As you can see we now have a moveXY() method.
The code for the act() method is now:
public void act()
{
if( atXboundary() )
{
xVel = -xVel;
}
if( atYboundary() )
{
yVel = -yVel;
}
moveXY() ;
}
The code checks to see if little red is at an X boundary, i.e. the left or right hand boundary of the world, and if so negates the x-velocity. The code then checks to see if little red is at a Y bounday, i.e. the top or bottom of the world, and if so negates the y-velocity. The code inside act() then calls moveXY() which moves little red in the X and Y direction.
The code for the moveXY() method is:
public void moveXY()
{
setLocation( getX() + xVel, getY() + yVel ) ;
}
You can see that both xVel and yVel are used to set the distance littleRed moves on every timestep.
We now are able to move a sprite around the world with it bouncing off the walls. But many (most) games have the player control one of the sprite's movements. In the last example in this chapter we show how to use the keyboard to control the movement of a sprite. Create an instance of LittleRedKey in RedHood2 and place it in the world. Click on run. It does not move, but, if you press on the keyboard's arrow keys you will see you can now control the sprite using the keys.
Open the code by double-clicking on the LittleRedKey class. The act() method is one line of code: tryMove(). The tryMove() method has for if statements corresponding to the four arrow keys. If the key pressed was up, then the code checks to see if the sprite can be moved up, and if it can it then sets the new location of the sprite to be one position higher. Similar tests and movements are done for each of the other three arrow keys.
The astute reader will have noticed we have not yet talked about some of the calls inside the code, namely getX(), getY(), and setLocation() and how they relate to a coordinate system. We leave this to a later chapter. Right now we want you to understand that if a method is supplied, a programmer can use that method without really understanding how it works, just understanding what it is supposed to do. This is one of the powerful concepts of object oriented programming.
---------------
An image:
