Interactivity and User Interfaces

KEY TOPICS

If you've ever played a chess game by yourself in which the chess pieces were glued to the board, you know what it's like to play a game without any interactivity. It's boring. Interactivity is essentially taking input from the user and changing what's displayed on the screen based on that input. Without interactivity, there would be no games-or, at least, the games would be really boring. In this chapter, you'll learn how to receive input-namely, keyboard and mouse events-from the user. You'll also integrate this input into your games and learn about how to implement user interfaces with Swing. As of Java SDK 1.4, there is no way to receive input from a joystick. Although this is a shortcoming, it won't affect too many people because most people don't have joysticks for their computers. Also, many prefer to use the mouse or keyboard anyway. Before we get started, let's note what code we will use. For the remainder of the tutorial, we'll be organizing the reusable code into subpackages of com.brackeen.javagamebook. This will keep the code organized and easier to find. The ScreenManager, Animation, and Sprite classes created in , "2D Graphics and Animation," are in the com.brackeen.javagamebook.graphics package. Reusable code created in this chapter belongs to the com.brackeen.javagamebook.input package. Also, any code that's just a quick test will be in the default, unnamed package. Finally, we'll need a simple class to make the quick test programs easier to implement. The GameCore class in does just that, implementing some of the common techniques from the previous chapter, such as setting the display mode and running an animation loop. All we have to do is extend this abstract class and implement the draw() and update() methods.

Listing 3.1 GameCore.java

package com.brackeen.javagamebook.test;
import java.awt.*;
import javax.swing.ImageIcon;
import com.brackeen.javagamebook.graphics.ScreenManager;
/**
 Simple abstract class used for testing. Subclasses should
 implement the draw() method.
*/
public abstract class GameCore {
 protected static final int FONT_SIZE = 24;
 private static final DisplayMode POSSIBLE_MODES[] = {
 new DisplayMode(800, 600, 32, 0),
 new DisplayMode(800, 600, 24, 0),
 new DisplayMode(800, 600, 16, 0),
 new DisplayMode(640, 480, 32, 0),
 new DisplayMode(640, 480, 24, 0),
 new DisplayMode(640, 480, 16, 0)
 };
 private boolean isRunning;
 protected ScreenManager screen;
 /**
 Signals the game loop that it's time to quit
 */
 public void stop() {
 isRunning = false;
 }
 /**
 Calls init() and gameLoop()
 */
 public void run() {
 try {
 init();
 gameLoop();
 }
 finally {
 screen.restoreScreen();
 }
 }
 /**
 Sets full screen mode and initiates and objects.
 */
 public void init() {
 screen = new ScreenManager();
 DisplayMode displayMode =
 screen.findFirstCompatibleMode(POSSIBLE_MODES);
 screen.setFullScreen(displayMode);
 Window window = screen.getFullScreenWindow();
 window.setFont(new Font("Dialog", Font.PLAIN, FONT_SIZE));
 window.setBackground(Color.blue);
 window.setForeground(Color.white);
 isRunning = true;
 }
 public Image loadImage(String fileName) {
 return new ImageIcon(fileName).getImage();
 }
 /**
 Runs through the game loop until stop() is called.
 */
 public void gameLoop() {
 long startTime = System.currentTimeMillis();
 long currTime = startTime;
 while (isRunning) {
 long elapsedTime =
 System.currentTimeMillis() - currTime;
 currTime += elapsedTime;
 // update
 update(elapsedTime);
 // draw the screen
 Graphics2D g = screen.getGraphics();
 draw(g);
 g.dispose();
 screen.update();
 // take a nap
 try {
 Thread.sleep(20);
 }
 catch (InterruptedException ex) { }
 }
 }
 /**
 Updates the state of the game/animation based on the
 amount of elapsed time that has passed.
 */
 public void update(long elapsedTime) {
 // do nothing
 }
 /**
 Draws to the screen. Subclasses must override this
 method.
 */
 public abstract void draw(Graphics2D g);
}

By default, the update() method doesn't do anything, but in subclasses, you'll use it for updating sprites and such. Also, you'll probably extend the init() method to do things such as load images or initialize any variables. One last thing to note is that, from now on, the code can be compiled with Apache Ant. In the source code for this tutorial, the source lives in the src folder and Ant compiles the classes in a build folder. If you are unfamiliar with Ant, skip on back to the Introduction or check out . Don't worry, I'll still be here when you get back. Okay, now let's move on to what you're here for: interactivity.