📄 wormpit.java
字号:
/* * @(#)WormPit.java 1.20 02/10/14 @(#) * * Copyright (c) 2001 Sun Microsystems, Inc. All rights reserved. * PROPRIETARY/CONFIDENTIAL * Use is subject to license terms. *//* * WormPit.java * * Created on March 30, 2001, 16:15 * @author Todd M Kennedy * @version 1.0 */package example.wormgame;import java.lang.System;import java.lang.Runnable;import java.lang.InterruptedException;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import javax.microedition.lcdui.Font;import javax.microedition.lcdui.Canvas;import javax.microedition.lcdui.Graphics;import javax.microedition.rms.RecordStore;import javax.microedition.rms.RecordStoreException;import javax.microedition.media.Player;import javax.microedition.media.Manager;import javax.microedition.media.MediaException;import javax.microedition.media.control.ToneControl;/** * The WormPit contains a Worm and some WormFood. The Worm will * slither around the pit in search of WormFood. If the Worm eats * it will grow in length. The Worm will be killed if it attempts * to slither past the edge of the pit or if it eats itself. */public class WormPit extends Canvas implements Runnable { /** Handle to target food. */ private WormFood myFood; /** Handle to current worm object. */ private Worm myWorm; /** Flag to indicate when the game is finished. */ private boolean gameOver = false; /** Flag to indicate if current game is paused. */ private boolean gamePaused = false; /** Flag to indicate game is restarted. */ private boolean gameRestart = false; /** Flag to indicate forced repaint is needed. */ private boolean forceRedraw = true; /** Flag to indicate the game is to be completely destroyed. */ private boolean gameDestroyed = false; /** Current game score. */ private int score = 0; /** Current game level. */ private int level = 5; /** Number of pieces of food eaten since the last level change. */ private int foodEaten = 0; /** Current screen width in pixels. */ private int width; /** Current screen height in pixels. */ private int height; /** Audio player for background tune. */ private Player audioPlayer; /** Tone player. */ private Player tonePlayer; /** Current screen size in cells. */ static int CellWidth; /** Current screen height in cells. */ static int CellHeight; /** Initial offset for screen rendering. */ private static final int START_POS = 3; /** Font height for rendering the score message. */ private static final int SCORE_CHAR_HEIGHT; /** Font width for rendering the score message. */ private static final int SCORE_CHAR_WIDTH; /** Height for two lines of score message text. */ private static final int SCORE_HEIGHT; /** Default delay between worm repaints. (400 milliseconds) */ private static final int DEFAULT_WAIT = 400; /** Maximum number of difficulty levels. (10) */ static final byte MAX_LEVELS = 10; /** Color for target food object. (0x00ff00) */ static final int FOOD_COLOUR = 0x0000ff00; /** Color for text objects. (0xff0000) */ static final int TEXT_COLOUR = 0x00ff0000; /** Color for erasing worm cells. (0xffffff) */ static final int ERASE_COLOUR = 0x00ffffff; /** Color for drawing worm cells. (0x000000) */ static final int DRAW_COLOUR = 0x00000000; /** Size of a cell for worm rendering. */ public static final int CELL_SIZE = 5; static { Font defaultFont = Font.getDefaultFont(); SCORE_CHAR_WIDTH = defaultFont.charWidth('S'); SCORE_CHAR_HEIGHT = defaultFont.getHeight(); SCORE_HEIGHT = SCORE_CHAR_HEIGHT * 2; } /** * Default constructor for worm pit. * Initialized the food and worm objects. */ public WormPit() { width = round(getWidth()); height = round(getHeight()-SCORE_HEIGHT); WormPit.CellWidth = (width-(START_POS*2)) / WormPit.CELL_SIZE; WormPit.CellHeight = (height-(START_POS*2)) / WormPit.CELL_SIZE; myWorm = new Worm(this); /* Generate food for worm to eat */ myFood = new WormFood(this); int x = myFood.getX(); int y = myFood.getY(); while (myWorm.contains(x, y)) { myFood.regenerate(); // regenerate if food placed under worm x = myFood.getX(); y = myFood.getY(); } } /** * Round the given value to next lowest number divisible by the * cell size. * @param val number to be rounded down * @return rounded down value */ private int round(int val) { int delta = (val-(START_POS*2)) % CELL_SIZE; return (val - delta); } /** * Set the difficulty level. If the new level is different from the * current level, any game currently in progress is terminated and * the score is lost. * @param level value of new level requested * @see #getLevel */ public void setLevel(int level) { if (this.level != level) { this.level = level; gameOver = true; gamePaused = false; foodEaten = 0; score = 0; } } /** * Get the difficulty level. * @return current game level * @see #setLevel */ public int getLevel() { return level; } /** * Get the score of this game. * @return current score */ public int getScore() { return score; } /** * Returns true if the given point is within the bounds of the * worm pit. * @param x x coordinate of point to check (0 - CellWidth) * @param y y coordinate of point to check (0 - CellHeight) * @return true, if coordinate is in the worm pit */ static boolean isInBounds(int x, int y) { if ((x < 0) || (x >= WormPit.CellWidth)) { return false; } if ((y < 0) || (y >= WormPit.CellHeight)) { return false; } return true; } /** * Restart the game. */ void restart() { if (gamePaused) { gamePaused = false; } else { myWorm.regenerate(); myFood.regenerate(); foodEaten = 0; score = 0; gameOver = false; if ((audioPlayer != null) && (audioPlayer.getState() == Player.PREFETCHED)) { try { audioPlayer.setMediaTime(0); audioPlayer.start(); } catch (MediaException me) { } } } forceRedraw = true; synchronized (myWorm) { myWorm.notifyAll(); } } /** * Handle keyboard input. This is used for worm movement. * @param keyCode pressed key is either Canvas arrow key (UP, * DOWN, LEFT, RIGHT) or simulated with KEY_NUM (2, 8, 4,6). */ public void keyPressed(int keyCode) { switch (getGameAction(keyCode)) { case Canvas.UP: myWorm.setDirection(Worm.UP); break; case Canvas.DOWN: myWorm.setDirection(Worm.DOWN); break; case Canvas.LEFT: myWorm.setDirection(Worm.LEFT); break; case Canvas.RIGHT: myWorm.setDirection(Worm.RIGHT); break; case 0: // There is no game action.. Use keypad constants instead switch (keyCode) { case Canvas.KEY_NUM2: myWorm.setDirection(Worm.UP); break; case Canvas.KEY_NUM8: myWorm.setDirection(Worm.DOWN); break; case Canvas.KEY_NUM4: myWorm.setDirection(Worm.LEFT); break; case Canvas.KEY_NUM6: myWorm.setDirection(Worm.RIGHT); break; } break; } } /** * Paint anything currently in the pit. * Overrides Canvas.paint. * @param g graphics object to be rendered */ private void paintPitContents(Graphics g) { try { myWorm.update(g); // update worm position if (myFood.isAt(myWorm.getX(), myWorm.getY())) { myWorm.eat(); score += level; foodEaten++; if (foodEaten > (level << 1)) { /* Increase difficulty level */ forceRedraw = true; foodEaten = 0; level++; if (tonePlayer != null) { try { tonePlayer.setMediaTime(0); tonePlayer.start(); } catch (MediaException me) { } } } else { if (audioPlayer != null) { try { Manager.playTone(69, 50, 100); // Play audio } catch (MediaException me) { } } } g.setColor(WormPit.ERASE_COLOUR); g.fillRect((width - (SCORE_CHAR_WIDTH * 3))-START_POS, height-START_POS, (SCORE_CHAR_WIDTH * 3), SCORE_CHAR_HEIGHT); g.setColor(WormPit.DRAW_COLOUR); // Display new score g.drawString("" + score, width - (SCORE_CHAR_WIDTH * 3) - START_POS, height - START_POS, g.TOP|g.LEFT); myFood.regenerate(); int x = myFood.getX(); int y = myFood.getY(); while (myWorm.contains(x, y)) { // generate again if food placed under worm.. myFood.regenerate(); x = myFood.getX(); y = myFood.getY(); } } myFood.paint(g); } catch (WormException se) { gameOver = true; } } /** * Paint the worm pit and its components * @param g graphics object to be rendered */ public void paint(Graphics g) { if (forceRedraw) { // Redraw the entire screen forceRedraw = false; // Clear background g.setColor(WormPit.ERASE_COLOUR); g.fillRect(0, 0, getWidth(), getHeight()); // Draw pit border g.setColor(WormPit.DRAW_COLOUR); g.drawRect(1, 1, (width - START_POS), (height - START_POS)); // Display current level g.drawString("L: " + level, START_POS, height, g.TOP|g.LEFT); g.drawString("" + score, (width - (SCORE_CHAR_WIDTH * 3)), height, g.TOP|g.LEFT); // Display current score g.drawString("S: ", (width - (SCORE_CHAR_WIDTH * 4)), height, g.TOP|g.RIGHT); g.drawString("" + score, (width - (SCORE_CHAR_WIDTH * 3)), height, g.TOP|g.LEFT); // Display highest score for this level g.drawString("H: ", (width - (SCORE_CHAR_WIDTH * 4)), (height + SCORE_CHAR_HEIGHT), g.TOP|g.RIGHT); g.drawString("" + WormScore.getHighScore(level), (width - (SCORE_CHAR_WIDTH * 3)), (height + SCORE_CHAR_HEIGHT), g.TOP|g.LEFT); // Draw worm & food g.translate(START_POS, START_POS); g.setClip(0, 0, CellWidth*CELL_SIZE, CellHeight*CELL_SIZE); myWorm.paint(g); myFood.paint(g); } else { // Draw worm & food g.translate(START_POS, START_POS); } if (gamePaused) { Font pauseFont = g.getFont(); int fontH = pauseFont.getHeight(); int fontW = pauseFont.stringWidth("Paused"); g.setColor(WormPit.ERASE_COLOUR); g.fillRect((width-fontW)/2 - 1, (height-fontH)/2, fontW + 2, fontH); g.setColor(WormPit.TEXT_COLOUR); g.setFont(pauseFont); g.drawString("Paused", (width-fontW)/2, (height-fontH)/2, g.TOP|g.LEFT); } else if (gameOver) { Font overFont = g.getFont(); int fontH = overFont.getHeight(); int fontW = overFont.stringWidth("Game Over"); g.setColor(WormPit.ERASE_COLOUR); g.fillRect((width-fontW)/2 - 1, (height-fontH)/2, fontW + 2, fontH); g.setColor(WormPit.TEXT_COLOUR); g.setFont(overFont); g.drawString("Game Over", (width-fontW)/2, (height-fontH)/2, g.TOP|g.LEFT); } else { paintPitContents(g); } g.translate(-START_POS, -START_POS); } /** * Notification handler when canvas hidden. * Forces a redraw when canvas is shown again. * Signals that the game is paused while the canvas is obscured. */ protected void hideNotify() { super.hideNotify(); forceRedraw = true; if (!gameOver) { gamePaused = true; } } /** * The main execution loop. */ public void run() { while (!gameDestroyed) { try { synchronized (myWorm) { if (gameOver) { if (WormScore.getHighScore(level) < score) { /* Display score screen */ WormScore.setHighScore(level, score, "me"); } if ((audioPlayer != null) && (audioPlayer.getState() == Player.STARTED)) { try { audioPlayer.stop(); Manager.playTone(60, 400, 100); } catch (Exception ex) { } } repaint(); // serviceRepaints(); // Draw immediately myWorm.wait(); // Wait until user presses 'restart' } else if (gamePaused) { repaint(); // serviceRepaints(); // Draw immediately myWorm.wait(); // Wait until user presses 'restart' } else { myWorm.moveOnUpdate(); repaint(); // serviceRepaints(); // Draw immediately myWorm.wait(DEFAULT_WAIT-(level*40)); } } } catch (java.lang.InterruptedException ie) { } } } /** * Destroy the entire game. Call this prior to destroying the MIDlet. */ public void destroyGame() { synchronized (myWorm) { gameDestroyed = true; //myWorm.notifyAll(); myWorm.notifyAll(); } } /** * Destroy the audio player. Call this destroy the audio player. */ public void destroyAudioPlayer() { synchronized (myWorm) { if (audioPlayer != null) { audioPlayer.close(); audioPlayer = null; } if (tonePlayer != null) { tonePlayer.close(); tonePlayer = null; } myWorm.notifyAll(); } } /** * Create an audio player. */ public void createAudioPlayer() { byte[] bkmelody = { ToneControl.VERSION, 1, ToneControl.SET_VOLUME, 40, 76, 8, 81, 24, 76, 8, 88, 24, 81, 8, 85, 16, 83, 8, 85, 8, 81, 16, 76, 16, 81, 16, 90, 16, 88, 16, 85, 8, 86, 8, 88, 48, ToneControl.SILENCE, 8, 76, 8, 81, 16, 90, 16, 88, 16, 85, 8, 86, 8, 88, 16, 83, 8, 85, 8, 81, 16, 76, 16, 81, 16, 85, 8, 86, 8, 83, 24, 81, 8, 81, 32 }; byte[] tseq = { ToneControl.VERSION, 1, 64, 4, 65, 4, 66, 4 }; if (audioPlayer != null) { audioPlayer.close(); audioPlayer = null; try { Thread.sleep(200); } catch (Exception ex) { } } try { ToneControl tControl; tonePlayer = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); tonePlayer.realize(); tControl = (ToneControl)tonePlayer.getControl("ToneControl"); tControl.setSequence(tseq); audioPlayer = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); audioPlayer.setLoopCount(-1); audioPlayer.realize(); tControl = (ToneControl)audioPlayer.getControl("ToneControl"); tControl.setSequence(bkmelody); audioPlayer.start(); } catch (Exception ex) { ex.printStackTrace(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -