package games; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; /// Generic adventure game framework. Manages Monster and /// Player classes. May be subclassed if changes to the /// management of Game and Monster objects are needed. public class Game { /// Prototype for newly created monsters: private Visible _prototypeMonster = new Monster(); /// Change the default kind of monster to use: public void setPrototypeMonster(Monster m) { _prototypeMonster = m; } /// Make a new monster of the appropriate type: public Monster newMonster() { return (Monster)_prototypeMonster.clone(); } /// Prototype for new players: private Visible _prototypePlayer = new Player(); /// Set the kind of Player to use: public void setPrototypeMonster(Player p) { _prototypePlayer = p; } /// Create a new player and insert into game: public void newPlayer() { _player = (Player)_prototypePlayer.clone(); } /// The current player: private Player _player; public Player getPlayer() {return _player;} /// Move the player to the given location. public void movePlayer(int x, int y) { _player.moveTo(x,y); getUI().repaint(); } // Create a new monster and add it to the game: public void insertNewMonster() { Monster m = newMonster(); m.reset(this); _visibles.addElement(m); } /// Remove a monster or player from the game. public void remove(Visible v) { _visibles.remove(v); System.out.println("Removed visible"); } /// Create the player public void insertPlayer() { newPlayer(); _visibles.addElement(_player); } public int getWidth() {return getUI().getWidth();} public int getHeight() {return getUI().getHeight();} private MonsterMover _monsterMover; private int _maxVisibles = 10; // An active object that controls the monsters: class MonsterMover extends Thread { private final int _monsterCreateDelayMSec=3000; public void run() { _numDefeatedMonsters = 0; long nextCreateTime = System.currentTimeMillis() + (int)(Math.random() * _monsterCreateDelayMSec); if (winCondition()) { System.out.println("Player wins!"); System.exit(0); } while (true) { // Create a monster if needed: if ( _visibles.size() < _maxVisibles && System.currentTimeMillis() >= nextCreateTime ) { insertNewMonster(); nextCreateTime = System.currentTimeMillis() + (int)(Math.random() * _monsterCreateDelayMSec); } // Move all visibles which need it. We want to do this for all // object whether or not the _visibles vector is modified during // our movement sweep; to do this we take a "snapshot" of the // current set of visibles, using Vector.clone(). Vector.clone() // does a "shallow copy", meaning the cloned vector contains // references to the original objects contained in the original // vector. Vector tmp = (Vector)_visibles.clone(); for(Iterator i = tmp.iterator(); i.hasNext(); ) { Visible v = (Visible)i.next(); if (!v.doAction(Game.this)) _numDefeatedMonsters++; } tmp = null; // Allow garbage collection. // Schedule a repaint: getUI().repaint(); // Wait a while: try { sleep(25); } catch (InterruptedException e) { return; } } } } private int _numDefeatedMonsters = 0; /// Returns true if the player has won the game. public boolean winCondition() { return (_numDefeatedMonsters >= 100); } private GameUI _ui; public GameUI getUI() {return _ui;} /// Collection of all visible objects in the game: private Vector _visibles = new Vector(); /// Draw the state of the game by delegating to each Visible object public void draw(Graphics g) { for(int i=0;i<_visibles.size();++i) { ((Visible)_visibles.elementAt(i)).draw(g); } } /// Set up a game public Game(String title) { _ui = new GameUI(title, this); _monsterMover = new MonsterMover(); } /// Start a game by showing UI, creating first player, and /// starting the monster mover thread. public void start() { _ui.setVisible(true); insertPlayer(); _monsterMover.start(); } /// Test driver: public static void main(String [] args) { Game g = new Game("Unit Test Game"); g.start(); } } /// A Mediator for the UI components of the game. class GameUI extends JFrame { private Game _game; public GameUI(String title, Game g) { super(title); _game = g; setup(); setSize(300,300); getContentPane().setBackground(Color.black); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { _game.movePlayer(e.getX(), e.getY()); } }); } public void paint(Graphics g) { super.paint(g); _game.draw(g); } public void setup() { WindowListener l = new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }; addWindowListener(l); } }