?? gamecanvas.java
字號:
/*
* GameCanvas.java
*
* Copyright 2001 SkyArts. All Rights Reserved.
*/
import javax.microedition.lcdui.*;
import java.util.*;
/**
* 游戲的操作與畫面描繪使用的Canvas類
*
* @author Hideki Yonekawa
* @version 1.0
*/
class GameCanvas extends Canvas implements Runnable, CommandListener {
/** 構造函數 */
private int screenWidth;
/** 儲存橫向長度的變量 */
private int screenHeight;
/** 儲存縱向長度的變量 */
private Cube cube;
/** 代表標題顯示狀態的常量 */
private static final short TITLE = 0;
/** 代表游戲開始顯示狀態的常量 */
private static final short GAME_START = 1;
/** 代表游戲中顯示狀態的常量 */
private static final short GAME_PLAYING = 2;
/** 代表游戲結束顯示狀態的常量 */
private static final short GAME_END = 5;
/** 儲存現在顯示狀態的變量 */
private short gameState;
/** 顯示暫停狀態的標志 */
private boolean isPaused;
/** 儲存使用在標題的圖像的變量 */
private Image titleImg;
/** 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);
/** 成為方塊的置入物的Piece數組變量 */
private Piece[] pieces;
/** 儲存方塊的列(縱向)數目的常量 */
private static final int COLUMN_LENGTH = 8;
/** 儲存方塊的行(橫向)數目的常量 */
private static final int ROW_LENGTH = 6;
/** 儲存了落下方塊組的中心點Index的變量 */
private int centerPoint;
/** 儲存了落下方塊組的左側Index的變量 */
private static final short FALL_START_INDEX1 = 2;
/** 儲存了落下方塊組的右側Index的變量 */
private static final short FALL_START_INDEX2 = 3;
//落下方塊的方向常量
/** 代表落下方塊組的方向為上的常量 */
private static final short DIRECTION_UP = 0;
/** 代表落下方塊組的方向為右的常量 */
private static final short DIRECTION_RIGHT = 1;
/** 代表落下方塊組的方向為下的常量 */
private static final short DIRECTION_DOWN = 2;
/** 代表落下方塊組的方向為左的常量 */
private static final short DIRECTION_LEFT = 3;
/** 代表落下方塊組之默認方向的常量 */
private static final short DIRECTION_DEFAULT= DIRECTION_RIGHT;
/** 儲存了落下方塊組現在方向的變量 */
private short currentDirection;
/** 儲存下一個方塊資訊的Piece數組變量 */
private Piece[] nextPieces;
/** 在制作下一個方塊組時所使用的Random變量 */
private Random random = new Random();
/** 代表按鍵輸入是否有效的標志變量 */
private boolean isKeyEnable;
private static final int DEFAULT_FALL_TICK_COUNT=10;
/** 儲存用來調整方塊組落下速度用的Tick計數的變量 */
private int tickCount4Speed;
/** 儲存用來計算落下方塊組時機的Tick計數的變量 */
private int tickCount4Fall;
/** 儲存方塊組落下次數的變量 */
private int fallCount;
/** 代表游戲循環是否停止的變量 */
private boolean isStopped;
/** 判斷是否要落下下一個方塊組的標志變量 */
private boolean isNextFall;
/** 存放描繪間隔(INTERVAL)的常量 */
private static final long DRAW_INTERVAL = 100;
/** 存放默認分數增加值的常量 */
private static final int DEFAULT_SCORE_VALUE = 100;
/** 存放分數的變量 */
private long score;
/** 存放最高分數的變量 */
private long highScore = 0;
/** 存放默認字體的變量 */
private Font defFont = Font.getDefaultFont();
/** 構造函數 */
GameCanvas(Cube cube) {
this.cube = cube;
//取得畫面的可描繪范圍
screenWidth = getWidth();
screenHeight = getHeight();
//取得標題圖像
try {
titleImg = Image.createImage("/title.png");
}catch(java.io.IOException e) {}
//登錄指令監聽
setCommandListener(this);
//將游戲的狀態變成顯示標題
gameState = TITLE;
}
/** 進行游戲初始化的方法 */
private void doGameInit() {
//清除分數
score = 0;
//取得下一個方塊組
nextPieces = getNextPieces();
//清除方塊置入數組
pieces = new Piece[COLUMN_LENGTH * ROW_LENGTH];
//將調整方塊組速度用的Tick計數設為默認值
tickCount4Speed = DEFAULT_FALL_TICK_COUNT;
//清除用來計算落下方塊組時機的Tick計數
tickCount4Fall = 0;
//清除落下方塊組的數目
fallCount = 0;
//清除停止循環標志
isStopped = false;
//清除暫停標志
isPaused = false;
//建立是否落下下一個方塊組的標志
isNextFall = true;
//讓按鍵有效
isKeyEnable = true;
}
/** 指令的事件發生時被調用出來的方法 */
public void commandAction(Command c, Displayable s) {
if(c == startCmd) {//Start指令
//初始化游戲以開始游戲
doGameInit();
gameState = GAME_START;
doThreadStart();
}else if(c == exitCmd) {//EXIT指令
//調用出Cube類的doExit方法以結束MIDlet本身
cube.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();
}
}
/** MIDlet的startApp()被調用出來時所調用的方法 */
void doStartApp() {
//根據現在的狀態來操作運作
switch(gameState) {
case TITLE: //顯示標題時
doTitle();
break;
case GAME_START: //游戲開始時
case GAME_PLAYING: //游戲中
//進行暫停
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;
}
}
/**
*產生下一個落下方塊組并傳回的方法
*在@return Piece[] 之后落下的Piece數組
*/
private Piece[] getNextPieces() {
//以Random所產生的值為基礎決定種類
int kindNo= random.nextInt() % 10;
//負數的時候就將其變為正數
if(kindNo < 0) kindNo = kindNo * (-1);
Piece[] retPieces = new Piece[] {
new Piece(),
new Piece()
};
switch(kindNo) {
case 0://紅紅
retPieces[0].currentColor = Piece.RED;
retPieces[1].currentColor = Piece.RED;
break;
case 1://紅綠
retPieces[0].currentColor = Piece.RED;
retPieces[1].currentColor = Piece.GREEN;
break;
case 2://紅藍
retPieces[0].currentColor = Piece.RED;
retPieces[1].currentColor = Piece.BLUE;
break;
case 3://紅黃
retPieces[0].currentColor = Piece.RED;
retPieces[1].currentColor = Piece.YELLOW;
break;
case 4://綠綠
retPieces[0].currentColor = Piece.GREEN;
retPieces[1].currentColor = Piece.GREEN;
break;
case 5://綠藍
retPieces[0].currentColor = Piece.GREEN;
retPieces[1].currentColor = Piece.BLUE;
break;
case 6://綠黃
retPieces[0].currentColor = Piece.GREEN;
retPieces[1].currentColor = Piece.YELLOW;
break;
case 7://藍藍
retPieces[0].currentColor = Piece.BLUE;
retPieces[1].currentColor = Piece.BLUE;
break;
case 8://藍黃
retPieces[0].currentColor = Piece.BLUE;
retPieces[1].currentColor = Piece.YELLOW;
break;
case 9://黃黃
retPieces[0].currentColor = Piece.YELLOW;
retPieces[1].currentColor = Piece.YELLOW;
break;
}
return retPieces;
}
/** 按鍵按下事件發生時被調用出來的方法 */
protected synchronized void keyPressed(int keyCode) {
if( ! isKeyEnable || gameState != GAME_PLAYING ||
(gameState == GAME_PLAYING && isPaused)) {
//按鍵為無效、或是不在游戲中、在游戲中暫停時為return
return;
}
//為清除按鍵時不處理
if(keyCode == 0) return; //for KDDI
int gameCode = getGameAction(keyCode);
switch(gameCode) {
case UP: //按下上按鍵時
case FIRE: //按下Fire鍵時
doRotat();
break;
case LEFT: //按下左按鍵時
doLeft();
break;
case DOWN: //按下下按鍵時
doFall();
break;
case RIGHT: //按下右按鍵時
doRight();
break;
}
}
/** 壓下按鍵狀態時被重復調用的方法 */
protected void keyRepeated(int keyCode) {
keyPressed(keyCode);
}
/** 壓下上按鍵、決定按鍵時所調用出來的方法 */
private void doRotat() {
switch(currentDirection) {
case DIRECTION_UP: //方向為上時
//因為要作順時鐘旋轉,所以要檢查右邊
if(centerPoint % ROW_LENGTH != ROW_LENGTH -1) {
//當不是在最右邊時
if( pieces[centerPoint +1] == null &&
pieces[centerPoint -ROW_LENGTH +1] == null )
{
//若在右邊以及右邊上面都沒有東西的話就向右轉動
pieces[centerPoint +1] = pieces[centerPoint -ROW_LENGTH];
pieces[centerPoint -ROW_LENGTH] = null;
//方向轉向右
currentDirection = DIRECTION_RIGHT;
}
}
break;
case DIRECTION_RIGHT: //方向為右時
//因為要作順時鐘旋轉,所以要檢查下方
if(centerPoint < (COLUMN_LENGTH -1) * ROW_LENGTH) {
//當不是在最下面時
if( pieces[centerPoint +ROW_LENGTH] == null &&
pieces[centerPoint +1 +ROW_LENGTH] == null)
{
//當右下與正下方什么都沒有時向下移動
pieces[centerPoint +ROW_LENGTH] = pieces[centerPoint +1];
pieces[centerPoint +1] = null;
//將方向變為向下
currentDirection = DIRECTION_DOWN;
}
}
break;
case DIRECTION_DOWN: //方向為向下時
//因為要作順時鐘旋轉,所以要檢查左邊
if(centerPoint % ROW_LENGTH != 0) {
//當不在最左邊的時候
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -