Chapter 8. Keyboard and Mouse Input

The keyboard and mouse are the only realistic devices for user input in a Java game, regardless of whether it’s a web-based applet or a standalone application. But even when considering a standard Windows-based game developed in DirectX or another library, the keyboard and mouse are by far the most common forms of user interaction in a game. This chapter covers the important subject of handling user input.

Here are the key topics you will learn in this chapter:

  • Listening for keyboard events

  • Testing keyboard input

  • Displaying key presses

  • Reading mouse motion

  • Detecting mouse buttons

  • Testing mouse input

Listening to the User

Java provides an interesting way to interact with users through a series of listener methods. You tell Java that you would like to listen to keyboard input events, and then Java sends keyboard events to your own listener methods, at which point you can check the key codes to figure out which keys have been pressed or released. The way Java tells your program that a key has been pressed (or that the mouse has moved) is through an interface that your program uses—or rather, implements. Your program must use the implements keyword to use an interface class. This is a type of class that just includes methods your program needs to use (or implement); the class doesn’t really have any functionality on its own. This type of class is called an interface because it represents a blueprint of the methods your program must use.

Keyboard Input

The KeyListener interface listens for events generated by the keyboard and sends those events to the callback methods implemented in your program. These methods are called keyPressed, keyReleased, and keyTyped, and these three methods all have a single parameter called KeyEvent. When writing a program to use the KeyListener, you modify the class definition of your program using the implements keyword:

public class KeyboardTest extends JFrame implements KeyListener

Tip

The interesting thing about the implements feature of Java classes is that you can implement multiple interfaces in your program by separating the interface class names with commas.

You may recall seeing the implements keyword used before with the Runnable interface (which added threading support). When you need to add more than one interface class, you can separate them with commas.

Listening for Keyboard Events

Your program needs to then call the addKeyListener method to initialize the keyboard listener so that key events will be sent to your program by the Java Runtime Environment. The sole parameter of this method is the instance of your program’s class, represented by the keyword this. You use this as a way to identify the current class in a block of code without referring to that class specifically by name. It is usually best to call addKeyListener(this) in the init method within your program. (Recall that the constructor method is automatically called when your program starts running.)

Next, you must implement the three keyboard events in your program to satisfy the KeyListener interface:

public void keyPressed(KeyEvent e)
public void keyReleased(KeyEvent e)
public void keyTyped(KeyEvent e)

There are two ways to determine the key that has been pressed or released using the KeyEvent parameter. If you want to determine the character code of a key, you can use the getKeyChar method, which returns a char. If you want to know whether a key has been pressed based on the key code instead of the character, you can use the getKeyCode method instead. If your program is listening to the keyboard and you press the A key, then getKeyChar will return “a” (or “A” if you are holding down Shift), while getKeyCode will return a virtual key code called VK_A. All of the virtual key codes are contained in a class called KeyEvent. Table 8.1 shows a partial list of virtual key codes for the most commonly used keys for a game.

Table 8.1. Virtual Key Codes (Partial List)

Key Code

Description

VK_LEFT

Left arrow

VK_RIGHT

Right arrow

VKJJP

Up arrow

VK_DOWN

Down arrow

VK_0...VK_9

Numeric keys

VK_A...VK_Z

Alphabetic keys

VK-F1...VK_F12

Function keys

VK-KP-LEFT

Numeric keypad left

VK-KP-RIGHT

Numeric keypad right

VK-KP-UP

Numeric keypad up

VK-KP-DOWN

Numeric keypad down

VK-ENTER

Enter key

VK-BACK-SPACE

Backspace key

VK-TAB

Tab key

Note

When you want to get the keys being typed for use in a chat message, for instance, then you will want to use the keyTyped event, which returns ASCII characters. Most of your game’s input will come from the keyPressed event, which provides key codes.

Testing Keyboard Input

Let’s write a program to test keyboard input so you will have a complete example of how this works with Java code. I have highlighted the important code in bold. You can see the output of this program in Figure 8.1.

Output from the KeyboardTest program.

Figure 8.1. Output from the KeyboardTest program.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class KeyboardTest extends JFrame implements KeyListener {
    int keyCode;
    char keyChar;

    public static void main(String[] args) {
        new KeyboardTest();
    }
    public KeyboardTest() {
        super("Keyboard Test");
        setSize(500,400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addKeyListener(this);
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.WHITE);
        g2d.fill(new Rectangle(0,0,500,400));
        g2d.setColor(Color.BLACK);
        g2d.drawString("Press a key. . .", 20, 40);
        g2d.drawString("Key code: " + keyCode, 20, 60);
        g2d.drawString("Key char: " + keyChar, 20, 80);
    }

     public void keyPressed(KeyEvent e) {
        keyCode = e.getKeyCode();
        keyChar = ' ';
        repaint();
    }

    public void keyReleased(KeyEvent e) { }

    public void keyTyped(KeyEvent e) {
        keyChar = e.getKeyChar();
        repaint();
    }
}

This is the bare-minimum code you need to provide keyboard support to your Java programs, so you might want to jot down this page number for future reference (or save the code in a file that you can easily find).

Tip

A virtual key code is a platform-neutral value for a key. When you write code to work with a certain virtual key code (such as VK_LEFT), you can be certain that the key will be detected on any platform (Windows, Linux, Mac, Solaris, and so on).

Tip

The constructor method is a special method in a JFrame application. The constructor is the first method that runs when an application starts up. There are several other events generated by JFrame, such as paint(), that I will explain as we go along. The paint() event, for instance, refreshes the graphics in the window, so this is often where programmers will write much of the code for a game.

Mouse Input

Tapping into the mouse handler in Java is similar to the process of programming the keyboard, as you might have suspected. Java handles mouse input using events that are generated by the Java Runtime Environment (JRE) and passed to your program when you implement a mouse listener.

Tip

The Java Runtime Environment, or JRE, is a subset of the Java Development Kit (JDK) that is designed to allow you to have access to an essential set of classes that you can use to run Java programs. The JRE is also most commonly installed on end-user PCs when they want to run a Java program (including web applets). Both the JDK and JRE are included in the Java SE 6 download package.

The first step you must take to incorporate mouse event handling in your program is to call two functions that will tell the JRE to begin sending your program mouse events. Since we’ll be dealing with two interfaces for the mouse, you must initialize both mouse handlers. This is similar to the function you learned about for initializing the keyboard handler. You put these functions in the constructor method so that they are sure to be called when the program starts up. You’ll recall from the keyboard section earlier in this chapter that the this keyword represents the current program; in more technical terms, this represents the primary object that was created based on the class definition in your program.

Tip

An object is not a class; it is the result of a class. Think of a class as a blueprint for a product, and an object as the product itself that has been constructed.

addMouseListener(this);
addMouseMotionListener(this);

Reading Mouse Motion

Java provides an interface class for mouse motion and button press events that is similar to the keyboard interface. The MouseListener class is an abstract class that provides your program with an interface, or blueprint, with five methods that you must implement in your program (regardless of whether you will use all of them):

  • public void mouseClicked(MouseEvent e)

  • public void mouseEntered(MouseEvent e)

  • public void mouseExited(MouseEvent e)

  • public void mousePressed(MouseEvent e)

  • public void mouseReleased(MouseEvent e)

The MouseListener interface keeps track of the mouse buttons, the mouse position in the window, and the mouse location when the mouse cursor moves into and out of the window.

There is another, completely different interface class for mouse movement. You can read the mouse’s position during a button or enter/leave event with a MouseListener, but receiving events for actual mouse motion on the window requires another interface. To receive events for the mouse’s movement across the window, you must use the MouseMotionListener interface. There are two events in this interface:

  • public void mouseDragged(MouseEvent e)

  • public void mouseMoved(MouseEvent e)

Detecting Mouse Buttons

Some of these events report when a mouse button is clicked, pressed, or released. The only methods that do not deal with the mouse buttons are mouseEntered, mouseExited, and mouseMoved, all of which deal with the mouse’s position and motion, regardless of button status. The remaining events (mouseClicked, mousePressed, mouseReleased, and mouseDragged) all have to do with the buttons.

As you might have noticed, all of these events have a single parameter called MouseEvent. This parameter is actually a class, and the JRE fills it with information for each mouse event. You can look inside this class to get the mouse’s position and button values. For the mouse’s X and Y position values, you can use MouseEvent.getX() and MouseEvent.getY(). The parameter is usually defined as (MouseEvent e), so in actual practice you would use e.getX() and e.getY() to read the mouse’s current position.

Likewise, MouseEvent tells you which button was pressed. Inside MouseEvent is a method called getButton() that will equal one of the following values depending on which button is being pressed:

  • BUTTON1

  • BUTTON2

  • BUTTON3

The getButton() method is useful if you only care about detecting a single button press. If, for whatever reason, you need to know when two or three mouse buttons are being pressed at the same time, you can use a different method in the MouseEvent class called getModifiers(). This function will report multiple events in the MouseEvent class, such as the following:

  • BUTTONI_MASK

  • BUTTON2_MASK

  • BUTTON3_MASK

There are many more masked values (that is, values that are bit-packed into a single variable) in the MouseEvent class that you can examine using the getModifiers() method. But if all you care about are the usual left-click and right-click events, you can make use of getButton().

Testing Mouse Input

I would like to show you a program called MouseTest that demonstrates all of the mouse events that you have just learned about. To build this program, you should create a new project called MouseTest, and then remove all of the automatically generated code to be replaced with the following code listing instead. This program uses the Graphics2D.drawString method and a bunch of variables to display the status of all the mouse events individually. Figure 8.2 shows what the program output looks like. Note the important parts of the code listing in bold.

Output from the MouseTest program.

Figure 8.2. Output from the MouseTest program.

The first part of the program includes the class definition (with the needed interfaces following the implements keyword) and variable declarations.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MouseTest extends JFrame
     implements MouseListener, MouseMotionListener {

    //declare some mouse event variables
    int clickx, clicky;
    int pressx, pressy;
    int releasex, releasey;
    int enterx, entery;
    int exitx, exity;
    int dragx, dragy;
    int movex, movey;
    int mousebutton;
    public static void main(String[] args) {
        new MouseTest();
    }

The constructor is the first method that gets run in an application, and in this case, it’s called public MouseTest(). So this is where you would initialize your game objects and variables, and this is also where you add the listeners for any input devices the program needs to use. If your program ever seems to be ignoring the keyboard or mouse, check this method to make sure you have added the appropriate listener.

   public MouseTest() {
       super("Mouse Test");
       setSize(500,400);
       setVisible(true);
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       addMouseListener(this);
       addMouseMotionListener(this);
   }

The paint() event method is called whenever the window needs to be refreshed. Since paint() comes with a parameter (Graphics g), we can use this object to draw onto the screen. In this program, I’ve used the Graphics.drawString() method to display text on the window. This code is messy in print due to the line wrapping, but it looks nice in the source code file included with this chapter’s resource files (www.courseptr.com/downloads).

   //redraw the window
   public void paint(Graphics g) {
       Graphics2D g2d = (Graphics2D)g;
       g2d.setColor(Color.WHITE);
       g2d.fill(new Rectangle(0,0,500,400));
       g2d.setColor(Color.BLACK);
       g2d.drawString("Mouse clicked " + mousebutton + " at " + clickx +
           "," + clicky, 10, 40);
       g2d.drawString("Mouse entered at " + enterx + "," + entery,10,55);
       g2d.drawString("Mouse exited at " + exitx + "," + exity, 10, 70);
       g2d.drawString("Mouse pressed " + mousebutton + " at " + pressx +
           "," + pressy, 10, 85);
       g2d.drawString("Mouse released " + mousebutton + " at " +
           releasex + "," + releasey, 10, 100);
       g2d.drawString("Mouse dragged at " + dragx + "," + dragy, 10, 115);
       g2d.drawString("Mouse moved at " + movex + "," + movey, 10, 130);
   }   

The next portion of code includes the checkButton() method, which I have written to support the mouse event handler in the program. This checkButton() method checks the current button that is being pressed and sets a variable (mousebutton) to a value representing the pressed button.

   //custom method called by mouse events to report button status
   private void checkButton(MouseEvent e) {
           //check the mouse buttons
           switch(e.getButton()) {
           case MouseEvent.BUTTON1:
               mousebutton = 1;
               break;
           case MouseEvent.BUTTON2:
               mousebutton = 2;
               break;
           case MouseEvent.BUTTON3:
               mousebutton = 3;
               break;
           default:
               mousebutton = 0;
           }
   }

The mouseClicked() event is part of the MouseListener interface. When you implement this interface, you must include all of the mouse events defined in the interface, or the compiler will generate some errors about the missing events. This event is called whenever you click the mouse button on the window—in which case both a press and release has occurred. This event is not usually needed when you program mousePressed() and mouseReleased() yourself.

public void mouseClicked(MouseEvent e) {
    //save the mouse position values
    clickx = e.getX();
    clicky = e.getY();

    //get an update on buttons
    checkButton(e);
    //refresh the screen (call the paint event)
 repaint();
}

The next two mouse event methods, mouseEntered() and mouseExited(), are called whenever the mouse cursor enters or leaves the window. These events are not often needed in a game.

        public void mouseEntered(MouseEvent e) {
        enterx = e.getX();
        entery = e.getY();
        repaint();
}
        public void mouseExited(MouseEvent e) {
        exitx = e.getX();
        exity = e.getY();
        repaint();
}

The mousePressed() and mouseReleased() event methods are called whenever you click and release the mouse button, respectively. When these events occur, you can get the current position of the mouse as well as the button being pressed or released.

   public void mousePressed(MouseEvent e) {
   pressx = e.getX();
   pressy = e.getY();
   checkButton(e);
   repaint();
   }
   public void mouseReleased(MouseEvent e) {
       releasex = e.getX();
       releasey = e.getY();
       checkButton(e);
       repaint();
   }

The MouseMotionListener interface defines the next two events—mouseDragged() and mouseMoved(). These events are helpful when you just want to know when the mouse is moving over the window (and when it is moving while the button is being held down).

    public void mouseDragged(MouseEvent e) {
     dragx = e.getX();
     dragy = e.getY();
     repaint();
    }
    public void mouseMoved(MouseEvent e) {
     movex = e.getX();
     movey = e.getY();
     repaint();
    }
}   

What You Have Learned

This chapter explained how to tap into the keyboard and mouse listeners in order to add user input to your Java programs.

  • You learned how to detect key presses.

  • You learned about key codes and character values.

  • You learned how to read the mouse’s motion and buttons.

Review Questions

The following questions will help you to determine how well you have learned the subjects discussed in this chapter. The answers are provided in Appendix A, “Chapter Quiz Answers.”

1.

What is the name of the method used to enable keyboard events in your program?

2.

What is the name of the keyboard event interface?

3.

What is the virtual key code for the Enter key?

4.

Which keyboard event will tell you the code of a pressed key?

5.

Which keyboard event will tell you when a key has been released?

6.

Which keyboard event will tell you the character of a pressed key?

7.

Which KeyEvent method returns a key code value?

8.

What is the name of the method used to enable mouse motion events?

9.

What is the name of the class used as a parameter for all mouse event methods?

10.

Which mouse event reports the actual movement of the mouse?

On Your Own

Use the following exercises to test your grasp of the material covered in this chapter. Are you ready to put mouse and keyboard input to the test in a real game yet? These exercises will challenge your understanding of this chapter.

Exercise 1

Modify the KeyboardTest program so that pressing numeric keys 1 to 9 will change the font size used to display the key code and character values. To do this, use the Graphics class in the paint event, which has a method called setFont that you can implement like this:

g.setFont(new Font("Ariel", Font.NORMAL, value));

I will give you a hint: The key code for “1” is 49, so you can subtract 40 from the key code to arrive at a good font size.

Exercise 2

Modify the MouseTest program so that a point is drawn whenever the user presses a mouse button. You can use the Graphics class’ fillRect method and the mouse position variables. (Just draw a rectangle with four corners that are one pixel apart.) If you are feeling confident with your new Java programming skills, try using the setColor method to change the color of the points.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.167.87