1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: FrameTrigger.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* This trigger is responsible for calling advanceFrame( ) on a GrameCanvas
* object.
**/
21 public class FrameTrigger extends Thread
{
/**
* The GameCanvas where we call advanceFrame.
**/
27 GameCanvas game_;
/**
* Time is miliseconds between frames
**/
private int frameDelay_;
/**
* Value which is true if the thread is to be stopped.
**/
private boolean stopped;
/**
* Constructor
* @param g Canvas for wich to trigger frame updates.
* @param frameDelay time in MS between frame updates.
**/
44 public FrameTrigger( GameCanvas g, int frameDelay )
{
game_ = g;
frameDelay_ = frameDelay;
stopped = true;
}
/**
* Stops the trigger from functioning.
* ( stops execution of the thread )
**/
55 public void stopTrigger( )
{ stopped = true; }
/**
* starts the trigger
*/
61 public void startTrigger( )
{ stopped = false; }
/**
* Starts the trigger running.
* - To be called by the thead start( ) function call.
**/
68 public void run( )
{
//stopped=false; // having this might cause problems
while ( !stopped )
{
game_.advanceFrame( );
try {
sleep( frameDelay_ );
} catch ( InterruptedException ie ) {}
}
System.out.println( "FrameTrigger Thread Stopped" );
}
}
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: GameBoard.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
import javax.microedition.lcdui.*;
import java.util.Vector;
/**
* A gameborad consists of a vector of GridNodes, and actors.
**/
19 public class GameBoard
{
//--------------------------//
// ENUM
//--------------------------//
/**
* Enum for a desired state
**/
public static final int ALIVE = 0;
public static final int DEAD = 1;
//--------------------------//
// MEMBER VARIABLES
//--------------------------//
/**
* A vector containing all of the GridNodes in this board.
**/
39 private Vector nodes_;
/**
* A vector containing all of the active GhostActors on this board.
**/
44 private Vector ghosts_;
/**
* The pacman for this board
**/
49 private PacmanActor pacman_;
/**
* The state of the GameBoard
* - state can be : ALIVE, DEAD
**/
private int state_;
//--------------------------//
// FUNCTIONS
//--------------------------//
/**
* Simple constructor, takes no parameters.
**/
64 public GameBoard( )
{
nodes_ = new Vector( );
ghosts_ = new Vector( );
state_ = ALIVE;
}
/**
* Adds a GridNode to this board.
**/
74 public void addGridNode( GridNode n )
{
nodes_.addElement( n );
}
/**
* Paints the board by calling paint on all GridNodes,
* pacman, and each ghost.
* @param g Graphics object where drawing should take place.
*/
84 public void paint( Graphics g )
{
for ( int i=0; i<nodes_.size( ); i++ )
{
GridNode n = ( GridNode ) nodes_.elementAt( i );
n.paint( g );
}
pacman_.paint( g );
for ( int i=0; i<ghosts_.size( ); i++ )
{
GhostActor ghost = ( GhostActor ) ghosts_.elementAt( i );
ghost.paint( g );
g.drawString( Integer.toString( pacman_.score_ ), 68, 65, 16|4 );
g.drawString( Integer.toString( pacman_.getLivesLeft( ) ), 58, 65, 16|4 );
}
}
/**
* advance all actors one frame:
* @return true if pacman has enough lives otherwise false
**/
108 public boolean advanceFrame( )
{
// and ghosts:
for ( int i=0; i<ghosts_.size( ); i++ )
{
GhostActor ghost = ( GhostActor ) ghosts_.elementAt( i );
//March 18, 2003
//Moved .advanceframe functions to try to get killing correct
// ( when pacman and ghost are in the same node, visually ) codewise this is correct.
//if we use .getNode( ), pacman gets killed before we see the ghost touch him
//if ( ghost.getNode( ) == pacman_.getNode( ) )
if ( ( Math.abs( ghost.getX( ) - pacman_.getX( ) ) < 3 ) && ( Math.abs( ghost.getY( ) - pacman_.getY( ) ) < 3 ) )
{
if( pacman_.isInvincible( ) == false )
{
state_ = DEAD;
}
else
{
pacman_.score_+=5;
ghost.restart( );
}
}
ghost.advanceFrame( );
}
if ( state_ == DEAD )
{
pacman_.restart( );
if ( pacman_.getLivesLeft( ) < 0 )
return false;
state_ = ALIVE;
for ( int i=0; i<ghosts_.size( ); i++ )
{
GhostActor ghost = ( GhostActor ) ghosts_.elementAt( i );
ghost.restart( );
}
}
else //If he's not dead, then he can still move
pacman_.advanceFrame( );
return true;
}
/**
* @param p the PacmanActor for this board
**/
163 public void setPacman( PacmanActor p )
{
pacman_ = p;
}
/**
* @return the PacmanActor for this board
**/
171 public PacmanActor getPacman( )
{
return pacman_;
}
/**
* Adds a GhostActor to this board.
* @param ghost the ghost to add.
**/
180 public void addGhost( GhostActor ghost )
{
ghosts_.addElement( ghost );
}
}
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: GameBoardFactory.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
/**
* Partial implementation of a Factory object to create GameBoard objects.
**/
16 public class GameBoardFactory
{
/**
* 2-D array of GridNode objects that represent the board
**/
21 private static GridNode nodes[][];
/**
* Creates a sample board
**/
26 public static GameBoard test( )
{
GridNode.setSize( 13 );
GameBoard gb = new GameBoard( );
int size = 8;
nodes = new GridNode[size][size-2];
for ( int i=0; i<size; i++ ) {
for ( int j=0; j<size-2; j++ )
{
nodes[i][j] = new GridNode( i, j );
gb.addGridNode( nodes[i][j] );
} }
// here we define our board:
PacmanActor pac = new PacmanActor( nodes[4][3] );
gb.setPacman( pac );
GhostActor ghost;
ghost = new GhostActor( nodes[0][0], pac );
gb.addGhost( ghost );
ghost = new GhostActor( nodes[0][5], pac );
gb.addGhost( ghost );
ghost = new GhostActor( nodes[7][0], pac );
gb.addGhost( ghost );
nodes[0][0].setPellet( GridNode.BIG_PELLET );
nodes[0][5].setPellet( GridNode.BIG_PELLET );
nodes[7][0].setPellet( GridNode.BIG_PELLET );
nodes[7][5].setPellet( GridNode.BIG_PELLET );
UDLink( 1, 1, 1, 2 );
UDLink( 1, 2, 1, 3 );
UDLink( 1, 3, 1, 4 );
UDLink( 1, 4, 1, 5 );
UDLink( 1, 5, 1, 6 );
UDLink( 2, 2, 2, 3 );
UDLink( 2, 3, 2, 4 );
UDLink( 2, 4, 2, 5 );
UDLink( 3, 2, 3, 3 );
UDLink( 3, 4, 3, 5 );
UDLink( 4, 1, 4, 2 );
UDLink( 4, 5, 4, 6 );
UDLink( 5, 1, 5, 2 );
UDLink( 5, 5, 5, 6 );
UDLink( 6, 2, 6, 3 );
UDLink( 6, 4, 6, 5 );
UDLink( 7, 2, 7, 3 );
UDLink( 7, 3, 7, 4 );
UDLink( 7, 4, 7, 5 );
UDLink( 8, 1, 8, 2 );
UDLink( 8, 2, 8, 3 );
UDLink( 8, 3, 8, 4 );
UDLink( 8, 4, 8, 5 );
UDLink( 8, 5, 8, 6 );
LRLink( 1, 1, 2, 1 );
LRLink( 2, 1, 3, 1 );
LRLink( 3, 1, 4, 1 );
LRLink( 4, 1, 5, 1 );
LRLink( 5, 1, 6, 1 );
LRLink( 6, 1, 7, 1 );
LRLink( 7, 1, 8, 1 );
LRLink( 1, 2, 2, 2 );
LRLink( 3, 2, 4, 2 );
LRLink( 5, 2, 6, 2 );
LRLink( 7, 2, 8, 2 );
LRLink( 2, 3, 3, 3 );
LRLink( 3, 3, 4, 3 );
LRLink( 4, 3, 5, 3 );
LRLink( 5, 3, 6, 3 );
LRLink( 6, 3, 7, 3 );
LRLink( 2, 4, 3, 4 );
LRLink( 3, 4, 4, 4 );
LRLink( 4, 4, 5, 4 );
LRLink( 5, 4, 6, 4 );
LRLink( 6, 4, 7, 4 );
LRLink( 1, 5, 2, 5 );
LRLink( 3, 5, 4, 5 );
LRLink( 5, 5, 6, 5 );
LRLink( 7, 5, 8, 5 );
LRLink( 1, 6, 2, 6 );
LRLink( 2, 6, 3, 6 );
LRLink( 3, 6, 4, 6 );
LRLink( 4, 6, 5, 6 );
LRLink( 5, 6, 6, 6 );
LRLink( 6, 6, 7, 6 );
LRLink( 7, 6, 8, 6 );
return gb;
}
/**
* Creates a up-down link in the nodes[][] array.
* - Upper left is ( 1, 1 )
**/
130 private static void UDLink( int x1, int y1, int x2, int y2 )
{
nodes[x1-1][y1-1].setDown( nodes[x2-1][y2-1] );
nodes[x2-1][y2-1].setUp( nodes[x1-1][y1-1] );
}
/**
* Creates a left-right link in the nodes[][] array.
* - Upper left is ( 1, 1 )
**/
139 private static void LRLink( int x1, int y1, int x2, int y2 )
{
nodes[x1-1][y1-1].setRight( nodes[x2-1][y2-1] );
nodes[x2-1][y2-1].setLeft( nodes[x1-1][y1-1] );
}
}
//----------------------------------------------------------------------------//
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: GameCanvas.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
import javax.microedition.lcdui.*;
/**
* This class is derived from a MIDlet canvas.
* It contains the main functionality of the game.
* It does three things basically
* -# Contains A GameBoard, which contains the game primitives and drawing code.
* -# Runs a FrameTrigger, which spawns a thread to periodically
* update the frames.
* -# Listens for key-presses, and notifies apropriate objects in the gameboard.
**/
24 public class GameCanvas extends Canvas implements CommandListener
{
/**
* The game board contains the game primitives, logic, and drawing code.
* This object is created during construction.
**/
31 GameBoard gameBoard_;
/**
* frameTrigger object is responsible for periodically calling back to
* this object to trigger a frame update.
**/
37 FrameTrigger frameTrigger_;
39 private final pacman midlet;
40 private final Command exitCommand;
41 private final Command menuCommand;
/**
* Constructor.
* @param disp The display where the game should run.
**/
47 public GameCanvas( pacman midlet )
{
this.midlet = midlet;
exitCommand = new Command( "Exit", Command.EXIT, 1 );
menuCommand = new Command( "Menu", Command.SCREEN, 1 );
addCommand( exitCommand );
addCommand( menuCommand );
setCommandListener( this );
gameBoard_ = GameBoardFactory.test( );
frameTrigger_ = new FrameTrigger( this, 20 );
frameTrigger_.start( );
frameTrigger_.startTrigger( );
}
63 public void unPause( )
{
frameTrigger_ = new FrameTrigger( this, 20 );
frameTrigger_.start( );
frameTrigger_.startTrigger( );
}
/**
* Called by the system to repaint the screen.
* @param g Graphics object where drawing should take place.
**/
74 protected void paint( Graphics g )
{
// clear the screen:
g.setColor( 255, 255, 255 );
g.fillRect( 0, 0, this.getWidth( ), this.getHeight( ) );
// draw the board
gameBoard_.paint( g );
}
/**
* This function is called periodically by FrameTrigger.
* It simply tells the gameboard to advance it's logic
* by one frame, then it requests a repaint from the system.
**/
89 public void advanceFrame( )
{
if ( gameBoard_.advanceFrame( ) )
{
midlet.gameOver =0;
repaint( );
}
else
{
frameTrigger_.stopTrigger( );
midlet.gameOver = 1;
System.out.println( "set gameover to 1" );
midlet.menuScreen( );
}
}
/**
* This function is called by the system when the user
* presses a key.
* @param keyCode The unique int value of the key being pressed'
*
* Modified: 3/4/03 : Paul Force
* Changed to use a more general key binding. Should work
* on any phone now
**/
114 protected void keyPressed( int keyCode )
{
int action = getGameAction( keyCode );
switch ( action )
{
case UP:
gameBoard_.getPacman( ).setDesiredDirection(
PacmanActor.UP );
break;
case DOWN:
gameBoard_.getPacman( ).setDesiredDirection(
PacmanActor.DOWN );
break;
case LEFT:
gameBoard_.getPacman( ).setDesiredDirection(
PacmanActor.LEFT );
break;
case RIGHT:
gameBoard_.getPacman( ).setDesiredDirection(
PacmanActor.RIGHT );
break;
}
}
/**
* Respond to a command issued on the canvas
**/
145 public void commandAction( Command c, Displayable s )
{
if ( c == exitCommand )
{
frameTrigger_.stopTrigger( );
midlet.quit( );
}
if ( c == menuCommand )
{
frameTrigger_.stopTrigger( );
midlet.menuScreen( );
}
}
}
//----------------------------------------------------------------------------//
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: GhostActor.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
import javax.microedition.lcdui.*;
/**
* Represents a ghost on the game board.
**/
18 public class GhostActor
{
//--------------------------//
// ENUM
//--------------------------//
/**
* Enum for a desired dirrection.
**/
public static final int NONE = 0;
/**
* Enum for a desired dirrection.
**/
public static final int UP = 1;
/**
* Enum for a desired dirrection.
**/
public static final int DOWN = 2;
/**
* Enum for a desired dirrection.
**/
public static final int LEFT = 3;
/**
* Enum for a desired dirrection.
**/
public static final int RIGHT = 4;
//--------------------------//
// MEMBER VARIABLES
//--------------------------//
/**
* The node where this ghost currently resides
**/
52 private GridNode myNode_;
/**
* This is the start node and where the ghost goes back to if
* pacman is killed
**/
59 private GridNode resetNode_;
/**
* The pacman which this ghost is chasing
* ( or running from )
**/
65 private PacmanActor target_;
/**
* current X Pixel coord of this actor
**/
private int pixelX_;
/**
* current Y Pixel coord of this actor
**/
private int pixelY_;
/**
* destination X Pixel coord for this actor
**/
private int newPixelX_;
/**
* destination Y Pixel coord for this actor
**/
private int newPixelY_;
/**
* This value is true if the ghosts should run from pacman.
**/
private static boolean runFromPac_;
//--------------------------//
// FUNCTIONS
//--------------------------//
/**
* Constructor for this GhostActor.
* @param startingPosition the GridNode where this ghosts begins the game
* @param target the PacmanActor this ghost should chase or run from.
**/
101 public GhostActor( GridNode startingPosition, PacmanActor target )
{
myNode_ = startingPosition;
resetNode_ = startingPosition;
target_ = target;
pixelX_ = myNode_.pixelCenterX( );
pixelY_ = myNode_.pixelCenterY( );
newPixelX_ = pixelX_;
newPixelY_ = pixelY_;
}
/**
* Sets when all ghosts should run from pacman.
**/
117 public static void setRunFromPac( boolean b )
{ runFromPac_ = b; }
/**
* Added by Benson Fung ( for killing pacman )
* @return the current node where this ghost resides
**/
124 public GridNode getNode( ) {
return myNode_;
}
/**
* Called to advance the logic of the game one frame.
**/
131 public void advanceFrame( )
{
// if we are in an animation:
if ( ( pixelX_ != newPixelX_ ) || ( pixelY_ != newPixelY_ ) )
{
// move closer to the destination:
if ( pixelX_ < newPixelX_ ) pixelX_++;
if ( pixelX_ > newPixelX_ ) pixelX_--;
if ( pixelY_ < newPixelY_ ) pixelY_++;
if ( pixelY_ > newPixelY_ ) pixelY_--;
}
else
{
// find out the XY for pacman:
int pacX = target_.getNode( ).pixelCenterX( );
int pacY = target_.getNode( ).pixelCenterY( );
// calculate distance from current position
pacX -= pixelX_;
pacY -= pixelY_;
System.out.println( "( " + pacX +", " + pacY + " )" );
// do some logic to pick directions:
if ( Math.abs( pacX ) > Math.abs( pacY ) )
{
if ( pacX > 0 ) moveTowards( RIGHT, UP, DOWN, LEFT );
else moveTowards( LEFT, DOWN, UP, RIGHT );
}
else
{
if ( pacY > 0 ) moveTowards( DOWN, LEFT, RIGHT, DOWN );
else moveTowards( UP, RIGHT, LEFT, UP );
}
}
}
/**
* Tries to move the ghost in these directions.
* The first one is most favorable.
* @param i1 First most desierable choice
* @param i2 Second most desierable choice
* @param i3 Third most desierable choice
* @param i4 Fourth most desierable choice
**/
177 private void moveTowards( int i1, int i2, int i3, int i4 )
{
// if we're running from pacman, we do these in the opposite order:
if ( runFromPac_ )
{
if ( goInDirection( i4 ) ) return;
if ( goInDirection( i3 ) ) return;
if ( goInDirection( i2 ) ) return;
if ( goInDirection( i1 ) ) return;
}
else
{
if ( goInDirection( i1 ) ) return;
if ( goInDirection( i2 ) ) return;
if ( goInDirection( i3 ) ) return;
if ( goInDirection( i4 ) ) return;
}
}
/**
* Tries to start moving in the specified dirrection.
* @param d desired dirrection in which to move
* @return true if we can go in this dirrection
**/
201 private boolean goInDirection( int d )
{
if ( d == LEFT ) return goToNode( myNode_.getLeft( ) );
if ( d == RIGHT ) return goToNode( myNode_.getRight( ) );
if ( d == UP ) return goToNode( myNode_.getUp( ) );
if ( d == DOWN ) return goToNode( myNode_.getDown( ) );
return false;
}
/**
* @param n Goes to this node if it is not null
* @return true when it's possible to go to the node
**/
214 private boolean goToNode( GridNode n )
{
if ( n == null ) return false;
myNode_ = n;
newPixelX_ = myNode_.pixelCenterX( );
newPixelY_ = myNode_.pixelCenterY( );
return true;
}
/**
* Paints the GhostActor
* @param g Graphics object where drawing should take place.
**/
227 public void paint( Graphics g )
{
g.setColor( 0, 0, 0 );
g.drawArc( pixelX_-4,
pixelY_-4,
8, 8,
0,
360 );
}
/**
* Returns the current x coordinate of the ghost
**/
240 public int getX( )
{
return pixelX_;
}
/**
* Returns the current y coordinate of the ghost
**/
248 public int getY( )
{
return pixelY_;
}
/*
Restart function:
Added 4-15-03 by Trevor Donarski
When pacman dies, this function will be called to move the ghosts to their initial
positions. This will also ensure that if a ghost is on the start position when pacman
dies, he doesn't respawn exactly on top of the ghost and start a loop of infinite kills.
*/
264 public void restart( )
{
myNode_ = resetNode_;
pixelX_ = resetNode_.pixelCenterX( );
pixelY_ = resetNode_.pixelCenterY( );
newPixelX_ = pixelX_;
newPixelY_ = pixelY_;
}
}
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: GridNode.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
import javax.microedition.lcdui.*;
/**
* Represents a cell on the gameboard.
* Nodes can draw itself and also contain informaion on the node's contents
**/
19 public class GridNode
{
//--------------------------//
// ENUM
//--------------------------//
//@{
/**
* Enum value for the pellet_ member.
**/
public static final int NO_PELLET = 0;
/**
* Enum value for the pellet_ member.
* Small pellets are worth points.
**/
public static final int SMALL_PELLET = 1;
/**
* Enum value for the pellet_ member.
* Large pellets make pacman eat ghosts for a set ammount of time.
**/
public static final int BIG_PELLET = 2;
//@}
//--------------------------//
// GRID SIZE
//--------------------------//
/**
* Defines the size of the grid squares.
* Units are pixels.
**/
private static int size_;
/**
* @param i size in pixels for all GridNode objects
**/
58 public static void setSize( int i )
{
size_ = i;
}
/**
* @return The size in pixels for all GridNode objects
**/
66 public static int getSize( )
{
return size_;
}
//--------------------------//
// MEMBER VARIABLES
//--------------------------//
/**
* Defines the type of pellet that is in the GridNode.
* Valid values are
* - NO_PELLET
* - SMALL_PELLET
* - BIG_PELLET
**/
private int pellet_;
//@{
/**
* Pointer to the GridNode to the left of this one on the game board.
* This value is null when there is no path for actors to move
* to the left.
**/
private GridNode left_;
/**
* Pointer to the GridNode to the right of this one on the game board.
* This value is null when there is no path for actors to move
* to the right.
**/
private GridNode right_;
/**
* Pointer to the GridNode up from this one on the game board.
* This value is null when there is no path for actors to move up.
**/
private GridNode up_;
/**
* Pointer to the GridNode down from this one on the game board.
* This value is null when there is no path for actors to move down.
**/
private GridNode down_;
//@}
/**
* Position of this GridNode in the X axis.
* - These are grid co-ordinates, not pixels.
* - This is specified during object construction.
**/
private int posX_;
/**
* Position of this GridNode in the Y axis.
* - These are grid co-ordinates, not pixels.
* - This is specified during object construction.
**/
private int posY_;
//@{
/**
* X pixel coord of the Upper Left corner of this GridNode
**/
private int pixelULX_;
/**
* Y pixel coord of the Upper Left corner of this GridNode
**/
private int pixelULY_;
/**
* X pixel coord of the Lower Right corner of this GridNode
**/
private int pixelLRX_;
/**
* Y pixel coord of the Lower Right corner of this GridNode
**/
private int pixelLRY_;
/**
* X pixel coord of the Center of this GridNode
**/
private int pixelCX_;
/**
* Y pixel coord of the Center of this GridNode
**/
private int pixelCY_;
//@}
//--------------------------//
// PUBLIC FUNCTIONS
//--------------------------//
/**
* Constructor for a GridNode
* - These are grid co-ordinates, not pixels.
* @param x Position of this GridNode in the X axis.
* @param y Position of this GridNode in the Y axis.
**/
172 public GridNode( int x, int y )
{
posX_ = x;
posY_ = y;
left_ = null;
right_ = null;
up_ = null;
down_ = null;
pellet_ = SMALL_PELLET;
//set the pixel positions:
// upper left
pixelULX_ = posX_ * size_;
pixelULY_ = posY_ * size_;
// lower right
pixelLRX_ = pixelULX_ + size_ -1;
pixelLRY_ = pixelULY_ + size_ -1;
// center
pixelCX_ = ( pixelULX_ + pixelLRX_ )/2;
pixelCY_ = ( pixelULY_ + pixelLRY_ )/2;
}
/**
* @return the X pixel coord of the Center of this GridNode
**/
200 public int pixelCenterX( )
{
return pixelCX_;
}
/**
* @return the X pixel coord of the Center of this GridNode
**/
208 public int pixelCenterY( )
{
return pixelCY_;
}
//@{
/**
* Sets the pointer to the GridNode to the left of this one on the game board.
* This value is null when there is no path for actors to move
* to the left.
*
* @param n GridNode object or null
**/
222 public void setLeft( GridNode n )
{
left_ = n;
}
/**
* Sets the pointer to the GridNode to the right of this one on the game board.
* This value is null when there is no path for actors to move
* to the right.
*
* @param n GridNode object or null
**/
234 public void setRight( GridNode n )
{
right_ = n;
}
/**
* Sets the pointer to the GridNode up from this one on the game board.
* This value is null when there is no path for actors to move up.
*
* @param n GridNode object or null
**/
245 public void setUp( GridNode n )
{
up_ = n;
}
/**
* Sets the pointer to the GridNode down from this one on the game board.
* This value is null when there is no path for actors to move down.
*
* @param n GridNode object or null
**/
256 public void setDown( GridNode n ) { down_ = n; }
/**
* Gets the pointer to the GridNode left from this one on the game board.
* This value is null when there is no path for actors to move left.
*
* @return GridNode object or null
**/
264 public GridNode getLeft( ) { return left_; }
/**
* Gets the pointer to the GridNode right from this one on the game board.
* This value is null when there is no path for actors to move right.
*
* @return GridNode object or null
**/
272 public GridNode getRight( ) { return right_; }
/**
* Gets the pointer to the GridNode up from this one on the game board.
* This value is null when there is no path for actors to move up.
*
* @return GridNode object or null
**/
280 public GridNode getUp( ) { return up_; }
/**
* Gets the pointer to the GridNode down from this one on the game board.
* This value is null when there is no path for actors to move down.
*
* @return GridNode object or null
**/
288 public GridNode getDown( ) { return down_; }
//@}
/**
* Sets the type of pellet that is in this GridNode.
* - Valid values are
* - NO_PELLET
* - SMALL_PELLET
* - BIG_PELLET
* @param i *_PELLET enum.
*/
300 public void setPellet( int i )
{
pellet_ = i;
}
/**
* Returns the type of pellet that is in this GridNode.
* - Valid values are
* - NO_PELLET
* - SMALL_PELLET
* - BIG_PELLET
* @return *_PELLET enum.
*/
313 public int getPellet( )
{
return pellet_;
}
/**
* This function is responsible for painting the GridNode
* @param g Graphics object where drawing should take place.
**/
322 public void paint( Graphics g )
{
// clear the square
g.setColor( 255, 255, 255 );
g.fillRect( pixelULX_, pixelULY_, pixelLRX_, pixelLRY_ );
// draw the borders:
g.setColor( 0, 0, 0 );
if ( left_ == null ) g.drawLine( pixelULX_, pixelULY_, pixelULX_, pixelLRY_ );
if ( right_ == null ) g.drawLine( pixelLRX_, pixelULY_, pixelLRX_, pixelLRY_ );
if ( up_ == null ) g.drawLine( pixelULX_, pixelULY_, pixelLRX_, pixelULY_ );
if ( down_ == null ) g.drawLine( pixelULX_, pixelLRY_, pixelLRX_, pixelLRY_ );
// draw the dots:
int radius = 0;
if ( pellet_ == BIG_PELLET )
radius = size_ / 3;
if ( pellet_ == SMALL_PELLET )
radius = size_ / 5;
if ( pellet_ != NO_PELLET )
g.fillArc( pixelCX_, pixelCY_, radius, radius, 0, 360 );
}
}
1 import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
5 public class MenuScreen
6 extends List
7 implements CommandListener
{
9 private final pacman midlet;
10 private final Command quitCommand;
11 private final String NEW_TEXT = "New Game";
12 private final String CONTINUE_TEXT = "Continue";
14 public MenuScreen( pacman midlet )
{
super( "PacMan", List.IMPLICIT );
this.midlet = midlet;
append( NEW_TEXT, null );
if ( !( midlet.gameOver == 1 ) )
{
append( CONTINUE_TEXT, null );
}
quitCommand = new Command( "Quit", Command.EXIT, 2 );
addCommand( quitCommand );
setCommandListener( this );
}
31 public void commandAction( Command c, Displayable d )
{
if ( c == List.SELECT_COMMAND )
{
if ( getString( getSelectedIndex( ) ).equals( NEW_TEXT ) )
{
try
{
midlet.restartApp( );
}
catch ( javax.microedition.midlet.MIDletStateChangeException midException )
{
midException.printStackTrace( );
System.exit( 1 );
}
}
if ( getString( getSelectedIndex( ) ).equals( CONTINUE_TEXT ) )
{
midlet.continueGame( );
}
}
else // quit command
{
midlet.quit( );
}
}
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* CS 329 - Design Project, Spring 2003
* University of Illinois, Urbana-Champaign
*
* file: PacmanActor.java
* contact: Trevor Donarski
* date: 02/01/03
**/
//----------------------------------------------------------------------------//
import javax.microedition.lcdui.*;
import java.util.Timer;
import java.util.TimerTask;
/**
* Represents pacman on the game board.
**/
21 public class PacmanActor
{
//--------------------------//
// ENUM
//--------------------------//
/**
* Enum for a desired dirrection.
**/
public static final int NONE = 0;
/**
* Enum for a desired dirrection.
**/
public static final int UP = 1;
/**
* Enum for a desired dirrection.
**/
public static final int DOWN = 2;
/**
* Enum for a desired dirrection.
**/
public static final int LEFT = 3;
/**
* Enum for a desired dirrection.
**/
public static final int RIGHT = 4;
//--------------------------//
// MEMBER VARIABLES
//--------------------------//
/**
* The node where pacman currently resides
**/
55 private GridNode myNode_;
/**
* The number of small pellets that pacman has eaten this game.
* This helps us calculate the score.
**/
private int pelletsEaten_;
/**
* Keeps track of pacman's current score.
*/
public int score_;
/**
* This is the invincibility variable... If pacman is invincible he'll eat the ghost :o )
**/
public boolean invincible_;
/**
* current X Pixel coord of this actor
**/
private int pixelX_;
/**
* current Y Pixel coord of this actor
**/
private int pixelY_;
/**
* destination X Pixel coord for this actor
**/
private int newPixelX_;
/**
* destination Y Pixel coord for this actor
**/
private int newPixelY_;
/**
* Desired dirrecton where pacman should move.
* This is specified by user actions ( pressing movment keys )
**/
private int direction_;
/**
* NEW Apr. 3, 2003 - PDF
* - addresses the problem with pacman moonwalking
*
* Direction PacMan is currently moving
**/
private int animDirection_ = RIGHT;
/**
* The Node where pacman starts
**/
111 private GridNode startNode_;
/**
* NEW Feb. 25, 2003
* Added By Benson Fung
*
* This helps speed up calculations for the mouth angle
*/
//Lags the controls
//private int currentDirection_;
/**
* The current angle of the opening of pacman's mouth
**/
private int mouthAngle_;
/**
* The amount and dirrection of change that the mouth will
* Take in the next frame.
**/
private int mouthAngleChange_;
/**
* Specifies startAngle in fillARc depending on
* direction pacman is facing
*/
private int mouthAngleDirection_;
/**
* New April 15th, 2003
* Implements Lives
*/
private int myLivesLeft_;
/**
* New April 28th, 2003
* Implements Invinciblity
*/
149 private PacmanTimer invincibleTimer;
//--------------------------//
// FUNCTIONS
//--------------------------//
/**
* Constructor for this PacmanActor.
* @param startingPosition the GridNode where this ghosts begins the game
**/
159 public PacmanActor( GridNode startingPosition )
{
myNode_ = startingPosition;
startNode_ = startingPosition;
invincible_ = false;
pixelX_ = myNode_.pixelCenterX( );
pixelY_ = myNode_.pixelCenterY( );
newPixelX_ = pixelX_;
newPixelY_ = pixelY_;
direction_ = NONE;
//currentDirection_ = direction_;
/*
myNode_ = startingPosition;
startNode_ = startingPosition;
pixelX_ = myNode_.pixelCenterX( );
pixelY_ = myNode_.pixelCenterY( );
newPixelX_ = pixelX_;
newPixelY_ = pixelY_;
direction_ = NONE;
//currentDirection_ = direction_;
*/
pelletsEaten_ = 0;
// mouthAngle starts Pacman facing right
mouthAngleDirection_ = 20;
// 40 degree arc mouth opening
mouthAngle_ = 320;
mouthAngleChange_ = +10;
//Number of lives left
myLivesLeft_ = 2;
}
/**
* @return the current node where pacman resides
**/
201 public GridNode getNode( ) {
return myNode_;
}
/**
* @return the number of small pellets that pacman has eaten in this game.
**/
208 public int getPelletsEaten( )
{
return pelletsEaten_;
}
/**
* @return Pacman's current x coordinate
*/
216 public int getX( )
{
return pixelX_;
}
/**
* @return Pacman's current y coordinate
*/
224 public int getY( )
{
return pixelY_;
}
/**
* @return Number of lives pacman has left. If < 0, then game is over
*/
232 public int getLivesLeft( )
{
return myLivesLeft_;
}
/**
* Sets the dirrection the user wishes pacman to move.
* @param d enum: NONE, RIGHT, LEFT, UP, DOWN
**/
241 public void setDesiredDirection( int d )
{
direction_ = d;
}
/**
* Sets the number of lives for this pacman
* @param i the number of lives left of pacman you want
*/
250 public void setLivesLeft( int i )
{
myLivesLeft_ = i;
}
/**
* @param n Goes to this node if it is not null
**/
258 private void goToNode( GridNode n )
{
if ( n == null ) return;
myNode_ = n;
newPixelX_ = myNode_.pixelCenterX( );
newPixelY_ = myNode_.pixelCenterY( );
}
266 public boolean isInvincible( )
{
if( invincible_ == true )
{
return true;
}
else
{
return false;
}
}
/**
* Resets Pacman to his original position but keeps the number of pellets eaten
*/
281 public void restart( )
{
myNode_ = startNode_;
pixelX_ = startNode_.pixelCenterX( );
pixelY_ = startNode_.pixelCenterY( );
newPixelX_ = startNode_.pixelCenterX( );
newPixelY_ = startNode_.pixelCenterY( );
invincible_ = false;
direction_ = NONE;
animDirection_ = RIGHT;
//currentDirection_ = direction_;
pelletsEaten_ = pelletsEaten_;
// mouthAngle starts Pacman facing right
mouthAngleDirection_ = 20;
// 40 degree arc mouth opening
mouthAngle_ = 320;
mouthAngleChange_ = +10;
// We only restart when pacman dies, so...
myLivesLeft_--;
}
/**
* Called to advance the logic of the game one frame.
**/
310 public void advanceFrame( )
{
// if we are in an animation:
if ( ( pixelX_ != newPixelX_ ) || ( pixelY_ != newPixelY_ ) )
{
// move closer to the destination:
if ( pixelX_ < newPixelX_ ) pixelX_++;
if ( pixelX_ > newPixelX_ ) pixelX_--;
if ( pixelY_ < newPixelY_ ) pixelY_++;
if ( pixelY_ > newPixelY_ ) pixelY_--;
}
else
{
// The else and if else statement directly after this comment
// were modified over the course of 2 weeks by Trevor Donarski
//
// Basically what I did was implement the scoring strategy and
// the ability for pacman to become invincible once he ate a
// power pellet ( known as BIG_PELLET ). I call PacmanTimer which
// is a class that implements the timer function found in
// java.util.Timer
if ( myNode_.getPellet( ) == GridNode.SMALL_PELLET )
{
myNode_.setPellet( GridNode.NO_PELLET );
pelletsEaten_++;
score_++;
}
// eat any pellets:
else if ( myNode_.getPellet( ) == GridNode.BIG_PELLET )
{
myNode_.setPellet( GridNode.NO_PELLET );
pelletsEaten_+=2;
score_+=2;
invincibleTimer = new PacmanTimer( );
}
// can we move in the direction requested?
// Modified 4/3/03 - PDF
// - Added support for animDirection_
if( direction_ == LEFT )
{
goToNode( myNode_.getLeft( ) );
animDirection_ = LEFT;
}
if( direction_ == RIGHT )
{
goToNode( myNode_.getRight( ) );
animDirection_ = RIGHT;
}
if( direction_ == DOWN )
{
goToNode( myNode_.getDown( ) );
animDirection_ = DOWN;
}
if( direction_ == UP )
{
goToNode( myNode_.getUp( ) );
animDirection_ = UP;
}
}
}
/**
* Paints the PacmanActor
* @param g Graphics object where drawing should take place.
**/
379 public void paint( Graphics g )
{
if ( mouthAngle_ <= 300 ) mouthAngleChange_ = +10;
if ( mouthAngle_ >= 360 ) mouthAngleChange_ = -10;
mouthAngle_ += mouthAngleChange_;
//Added by Benson Fung - make mouth move correctly
//Added a variable speed optimization
//if ( direction_ != currentDirection_ )
//Modified 4/3/03 - PDF
// - Now switches on animDirection_ instead of direction_
switch ( animDirection_ )
{
case RIGHT: mouthAngleDirection_ = 30; break; // 0 degrees + 20
case LEFT: mouthAngleDirection_ = 210; break; // 180 degrees + 20
case UP: mouthAngleDirection_ = 120; break; // 90 degrees + 20
case DOWN: mouthAngleDirection_ = 300; break; // 270 degrees + 20
default: break;
}
// both sides of his mouth move, so this must account for change also
mouthAngleDirection_ -= mouthAngleChange_;
g.setColor( 0, 0, 0 );
//fillArc( x, y, sizeX, sizeY, startAngle, arcAngle
//startAngle should determine which side the mouth faces
//arcAngle should be between 360 - 60 to 360 - 20
g.fillArc( pixelX_-4,
pixelY_-4,
8, 8,
mouthAngleDirection_,
mouthAngle_ );
}
/**
* Simple timer that uses java.util.Timer to schedule a task
* to execute for 6 seconds
**/
418 public class PacmanTimer
{
421 Timer timer;
/**
* Constructor for PacmanTimer.
* Creates a new Timer and schedules a task
* to run in 6000 milliseconds = 6 sec
**/
428 public PacmanTimer( )
{
invincible_ = true;
timer = new Timer ( );
timer.schedule( new PacmanTask( ), 6000 );
}
/**
* This is PacmanTask which simply outputs to the screen
* when the time is up and turns inviciblity off
**/
440 class PacmanTask extends TimerTask
{
442 public void run( )
{
System.out.println( "Time's up!" );
//Terminate the timer thread
timer.cancel( );
invincible_ = false;
}
}
}
}
1 import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.util.Random;
6 public class SplashScreen extends Canvas implements CommandListener
{
8 private final pacman midlet;
9 private final Command exitCommand;
private int x;
private int y = 40;
private int pacDirection = 1;
private int mouthAngle = 320;
private int mouthAngleChange = 10;
private int mouthAngleDirection = 20;
16 private SplashTrigger splashTrigger;
17 private Random generator = new Random( );
19 public SplashScreen( pacman midlet )
{
this.midlet = midlet;
exitCommand = new Command( "Next", Command.EXIT, 1 );
addCommand( exitCommand );
setCommandListener( this );
splashTrigger = new SplashTrigger( this, 20 );
splashTrigger.start( );
}
30 public void paint( Graphics g )
{
g.setColor( 255, 255, 255 );
g.fillRect( 0, 0, 120, 120 );
g.setColor( 0, 0, 0 );
g.setFont( Font.getFont( Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_LARGE ) );
g.drawString( "PacMan", 25, 5, ( Graphics.TOP | Graphics.LEFT ) );
animateScene( g );
}
40 public void animateScene( Graphics g )
{
if ( mouthAngle <= 300 ) mouthAngleChange = +10;
if ( mouthAngle >= 360 ) mouthAngleChange = -10;
mouthAngle += mouthAngleChange;
mouthAngleDirection -= mouthAngleChange;
g.setColor( 0, 0, 0 );
g.fillArc( x,
y,
8, 8,
mouthAngleDirection,
mouthAngle );
g.drawArc( x-30,
y,
8, 8,
0,
360 );
g.drawArc( x-50,
y,
8, 8,
0,
360 );
g.drawArc( x-70,
y,
8, 8,
0,
360 );
}
73 public void advanceFrame( )
{
x += pacDirection * 1;
if ( x == 180 ) {
pacDirection = -1;
mouthAngleDirection = 210;
y = Math.abs( generator.nextInt( ) % 40 ) + 25;
}
if ( x == -30 ) {
pacDirection = 1;
mouthAngleDirection = 20;
y = Math.abs( generator.nextInt( ) % 40 ) + 25;
}
repaint( );
}
89 public void commandAction( Command c, Displayable d )
{
if ( c == exitCommand )
{
splashTrigger.stopTrigger( );
midlet.splashScreenDone( );
}
}
1 import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* This trigger is responsible for calling advanceFrame( ) on a SplashScreen
* object.
**/
9 public class SplashTrigger extends Thread
{
/**
* The SplashScreen where we call advanceFrame.
**/
15 private SplashScreen splashScreen;
/**
* Time is miliseconds between frames
**/
private int frameDelay;
/**
* Value which is true if the thread is to be stopped.
**/
private boolean stopped;
/**
* Constructor
* @param g Canvas for wich to trigger frame updates.
* @param frameDelay time in MS between frame updates.
**/
32 public SplashTrigger( SplashScreen g, int frameDelay )
{
this.splashScreen = g;
this.frameDelay = frameDelay;
}
/**
* Stops the trigger from functioning.
* ( stops execution of the thread )
**/
42 public void stopTrigger( )
{ stopped = true; }
/**
* Starts the trigger running.
* - To be called by the thead start( ) function call.
**/
49 public void run( )
{
stopped=false;
while ( !stopped )
{
splashScreen.advanceFrame( );
try {
sleep( frameDelay );
} catch ( InterruptedException ie ) {}
}
}
1 /**
* PacMan for J2ME Devices
* CS 327 - Design Project, Fall 2002
* University of Illinois, Urbana-Champaign
*
* file: pacman.java
* contact: Braden Kowitz
* date: 11/24/02
**/
//----------------------------------------------------------------------------//
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
/**
* This is the base class for the midlet.
* It starts up and shuts down the game.
**/
20 public class pacman extends MIDlet
{
/**
* A canvas draws to the screen.
* The game canvas contains all of main
* functionality of the gameplay.
**/
28 private GameCanvas gameCanvas;
29 private SplashScreen splashScreen;
30 private MenuScreen menuScreen;
public int gameOver;
/**
* Constructor for this MIDlet.
* This function get's the current display,
* and creates a GameCanvas with the display.
**/
40 public pacman( )
{
}
/**
* When the OS tells this midlet to start,
* we simply show the GameCanvas.
**/
48 public void startApp( )
{
gameOver = 1;
Displayable current = Display.getDisplay( this ).getCurrent( );
if( current == null )
{
// first time we've been called
splashScreen = new SplashScreen( this );
Display.getDisplay( this ).setCurrent( splashScreen );
}
else
{
Display.getDisplay( this ).setCurrent( current );
}
}
/**
* Handles a request from the OS to pause the game.
* This is not currently implemented.
**/
68 public void pauseApp( )
{
}
/**
* Handles a restart of the game
*/
75 public void restartApp( ) throws MIDletStateChangeException
{
gameOver = 0;
gameCanvas = new GameCanvas( this );
Display.getDisplay( this ).setCurrent( gameCanvas );
}
82 public void continueGame( )
{
gameCanvas.unPause( );
Display.getDisplay( this ).setCurrent( gameCanvas );
}
/**
* Handles a request from the OS to end the game.
* Calls to destroy FrameTrigger thread accessable
* in GameCanvas
**/
93 public void destroyApp( boolean unconditional )
{
}
97 public void splashScreenDone( )
{
menuScreen = new MenuScreen( this );
Display.getDisplay( this ).setCurrent( menuScreen );
}
103 public void menuScreen( )
{
menuScreen = new MenuScreen( this );
Display.getDisplay( this ).setCurrent( menuScreen );
}
109 public void quit( )
{
destroyApp( false );
notifyDestroyed( );
}