GameGrid: Game programming with Java

Research project PHBern  
HomePrintJava-Online

Key Events

Many games use the keyboard to control its actors. The following examples show three different possibilities of key controlling:

The method kbhit() returns true, if a key was hit. To know which key was hit, the methods getKeyCode() or getKeyChar() can be used. After calling one of these methods, kbhit() returns false until a key is hit again. The disadvantage of the kbhit()-mechanism is, that it only reacts to the key hit and does not return any infomation about its release. By using a GGKeyListener this information can be retrieved. Using polls, keys are only checked when the polls are called. Therefore it is possible, that a key hit can be missed, if the polls are not called often enough.


Example 1: using kbhit() and getKeyCode()

The frog can be moved with the cursor keys UP, DOWN, LEFT and RIGHT. The goal of this game is to eat all the flies as fast as possible.

getKeyCode() returns the key's code which is "symbolicaly " predefinied in the class java.awt.Event.KeyEvent. The actions of the frog, after a key was hit, are controlled with a switch structure.

 

Run this example

Edit this example in the Online-Editor

 

// JGameEx17.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.awt.event.KeyEvent;

public class JGameEx17 extends GameGrid
{
  public JGameEx17()
  {
    super(10, 10, 60, Color.red, false);
    Frog frog = new Frog();
    addActor(frog, new Location(0, 0));
    for (int = 0; i < 10; i++)
      addActor(new Fly(), getRandomEmptyLocation());
    addKeyListener(frog);
    show();
    doRun();
  }

  public static void main(String[] args)
  {
    new JGameEx17();
  }
}

// ------------------ class Frog ---------------------------
class Frog extends Actor implements GGKeyListener
{
  public Frog()
  {
    super(true"sprites/frog1.gif");
  }

  public boolean keyPressed(KeyEvent evt)
  {
    switch (evt.getKeyCode())
    {
      case KeyEvent.VK_UP:
        setDirection(270);
        break;
      case KeyEvent.VK_RIGHT:
        setDirection(0);
        break;
      case KeyEvent.VK_LEFT:
        setDirection(180);
        break;
      case KeyEvent.VK_DOWN:
        setDirection(90);  
        break;
    }
     move();
     tryToEat();
    
    return true;
  }

  public boolean keyReleased(KeyEvent evt)
  {
    return true;
  }

  public void tryToEat()
  {
    Actor actor = gameGrid.getOneActorAt(getLocation(), Fly.class);
    if (actor != null)
       actor.hide();
  }
}

// --------------------- class Fly ---------------------------
class Fly extends Actor
{

  public Fly()
  {
    super("sprites/fly.gif");
  }
}

Explaining the program code:
doRun() calling this method in the constructor has the same effect as pressing the button Run in the game grid's navigation bar - it starts the simulation cycle
if (kbhit()) in each simulation cycle, the program checks if a key is hit
getKeyCode() returns the numeric code of the key
KeyEvent.VK_LEFT instead of using the symbolic key code definitions, it is also possible to use its direct code (e.g. LEFT is 39). Although, it is recommended to work with the predefined codes VK_LEFT, VK_UP, VK_DOWN and VK_RIGHT to make reading the code easier.
setDirection(270)
move()
after the key hit, the frog turns and moves to the next cell in the given direction. Since the frog has been declared as rotable (new Actor (true"sprites/frog1.gif")), the frog's Sprite rotates to the give direction as well
tryToEat() take a look at example JGameEx12.java
playSound(this, GGSound.DUMMY) the sound system is initialized. Leaving this line out of the code, the first time the sound is play with a small delay
playSound(this, GGSound.FROG) the wav-file FROG is played. this is a reference to the application class

 


Example 2: using GGKeyListeners
The frog eats flies and changes its form. After each eaten fly it gets fatter.

If a key hit is declared as an event, a GGKeyListener must be initialized to monitor the keyboard. GGKeyListener has two callbackmethodes: keyPressed() and keyReleased(). These must be include in the class BigFrog. In case true is returned, no other KeyListeners will be able to receive any notification (this is called event consuming). In this example, this fact does not matter, since we only have one KeyListener.

Run this example

Edit this example in the Online-Editor

 

// JGameEx18.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.awt.event.KeyEvent;

public class JGameEx18 extends GameGrid
{
  public JGameEx18()
  {
    super(10, 10, 60, Color.red, false);
    BigFrog frog = new BigFrog();
    addActor(frog, new Location(0, 0));
    for (int = 0; i < 6; i++)
      addActor(new Fly(), getRandomEmptyLocation());
    playSoundGGSound.DUMMY);
    addKeyListener(frog);
    show();
    doRun();
  }

  public static void main(String[] args)
  {
    new JGameEx18();
  }
}

// --------------------- class BigFrog --------------------------
class BigFrog extends Actor implements GGKeyListener
{
  private int nbEatedFlies = 0;

  public BigFrog()
  {
    super(true"sprites/frog.gif"7);
  }

  public boolean keyPressed(KeyEvent evt)
  {
    switch (evt.getKeyCode())
    {
      case KeyEvent.VK_UP:
        setDirection(270);
        move();
        tryToEat();
        break;
      case KeyEvent.VK_RIGHT:
        setDirection(0);
        move();
        tryToEat();
        break;
      case KeyEvent.VK_LEFT:
        setDirection(180);
        move();
        tryToEat();
        break;
      case KeyEvent.VK_DOWN:
        setDirection(90);
        move();
        tryToEat();
        break;
    }
    return true;
  }

  public boolean keyReleased(KeyEvent evt)
  {
    return true;
  }

  private void tryToEat()
  {
    Actor actor = gameGrid.getOneActorAt(getLocation(), Fly.class);
    if (actor != null)
    {
      actor.hide();
      nbEatedFlies++;
      show(nbEatedFlies);
      gameGrid.playSound(GGSound.FROG);
    }
  }
}

// --------------------- class Fly ---------------------------
class Fly extends Actor
{
  public Fly()
  {
    super("sprites/fly.gif");
  }
}

Explaining the program code:
addKeyListener(frog) the KeyListener of the class Frog is initialized
Actor frog = new Actor(true, "sprites/frog.gif", 7) in the declaration of the actor Frog, the number of Sprites can be defined. The Sprites' pictures must be saved as frog_0.gif, frog_1.gif, ..., frog_6.gif
nbEatedFlies++
frog.show(nbEatedFlies)

the amount of eaten flies is relevant for the fatness of the frog. It gives us the spriteId and with the method show() the designated picture is shown

 

Example 3: using GGKeyListener

The red ball can be guided through the labyrinth with the cursor keys DOWN, UP, LEFT and RIGHT. The ball can only move on the white cells.

 

 

Run this example

Edit this example in the Online-Editor

 

// JGameEx19.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.awt.event.KeyEvent;

public class JGameEx19 extends GameGrid
{
  private Ball ball;

  public JGameEx19()
  {
    super(15, 15, 40, Color.red, "sprites/mazeGrid.gif"false);
    ball = new Ball();
    addActor(ball, new Location(0, 1));
    addKeyListener(ball);
    show();
    doRun();
  }

  public static void main(String[] args)
  {
    new JGameEx19();
  }
}

// --------------------
class Ball extends Actor implements GGKeyListener
{
  public Ball()
  {
    super("sprites/ball.gif");
  }

  public boolean keyPressed(KeyEvent evt)
  {
    Location next = null;
    switch (evt.getKeyCode())
    {
      case KeyEvent.VK_UP:
        next = getLocation().getNeighbourLocation(Location.NORTH);
        setDirection(Location.NORTH);
        break;
      case KeyEvent.VK_RIGHT:
        next = getLocation().getNeighbourLocation(Location.EAST);
        setDirection(Location.EAST);
        break;
      case KeyEvent.VK_LEFT:
        next = getLocation().getNeighbourLocation(Location.WEST);
        setDirection(Location.WEST);
        break;
      case KeyEvent.VK_DOWN:
        next = getLocation().getNeighbourLocation(Location.SOUTH);
        setDirection(Location.SOUTH);
        break;
    }
    if (next != null && canMove(next))
      setLocation(next);
    return true;
  }

  public boolean keyReleased(KeyEvent evt)
  {
    return false;
  }

  private boolean canMove(Location location)
  {
    Color c = gameGrid.getBg().getColor(location);
    if (c.equals(Color.black))
      return false;
    else
      return true;
  }
}

Explaining the program code:
implements GGKeyListener implements the GGKeyListener
sprites/mazeGrid.gif in this example the labyrinth is a backgorund image. Looking at the labyrinth game inside the grid games, the "real" labyrinth game can be found. It sets the path of the maze randomly at the start
next = ball.getLocation().getNeighbourLocation(Location.NORTH)
ball.setDirection(Location.NORTH);
hitting the UP-key the neighbouring cell in the north is saved in next and the balls direction is set to north
Color c = getBackground().getColor(location) returns the background color of the current cell
if (c.equals(Color.black))
      return false
if the background color is black, canMove() returns false

 

Example 4: polls (continuously check if a key is hit)

The method isKeyPressed() is used. It returns true as soon as a certain key is hit. The different key codes are predefined in the class KeyEvent.

A fish moves back and forth. By using the curser keys UP and DOWN, the vertical position of the fish can be changed.

 

 

Run this example

Edit this example in the Online-Editor

 

// JGameEx20.java

import ch.aplu.jgamegrid.*;
import java.awt.Color;
import java.awt.event.KeyEvent;

public class JGameEx20 extends GameGrid
{
  public JGameEx20()
  {
    super(101060Color.red, "sprites/reef.gif");
    CoralFish nemo = new CoralFish();
    addActor(nemo, new Location(00));
    show();
  }

  public static void main(String[] args)
  {
    new JGameEx20();
  }
}

//--------------- class CoralFish ------------------------------
class CoralFish extends Actor
{
  public CoralFish()
  {
    super("sprites/nemo.gif");
  }

  public void act()
  {
    move();
    if (gameGrid.isKeyPressed(KeyEvent.VK_UP) && getY() > 0)
      setY(getY() - 1);
    if (gameGrid.isKeyPressed(KeyEvent.VK_DOWN) && getY() < 9)
      setY(getY() + 1);
    if (getX() == 0 || getX() == 9)
    {
      turn(180);
      setHorzMirror(isHorzMirror() ? false : true);
    }
  }
}

Explaining the program code:
isKeyPressed(KeyEvent.VK_UP returns true if the UP-key is pressed
isKeyPressed(KeyEvent.VK_DOWN returns true if the DOWN-key is pressed

If the default simulation periode is used, the method act() will only be called each 200 milliseconds. If the keys are hit really fast, it might be possible, that the program does not realize the hit. If the simulation periode is shortend, it is possible that the fish moves through several cells at once.