Java cooperation home
Tutorial
type and press Enter

A shooting spaceship

In this chapter I want to talk about the "problem" of how to make a starship (or any other game object) shoot. This behaviour is used in nearly every action game like MarsAttacks or my game J-Rio and even though it's really simple to implement it, I got many mails from people who didn't know how to start this (which is absolutly no shame;-). Well, let's start this chapter!

Outline of the classes and the important steps

As always I want to start this chapter by explaining the outline of the classes and the main steps and techniques I'm going to use. As Java is a object oriented programming language and a shot has many attributes and behaviours (movement, tests for collisions with enemies, walls..., ...) it should be clear that we will implement a class Shot to implement all this behaviour. This class will hold all the attribute variables (x and y position, speed...) of the shot and will have methods to represent behaviour like movement... . In most cases a shot is generated by a player object, so we will have a player object with a method called generateShot. This method will generate a shot (no wonder with this name ;-) at the position of the player, with the right direction... and will return this object to the calling class. In my example applet the calling class will be the class Main. This class stores the generated shot in a array of shot objects. Everytime the run - method of this main class is called, we will iterate over this array to move the shots, destroy them if they leave the game area and we can also test for collisions with enemies or level elements (which is not implemented in my example applet). The paint - method of the applet will also run through the shots array and will draw every existing shot in it.
If you understand everything so far, which means that you got the message, you don't have to read on but you can download the example source code and take a look at it on your own. The classes are really simple and nothing special. But of course you may read on, I'll show you the sourcecode and I'll also give some explanations to it.

The class Shot

As I already said, this class stores the coordinates of the shot, has a moveShot - method to implement moving behaviour in y - direction and a drawShot() - method, to paint the shot to the screen. Ok, here comes the code:

    import java.awt.Graphics;
    import java.awt.Color;

    public class Shot
    {
      // variables
      private int x_pos;
      private int y_pos;

      // size of the shot
      private final int radius = 3;

      // constructor
      public Shot(int x, int y)
      {
        x_pos = x;
        y_pos = y;
      }

      // returns y - position, needed for testing if shot has left the game area
      public int getYPos()
      {
        return y_pos;
      }

      // moving shot in y - direction
      public void moveShot(int speed)
      {
        y_pos += speed;
      }

      // draw the shot to the screen
      public void drawShot(Graphics g)
      {
        g.setColor(Color.yellow);
        g.fillOval(x_pos, y_pos, radius, radius);
      }
    }

The class Player

This class is simple, too. It also has a move - method (to move player in x - direction), a draw - method and stores the coordinates of the spaceship. The only "interesting" method is the generateShot - method.


    import java.awt.Graphics;
    import java.awt.Color;

    public class Player
    {
      // variables
      private int x_pos;
      private int y_pos;

      // constructor
      public Player(int x, int y)
      {
        x_pos = x;
        y_pos = y;
      }

      // move spaceship in x - direction
      public void moveX(int speed)
      {
        x_pos += speed;
      }

      // generate a shot at the current position of the spaceship
      // and return this shot to the calling method
      public Shot generateShot()
      {
        Shot shot = new Shot(x_pos, y_pos);

        return shot;
      }

      // draw the player
      public void drawPlayer(Graphics g)
      {
        g.setColor(Color.red);
        int [] x_poly = {x_pos, x_pos - 10, x_pos, x_pos + 10};
        int [] y_poly = {y_pos, y_pos + 15, y_pos + 10, y_pos + 15};
        g.fillPolygon(x_poly, y_poly, 4);
      }
    }

The class Main

And now we'll take a look at the class Main. I've deleted all for the shooting behaviour of the spaceship unimportant parts (marked with "..."). You can take y look at those parts if you download the sourcecode.

    import java.applet.*;
    import java.awt.*;

    public class Main extends Applet implements Runnable
    {
      // variables
      ...
      private Player player;
      private Shot [] shots;

      // constants
      private final int shotSpeed = -2;
      ...

      // double buffering
      private Image dbImage;
      private Graphics dbg;

      public void init()
      {
        ...
        // generate shot array
        shots = new Shot[5];
      }

      ...

      public void run ()
      {

        while (true)
        {
          // Iterate over the shot array and move shots,
          // test if a shot has left the game area.
          // You can add other tests here (test for collisions
          // of enemies and shots...
          for(int i=0; i<shots.length; i++)
          {
            if(shots[i] != null)
            {
              // move shot
              shots[i].moveShot(shotSpeed);

              // test if shot has left the game area
              // if true, delete from array
              if(shots[i].getYPos() < 0)
              {
                // delete shot
                shots[i] = null;
              }

              // other operations to be added
              // ...
              // for example collision testing...
              // ...
            }
          }

          // move player
          ...

          ...
        }
      }

      public boolean keyDown(Event e, int key)
      {
        ...

        // Spacebar is hit, generate new shot
        else if(key == 32)
        {
          // generate new shot and try to store it in shots array
          for(int i=0; i<shots.length; i++)
          {
          // only store shot if there is a place left in the array
            if(shots[i] == null)
            {
              shots[i] = player.generateShot();
              // call break to store shot only once, important!
              break;
            }
          }
        }

        ...
      }

      public void paint (Graphics g)
      {
        // draw player
        ...

        // draw shots
        for(int i=0; i<shots.length; i++)
        {
          if(shots[i] != null)
          {
            shots[i].drawShot(g);
          }
        }
      }
    }

Conclusion

I hope I could convince you that it is really simple to generate shots. The technique to store game objects of the same kind in a array and iterate over this array everytime the run and paint - methods are called is used very often when programming games and other applications, so don't forget about it if you are in a similar situation. I hope that I could help you a little bit with this chapter and as always you can download the sourcecode and take a look at the example applet.

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

Next chapter

Platform game basics
Fabian Birzele, 2001-2004.
web-design: Vadim Murzagalin, 2004.