06 Feb 2012 [ 201 week5 ]

We'll start to cover how to define your own classes in Java, and go into more detail on some parts of Java's GUI libraries.

Robots

One example we'll cover is a basic version of the game Robots. See the course materials for a project to start from.

Here's a start for the code for the main board; we'll fill this in later on, and reorganize when we have better designs for all the data types involved.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/** Class to represent and draw Robots game board
 *  
 */
public class Board extends JPanel implements KeyListener {

    static final int ROWS = 40;
    static final int COLS = 40;
    
    static final int ROBOTS = 60;
    
    // Human player object
    Player human;
    ArrayList<Player> robots;
    
    // Constructor
    public Board() {
        reset();
    }
    
    // Reset game to initial state
    public void reset() {
        Random rand = new Random();
        human = new Player(rand.nextInt(COLS), 
                rand.nextInt(ROWS));
        robots = new ArrayList<Player>();
        for (int i = 0; i < ROBOTS; i++) {
            Player r = new Player(rand.nextInt(COLS), 
                rand.nextInt(ROWS));
            robots.add(r);
        }
        repaint();
    }

    // Handle arrow key presses
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        
        // Handle game resets
        if (key == KeyEvent.VK_R) {
            System.out.println("reset");
            reset();
            return;
        }
        
        // Don't update if human died.
        if (!human.alive())
            return;
        
        // Allow movement in 8 directions
        if (key == KeyEvent.VK_Z) {
            human.left();
            human.down();
        } else if (key == KeyEvent.VK_X) {
            human.down();
        } else if (key == KeyEvent.VK_C) {
            human.right();
            human.down();
        } else if (key == KeyEvent.VK_A) {
            human.left();
        } else if (key == KeyEvent.VK_D) {
            human.right();
        } else if (key == KeyEvent.VK_Q) {
            human.left();
            human.up();
        } else if (key == KeyEvent.VK_W) {
            human.up();
        } else if (key == KeyEvent.VK_E) {
            human.right();
            human.up();
        } else if (key == KeyEvent.VK_SPACE) {
            human.teleport();
        } else {
            // Don't do any updates if key not recognized.
            return;
        }
        
        for (Player r : robots) {
            r.moveTowards(human);
            // Check to see if human is dead.
            if (r.hits(human))
                human.kill();
        }
        
        // Check every pair of robots for collisions
        for (int a = 0; a < robots.size() - 1; a++) {
            for (int b = a + 1; b < robots.size(); b++) {
                Player p1 = robots.get(a);
                Player p2 = robots.get(b);
                if (p1.hits(p2)) {
                    p1.kill();
                    p2.kill();
                }
            }
        }
        
        // Tell board to redraw
        repaint();
    }

    // Unused KeyListener methods
    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

        // Draw board squares
        g2.setColor(Color.BLACK);
        for (int r = 0; r < ROWS; r++) {
            for (int c = 0; c < ROWS; c++) {
                drawSquare(g2, r, c);
            }
        }

        // Draw robots
        for (Player robot : robots) {
            if (robot.alive())
                g2.setColor(Color.RED);
            else
                g2.setColor(Color.GRAY);
            drawSquare(g2, robot.getX(), robot.getY());
        }
        
        // Draw player square
        if (human.alive())
            g2.setColor(Color.GREEN);
        else
            g2.setColor(Color.YELLOW);
        drawSquare(g2, human.getX(), human.getY());
        
    }

    // Draw a squre at given board location
    public void drawSquare(Graphics2D g, int r, int c) {
        int w = getWidth() / ROWS;
        int h = getHeight() / COLS;
        g.fillRect(r * w + 1, c * h + 1, w - 1, h - 1);
    }
    
    // Below is basic setup code that we'll discuss in more detail later.

    public static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("Robots");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(500, 500));

        // Add our drawing panel.
        Board board = new Board();
        frame.getContentPane().add(board);
        frame.addKeyListener(board);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Readings

Read Chapter 4 (Writing Classes) in the book. See also the sections on creating and designing data types from the online outline for Introduction to Programming in Java.