前幾天看Android自帶的例子代碼,其中有個(gè)貪吃蛇的游戲,看了其代碼后覺得寫得非常好,同時(shí)又有了想寫一個(gè)俄羅斯方塊游戲的想法。俄羅斯方塊的游戲我以前曾經(jīng)用JAVA實(shí)現(xiàn)過,當(dāng)時(shí)實(shí)現(xiàn)得很復(fù)雜,而現(xiàn)在有了這個(gè)貪吃蛇的例子后,實(shí)現(xiàn)起來就簡單多了。在貪吃蛇游戲中有個(gè)類TileView.java,這個(gè)類基本實(shí)現(xiàn)了對(duì)單個(gè)方塊的操作,因此我就直接拿來用了,并沒有做任何的修改,這個(gè)類的代碼就不在這里貼出了。 俄羅斯方塊游戲比貪吃蛇稍微復(fù)雜一些,其主要的難點(diǎn)主要有: 1.實(shí)現(xiàn)方塊的旋轉(zhuǎn)。我們都知道在游戲中按上方塊是要旋轉(zhuǎn)的,我對(duì)方塊的旋轉(zhuǎn)就是選擇一個(gè)方塊作為中心,另外3個(gè)方塊都繞著它順時(shí)針旋轉(zhuǎn)90度。需要注意的一點(diǎn)就是田形的方塊是不需要旋轉(zhuǎn)的,如果按照我的方法旋轉(zhuǎn)田形方塊就會(huì)造成方塊平移的結(jié)果。 2.邊界的判定。就是判斷一下方塊是否可以移動(dòng),這包含兩方面的內(nèi)容,一方面是水平方向的移動(dòng),這里需要注意的就是在邊界上旋轉(zhuǎn)方塊又可能使方塊旋轉(zhuǎn)出邊界,所以在旋轉(zhuǎn)前必要預(yù)先判斷一下旋轉(zhuǎn)后的方塊是否已經(jīng)超出了邊界;另一方面是往下移動(dòng),一旦不能移動(dòng)了就需要凍結(jié)方塊并產(chǎn)生新的方塊。 3.消行。每落下一個(gè)方塊都需要判斷一下是否可以消行。而消行后上面的方塊又都要垂直下落,同時(shí)原來的位置也要被清空。
下面說一下實(shí)現(xiàn)這個(gè)游戲的步驟: 1.創(chuàng)建一個(gè)新的ANDROID工程,命名為Tetris,包名為com.test。 2.創(chuàng)建一個(gè)activity類,命名為:Tetris.java。
- package com.test;
-
-
import android.content.Context;
-
import android.content.res.Resources;
-
import android.os.Bundle;
-
import android.os.Handler;
-
import android.os.Message;
-
import android.util.AttributeSet;
-
import android.util.Log;
-
import android.view.KeyEvent;
-
import android.view.View;
-
import android.widget.TextView;
-
-
import java.io.File;
-
import java.io.FileNotFoundException;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
import java.util.ArrayList;
-
import java.util.Random;
-
-
public class TetrisView extends TileView {
-
-
private static final String TAG = "TetrisView";
-
-
/**
-
* 游戲的四種狀態(tài)
-
*/
-
private int mMode = READY;
-
-
public static final int PAUSE = 0;
-
-
public static final int READY = 1;
-
-
public static final int RUNNING = 2;
-
-
public static final int LOSE = 3;
-
-
/**
-
* 三種背景圖片,由這些圖片拼裝成游戲的基本界面
-
*/
-
private static final int RED_STAR = 1;
-
-
private static final int YELLOW_STAR = 2;
-
-
private static final int GREEN_STAR = 3;
-
-
/**
-
* 產(chǎn)生隨機(jī)數(shù),根據(jù)隨機(jī)數(shù)決定方塊的形狀
-
*/
-
private static final Random RNG = new Random();
-
-
/**
-
* 當(dāng)前游戲的分?jǐn)?shù)
-
*/
-
private long mScore = 0;
-
-
/**
-
* 歷史最高分
-
*/
-
public static long historyScore = 0;
-
-
/**
-
* 是否超出了最高分,如果超出了,則在退出時(shí)會(huì)保存數(shù)據(jù)
-
*/
-
public static boolean overhistroy=false;
-
/**
-
* 方塊移動(dòng)的速度,數(shù)值越小則方塊的速度越高,難度也就越大
-
*/
-
private long mMoveDelay;
-
-
/**
-
* 當(dāng)前方塊移動(dòng)的速度,和mMoveDelay配合使用,在游戲中更改游戲的速度都是更改此變量值
-
* 在每個(gè)方塊產(chǎn)生的時(shí)候,將此變量值賦給mMoveDelay。之所以采用兩個(gè)變量是因?yàn)楫?dāng)按下加速 方塊落下之后,下一個(gè)方塊的速度還要保持原來的速度。
-
*/
-
private long currentDelay;
-
-
/**
-
* 預(yù)先顯示的方塊,在前一個(gè)方塊落下后,使其變?yōu)楫?dāng)前方塊
-
*/
-
private ArrayList<Coordinate> preShape = new ArrayList<Coordinate>();
-
-
/**
-
* 當(dāng)前正在下落的方塊
-
*/
-
private ArrayList<Coordinate> mShape = new ArrayList<Coordinate>();
-
-
private ArrayList<Coordinate> oldShape = new ArrayList<Coordinate>();
-
-
/**
-
* 顯示歷史最高分的文本框
-
*/
-
private TextView highestScore;
-
-
/**
-
* 顯示當(dāng)前分?jǐn)?shù)的文本框
-
*/
-
private TextView currentScore;
-
-
/**
-
* 顯示當(dāng)前游戲級(jí)別的文本框
-
*/
-
private TextView currentLevel;
-
-
/**
-
* 記錄游戲的級(jí)別
-
*/
-
private int gameLevel = 1;
-
-
/**
-
* 在屏幕中央顯示提示信息的文本框
-
*/
-
private TextView info;
-
-
/**
-
* 記錄目前落下的方塊的最高層數(shù)
-
*/
-
private int highLevel = 0;
-
-
/**
-
* 當(dāng)前方塊類型,主要用來標(biāo)示田形方塊,從而在旋轉(zhuǎn)方塊的時(shí)候可以讓田形方塊不旋轉(zhuǎn)
-
*/
-
private int shapeType;
-
-
/**
-
* 預(yù)先顯示方塊的類型
-
*/
-
private int preType;
-
-
/**
-
* 構(gòu)造方法
-
*/
-
public TetrisView(Context context, AttributeSet attrs) {
-
super(context, attrs);
-
initGame();
-
}
-
-
public TetrisView(Context context, AttributeSet attrs, int defStyle) {
-
super(context, attrs, defStyle);
-
initGame();
-
}
-
-
/**
-
* 通過一個(gè)handler來更新界面的顯示,以及方塊下落的速度
-
*/
-
private RefreshHandler mRedrawHandler = new RefreshHandler();
-
-
class RefreshHandler extends Handler {
-
-
@Override
-
public void handleMessage(Message msg) {
-
TetrisView.this.update();
-
TetrisView.this.invalidate();
-
-
}
-
-
public void sleep(long delayMillis) {
-
this.removeMessages(0);
-
sendMessageDelayed(obtainMessage(0), delayMillis);
-
}
-
};
-
-
/**
-
* 初始化游戲
-
*/
-
private void initGame() {
-
setFocusable(true);
-
Resources r = this.getContext().getResources();
-
resetTiles(4);
-
loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
-
loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
-
loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));
-
-
}
-
-
/**
-
* 開始一個(gè)新游戲,重置各種數(shù)據(jù)
-
*/
-
private void startGame() {
-
clearTiles();
-
gameLevel = 1;
-
highLevel = 0;
-
currentDelay = 600;
-
mScore = 0;
-
currentScore.setText("當(dāng)前分?jǐn)?shù):\n" + mScore);
-
currentLevel.setText("當(dāng)前級(jí)別:\n" + gameLevel);
-
highestScore.setText("最高分?jǐn)?shù):\n"+historyScore);
-
setMode(RUNNING);
-
}
-
-
-
/**
-
* 將arraylist轉(zhuǎn)換為數(shù)組,從而可以將該部分?jǐn)?shù)據(jù)保存起來
-
*/
-
private int[] coordArrayListToArray(ArrayList<Coordinate> cvec) {
-
int count = cvec.size();
-
int[] rawArray = new int[count * 2];
-
for (int index = 0; index < count; index++) {
-
Coordinate c = cvec.get(index);
-
rawArray[2 * index] = c.x;
-
rawArray[2 * index + 1] = c.y;
-
}
-
return rawArray;
-
}
-
-
/**
-
* 將已經(jīng)落下來的方塊的坐標(biāo)保存在一個(gè)ArrayList中
-
*/
-
private ArrayList<Coordinate> tailsToList(int[][] tileGrid) {
-
ArrayList<Coordinate> tranList = new ArrayList<Coordinate>();
-
for (int i = 0; i < mXTileCount - 6; i++) {
-
for (int j = 1; j < mYTileCount - 1; j++) {
-
if (tileGrid[i][j] == RED_STAR) {
-
Coordinate cor = new Coordinate(i, j);
-
tranList.add(cor);
-
}
-
}
-
}
-
return tranList;
-
}
-
-
/**
-
* 保存游戲的狀態(tài),從而在切換游戲后還可以繼續(xù)游戲
-
*
-
* @return a Bundle with this view's state
-
*/
-
public Bundle saveState() {
-
Bundle map = new Bundle();
-
map.putIntArray("preShapeList", coordArrayListToArray(preShape));
-
map.putIntArray("mShapeList", coordArrayListToArray(mShape));
-
map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
-
map.putLong("mScore", Long.valueOf(mScore));
-
map.putLong("hisScore", Long.valueOf(historyScore));
-
map.putInt("mLevel", highLevel);
-
map.putIntArray("tailList", coordArrayListToArray(tailsToList(mTileGrid)));
-
-
return map;
-
}
-
-
/**
-
* 將數(shù)組轉(zhuǎn)換為Arraylist,從而將保存的數(shù)據(jù)轉(zhuǎn)化為游戲的狀態(tài)
-
*
-
* @param rawArray : [x1,y1,x2,y2,...]
-
* @return a ArrayList of Coordinates
-
*/
-
private ArrayList<Coordinate> coordArrayToArrayList(int[] rawArray) {
-
ArrayList<Coordinate> coordArrayList = new ArrayList<Coordinate>();
-
int coordCount = rawArray.length;
-
for (int index = 0; index < coordCount; index += 2) {
-
Coordinate c = new Coordinate(rawArray[index], rawArray[index + 1]);
-
coordArrayList.add(c);
-
}
-
return coordArrayList;
-
}
-
-
/**
-
* 從保存的數(shù)據(jù)中讀取已經(jīng)落下的方塊坐標(biāo),并重新在界面上畫出這些方塊
-
*/
-
private void listToTail(ArrayList<Coordinate> cor) {
-
int count = cor.size();
-
-
for (int index = 0; index < count; index++) {
-
Coordinate c = cor.get(index);
-
mTileGrid[c.x][c.y] = RED_STAR;
-
}
-
}
-
-
/**
-
* 切換到游戲的時(shí)候,讀取所保存的數(shù)據(jù),重現(xiàn)游戲先前的狀態(tài)
-
*
-
* @param icicle a Bundle containing the game state
-
*/
-
public void restoreState(Bundle icicle) {
-
setMode(PAUSE);
-
historyScore = icicle.getLong("hisScore");
-
highLevel = icicle.getInt("mLevel");
-
mMoveDelay = icicle.getLong("mMoveDelay");
-
mScore = icicle.getLong("mScore");
-
preShape = coordArrayToArrayList(icicle.getIntArray("preShapeList"));
-
mShape = coordArrayToArrayList(icicle.getIntArray("mShapeList"));
-
listToTail(coordArrayToArrayList(icicle.getIntArray("tailList")));
-
}
-
-
/**
-
* 對(duì)按鍵的響應(yīng)
-
*/
-
public boolean onKeyDown(int keyCode, KeyEvent msg) {
-
// 按下了上鍵
-
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
-
if (mMode == READY | mMode == LOSE) {
-
-
startGame();
-
setMode(RUNNING);
-
return (true);
-
} else if (mMode == RUNNING) {
-
transShape();
-
update();
-
return (true);
-
}
-
if (mMode == PAUSE) {
-
setMode(RUNNING);
-
update();
-
return (true);
-
}
-
}
-
// 按下了下鍵
-
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
-
moveDown();
-
-
return (true);
-
}
-
// 按下了左鍵
-
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
-
moveLeft();
-
updateShape();
-
return (true);
-
}
-
// 按下了右鍵
-
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
-
moveRight();
-
updateShape();
-
return (true);
-
}
-
return super.onKeyDown(keyCode, msg);
-
}
-
-
/**
-
* 加速方塊的下落
-
*/
-
private void moveDown() {
-
mMoveDelay = 50;
-
}
-
-
/**
-
* 將方塊向右移動(dòng),在移動(dòng)前要判斷一下是否可以移動(dòng)
-
*/
-
private void moveRight() {
-
newToOld(mShape, oldShape);
-
for (Coordinate c : mShape) {
-
c.x = c.x + 1;
-
}
-
// 如果不可以移動(dòng),則保持位置不變
-
if (!isMoveAble(mShape)) {
-
for (Coordinate c : mShape) {
-
c.x = c.x - 1;
-
}
-
}
-
}
-
-
/**
-
* 將方塊向左移動(dòng)
-
*/
-
private void moveLeft() {
-
newToOld(mShape, oldShape);
-
for (Coordinate c : mShape) {
-
c.x = c.x - 1;
-
}
-
if (!isMoveAble(mShape)) {
-
for (Coordinate c : mShape) {
-
c.x = c.x + 1;
-
}
-
}
-
}
-
-
/**
-
* 旋轉(zhuǎn)方塊
-
*/
-
private void transShape() {
-
Coordinate core = mShape.get(0);
-
if (shapeType == 3) {
-
// 田形,不用做任何事情
-
} else {
-
newToOld(mShape, oldShape);
-
for (Coordinate c : mShape) {
-
int x = core.x + (core.y - c.y);
-
int y = core.y + (c.x - core.x);
-
c.x = x;
-
c.y = y;
-
}
-
// 如果可以旋轉(zhuǎn),則旋轉(zhuǎn)90度并更新顯示
-
if (isMoveAble(mShape)) {
-
updateShape();
-
TetrisView.this.invalidate();
-
} else {
-
for (Coordinate c : mShape) {
-
int x = core.x + (c.y - core.y);
-
int y = core.y + (core.x - c.x);
-
c.x = x;
-
c.y = y;
-
}
-
}
-
-
}
-
-
}
-
-
/**
-
* 將一個(gè)方塊的形狀賦給另外一個(gè)
-
*
-
* @param mShape2
-
* @param oldShape2
-
*/
-
private void newToOld(ArrayList<Coordinate> mShape2, ArrayList<Coordinate> oldShape2) {
-
oldShape2.clear();
-
for (int i = 0; i < 4; i++) {
-
Coordinate c1 = mShape2.get(i);
-
Coordinate c2 = new Coordinate(c1.x, c1.y);
-
oldShape2.add(c2);
-
}
-
-
}
-
-
/**
-
* 處理游戲的更新
-
*/
-
public void update() {
-
if (mMode == RUNNING) {
-
// clearTiles();
-
updateBlackGround();
-
if (mXTileCount != 0) {
-
// 如果是剛開始游戲,則初始化方塊形狀
-
if (mShape.size() == 0) {
-
shapeType = RNG.nextInt(7);
-
mShape = getShape(shapeType);
-
preType = RNG.nextInt(7);
-
preShape = getShape(preType);
-
mMoveDelay = currentDelay;
-
// 設(shè)置方塊的初始位置
-
for (Coordinate c : mShape) {
-
c.x = c.x + mXTileCount / 3;
-
c.y = c.y + 1;
-
}
-
}
-
// 將方塊往下移動(dòng)一格
-
newToOld(mShape, oldShape);
-
for (Coordinate c : mShape) {
-
c.y++;
-
}
-
// 如果方塊可以往下移動(dòng),則更新圖形
-
if (canMoveDown(mShape)) {
-
updateShape();
-
} else {
-
// 如果不可以往下移動(dòng)則將方塊的狀態(tài)改為已落下并開始落下新方塊
-
updateBlew();
-
mShape = preShape;
-
shapeType = preType;
-
for (Coordinate c : mShape) {
-
c.x = c.x + mXTileCount / 3;
-
c.y = c.y + 1;
-
}
-
preType = RNG.nextInt(7);
-
preShape = getShape(preType);
-
mMoveDelay = currentDelay;
-
}
-
updatePreShape();
-
}
-
}
-
// 設(shè)置方塊落下的速度
-
mRedrawHandler.sleep(mMoveDelay);
-
-
}
-
-
// 方塊落下過程中顏色為黃色
-
private void updateShape() {
-
for (Coordinate c : oldShape) {
-
setTile(0, c.x, c.y);
-
Log.d(TAG, "old" + c.x + c.y);
-
}
-
for (Coordinate c : mShape) {
-
Log.d(TAG, "new" + c.x + c.y);
-
if (mXTileCount != 0) {
-
setTile(YELLOW_STAR, c.x, c.y);
-
}
-
-
}
-
-
}
-
-
// 方塊落下后顏色為紅色
-
private void updateBlew() {
-
for (Coordinate c : mShape) {
-
if (mXTileCount != 0) {
-
setTile(RED_STAR, c.x, c.y - 1);
-
if (mYTileCount - c.y > highLevel) {
-
highLevel = mYTileCount - c.y;
-
-
}
-
}
-
-
}
-
// GAME OVER
-
if (highLevel > mYTileCount - 3) {
-
setMode(LOSE);
-
}
-
// 已經(jīng)消去的行數(shù)
-
int deleRows = 0;
-
for (int i = 1; i <= highLevel + 1; i++) {
-
int redCount = 0;
-
for (int x = 1; x < mXTileCount - 7; x++) {
-
if (mTileGrid[x][mYTileCount - i] == RED_STAR) {
-
redCount++;
-
}
-
}
-
// 如果某一行的紅色方格數(shù)等于列總數(shù),則該列需要消去
-
if (redCount == mXTileCount -8 ) {
-
deleRows++;
-
continue;
-
} else {
-
// 將不需要消去的行向下移動(dòng),移動(dòng)的幅度取決于前面消去的行數(shù)
-
if (deleRows != 0) {
-
for (int x = 1; x < mXTileCount - 6; x++) {
-
mTileGrid[x][mYTileCount - i + deleRows] = mTileGrid[x][mYTileCount - i];
-
mTileGrid[x][mYTileCount - i] = 0;
-
}
-
}
-
}
-
}
-
// 更改分?jǐn)?shù),一次性消去的行數(shù)越多,得到的分?jǐn)?shù)就越多
-
switch (deleRows) {
-
case 1:
-
mScore = mScore + 100;
-
break;
-
case 2:
-
mScore = mScore + 300;
-
break;
-
case 3:
-
mScore = mScore + 500;
-
break;
-
case 4:
-
mScore = mScore + 800;
-
break;
-
}
-
// 更新最高分
-
if (mScore > historyScore) {
-
overhistroy=true;
-
historyScore = mScore;
-
highestScore.setText("最高分?jǐn)?shù): \n" + historyScore);
-
}
-
// 更新當(dāng)前分
-
currentScore.setText("當(dāng)前分?jǐn)?shù):\n" + mScore);
-
// 當(dāng)級(jí)別達(dá)到一定的程度后不再增加方塊下落的速度
-
if (mScore >= (500 * (gameLevel * 2 - 1))) {
-
gameLevel++;
-
currentDelay -= 50;
-
if (currentDelay < 50)
-
currentDelay = 50;
-
}
-
// 更新當(dāng)前級(jí)別
-
currentLevel.setText("當(dāng)前級(jí)別:\n" + gameLevel);
-
}
-
-
/**
-
* 設(shè)置游戲的狀態(tài)
-
*
-
* @param newMode
-
*/
-
public void setMode(int newMode) {
-
int oldMode = mMode;
-
mMode = newMode;
-
if (newMode == RUNNING & oldMode != RUNNING) {
-
info.setVisibility(View.INVISIBLE);
-
update();
-
return;
-
}
-
-
Resources res = getContext().getResources();
-
CharSequence str = "";
-
if (newMode == PAUSE) {
-
str = res.getText(R.string.mode_pause);
-
}
-
if (newMode == READY) {
-
str = res.getText(R.string.mode_ready);
-
}
-
if (newMode == LOSE) {
-
str = res.getString(R.string.mode_lose_prefix) + mScore
-
+ res.getString(R.string.mode_lose_suffix);
-
}
-
// 顯示提示信息
-
info.setText(str);
-
info.setVisibility(View.VISIBLE);
-
}
-
-
/**
-
* 更新預(yù)先顯示方塊
-
*/
-
private void updatePreShape() {
-
for (int x = mXTileCount - 4; x < mXTileCount; x++) {
-
for (int y = 1; y < 6; y++) {
-
setTile(0, x, y);
-
-
}
-
}
-
for (Coordinate c : preShape) {
-
if (mXTileCount != 0) {
-
setTile(YELLOW_STAR, c.x + mXTileCount - 3, c.y + 2);
-
}
-
}
-
}
-
-
/**
-
* 判斷方塊是否可以移動(dòng)
-
*
-
* @param list
-
* @return
-
*/
-
private boolean isMoveAble(ArrayList<Coordinate> list) {
-
boolean moveAble = true;
-
for (Coordinate c : list) {
-
-
if (mTileGrid[c.x][c.y] != GREEN_STAR && mTileGrid[c.x][c.y] != RED_STAR) {
-
continue;
-
} else {
-
moveAble = false;
-
break;
-
}
-
}
-
return moveAble;
-
-
}
-
-
/**
-
* 判斷方塊是否可以往下移動(dòng)
-
*
-
* @param list
-
* @return
-
*/
-
private boolean canMoveDown(ArrayList<Coordinate> list) {
-
boolean moveAble = true;
-
for (Coordinate c : list) {
-
if (c.y < mYTileCount - 1 && mTileGrid[c.x][c.y] != RED_STAR) {
-
continue;
-
} else {
-
moveAble = false;
-
break;
-
}
-
}
-
return moveAble;
-
-
}
-
-
/**
-
* 畫出游戲的背景.即游戲的邊框
-
*
-
*/
-
private void updateBlackGround() {
-
for (int x = 0; x < mXTileCount - 5; x++) {
-
setTile(GREEN_STAR, x, 0);
-
setTile(GREEN_STAR, x, mYTileCount - 1);
-
}
-
for (int y = 1; y < mYTileCount - 1; y++) {
-
setTile(GREEN_STAR, 0, y);
-
setTile(GREEN_STAR, mXTileCount - 6, y);
-
}
-
}
-
-
/**
-
* 根據(jù)隨機(jī)數(shù)產(chǎn)生各種形狀的方塊
-
*
-
* @param n
-
* @return
-
*/
-
private ArrayList<Coordinate> getShape(int n) {
-
ArrayList<Coordinate> shape = new ArrayList<Coordinate>();
-
switch (n) {
-
case 1:
-
// 反Z拐角
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(1, 0));
-
shape.add(new Coordinate(0, 1));
-
shape.add(new Coordinate(-1, 1));
-
break;
-
case 2:
-
// 正Z拐角
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(-1, 0));
-
shape.add(new Coordinate(0, 1));
-
shape.add(new Coordinate(1, 1));
-
break;
-
case 3:
-
// 田形
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(0, 1));
-
shape.add(new Coordinate(1, 0));
-
shape.add(new Coordinate(1, 1));
-
break;
-
case 4:
-
// 長條
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(-1, 0));
-
shape.add(new Coordinate(1, 0));
-
shape.add(new Coordinate(2, 0));
-
break;
-
case 5:
-
// 長左拐形
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(-1, 0));
-
shape.add(new Coordinate(0, 1));
-
shape.add(new Coordinate(0, 2));
-
break;
-
case 6:
-
// 長右拐形
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(1, 0));
-
shape.add(new Coordinate(0, 1));
-
shape.add(new Coordinate(0, 2));
-
break;
-
case 0:
-
// 凸形
-
shape.add(new Coordinate(0, 0));
-
shape.add(new Coordinate(-1, 0));
-
shape.add(new Coordinate(1, 0));
-
shape.add(new Coordinate(0, 1));
-
break;
-
}
-
return shape;
-
}
-
-
public void setTextView(TextView curView, TextView higView, TextView infView, TextView levView) {
-
currentScore = curView;
-
highestScore = higView;
-
info = infView;
-
currentLevel = levView;
-
}
-
-
/**
-
* 用來標(biāo)示某一坐標(biāo)上的方塊
-
*
-
*/
-
private class Coordinate {
-
public int x;
-
-
public int y;
-
-
public Coordinate(int newX, int newY) {
-
x = newX;
-
y = newY;
-
}
-
-
public boolean equals(Coordinate other) {
-
if (x == other.x && y == other.y) {
-
return true;
-
}
-
return false;
-
}
-
-
public String toString() {
-
return "Coordinate: [" + x + "," + y + "]";
-
}
-
}
-
}
4.創(chuàng)建類TileView.java。該類是從貪吃蛇中復(fù)制過來的,沒做任何修改,可以直接拿來用? 以在sdk的smples/android 2.x.x/Snake目錄中找到。
5.將貪吃蛇游戲res/drawable目錄下的三個(gè)圖片文件復(fù)制到自己工程的res/drawable目錄中,如果沒有這個(gè)目錄可以創(chuàng)建或者放在其他的drawable-xxx目錄中。
6.創(chuàng)建布局文件tetris_layout.xml
- <?xml version="1.0" encoding="utf-8"?>
-
<FrameLayout
-
xmlns:android="http://schemas.android.com/apk/res/android"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
<com.test.TetrisView
-
android:id="@+id/tetris"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
tileSize="24" />
-
<RelativeLayout
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
<TextView
-
android:id="@+id/info"
-
android:text="@string/mode_ready"
-
android:visibility="visible"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_centerInParent="true"
-
android:gravity="center_horizontal"
-
android:textColor="#ff8888ff"
-
android:textSize="20sp" />
-
<TextView
-
android:id="@+id/current_score"
-
android:text="當(dāng)前分?jǐn)?shù):\n 0"
-
android:visibility="visible"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_centerVertical="true"
-
-
android:layout_alignParentRight="true"
-
android:textColor="#ff8888ff"
-
android:textSize="16sp" />
-
<TextView
-
android:id="@+id/highest_score"
-
android:text="最高分?jǐn)?shù):\n 0"
-
android:visibility="visible"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_above="@id/current_score"
-
android:layout_alignParentRight="true"
-
android:textColor="#ff8888ff"
-
android:textSize="16sp" />
-
-
<TextView
-
android:id="@+id/current_level"
-
android:text="當(dāng)前級(jí)別:\n 1"
-
android:visibility="visible"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_below="@id/current_score"
-
android:layout_alignParentRight="true"
-
android:textColor="#ff8888ff"
-
android:textSize="16sp" />
-
-
</RelativeLayout>
-
</FrameLayout>
7.打開res/values/strings.xml,將其修改為以下內(nèi)容:
- <?xml version="1.0" encoding="utf-8"?>
-
<resources>
-
-
<string
-
name="app_name">Tetris</string>
-
<string
-
name="mode_ready">\n按上開始游戲 </string>
-
<string
-
name="mode_pause"> 暫停\n按上繼續(xù)游戲 </string>
-
<string
-
name="mode_lose_prefix">Game Over\nScore: </string>
-
<string
-
name="mode_lose_suffix">\n按上重新開始游戲 </string>
-
</resources>
8.打開AndroidManifest.xml,修改其內(nèi)容如下:
- <?xml version="1.0" encoding="utf-8"?>
-
<manifest
-
xmlns:android="http://schemas.android.com/apk/res/android"
-
package="com.test"
-
android:versionCode="1"
-
android:versionName="1.0">
-
<application
-
android:icon="@drawable/icon"
-
android:label="@string/app_name">
-
<activity
-
android:name=".Tetris"
-
android:theme="@android:style/Theme.NoTitleBar"
-
android:screenOrientation="portrait"
-
android:configChanges="keyboardHidden|orientation">
-
<intent-filter>
-
<action
-
android:name="android.intent.action.MAIN" />
-
<category
-
android:name="android.intent.category.LAUNCHER" />
-
</intent-filter>
-
</activity>
-
-
</application>
-
</manifest>
至此,一個(gè)簡單的俄羅斯方塊游戲就完成了,游戲運(yùn)行時(shí)的圖片為:
|