📄 tumbleweedgame.java
字号:
}
//-----------------------------------------------------
// initialization and game state changes
/**
* Constructor sets the data, performs dimension calculations, and creates
* the graphical objects.
*/
public JumpCanvas(Jump midlet) throws Exception {
super(false);
myDisplay = Display.getDisplay(midlet);
myJump = midlet;
// calculate the dimensions
DISP_WIDTH = getWidth();
DISP_HEIGHT = getHeight();
Display disp = Display.getDisplay(myJump);
if (disp.numColors() < 256) {
throw (new Exception("game requires 256 shades"));
}
if ((DISP_WIDTH < 150) || (DISP_HEIGHT < 170)) {
throw (new Exception("Screen too small"));
}
if ((DISP_WIDTH > 250) || (DISP_HEIGHT > 250)) {
throw (new Exception("Screen too large"));
}
FONT = getGraphics().getFont();
FONT_HEIGHT = FONT.getHeight();
SCORE_WIDTH = FONT.stringWidth("Score: 000");
TIME_WIDTH = FONT.stringWidth("Time: " + myInitialString);
if (myManager == null) {
myManager = new JumpManager(CORNER_X, CORNER_Y + FONT_HEIGHT * 2,
DISP_WIDTH, DISP_HEIGHT - FONT_HEIGHT * 2 - GROUND_HEIGHT);
}
}
/**
* This is called as soon as the application begins.
*/
void start() {
myGameOver = false;
myDisplay.setCurrent(this);
repaint();
}
/**
* sets all variables back to their initial positions.
*/
void reset() {
myManager.reset();
myScore = 0;
myGameOver = false;
myGameTicks = myInitialGameTicks;
myOldGameTicks = myInitialGameTicks;
repaint();
}
/**
* clears the key states.
*/
void flushKeys() {
getKeyStates();
}
/**
* pause the game when it's hidden.
*/
protected void hideNotify() {
try {
myJump.systemPauseThreads();
} catch (Exception oe) {
myJump.errorMsg(oe);
}
}
/**
* When it comes back into view, unpause it.
*/
protected void showNotify() {
try {
myJump.systemStartThreads();
} catch (Exception oe) {
myJump.errorMsg(oe);
}
}
//-------------------------------------------------------
// graphics methods
/**
* paint the game graphic on the screen.
*/
public void paint(Graphics g) {
// clear the screen:
g.setColor(WHITE);
g.fillRect(CORNER_X, CORNER_Y, DISP_WIDTH, DISP_HEIGHT);
// color the grass green
g.setColor(0, 255, 0);
g.fillRect(CORNER_X, CORNER_Y + DISP_HEIGHT - GROUND_HEIGHT,
DISP_WIDTH, DISP_HEIGHT);
// paint the layer manager:
try {
myManager.paint(g);
} catch (Exception e) {
myJump.errorMsg(e);
}
// draw the time and score
g.setColor(BLACK);
g.setFont(FONT);
g.drawString("Score: " + myScore, (DISP_WIDTH - SCORE_WIDTH) / 2,
DISP_HEIGHT + 5 - GROUND_HEIGHT, g.TOP | g.LEFT);
g.drawString("Time: " + formatTime(), (DISP_WIDTH - TIME_WIDTH) / 2,
CORNER_Y + FONT_HEIGHT, g.TOP | g.LEFT);
// write game over if the game is over
if (myGameOver) {
myJump.setNewCommand();
// clear the top region:
g.setColor(WHITE);
g.fillRect(CORNER_X, CORNER_Y, DISP_WIDTH, FONT_HEIGHT * 2 + 1);
int goWidth = FONT.stringWidth("Game Over");
g.setColor(BLACK);
g.setFont(FONT);
g.drawString("Game Over", (DISP_WIDTH - goWidth) / 2, CORNER_Y
+ FONT_HEIGHT, g.TOP | g.LEFT);
}
}
/**
* a simple utility to make the number of ticks look like a time...
*/
public String formatTime() {
if ((myGameTicks / 16) + 1 != myOldGameTicks) {
myTimeString = "";
myOldGameTicks = (myGameTicks / 16) + 1;
int smallPart = myOldGameTicks % 60;
int bigPart = myOldGameTicks / 60;
myTimeString += bigPart + ":";
if (smallPart / 10 < 1) {
myTimeString += "0";
}
myTimeString += smallPart;
}
return (myTimeString);
}
//-------------------------------------------------------
// game movements
/**
* Tell the layer manager to advance the layers and then update the display.
*/
void advance() {
myGameTicks--;
myScore += myManager.advance(myGameTicks);
if (myGameTicks == 0) {
setGameOver();
}
// paint the display
try {
paint(getGraphics());
flushGraphics();
} catch (Exception e) {
myJump.errorMsg(e);
}
}
/**
* Respond to keystrokes.
*/
public void checkKeys() {
if (!myGameOver) {
int keyState = getKeyStates();
if ((keyState & LEFT_PRESSED) != 0) {
myManager.setLeft(true);
}
if ((keyState & RIGHT_PRESSED) != 0) {
myManager.setLeft(false);
}
if ((keyState & UP_PRESSED) != 0) {
myManager.jump();
}
}
}
}
/**
* This class draws the background grass.
*
* @author Carol Hamer
*/
class Grass extends TiledLayer {
//---------------------------------------------------------
// dimension fields
// (constant after initialization)
/**
* The width of the square tiles that make up this layer..
*/
static final int TILE_WIDTH = 20;
/**
* This is the order that the frames should be displayed for the animation.
*/
static final int[] FRAME_SEQUENCE = { 2, 3, 2, 4 };
/**
* This gives the number of squares of grass to put along the bottom of the
* screen.
*/
static int COLUMNS;
/**
* After how many tiles does the background repeat.
*/
static final int CYCLE = 5;
/**
* the fixed Y coordinate of the strip of grass.
*/
static int TOP_Y;
//---------------------------------------------------------
// instance fields
/**
* Which tile we are currently on in the frame sequence.
*/
private int mySequenceIndex = 0;
/**
* The index to use in the static tiles array to get the animated tile..
*/
private int myAnimatedTileIndex;
//---------------------------------------------------------
// gets / sets
/**
* Takes the width of the screen and sets my columns to the correct
* corresponding number
*/
static int setColumns(int screenWidth) {
COLUMNS = ((screenWidth / 20) + 1) * 3;
return (COLUMNS);
}
//---------------------------------------------------------
// initialization
/**
* constructor initializes the image and animation.
*/
public Grass() throws Exception {
super(setColumns(JumpCanvas.DISP_WIDTH), 1, Image
.createImage("/images/grass.png"), TILE_WIDTH, TILE_WIDTH);
TOP_Y = JumpManager.DISP_HEIGHT - TILE_WIDTH;
setPosition(0, TOP_Y);
myAnimatedTileIndex = createAnimatedTile(2);
for (int i = 0; i < COLUMNS; i++) {
if ((i % CYCLE == 0) || (i % CYCLE == 2)) {
setCell(i, 0, myAnimatedTileIndex);
} else {
setCell(i, 0, 1);
}
}
}
//---------------------------------------------------------
// graphics
/**
* sets the grass back to its initial position..
*/
void reset() {
setPosition(-(TILE_WIDTH * CYCLE), TOP_Y);
mySequenceIndex = 0;
setAnimatedTile(myAnimatedTileIndex, FRAME_SEQUENCE[mySequenceIndex]);
}
/**
* alter the background image appropriately for this frame..
*
* @param left
* whether or not the player is moving left
*/
void advance(int tickCount) {
if (tickCount % 2 == 0) { // slow the animation down a little
mySequenceIndex++;
mySequenceIndex %= 4;
setAnimatedTile(myAnimatedTileIndex,
FRAME_SEQUENCE[mySequenceIndex]);
}
}
}
/**
* This class contains the loop that keeps the game running.
*
* @author Carol Hamer
*/
class GameThread extends Thread {
//---------------------------------------------------------
// fields
/**
* Whether or not the main thread would like this thread to pause.
*/
private boolean myShouldPause;
/**
* Whether or not the main thread would like this thread to stop.
*/
private boolean myShouldStop;
/**
* A handle back to the graphical components.
*/
private JumpCanvas myJumpCanvas;
/**
* The System.time of the last screen refresh, used to regulate refresh
* speed.
*/
private long myLastRefreshTime;
//----------------------------------------------------------
// initialization
/**
* standard constructor.
*/
GameThread(JumpCanvas canvas) {
myJumpCanvas = canvas;
}
//----------------------------------------------------------
// utilities
/**
* Get the amount of time to wait between screen refreshes. Normally we wait
* only a single millisecond just to give the main thread a chance to update
* the keystroke info, but this method ensures that the game will not
* attempt to show too many frames per second.
*/
private long getWaitTime() {
long retVal = 1;
long difference = System.currentTimeMillis() - myLastRefreshTime;
if (difference < 75) {
retVal = 75 - difference;
}
return (retVal);
}
//----------------------------------------------------------
// actions
/**
* pause the game.
*/
void pauseGame() {
myShouldPause = true;
}
/**
* restart the game after a pause.
*/
synchronized void resumeGame() {
myShouldPause = false;
notify();
}
/**
* stops the game.
*/
synchronized void requestStop() {
myShouldStop = true;
notify();
}
/**
* start the game..
*/
public void run() {
// flush any keystrokes that occurred before the
// game started:
myJumpCanvas.flushKeys();
myShouldStop = false;
myShouldPause = false;
while (true) {
myLastRefreshTime = System.currentTimeMillis();
if (myShouldStop) {
break;
}
synchronized (this) {
while (myShouldPause) {
try {
wait();
} catch (Exception e) {
}
}
}
myJumpCanvas.checkKeys();
myJumpCanvas.advance();
// we do a very short pause to allow the other thread
// to update the information about which keys are pressed:
synchronized (this) {
try {
wait(getWaitTime());
} catch (Exception e) {
}
}
}
}
}
/**
* This class represents the player.
*
* @author Carol Hamer
*/
class Cowboy extends Sprite {
//---------------------------------------------------------
// dimension fields
/**
* The width of the cowboy's bounding rectangle.
*/
static final int WIDTH = 32;
/**
* The height of the cowboy's bounding rectangle.
*/
static final int HEIGHT = 48;
/**
* This is the order that the frames should be displayed for the animation.
*/
static final int[] FRAME_SEQUENCE = { 3, 2, 1, 2 };
//---------------------------------------------------------
// instance fields
/**
* the X coordinate of the cowboy where the cowboy starts the game.
*/
private int myInitialX;
/**
* the Y coordinate of the cowboy when not jumping.
*/
private int myInitialY;
/**
* The jump index that indicates that no jump is currently in progress..
*/
private int myNoJumpInt = -6;
/**
* Where the cowboy is in the jump sequence.
*/
private int myIsJumping = myNoJumpInt;
/**
* If the cowboy is currently jumping, this keeps track of how many points
* have been scored so far during the jump. This helps the calculation of
* bonus points since the points being scored depend on how many tumbleweeds
* are jumped in a single jump.
*/
private int myScoreThisJump = 0;
//---------------------------------------------------------
// initialization
/**
* constructor initializes the image and animation.
*/
public Cowboy(int initialX, int initialY) throws Exception {
super(Image.createImage("/images/cowboy.png"), WIDTH, HEIGHT);
myInitialX = initialX;
myInitialY = initialY;
// we define the reference pixel to be in the middle
// of the cowboy image so that when the cowboy turns
// from right to left (and vice versa) he does not
// appear to move to a different location.
defineReferencePixel(WIDTH / 2, 0);
setRefPixelPosition(myInitialX, myInitialY);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -