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()
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.
|
![]() |
// 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 i = 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"); } } |
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
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.
|
|
// 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 i = 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"); } } |
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
|
![]() |
// 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; } } |
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.
|
![]() |
// JGameEx20.java import ch.aplu.jgamegrid.*; import java.awt.Color; import java.awt.event.KeyEvent; public class JGameEx20 extends GameGrid { public JGameEx20() { super(10, 10, 60, Color.red, "sprites/reef.gif"); CoralFish nemo = new CoralFish(); addActor(nemo, new Location(0, 0)); 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); } } } |
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.