Code is also available in an archive.
PeanutsApplet.java
/*
<APPLET CODE="PeanutsApplet.class" WIDTH=600 HEIGHT=600></APPLET>
*/
import javax.swing.*;
import java.awt.*;
/**
* An applet that displays a game.
*
* @author Jim Glenn
* @version 0.1 from LiberationApplet of 1/8/2009
*/
public class PeanutsApplet extends JApplet
{
public void init()
{
PeanutsModel model = new PeanutsModel();
GameView view = new GameView(model);
PeanutsControl control = new PeanutsControl(model);
view.addKeyListener(control);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(view, BorderLayout.CENTER);
}
}
PeanutsControl.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* The controller for a game. The controller handles the time and
* the player's input.
*
* @author Jim Glenn
* @version 0.1 1/20/2009 :)
*/
public class PeanutsControl extends GameControl
{
/**
* Creates a controller connected to the given game model.
*
* @param g a Pick Up The Peanuts game
*/
public PeanutsControl(PeanutsModel m)
{
super(m);
}
private PeanutsModel getModel()
{
return (PeanutsModel)model;
}
public synchronized void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_NUMPAD1:
getModel().movePlayer(-1, 1);
break;
case KeyEvent.VK_NUMPAD2:
getModel().movePlayer(0, 1);
break;
case KeyEvent.VK_NUMPAD3:
getModel().movePlayer(1, 1);
break;
case KeyEvent.VK_NUMPAD4:
getModel().movePlayer(-1, 0);
break;
case KeyEvent.VK_NUMPAD6:
getModel().movePlayer(1, 0);
break;
case KeyEvent.VK_NUMPAD7:
getModel().movePlayer(-1, -1);
break;
case KeyEvent.VK_NUMPAD8:
getModel().movePlayer(0, -1);
break;
case KeyEvent.VK_NUMPAD9:
getModel().movePlayer(1, -1);
break;
}
}
}
PeanutsModel.java
/**
* A game of Pick up the Peanuts. Pick up the Peanuts has a player
* and an elephant who race to pick up peanuts.
*
* @author Jim Glenn
* @version 2K9 translated to Java
* @version 1.0 1982 or so in Atari BASIC
*/
public class PeanutsModel extends GameModel
{
/**
* The objects in this game. Distinguished objects (OK, all of them)
* are kept separately from the list for easy access.
*/
private Player player;
private Elephant elephant;
private Peanut peanut;
/**
* Creates a new Pick up the Peanut game with player and elephant
* at their starting positions (left and right respectively)
* and a randomly placed peanut.
*/
public PeanutsModel()
{
// create player near middle of left edge
player = new Player(0.1, 0.5);
addSprite(player);
// create elephant near middle of right edge
elephant = new Elephant(0.9, 0.5);
addSprite(elephant);
// throw a peanut at a random location
makePeanut();
}
/**
* Returns the current peanut in this game.
*
* @return the peanut
*/
public Peanut getPeanut()
{
return peanut;
}
/**
* Forwards move events to the player. The direction is given
* as an x- and a y-component.
*
* @param dx -1, 0, or 1
* @param dy -1, 0, or 1
*/
public void movePlayer(int dx, int dy)
{
player.move(dx, dy);
}
/**
* Places a new peanut randomly in this game.
*/
private void makePeanut()
{
if (peanut != null)
{
removeSprite(peanut);
}
peanut = new Peanut(Math.random(), Math.random());
addSprite(peanut);
}
/**
* Handles collisions between the given objects.
*
* @param s1 a sprite
* @param s2 a sprite that has collided with s1
*/
protected void handleCollision(Sprite s1, Sprite s2)
{
if (s1 instanceof Peanut || s2 instanceof Peanut)
{
// swap to make s1 the one that ate the peanut
if (s1 instanceof Peanut)
{
Sprite temp = s1;
s1 = s2;
s2 = temp;
}
if (s1 instanceof Player)
{
// player ate the peanut
}
else
{
// elephant ate the peanut
}
// make a new peanut
makePeanut();
}
else
{
// must be player/elephant
player.trample();
}
}
}
PeanutsWindow.java
import javax.swing.*;
import java.awt.*;
/**
* A window that displays a game.
*
* @author Jim Glenn
* @version 0.1 from LiberationApplet of 1/8/2009
*/
public class PeanutsWindow extends JFrame
{
public PeanutsWindow()
{
super("Pick up the Peanuts 2K9");
PeanutsModel model = new PeanutsModel();
GameView view = new GameView(model);
PeanutsControl control = new PeanutsControl(model);
view.addKeyListener(control);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(view, BorderLayout.CENTER);
}
public static void main(String[] args)
{
JFrame win = new PeanutsWindow();
win.setSize(600, 600);
win.setVisible(true);
win.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
Peanut.java
import java.awt.Color;
/**
* A peanut in Pick up the Peanuts.
*
* @author Jim Glenn
* @version 0.1 1/20/2009
*/
public class Peanut extends Sprite
{
/**
* The size of a peanut.
*/
public static final double DEFAULT_SIZE = 0.01;
/**
* Creates a new peanut at the given position.
* The peanut will be red.
*
* @param initX an x-coordinate within the world this peanut will be in
* @param initY a y-coordinate within the world this peanut will be in
*/
public Peanut(double initX, double initY)
{
super(initX, initY, DEFAULT_SIZE, Color.ORANGE);
}
}
Player.java
import java.awt.Color;
/**
* A human player in Pick up the Peanuts.
*
* @author Jim Glenn
* @version 0.1 1/21/2009
*/
public class Player extends Sprite
{
/**
* The size of the human player.
*/
public static final double DEFAULT_SIZE = 0.025;
/**
* The amount of time, in seconds, that this player takes to recover
* from being trampled.
*/
private static final double RECOVERY_TIME = 0.5;
/**
* Constants for state.
*/
private static final int STATE_TRAMPLED = 1;
/**
* The direction this player will go when it recovers from being trampled.
*/
private int recoverDx;
private int recoverDy;
/**
* Creates a new human player at the given position.
* The player will be red.
*
* @param initX an x-coordinate within the world this playwe will be in
* @param initY a y-coordinate within the world this Player will be in
*/
public Player(double initX, double initY)
{
super(initX, initY, DEFAULT_SIZE, Color.RED);
}
/**
* Returns the maximum speed of this player.
*
* @return the speed
*/
public double getMaximumSpeed()
{
return 0.2;
}
/**
* Changes the velocity of this player so that it is moving in
* the given direction. Its speed will be set to the maximum.
*
* @param dx -1, 0, or 1
* @param dy -1, 0, or 1
*/
public void move(int dx, int dy)
{
if (getState() != STATE_TRAMPLED)
{
setVelocity(getMaximumSpeed() * dx, getMaximumSpeed() * dy);
}
else
{
recoverDx = dx;
recoverDy = dy;
}
}
/**
* Tramples this player. This player will not be able to move until
* it recovers.
*/
public void trample()
{
if (getState() != STATE_TRAMPLED)
{
setState(STATE_TRAMPLED);
recoverDx = 0;
recoverDy = 0;
}
}
/**
* Updates this player.
*
* @param t the time since the last update
* @param m the model this player belongs to
*/
public void update(double t, GameModel m)
{
if (getState() == STATE_TRAMPLED)
{
if (getStateTime() > RECOVERY_TIME)
{
setState(STATE_NORMAL);
setVelocity(recoverDx, recoverDy);
}
else
{
setVelocity(0, 0);
}
}
super.update(t, m);
// do wraparound
if (x < getBoundingRadius() / 2)
{
x = m.getWidth() - getBoundingRadius() / 2;
}
else if (x + getBoundingRadius() / 2 > m.getWidth())
{
x = getBoundingRadius() / 2;
}
if (y < getBoundingRadius() / 2)
{
y = m.getHeight() - getBoundingRadius() / 2;
}
else if (y + getBoundingRadius() / 2 > m.getHeight())
{
y = getBoundingRadius() / 2;
}
}
}
Elephant.java
import java.awt.Color;
import java.awt.geom.*;
/**
* A human player in Pick up the Peanuts.
*
* @author Jim Glenn
* @version 0.1 1/21/2009
*/
public class Elephant extends Sprite
{
/**
* The size of an elephant.
*/
public static final double DEFAULT_SIZE = 0.025;
/**
* Creates a new elephant at the given position.
* The elephant will be gray.
*
* @param initX an x-coordinate within the world this elephant will be in
* @param initY a y-coordinate within the world this elephant will be in
*/
public Elephant(double initX, double initY)
{
super(initX, initY, DEFAULT_SIZE, Color.GRAY);
}
/**
* Returns the maximum speed of this elephant.
*
* @return the speed
*/
public double getMaximumSpeed()
{
return 0.2;
}
/**
* Updates this elephant.
*
* @param t the time since the last update
* @param m the model this player belongs to
*/
public void update(double t, GameModel m)
{
}
public GeneralPath getOutline()
{
double r = getBoundingRadius();
double earTop = y - r * Math.cos(Math.PI / 4);
double earXOff = r * Math.sin(Math.PI / 4);
double earLeft = x - earXOff;
double earRight = x + earXOff;
double trunkY = y + r * Math.cos(Math.PI / 10);
double trunkOff = r * Math.sin(Math.PI / 10);
double trunkLeft = x - trunkOff;
double trunkRight = x + trunkOff;
// we should be able to do a little better than this very
// crude rendering of an elephant's head
GeneralPath outline = new GeneralPath();
outline.moveTo((float)earLeft, (float)earTop);
outline.lineTo((float)(earLeft + r / 4), (float)earTop);
outline.lineTo((float)(earRight - r / 4), (float)earTop);
outline.lineTo((float)earRight, (float)earTop);
outline.lineTo((float)earRight, (float)(y + r / 8));
outline.lineTo((float)(earRight - r / 4), (float)(y + r / 8));
outline.lineTo((float)(earRight - r / 4), (float)(y + r / 2));
outline.lineTo((float)trunkRight, (float)(y + r / 2));
outline.lineTo((float)trunkRight, (float)trunkY);
outline.lineTo((float)trunkLeft, (float)trunkY);
outline.lineTo((float)trunkLeft, (float)(y + r / 2));
outline.lineTo((float)(earLeft + r / 4), (float)(y + r / 2));
outline.lineTo((float)(earLeft + r / 4), (float)(y + r / 8));
outline.lineTo((float)earLeft, (float)(y + r / 8));
outline.closePath();
return outline;
}
}
This code can also be downloaded from the files
PeanutsApplet.java,
PeanutsControl.java,
PeanutsModel.java,
PeanutsWindow.java,
Peanut.java,
Player.java,
and Elephant.java.