Tutorial2:Wackadot:Eclipse

From FANG

Jump to: navigation, search

Using the FANG Engine you can write a working game very quickly. The steps below will guide you to making a game where red and blue circles appear randomly and you have to move your mouse over them to make the circles go away. The game will keep score of how many red circles and how many blue circles you catch on in 10 seconds.

These instructions assume you have downloaded and installed the software needed for designing your game which includes Eclipse and Java 1.5. These instructions include information about using Eclipse 3.4.2 on Mac OS X 10.5. Your Eclipse may be a different version and you may be running on a different operating system, so the screenshots and menu options may be slightly different.

As with any game you make, you want to keep it functional as much as possible. After you make additions, test them completely before moving on. Keep the additions you make short and simple. Complex games are best written by many simple steps rather than few complex steps. We're going to follow these guidelines in making our game.

Be sure read the Explanations of the Source Code in each of the tables below. Also if you are having trouble, try visiting the FAQ.

Before you get started, be sure to read some advice from students who have already made this game. They will tell you what it feels like working on the game, the types of problems they encountered, the best strategies for solving these problems, and best of of all, what it feels like when you have your own working game.

Contents

1. Getting the Gaming Engine and Setting Up the Project

Save to your computer the latest version of the FANG Engine. Click here to go to the downloads page.

Open up Eclipse and start a new Java Project. To start a new project, go to File->New->Java Project. A dialog with several screens (the first is shown below) will come up.

Image:Newjavaproject1A.png

Click Next. On the second screen of the dialog, enter Wacky in the Project name field, as shown below.

Image:Newjavaproject2A.png

In the JRE section of this dialog, make sure you have Java 1.5 or higher selected (nearly all version are like this by default). If the option instead says something else (such as Currently 1.4), then click on the link to the right of the option that says Configure default.... Follow the instructions for changing to 1.5 or higher.

In Eclipse right click on src within Wacky in the Package Explorer then select Build Path->Add External Archives...

Image:BuildPath.png

You will then see the screen shown below. Find and select the jar file you downloaded at the beginning of this step, then click on Open

Image:BuildPathSelect.png

2. Making the Packages

Each game should be made in its own package, and there should be subpackages within the game's primary package We're going to name the game in this example wackadot. You need to make the following packages in your project:

  • wackadot
  • wackadot.resources

To make a package in your project, right-click on the src under the project name (in the Package Explorer pane on the left) and choose New->Package in the menu that appears, as shown below.

Image:Newjavapackage1A.png

Then complete the dialog that appears with the name of the new package that you want to create, as seen in the example screenshot below.

Image:Newjavapackage2A.png

All of the classes will be put in the wackadot package, and all other files (like audio, images, help files) will go in wackadot.resources.

3. Extending Game

Every game you make will have a class that extends GameLoop. GameLoop is in the fang package. Create a new class in the package wackadot and call the class Wackadot. Creating a new class is similar to creating a new package: right click the name of the package that you want the class to be under and then choose New->Class and complete the dialog that will appear.

Image:NewClassA.png

Image:NameClassA.png

Image:EmptySourceCodeA.png

Image:SkeletonSourceCodeA.png

Some code will be automatically generated when you create the Wackadot class. Replace the generated code with the code in the table below.

A
Source code
Explanation of Source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package wackadot;


import fang.*;
import java.awt.*;
import java.awt.geom.*;

/**
* All about my game here.
* @author YourName
*/
public class Wackadot extends GameLoop
{
   public static void main(String[] argv)
   {
      Wackadot dot=new Wackadot();
      dot.runAsApplication();
   }
}

Line 1: the package this class is in

Line 4: importing the fang package for use in the class.

Lines 14-18: the main method is required to allow the game to be run as an application in addition to it being an applet. (It is an applet because it is derived from the GameLoop class which is indirectly derived from the JApplet class.)

4. Running the Game

The method runAsApplication in main is what starts the game running. (The method is from the FANG engine.)

There are three ways to run your game: as an applet, as an application, and as a networked game. For now we are going to run Wackadot as an application. To do this, highlight the Wackadot class in the Package Explorer, right click, then select Run As... and then select Java Application.

Image:WackadotAsApplication.png

You should see a window come up that looks like the image in this section.

Image:Wackadot0A.png

5. Adding Sprites

To make Wackadot, we definitely need dots. The visual elements on the screen in games are called sprites. Sprites have some basic properties such as shape, orientation, location, and color. We're going to start by making a red dot appear in the middle of the screen. The coordinates in the gaming engine are designed such that resizing the screen is not difficult. The location of sprites is given in fractions of the screen. Internally, this fraction is then multiplied by the actual width and actual height of the screen to get the actual location. In this way, the sprites in the game scale smoothly with the size of the screen.

Add the code below which is not already there. You already have some of the code below from the previous instructions: new code is shown in bold. This code should make a sprite appear in the middle of the screen.

Test the changes to make sure you see the dot appear before going to the next step. Perform the test by running the program as an application, as in the previous section.

Note: the line numbers in this and each of the following tables match the line numbers in your program.

Line
Source code
Explanation of Source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package wackadot;

import fang2.core.*;
import fang2.sprites.*;
import fang2.attributes.*;
import fang2.transformers.*;

/**
* All about my game here.
* @author YourName
*/
public class Wackadot extends Game
{
   private Sprite dot;
    
   public void setup()
   {
       makeSprites();
       addSprites();
   }
    
   private void makeSprites()
   {
       dot=new OvalSprite(0.1, 0.1);
       dot.setLocation(0.5, 0.5);
       dot.setColor(getColor("Red"));
   }
    
   private void addSprites()
   {
       addSprite(dot);
   }

   public static void main(String[] argv)
   {
       Wackadot dot=new Wackadot();
       dot.runAsApplication();
   }
}

Line 1: declares the package this class resides in

Line 14: declares a Sprite instance variable that will be used in the game logic eventually.

Lines 16-20: the setup method is called when the Start button is pressed the first time. In this method, you need to make and add all the sprites. Note: for multiplayer games, the number of players is only available once the setup method is called.

Lines 22-27: helper method for constructing and placing sprites. The positions and sizes are relative to a screen which spans (0, 0) to (1, 1).

Lines 29-32: helper method for adding sprites to the canvas. Simply making a sprite does not make it visible. Sprites are only visible once they are added to the canvas within the bounds of the canvas and sized properly.

6. Making the Sprite Move with the Mouse

The gaming engine redraws the screen up to 25 times per second, and may calculate up to 40 intermediate frames for every single frame it displays. After each of these frames, there is an opportunity to provide the game logic in the advance method. The advance method is called for you by the gaming engine between frames. To start with, we are going to make the position of the dot follow the mouse. Add the following method to your Wackadot class.

Line
Source code
Explanation of Source code
33
34
35
36
37
38
39
  
   public void advance()
   {
      Location2D mouse=
          getMouse2D();
      dot.setLocation(mouse);
   }

Line 33: this line is intentionally left blank. In general, it is good practice to leave a blank line between methods

Line 34: this method is called automatically between each frame calculated/displayed.

Lines 36-37: gets the mouse of the current player.

Line 38: places the sprite at the same position as the mouse.

Line 39: close brace ending the advance method. Every method body begins and ends with braces.

Last Line of your Code: don't forget the close brace for your entire program. The very last character in every single program is a close brace. Leaving off the close brace will cause many errors to appear. Every class body begins and ends with braces.


7. Test Your Changes

Always test your changes before making more modifications. Run the game. Does the dot follow the mouse? (Remember to click Start to start the game running!) If so, go on to the next step. If not, reread the instructions above to see what went wrong.

8. Make Other Dots Appear Randomly

Now we're going to add one red dot and one blue dot which will appear at random positions on the screen. When writing your games, it is important to use the provided random number generator if you are going to make networked games. The provided random number generator gives the same sequence of numbers every time which is essential for making the networked games stay consistent. The gaming engine only sends mouse and keyboard input from all of the players and relies upon common game logic to keep the games consistent. If two games use different sequences of random numbers, then this logic is not identical over the networked games and they will quickly become inconsistent. Add the following instance variables (just below where you declared dot)

Line
Source code
Explanation of Source code
13
14
15
16
17
{
   private Sprite dot;
   private Sprite redDot;
   private Sprite blueDot;

Line 15: declares the red dot

Line 16: declares the blue dot

Then, alter the existing methods (new code is bold):

Line
Source code
Explanation of Source code
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 
private void makeSprites()
{
   dot=new OvalSprite(0.1, 0.1);
   dot.setLocation(0.5, 0.5);
   dot.setColor(getColor("red"));

   redDot=new OvalSprite(0.1, 0.1);
   redDot.setLocation(
          randomDouble(),
          randomDouble());
   redDot.setColor(getColor("red"));

   blueDot=new OvalSprite(0.1, 0.1);
   blueDot.setLocation(
          randomDouble(),
          randomDouble());
   blueDot.setColor(getColor("blue"));
}

private void addSprites()
{
   addSprite(dot);
   addSprite(redDot);
   addSprite(blueDot);
}

Lines 32-33, 38-39: uses the provided random number generator to get a random number between 0 and 1.

Lines 46-47: adds the sprites to make them visible

9. Test Your Changes

Always test your changes before making more modifications. Run the game. Do the red and blue dots appear? If so, go on to the next step. If not, reread the instructions above to see what went wrong.

10. Repositioning Dots When They Collide

The advance method is where the game logic is based and is where you will need to test for collisions. We will write a helper method called handleCollisions and call this from the advance method. Add the following code to your class (new code is bold).

Line
Source code
Explanation of Source code
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 
private void repositionRandomly(Sprite sprite)
{    
   sprite.setLocation(
       randomDouble(), 
       randomDouble());
}

private void handleCollisions()
{    
   if(dot.intersects(blueDot))
   {
       repositionRandomly(blueDot);    
   }    
   if(dot.intersects(redDot))    
   {
       repositionRandomly(redDot);    
   }
}

public void advance()
{
   Location2D mouse=
       getMouse2D();
   dot.setLocation(mouse);
   handleCollisions();
}

Lines 50-55: helper method for randomly positioning the dot.

Lines 57-67: helper method for handling dot collisions

Lines 59-62: if the dot moving with the mouse collides with the blue dot, then the blue dot is positioned in a random location.

Lines 63-66: if the dot moving with the mouse collides with the red dot, then the red dot is positioned in a random location.

Lines 69-75: don't duplicate the advance method, just add line 77.

Line 74: calls the helper method for handling collisions

11. Test Your Changes

Always test your changes before making more modifications. Run the game. Do the red and blue dots reposition randomly when they intersect with the moving dot? If not, reread the instructions above to see what went wrong. If so, do you notice how they always follow the same next random positions each time you run the program?

12. Change Dot Color

When the circle intersects with a dot of the same color, it should change to the other color. The goal of the game will be to move your dot over the dot of the same color. Alter the handleCollisions method to make this happen (new code is bold).

Line
Source code
Explanation of Source code
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 
private void handleCollisions()
{
   if(dot.intersects(blueDot))
   {
       repositionRandomly(blueDot);
       if(dot.getColor().equals(getColor("blue")))
       {
           dot.setColor(getColor("red"));
       }
   }
   if(dot.intersects(redDot))
   {
       repositionRandomly(redDot);
       if(dot.getColor().equals(getColor("red")))
       {
           dot.setColor(getColor("blue"));
       }
   }
}
 

Lines 62-65, 70-73: checks to see if the dot intersected matches the color of the dot. If it does, the color of the dot is changed to the other color.

13. Test Your Changes

Hopefully you get the point by now: Always test your changes before making more modifications. This Testing your changes step will now just be implied after every step.

14. Display the Score

Score can be kept using a StringSprite. First, we're going to display the score. In the next step we'll update the score when dots collide. Add the following instance variable (just under where you have declared the other Sprite instance variables like on Step 8):

Line
Source code
Explanation of Source code
16
17
18
private Sprite blueDot;
private StringSprite scoreSprite;
 

Line 17: a sprite which will consist of text

Alter the following methods (new code is bold):

Line
Source code
Explanation of Source code
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
private void makeSprites()
{
   dot=new OvalSprite(0.1, 0.1);
   dot.setLocation(0.5, 0.5);
   dot.setColor(getColor("red"));

   redDot=new OvalSprite(0.1, 0.1);
   redDot.setLocation(
          random.nextDouble(),
          random.nextDouble());
   redDot.setColor(getColor("red"));

   blueDot=new OvalSprite(0.1, 0.1);
   blueDot.setLocation(
          random.nextDouble(),
          random.nextDouble());
   blueDot.setColor(getColor("blue");

   scoreSprite=new StringSprite("Score: 0");
   scoreSprite.setHeight(0.1);
   scoreSprite.rightJustify();
   scoreSprite.topJustify();
   scoreSprite.setLocation(1, 0);
}

private void addSprites()
{
   addSprite(dot);
   addSprite(redDot);
   addSprite(blueDot);
   addSprite(scoreSprite);
}

Lines 43-47: makes the score sprite. Right justifying means the location will represent the rightmost location. Similarly top justifying means the location represents the topmost location. (1, 0) is the top right which is where the score will be. The text will be 1/10 of the screen high.

Line 55: adds the score sprite to make it visible

15. Update the Score

Now we're actually going to keep the score using an int instance variable. Let's keep score like this: you get 1 point for matching colors, and -1 point for intersecting different colors. Add the following instance variable just under where you have declared the other instance variables like on Step 8 and 14:

Line
Source code
Explanation of Source code
17
18
19
private StringSprite scoreSprite;
private int score;
 

Line 18: the integer which will keep the score

Alter the following methods (new code is bold):

Line
Source code
Explanation of Source code
20
21
22
23
24
25
26
27
28
29
30
31
32 
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
public void setup()
{
   score=0;
   makeSprites();
   addSprites();
}

private void makeSprites()
{
   dot=new OvalSprite(0.1, 0.1);
   dot.setLocation(0.5, 0.5);
   dot.setColor(getColor("red"));

   redDot=new OvalSprite(0.1, 0.1);
   redDot.setLocation(
          random.nextDouble(),
          random.nextDouble());
   redDot.setColor(getColor("red"));

   blueDot=new OvalSprite(0.1, 0.1);
   blueDot.setLocation(
          random.nextDouble(),
          random.nextDouble());
   blueDot.setColor(getColor("blue"));

   scoreSprite=new StringSprite("Score: "+score);
   scoreSprite.setHeight(0.1);
   scoreSprite.rightJustify();
   scoreSprite.topJustify();
   scoreSprite.setLocation(1, 0);
}
... code not shown
 
private void updateScore()
{
   scoreSprite.setText("Score: "+score);
}

private void handleCollisions()
{
   if(dot.intersects(blueDot))
   {
      repositionRandomly(blueDot);
      if(dot.getColor().equals(getColor("blue")))
      {
         dot.setColor(getColor("red"));
         score++;
      }
      else
      {
         score--;
      }
      updateScore();
   }
   if(dot.intersects(redDot))
   {
      repositionRandomly(redDot);
      if(dot.getColor().equals(getColor("red")))
      {
         dot.setColor(getColor("blue"));
         score++;
      }
      else
      {
         score--;
      }
      updateScore();
   }
}

Line 22: starts the score out at 0

Line ... : Don't type this line into your code.

Lines 45: initializes the score sprite using the score instance variable. You need to change this line to what it looks like here since originally it just made the score zero.

Lines 69-72: updates the score sprite to make sure it represents the current score

Lines 80, 84, 94, 98: changes the score when the dot intersects one of the colored dots. If the dot is the same color as the one intersected, then 1 is added to the score. If the dot is the opposite color of the one intersected, then 1 is subtracted from the score.

Lines 86, 100: when the int score changes, the StringSprite scoreSprite should change. These lines call the helper method to change the scoreSprite to represent the current score.

16. Display the Timer

Add similar code to make a timer. The timer won't yet be functional, but it will appear on the screen. Make the following additions/modifications to the code:

Line
Source code
Explanation of Source code
18
19
20
21
private int score;
private int timeLeft;
private StringSprite timerSprite;
 

Line 19: an integer representing the number of second left

Line 20: the StringSprite which will show the time left

Alter the following methods (new code is bold).

Line
Source code
Explanation of Source code
21
22
23
24
25
26
27
28
29
30
31
...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 
public void setup()
{
   score=0;
   timeLeft=10;
   makeSprites();
   addSprites();
}

private void makeSprites()
{
   ... code not shown for brevity

   scoreSprite.setLocation(1, 0);

   timerSprite=new StringSprite("Timer: "+timeLeft);
   timerSprite.leftJustify();
   timerSprite.topJustify();
   timerSprite.setHeight(0.1);
   timerSprite.setLocation(0, 0);
}

private void addSprites()
{
   addSprite(dot);
   addSprite(redDot);
   addSprite(blueDot);
   addSprite(scoreSprite);
   addSprite(timerSprite);
}

private void updateTimer()
{
   timerSprite.setText("Timer: "+timeLeft);
}

Line 25: starts the timer out at 10

Line ... : Do not copy this line, just read it.

Lines 54-58: makes the timer sprite

Line 67: adds the timer sprite to make it visible

Lines 70-73: updates the timer sprite to make sure it represents the current time

17. Make the Timer Tick

You need an Alarm to make the timer go down every second. To make an Alarm, the class needs to have only a single method called act. This method will be called when it is scheduled. We're going to write a class to make the time go down by 1 second in the act method. Because this class is trivial, we're going to write it as an inner class. We'll call the act method every second while there is time remaining. Add the following inner class modification and make the other changes indicated (new code is bold):

Line
Source code
Explanation of Source code
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
...
133
134
135
136
137
138
139
140
141
142
 
public void setup()
{
   score=0;
   timeLeft=10;
   makeSprites();
   addSprites();
   scheduleRelative(new TimeUpdater(), 1);
}

class TimeUpdater implements Alarm
{
   public void act()
   {
      timeLeft--;
      updateTimer();
      if(timeLeft>0)
      {
         scheduleRelative(this, 1);
      }
   }
}
... Code not shown
public void advance()
{
   if(timeLeft>0)
   {
       Location2D mouse=
           getMouse2D;
       dot.setLocation(mouse);
       handleCollisions();
   }
}

Line 28: schedules the act method of TimeUpdater to be called 1 second from the start of the game. Adding this line will cause an error until the class below in line 31-42 is copied into the class.

Lines 31-42: an inner class in Wackadot used to update the timeLeft.

Lines 33-41: the method called when scheduled

Lines 37-40: if there is still time remaining, this schedules the act method to be called again in 1 second

Line ... : Don't type this line into your code.

Lines 135-141: allows game control and scoring only while there is time left

18. Make the Help File

Every game should have a help screen. For now it does not matter what you put in the help screen, just that you have one.

Alter the following method (new code is bold).

Line
Source code
Explanation of Source code
21
22
23
24
25
26
27
28
29
30
 
public void setup()
{
   score=0;
   timeLeft=10;
   makeSprites();
   addSprites();
   schedule(new TimeUpdater(), 1);
   setHelpText("Lots of help text here later");
}
Line 29: customizes the help to display "Lots of help text here later". You should change this later to provide more information.

19. Comment the Code

The game works. Congratulations! Comment the code you've written/copied. Documenting your code is essential if you are to share it or collaborate with others.

Line
Source code
Explanation of Source code
8
9
10
11
12
13
/**This is a fun, simple game I made using
 * the FANG Engine.
 * @author Your Name Here
 */
public class Wackadot extends Game
{

Lines 8-11: javadoc style comments. When you learn about how to use these, you can make web page documentation using the comments in your program.

20. Make it a Mod

Now that you have a working version, play with it. Make modifications and enhancements. Take a look at the examples page for some ideas. The game you have written is also an applet. You can also make a jar file of the project and put your code on this wiki or another web page. See instructions about posting your game on this wiki or another web page.

If you have any questions about making this sample game, be sure to take a look at the FAQ. Chances are someone else has had the same difficulty and the solution has been posted.

Good luck making your games with the FANG Engine!





Views
Personal tools
Add to 
del.icio.usAdd to 
diggAdd to 
FacebookAdd to 
favoritesAdd to 
GoogleAdd to 
MySpaceAdd to 
PrintAdd to 
SlashdotAdd to 
StumbleUponAdd to 
Twitter

Games
Games