Java cooperation home
Tutorial
type and press Enter

Our first game

The game idea

In our game, the player has to shot at two balls (a red and a blue one) which are flying around in our applet. The direction and speed will be chosen at random, the user can hit a ball by clicking on it with the mouse pointer. If a ball reaches a border of the applet, without being hit, the player looses one of 10 lifes. If the player lost all of his lifes, the game is over.

Outline of classes and methods

The Main class

This class implements all methods concerning the animation of objects (balls) and "management" of the game. These are init(), start(), stop(), paint(), update(), run() and mouseDown() to handle mouse click events. The class also manages all objects (two ball objects, the player object) and the thread in which the game is running!

  1. init(): Initializes all objects, gets audio data, sets mouse pointer and gets the game speed from a parameter in the HTML - file.
  2. start(): starts thread
  3. stop(): stops thread
  4. run(): moves the balls
  5. paint(...): calls paint methods of the both balls, paints score and lifes information to the screen. If game is over it writes out a information text, how good the player has been playing (for example: "You are the champingon")
  6. update(...): Implements double buffering
  7. mouseDown (...): Listens to mouse events. If game is running it is watching out for "player hits ball" if game is stopped (start or over) then it listens for a double click and starts game (again).
The class Player

This class is very simple. It has two instance variables to store score and lifes of the player. There are also two methods to add score (addScore(int plus)), loose lifes (looseLife) and two methods to transmit these values to the Main class (getScore(), getLifes()). As you see, a pretty simple class.

The class Ball

This class is the most complicated one in the game. It implements all important methods for a ball object including the following functions:

  1. Ball(...): Constructor, gets all important attributes of a ball object (color, speed, y - direction, ...) and initializes variables in the ball object.
  2. move(): Method moves the ball and tests by calling isOut() if ball is out which means, player looses one life.
  3. ballWasHit(): This method is called if ball was hit by the player. Afterwards new direction of the ball is set at random, and ball is set back to start position.
  4. userHit (int x, int y): This method tests with help of vectors, if ball was hit or not (details later).
  5. isOut(): Method tests if ball is out. Player looses one life if this is true.
  6. DrawBall(Graphics g): This method draws the ball and is called from the paint method of the Main - class.
How the methods work together:

Everytime we call the run - method in our Main class, we call the move - methods of the ball. This method moves the ball and tests if the ball left the applet area by calling isOut(). If the ball has left the applet area, isOut() calles the looseLife() method of the player object and the number of lifes is decreased by one.
Everytime the user clicks in the applet area, the mouseDown method in the Main class is called. This method calls userHit(), which is testing if the ball was hit by the user and returns true if this is the case and returns false if the ball was not hit. If true is returned by userHit() ballWasHit() is called. This method adds the score to the player score, resets the ball... .

One important thing before we start

It is essential, if you want to understand what I'm doing, that you download the sourcecode and read in it while I'm explaning things. I won't explain every step in detail, instead you should read the sourcecode, try to understand these things I'm not talking about with help of the other chapters, and learn things by yourself that way.
Even more important might be that you begin to write your own little programs very soon and try to solve problems on your own. Because every game needs its own, very special solutions and mostly there will be noone to help you to find these. Use this little game and all the other applets and sourcecodes on these pages as blueprints and "dictionarys" which help you to implement your own games. You'll learn most if you try it by yourself!

Randomize the movement direction of the two balls

As I said in the second chapter, we will move our ball in this game not only in the x - direction but in the y - direction, too. To do this we have to add a y_speed vector to the applet as well as the x_speed vector you already know. Our ball will have a x_pos variable which will be changed with every call of move() by adding the value of x_speed to it (remenber: x_speed can be negative) and our ball will also have a y_pos variable which will be changed by adding y_speed. In our game the value of y_speed shall be not changing. The first ball will be moving up (y_speed = -1) and the other ball will be movind down (y_speed = 1). Be careful, in Jave the y - coordinates get bigger when moving down!! The value of x_speed will be chosen at random everytime a ball left the applet.

Random number generator

First of all we need a random generator in Java. We have to import the class java.util.*; into the class Ball and declare the following instance variable afterwards:

    Random rnd = new Random ();

Now we can generate a random integer number by calling rnd.nextInt() . Because we want to have values between -3 and +3 in our game, we have to calculate this random number mod 4 afterwards.
Now we can randomize the movement direction of the ball. We have to set the value of x_speed to a new random value, everytime the ball was hit or the ball left the applet area.

The move() - method of the ball object

First of all we have to declare four instance variables (x_speed, y_speed, x_pos, y_pos) and initialize them in the constructor of our ball object. Everytime move() is called we add the value of x_speed to the x_pos variable and the value of y_speed to the y_pos variable. Everytime the ball is hit or has left the applet, we initialize x_speed with a random generated value, y_speed will be constant. Here comes the code:

    public void move()
    {
      // Add values of y and x_speed to x and y position
      pos_x += x_speed;
      pos_y += y_speed;

      /* Call isOut() and test if ball is still within the applet area */
      isOut();
    }
The method isOut()

This method tests if a ball has left the applet. If one of the four if - statements is true, the position of the ball will be reset, a audio file will be played, the player looses one life and x_speed will get a new value (per random).
The tests of this method are quite the same as in chapter 2c, but there are four borders we have to test, not only two. But it stays the same technique and you should try to understand this method by yourself, with help of chapter 2c this should be no problem for you.

How to hit a ball

This game was the first one I've ever programmed and this problem of how to hit a ball by clicking on it caused me a lot of headache. Now I will try to explain my solution to you: Our ball has a x and a y position. The mouseDown - method in the main class, which calls userHit (int x_mouse, int y_mouse) gives the coordinates, where the user clicked on the applet, to the method userHit(). Now, our method has to decide if a ball has been hit or not. But how can we do this?

It is not enough to test if the x and y position of the ball is exactly the same as the position where the player clicked on the applet! This would mean that the player has to hit exactly in the middle of our ball, something that is almost imposible when the ball is moving!

Ok, second idea: We accept all mouseDown coordinates as a hit that are in a certain range around the exact position of our ball. Of course the x and the y position have to be in this range at the same time (&& - test). That way we would test if the player hit into a rectangle around the ball (for example if the ball has the radius 10, this rectangle should be 20 pixles each side). This was the first idea I tried to implement but it didn't work out that well as I thought it would. The whole thing worked sometimes and sometimes not, even if I hit the ball exactly! I don't even have the slightest idea why it didn't work .

Well, alright, third idea: I think, everyone has heard of vectors. In our game we have two vectors: one is the x and y position of the ball and the other one is the x and y position of the mouse click. If we calculate the length of the connection vector of these two vectors and if the length of this connection vector is smaller than the radius of the ball, the player has hit the ball.
First of all we have to calculate the connection vector:

    // Calculate connection vector
    double x = maus_x - pos_x;
    double y = maus_y - pos_y;

Now we use Pythagoras (c = Math.sqrt a? + b?) to get the length of this vector, which is the distance between the mouse click and the position of the ball:

    // Calculate distance
    double distance = Math.sqrt ((x*x) + (y*y));

In the last step of the method we are testing, if the distance, we calculated in the step before is smaller than a certain value (for example the radius of the ball). I have choosen 15 as a good value although our ball has only the radius 10. But that has no special reason, it just seemed to fit best!

    // If distance is smaller than 15, player has hit the ball
    if (distance < 15)
    {
      player.addScore (10* Math.abs(x_speed) + 10);
      return true;
    }
    else return false;

Now we are able to hit the ball by clicking on it with the mouse pointer.

The player- object: Count score and loose lifes

To count the score and loose lifes, we added the methods looseLife() and addScore (int plus) to our player class. Everytime a ball leaves the applet, isOut() calles player.looseLife(), that way the player looses one life. If the player hits a ball, the method userHit() calls player.addScore (10* Math.abs(x_speed) + 10) and adds the score to the score in the player object (the faster the ball has been, the more points the player gets). The methods addScore and looseLife are really simple.
But there is one important point: The player object is initialized in the Main class! This means that the refference to the player object has to be initialized in the ball object too, to make it possible, that the ball object calls methods of the player object!!
This is a very important technique because it happens quite often that more than one class needs a refference to a special object. But it means, one has to initialize the object in one class (I'm using the Main class to manage all game objects) and has to give the reference to this object, which is needed in more classes, to the other classes!

Change the mouse pointer to a crosshair cursor

In this game it would look much better to have a crosshair mouse pointer than a normal mouse pointer. To get such a cursor, we have to add three lines of code to the Main class of our applet: First of all a instance variable of the class cursor:

    // Crosshair cursor
    Cursor c;

Now we add the following lines to the init() method:

    // generate a Crosshair cursor
    c = new Cursor (Cursor.CROSSHAIR_CURSOR);
    // set this cursor as the standard cursor of the applet
    this.setCursor (c);

You can find other mouse pointers in the Java API

Start the game with a double click on it
and finish it if player lost all his lifes:

Now we have almost done it, there is just one thing left to do: We want to start the game when the player clicked two times on the applet (double click) and not earlier. The advantage of this is not only that the player can decide when to start the game but in games where we need the keyboard, we can get the keyboard focus for this applet very easy this way. And of course the game shall be finished if the player lost all of his lifes!

As a first step we add a boolean instance variable called isStoped to our Main class. If the value of isStoped is true, our game is not running, if the value is false, the game is running! Now we add a test to the run - method of the main class, which tests if the game is running (isStoped = false) and if the player has more than 0 lifes. If these two things are alright, the two balls are moved.

    // run - method
    while (true)
    {
      if (player.getLives() >= 0 && !isStoped)
      {
        redball.move();
        blueball.move();
      }

      ...
    }

In the next step we'll add a second test to the paint() - method of the applet. As long as the player has lifes left, this method paints the two balls, the score and the lifes of the player. If the game is stoped it paints also the information on the screen, that the game can be started with a double click. If the player lost all of his lifes, the paint method writes out the final score and the information, that the game can be restarted by double clicking on the applet. The paint method looks like this:

    // paint() - method
    public void paint (Graphics g)
    {
      // player has lifes left
      if (player.getLives() >= 0)
      {
        // Paint the two balls, score ...

        ...

        // If game is stopped
        if (isStoped)
        {
          // paint information: "Start game with a double click"
        }
      }
      // Player has no lifes left
      else if (player.getLiver() < 0)
      {
        // paint final score, set isStopped true...
        // for details see sourcecode!
      }
    }

We have almost made it, but...! At the moment we can't switch between the two game states (game stopped, game running) because we have no way to control the value of isStoped. To get this control, we have to add the following code to the mouseDown - method:

    // listen to mouse clicks
    public void mouseDown (Event e, int x, int y)
    {
      // handle mouse events when game is running
      if (!isStoped)
      {
        // Test if red ball has been hit
        if (redball.userHit (x, y))
        {
          // play audio file
          hitnoise.play();

          // reset ball
          redball.ballWasHit ();
        }
        // Test if blue ball has been hit
        if (blueball.userHit (x, y))
        {
          // play audio file
          hitnoise.play();

          // reset ball
          blueball.ballWasHit ();
        }
        else
        {
          // play normal shot audio file
          shotnoise.play();
        }
      }
      // handle mouse events if game is stopped
      else if (isStoped && e.clickCount == 2)
      {
        // reset all important values!
        isStoped = false;
        init ();
      }

      return true;
    }

That's it!!

Well, you've made it. I hope you understood everything and also these parts, I didn't explain in detail. The next chapters will tell you something about very special solutions to problems I once had.
Now feel free to program any game you want to program, use the power of Java, which makes almost everything possible, good luck in developing your own games and I hope, that I could help you a little bit with this tutorial! If you have problems, tutorials, games ... please send me a mail!
Now you can take a look at the game, download the sourcecode and have fun!

SourceCode download (*.zip - file)
Take a look at the applet

Next chapter

AI in a Pong game
Fabian Birzele, 2001-2004.
web-design: Vadim Murzagalin, 2004.