?? gamecanvas.java
字號:
/*
* GameCanvas.java
*
* Copyright 2001 SkyArts. All Rights Reserved.
*/
import javax.microedition.lcdui.*;
import java.util.*;
/**
* PocketBoxing的游戲內容描繪與操作所用的類
*
* @author Hideki Yonekawa
* @version 1.0
*/
class GameCanvas extends Canvas implements Runnable, CommandListener {
/** 用來儲存橫向長度的變量 */
private int screenWidth;
/** 用來儲存縱向長度的變量 */
private int screenHeight;
/** 儲存PocketBoxing對象的變量 */
private PocketBoxing boxing;
/** Start指令變量 */
private Command startCmd = new Command("Start", Command.SCREEN, 5);
/** Exit指令變量 */
private Command exitCmd = new Command("Exit", Command.SCREEN, 1);
/** Pause指令變量 */
private Command pauseCmd = new Command("Pause", Command.SCREEN, 5);
/** Resume指令變量 */
private Command resumeCmd = new Command("Resume", Command.SCREEN, 5);
/** Quit指令變量 */
private Command quitCmd = new Command("Quit", Command.SCREEN, 1);
/**儲存默認字體的變量 */
private Font defFont = Font.getDefaultFont();
/** 代表標題顯示狀態的常量 */
private static final short TITLE = 0;
/** 代表回合開始顯示狀態的常量 */
private static final short ROUND_START = 1;
/** 代表比賽顯示狀態的常量 */
private static final short FIGHTING = 2;
/** 代表回合結束顯示狀態的常量 */
private static final short ROUND_END = 9;
/** 代表全部回合過關狀態的常量 */
private static final short ALL_ROUND_CLEAR = 10;
/** 儲存現在顯示狀態的變量 */
private short gameState;
/** 代表玩家勝利狀態的常量 */
private static final int WIN = 0;
/** 代表玩家失敗狀態的常量 */
private static final int LOSE = 2;
/** 儲存玩家勝敗結果的變量 */
private int result;
/** 儲存默認生命點數的定數 */
private static final long DRAW_INTERVAL = 100;
/** 決定對手動作時所使用的Random變量 */
private Random random = new Random();
/** 代表玩家的變量 */
private Boxer player;
/** 代表對手的變量 */
private Enemy enemy;
/** 停止描繪線程的標志變量 */
private boolean isStopped;
/** 代表暫停狀態的標志 */
private boolean isPaused;
/** 代表對手是否為揮出拳擊的標志變量 */
private boolean isEnemyPanch;
/** 儲存使用在標題畫面上的變量 */
private Image titleImg;
/** 儲存在每一回合中對手之拳擊力的數組常量 */
private static final int[] DAMAGES = new int[] {
5, 8, 10, 12, 15
};
/** 儲存現在回合的變量 */
private int round;
/** 儲存回合數的常量 */
private static final int MAX_ROUND = DAMAGES.length;
/**
* 構造函數
* @param boxing PocketBoxing對象
*/
GameCanvas(PocketBoxing boxing) {
this.boxing = boxing;
//取得畫面的描繪范圍
screenWidth = getWidth();
screenHeight = getHeight();
try {
//初始化玩家
player = new Boxer();
player.setDrawX((screenWidth - 120) /2);
player.setDrawY(screenHeight - player.getHeight());
//初始化對手
enemy = new Enemy();
enemy.setDrawX(screenWidth - ((screenWidth - 120) /2));
enemy.setDrawY(screenHeight - enemy.getHeight());
//取得標題圖像
titleImg = Image.createImage("/title.png");
}catch(Exception e) {}
//登錄指令監聽
setCommandListener(this);
//將游戲狀態顯示到標題
gameState = TITLE;
}
/** 對游戲中所使用之值進行初始化的常量 */
private void doGameInit() {
round = 1;
doRoundInit();
isPaused = false;
}
/** 對使用在各回合之值進行初始化的常量 */
private void doRoundInit() {
gameState = ROUND_START;
result = WIN;
player.doInitialize();
enemy.doInitialize();
isEnemyPanch = false;
//清除描繪線程停止標志
isStopped = false;
}
/** MIDlet的startApp()被調用出來時所調用的方法 */
void doStartApp() {
//根據現在的狀態來操作運作
switch(gameState) {
case TITLE: //顯示標題時
doTitle();
break;
case ROUND_START: //回合開始時
case FIGHTING: //回合進行中
//進行暫停
isPaused = true;
//停止游戲循環
isStopped = true;
//以防萬一先刪除關卡中的指令
removeCommand(pauseCmd);
removeCommand(resumeCmd);
//新增Resume指令
addCommand(resumeCmd);
break;
default: //上述情形以外時
//解除暫停
isPaused = false;
break;
}
}
/** 進行標題顯示的方法 */
private void doTitle() {
//將游戲狀態顯示到標題
gameState = TITLE;
//以防萬一先刪除關卡中的指令
removeCommand(pauseCmd);
removeCommand(resumeCmd);
removeCommand(quitCmd);
//顯示標題畫面
repaint();
//新增指令
addCommand(exitCmd);
addCommand(startCmd);
}
/** MIDlet的pauseApp()方法被調用出來時所調用的方法 */
void doPauseApp() {
switch(gameState) {
case TITLE: //顯示標題時
break;
default: //上述情形以外時
//暫停
isPaused = true;
//停止游戲循環
isStopped = true;
break;
}
}
/** 啟動描繪線程的方法 */
private void doThreadStart() {
new Thread(this).start();
}
/** 結束游戲的方法 */
void doGameStop() {
isStopped= true;
}
/** 用來進行暫?;蚴侵匦麻_始的方法 */
void doPauseOrResume() {
if(isPaused) {
//暫停時
//重新開始
isPaused = false;
doThreadStart();
}else {
//不是暫停的時候
//進行暫停
isPaused = true;
doGameStop();
}
repaint();
}
/**
* 進行描繪的方法,一般不會直接從類本身來調用
* @param g Graphics對象
*/
protected void paint(Graphics g) {
//以白色來清除背景
g.setColor(0x00FFFFFF);
g.fillRect(0, 0, screenWidth, screenHeight);
//設定字體
g.setFont(defFont);
String drawSt;
String drawSt2 = null;
int drawX, drawY, stWidth, drawHeight;
int stHeight = defFont.getHeight();
//依照游戲狀態變更描繪內容
switch(gameState) {
case TITLE: //標題顯示時
//描繪標題畫面
drawX = (screenWidth - titleImg.getWidth()) /2;
g.drawImage(titleImg, drawX, 0, Graphics.TOP|Graphics.LEFT);
//著作權的顯示
g.setColor(0x00000000);
drawSt = "Copyright 2001";
drawX = (screenWidth - defFont.stringWidth(drawSt)) / 2;
drawY = getHeight() - stHeight *2;
g.drawString(drawSt, drawX, drawY, Graphics.TOP|Graphics.LEFT);
drawSt = "SkyArts.com";
drawX = (screenWidth - defFont.stringWidth(drawSt)) / 2;
drawY = drawY + stHeight;
g.drawString(drawSt, drawX, drawY, Graphics.TOP|Graphics.LEFT);
return;
case ROUND_START: //回合開始時
g.setColor(0x00000000);
drawSt = "Round " + String.valueOf(round);
drawX = (screenWidth - defFont.stringWidth(drawSt)) /2;
drawY = (screenHeight - stHeight * 2) / 2;
g.drawString(drawSt, drawX, drawY, Graphics.TOP|Graphics.LEFT);
drawSt = "Ready fight!";
drawX = (screenWidth - defFont.stringWidth(drawSt)) /2;
drawY = drawY + stHeight;
g.drawString(drawSt, drawX, drawY, Graphics.TOP|Graphics.LEFT);
return;
}
//描繪玩家與對手的生命點數
g.setColor(0x00000000);
drawSt = "You:" + String.valueOf(player.getLifePoint());
g.drawString(drawSt, 0, 0, Graphics.TOP|Graphics.LEFT);
drawSt = "Com:" + String.valueOf(enemy.getLifePoint());
g.drawString(drawSt, screenWidth - defFont.stringWidth(drawSt), 0, Graphics.TOP|Graphics.LEFT);
//描繪對手與玩家
enemy.doDraw(g);
player.doDraw(g);
//在暫停時等在畫面顯示字符串
switch(gameState) {
case FIGHTING: //回合中
if(isPaused) {
//顯示代表暫停的字符串
drawSt = "Pause";
}else {
//不是暫停時為return
return;
}
break;
case ROUND_END: //回合結束時
drawSt = "Round " + String.valueOf(round);
switch(result) {
case WIN: //勝利
drawSt2 = "You win!";
break;
case LOSE: //失敗
drawSt2 = "You lose!";
break;
}
break;
case ALL_ROUND_CLEAR://全回合過關時
drawSt = "You are Champion!";
break;
}
//描繪文本框
stWidth = defFont.stringWidth(drawSt);
if(drawSt2 == null) {
drawHeight = stHeight;
}else {
int tmpStWidth = defFont.stringWidth(drawSt2);
stWidth = (stWidth > tmpStWidth ? stWidth : tmpStWidth);
drawHeight = stHeight * 2;
}
drawX = (screenWidth-stWidth) / 2;
drawY = (screenHeight - (drawHeight)) / 2;
//輸出第一行的消息
g.setColor(0x00BBBBBB);
g.fillRoundRect(drawX-2, drawY+2, stWidth+9, drawHeight+2, 5, 5);
g.setColor(0x00000000);
g.fillRoundRect(drawX-6, drawY-2, stWidth+11, drawHeight+4, 5, 5);
g.setColor(0x00FFFFFF);
g.fillRoundRect(drawX-4, drawY, stWidth+7, drawHeight, 5, 5);
//輸出第一行的消息
g.setColor(0x00000000);
drawX = (screenWidth -defFont.stringWidth(drawSt)) / 2;
g.drawString(drawSt, drawX, drawY, Graphics.TOP|Graphics.LEFT);
//輸出第二行的消息
if(drawSt2 != null) {
drawX = (screenWidth -defFont.stringWidth(drawSt2)) / 2;
drawY = drawY + stHeight;
g.drawString(drawSt2, drawX, drawY, Graphics.TOP|Graphics.LEFT);
}
}
/** 指令的事件發生時所調用的方法 */
public void commandAction(Command c, Displayable s) {
if(c == startCmd) {//Start指令
//初始化游戲以開始游戲
doGameInit();
gameState = ROUND_START;
//先將標題指令刪除
removeCommand(startCmd);
removeCommand(exitCmd);
doThreadStart();
}else if(c == exitCmd) {//Exit指令
//調用出PocketBoxing類的doExit方法,將MIDlet本身結束
boxing.doExit();
}else if(c == pauseCmd) {//Pause指令
//交換Pause指令與Resume指令,調用出Pause、Resume處理方法
removeCommand(pauseCmd);
addCommand(resumeCmd);
doPauseOrResume();
}else if(c == resumeCmd) {//Resume指令
//交換Resume指令與Pause指令,調用出Pause、Resume處理方法
removeCommand(resumeCmd);
addCommand(pauseCmd);
doPauseOrResume();
}else if(c == quitCmd) {//Quit指令
//調用出游戲結束方法
doGameStop();
//刪除指令
removeCommand(pauseCmd);
removeCommand(resumeCmd);
removeCommand(quitCmd);
//顯示標題
doTitle();
}
}
/** 按鍵按下事件發生時所調用的方法 */
protected synchronized void keyPressed(int keyCode) {
if( gameState != FIGHTING ||
(gameState == FIGHTING && isPaused)) {
//回合中以外,或是在回合中暫停時為return
return;
}
//為清除按鍵的時候就不處理
if(keyCode == 0) return; //for KDDI
//玩家為拳擊中時就是return
switch(player.getCurrentState()) {
case Boxer.PANCH_UP:
case Boxer.PANCH_DOWN:
return;
}
switch(keyCode) {
case KEY_NUM1: //按鍵1
case KEY_NUM4: //按鍵4
//進行防御時
switch(player.getCurrentState()) {
case Boxer.GUARD_UP:
case Boxer.GUARD_DOWN:
//讓玩家拳擊手后退
player.setCurrentState(Boxer.BACK_STEP);
break;
}
break;
case KEY_NUM2: //按鍵2
switch(player.getCurrentState()) {
case Boxer.BACK_STEP:
case Boxer.GUARD_DOWN:
//后退或是進行下段防御時
//讓玩家的拳擊手進行上段防御
player.setCurrentState(Boxer.GUARD_UP);
break;
}
break;
case KEY_NUM5: //按鍵5
switch(player.getCurrentState()) {
case Boxer.BACK_STEP:
case Boxer.GUARD_UP:
//進行后退或是上段防御時
//讓玩家拳擊手進行下段防御
player.setCurrentState(Boxer.GUARD_DOWN);
break;
}
break;
case KEY_NUM3: //按鍵3
switch(player.getCurrentState()) {
case Boxer.BACK_STEP:
case Boxer.GUARD_UP:
case Boxer.GUARD_DOWN:
//后退或是進行防御時
//讓玩家的拳擊手進行上段拳擊
player.setCurrentState(Boxer.PANCH_UP);
//根據對手的狀態來減少生命點數
doLifepointCheck4Enemy();
break;
}
break;
case KEY_NUM6: //按鍵6
switch(player.getCurrentState()) {
case Boxer.BACK_STEP:
case Boxer.GUARD_UP:
case Boxer.GUARD_DOWN:
//后退或是進行防御時
//讓玩家拳擊手進行下段拳擊
player.setCurrentState(Boxer.PANCH_DOWN);
//根據對手的狀態來減少生命點數
doLifepointCheck4Enemy();
break;
}
break;
}
}
/** 按鍵按下狀態時被重復調用的方法 */
protected void keyRepeated(int keyCode) {
keyPressed(keyCode);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -