




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】Android實現(xiàn)俄羅斯方塊的方法
這篇文章主要介紹了Android實現(xiàn)俄羅斯方塊的方法,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓在下帶著大家一起了解一下。具體內(nèi)容如下思路:首先要畫出游戲背景墻;其次,要有方塊,以及方塊單元;方塊的不同形狀,顏色隨機產(chǎn)生;游戲的控制面板??赡軙霈F(xiàn)的問題或者難點:邊界問題:①處于邊界的時候,方塊不可以再左右移動;②下降的時候,到達(dá)邊界即底部,則不可繼續(xù)下落,此時應(yīng)該產(chǎn)生一個新的方塊;與其它方塊接觸問題:①下落的時候,如果碰到其它的方塊則停止下落;②左右移動的時候,移動的過程中,如果接觸到其他方快,則不可再繼續(xù)左右移動;方塊的消除:①調(diào)用方塊消除方法的時間:當(dāng)方塊下落到底部的時候,判斷是否有需要消除的行;②消除某一行之后,應(yīng)該把這一行上面的全部方塊下移一行;方塊的旋轉(zhuǎn):在當(dāng)前項目中,我采用的是順時針旋轉(zhuǎn)。①當(dāng)旋轉(zhuǎn)的時候,如果出現(xiàn)方塊部分超出了邊界,應(yīng)該對方塊進(jìn)行平移,使其回到邊界以內(nèi)。(曾在網(wǎng)上看到有人做過,判斷旋轉(zhuǎn)之后是否會超出邊界,如果會超出,則不進(jìn)行旋轉(zhuǎn),我覺得不好,方塊只要沒有下落到底部,我覺得都可以進(jìn)行旋轉(zhuǎn),除了沒有空間讓其旋轉(zhuǎn)外);②如果空間不足以旋轉(zhuǎn),也不可以旋轉(zhuǎn)??臻g不足以旋轉(zhuǎn)的意思是:比如橫向方向只有兩個的空間,而方塊旋轉(zhuǎn)后會占用三個空間,此時也不可進(jìn)行旋轉(zhuǎn);③當(dāng)無法繼續(xù)下落或者下落到了底部也不可再進(jìn)行旋轉(zhuǎn)控制面板:①游戲開始、暫停、繼續(xù)、結(jié)束,這些狀態(tài)應(yīng)該怎么去控制,以及游戲與控制臺的事件關(guān)聯(lián)。未發(fā)現(xiàn)的問題:因為本人能力,只做到這么多,如果有人發(fā)現(xiàn)問題,可以留言交流,歡迎挑問題。游戲的運行界面如下所示,基本的功能以及操作很簡單。下面直接看項目代碼項目文件結(jié)構(gòu)下面分別介紹每個類的功能TetrisViewAW.java游戲的主界面,背景墻以及方塊都在此TetrisViewAW.Java里面,就是一個自定義的View,(默認(rèn)大家對于自定義View是熟悉的),在改類里面,有一個游戲主線程,用于控制游戲的開始,暫停,繼續(xù),停止,以及方塊下落的速率。代碼我加了很多注釋,看不懂的可以留言。還有一點需要注意,當(dāng)停止游戲時,要釋放線程,養(yǎng)成好習(xí)慣/**
*
俄羅斯方塊Game主界面
*
*
@sign
Created
by
wang.ao
on
2017年1月12日
*/
@SuppressLint("DrawAllocation")
public
class
TetrisViewAW
extends
View
{
/**
網(wǎng)格開始坐標(biāo)值,橫縱坐標(biāo)的開始值都是此值
*/
public
static
final
int
beginPoint
=
10;
/**
俄羅斯方塊的最大坐標(biāo)
*/
private
static
int
max_x,
max_y;
/**
行數(shù)和列數(shù)
*/
private
static
int
num_x
=
0,
num_y
=
0;
/**
背景墻畫筆
*/
private
static
Paint
paintWall
=
null;
/**
俄羅斯方塊的單元塊畫筆
*/
private
static
Paint
paintBlock
=
null;
private
static
final
int
BOUND_WIDTH_OF_WALL
=
2;
/**
當(dāng)前正在下落的方塊
*/
private
List<BlockUnit>
blockUnits
=
new
ArrayList<BlockUnit>();
/**
下一個要顯示的方塊
*/
private
List<BlockUnit>
blockUnitBufs
=
new
ArrayList<BlockUnit>();
/**
下一個要顯示的方塊
*/
private
List<BlockUnit>
routeBlockUnitBufs
=
new
ArrayList<BlockUnit>();
/**
全部的方塊allBlockUnits
*/
private
List<BlockUnit>
allBlockUnits
=
new
ArrayList<BlockUnit>();
/**
調(diào)用此對象的Activity對象
*/
private
TetrisActivityAW
father
=
null;
private
int[]
map
=
new
int[100];
//
保存每行網(wǎng)格中包含俄羅斯方塊單元的個數(shù)
/**
游戲的主線程
*/
private
Thread
mainThread
=
null;
//
游戲的幾種狀態(tài)
/**
標(biāo)識游戲是開始還是停止
*/
private
boolean
gameStatus
=
false;
/**
標(biāo)識游戲是暫停還是運行
*/
private
boolean
runningStatus
=
false;
/**
俄羅斯方塊顏色數(shù)組
*/
private
static
final
int
color[]
=
{
Color.parseColor("#FF6600"),
Color.BLUE,
Color.RED,
Color.GREEN,
Color.GRAY
};
/**
方塊的中心方塊單元的坐標(biāo),
*/
private
int
xx,
yy;
/**
方塊,用戶隨機獲取各種形狀的方塊
*/
private
TetrisBlock
tetrisBlock;
/**
分?jǐn)?shù)
*/
private
int
score
=
0;
/**
當(dāng)前方塊的類型
*/
private
int
blockType
=
0;
public
TetrisViewAW(Context
context)
{
this(context,
null);
}
public
TetrisViewAW(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
if
(paintWall
==
null)
{//
初始化化背景墻畫筆
paintWall
=
new
Paint();
paintWall.setColor(Color.LTGRAY);
paintWall.setStyle(Paint.Style.STROKE);
paintWall.setStrokeWidth(BOUND_WIDTH_OF_WALL
+
1);
}
if
(paintBlock
==
null)
{//
初始化化背景墻畫筆
paintBlock
=
new
Paint();
paintBlock.setColor(Color.parseColor("#FF6600"));
}
tetrisBlock
=
new
TetrisBlock();
routeBlockUnitBufs
=
tetrisBlock.getUnits(beginPoint,
beginPoint);
Arrays.fill(map,
0);
//
每行網(wǎng)格中包含俄羅斯方塊單元的個數(shù)全部初始化為0
//
繪制方塊
}
/**
*
設(shè)置當(dāng)前游戲頁面的父類activity
*
*
@param
tetrisActivityAW
*/
public
void
setFather(TetrisActivityAW
tetrisActivityAW)
{
father
=
tetrisActivityAW;
}
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
max_x
=
getWidth();
max_y
=
getHeight();
RectF
rel;
//
繪制網(wǎng)格
num_x
=
0;
num_y
=
0;
for
(int
i
=
beginPoint;
i
<
max_x
-
BlockUnit.UNIT_SIZE;
i
+=
BlockUnit.UNIT_SIZE)
{
for
(int
j
=
beginPoint;
j
<
max_y
-
BlockUnit.UNIT_SIZE;
j
+=
BlockUnit.UNIT_SIZE)
{
rel
=
new
RectF(i,
j,
i
+
BlockUnit.UNIT_SIZE,
j
+
BlockUnit.UNIT_SIZE);
canvas.drawRoundRect(rel,
8,
8,
paintWall);
num_y++;
}
num_x++;
}
//
隨機產(chǎn)生一個俄羅斯方塊
int
len
=
blockUnits.size();
//
繪制方塊
//
Toast.makeText(context,
""
+
len,
Toast.LENGTH_SHORT).show();
for
(int
i
=
0;
i
<
len;
i++)
{
int
x
=
blockUnits.get(i).x;
int
y
=
blockUnits.get(i).y;
//
設(shè)置當(dāng)前方塊的顏色
paintBlock.setColor(color[blockUnits.get(i).color]);
rel
=
new
RectF(x
+
BOUND_WIDTH_OF_WALL,
y
+
BOUND_WIDTH_OF_WALL,
x
+
BlockUnit.UNIT_SIZE
-
BOUND_WIDTH_OF_WALL,
y
+
BlockUnit.UNIT_SIZE
-
BOUND_WIDTH_OF_WALL);
canvas.drawRoundRect(rel,
8,
8,
paintBlock);
}
//
隨機產(chǎn)生一個俄羅斯方塊
len
=
allBlockUnits.size();
//
繪制方塊
//
Toast.makeText(context,
""
+
len,
Toast.LENGTH_SHORT).show();
for
(int
i
=
0;
i
<
len;
i++)
{
int
x
=
allBlockUnits.get(i).x;
int
y
=
allBlockUnits.get(i).y;
paintBlock.setColor(color[allBlockUnits.get(i).color]);
rel
=
new
RectF(x
+
BOUND_WIDTH_OF_WALL,
y
+
BOUND_WIDTH_OF_WALL,
x
+
BlockUnit.UNIT_SIZE
-
BOUND_WIDTH_OF_WALL,
y
+
BlockUnit.UNIT_SIZE
-
BOUND_WIDTH_OF_WALL);
canvas.drawRoundRect(rel,
8,
8,
paintBlock);
}
}
/**
*
開始游戲
*/
public
void
startGame()
{
gameStatus
=
true;
runningStatus
=
true;
if
(mainThread
==
null
||
!mainThread.isAlive())
{
getNewBlock();
mainThread
=
new
Thread(new
MainThread());
mainThread.start();
}
}
/**
*
暫停游戲
*/
public
void
pauseGame()
{
runningStatus
=
false;
}
/**
*
繼續(xù)游戲
*/
public
void
continueGame()
{
runningStatus
=
true;
}
/**
*
停止游戲
*/
public
void
stopGame()
{
//
停止游戲,釋放游戲主線程
runningStatus
=
false;
gameStatus
=
false;
mainTerrupt();
blockUnits.clear();
allBlockUnits.clear();
score
=
0;
invalidate();
}
/**
*
向左滑動
*/
public
void
toLeft()
{
if
(BlockUnit.toLeft(blockUnits,
max_x,
allBlockUnits))
{
xx
=
xx
-
BlockUnit.UNIT_SIZE;
}
invalidate();
}
/**
*
向右滑動
*/
public
void
toRight()
{
if
(BlockUnit.toRight(blockUnits,
max_x,
allBlockUnits))
{
xx
=
xx
+
BlockUnit.UNIT_SIZE;
}
invalidate();
}
/**
*
按順時針旋轉(zhuǎn)
*/
public
void
route()
{
if
(blockType
==
3)
{//
如果當(dāng)前正在下落的方塊為正方形,則不進(jìn)行旋轉(zhuǎn)
return;
}
if
(routeBlockUnitBufs.size()
!=
blockUnits.size())
{
routeBlockUnitBufs
=
tetrisBlock.getUnits(xx,
yy);
}
for
(int
i
=
0;
i
<
blockUnits.size();
i++)
{
routeBlockUnitBufs.get(i).x
=
blockUnits.get(i).x;
routeBlockUnitBufs.get(i).y
=
blockUnits.get(i).y;
}
for
(BlockUnit
blockUnit
:
routeBlockUnitBufs)
{
int
tx
=
blockUnit.x;
int
ty
=
blockUnit.y;
blockUnit.x
=
-(ty
-
yy)
+
xx;
blockUnit.y
=
tx
-
xx
+
yy;
}
routeTran(routeBlockUnitBufs);
if
(!BlockUnit.canRoute(routeBlockUnitBufs,
allBlockUnits))
{
//
Toast.makeText(father,
"不可旋轉(zhuǎn)",
Toast.LENGTH_SHORT).show();
return;
}
for
(BlockUnit
blockUnit
:
blockUnits)
{
int
tx
=
blockUnit.x;
int
ty
=
blockUnit.y;
blockUnit.x
=
-(ty
-
yy)
+
xx;
blockUnit.y
=
tx
-
xx
+
yy;
}
routeTran(blockUnits);
invalidate();
}
/**
*
如果方塊處于邊緣,則翻轉(zhuǎn)過后,會出現(xiàn)方塊部分處于邊緣之外的情況,
因此,通過遞歸判斷是否有超出邊緣的部分,
*
如果有,則進(jìn)行左右平移,把處于邊緣外的方塊移動到邊緣內(nèi)
*/
public
void
routeTran(List<BlockUnit>
blockUnitsBuf)
{
boolean
needLeftTran
=
false;
boolean
needRightTran
=
false;
for
(BlockUnit
u
:
blockUnitsBuf)
{
if
(u.x
<
beginPoint)
{
needLeftTran
=
true;
}
if
(u.x
>
max_x
-
BlockUnit.UNIT_SIZE)
{
needRightTran
=
true;
}
}
if
(needLeftTran
||
needRightTran)
{
for
(BlockUnit
u
:
blockUnitsBuf)
{
if
(needLeftTran)
{
u.x
=
u.x
+
BlockUnit.UNIT_SIZE;
}
else
if
(needRightTran)
{
u.x
=
u.x
-
BlockUnit.UNIT_SIZE;
}
}
routeTran(blockUnitsBuf);
}
else
{
return;
}
}
/**
*
獲取一個新的方塊
*/
private
void
getNewBlock()
{
//
新的方塊的坐標(biāo),x坐標(biāo)位于x軸的中間,y
位于起始位置
this.xx
=
beginPoint
+
(num_x
/
2)
*
BlockUnit.UNIT_SIZE;
this.yy
=
beginPoint;
if
(blockUnitBufs.size()
==
0)
{
//
當(dāng)游戲第一次開始的時候,先初始化一個方塊
blockUnitBufs
=
tetrisBlock.getUnits(xx,
yy);
}
blockUnits
=
blockUnitBufs;
blockType
=
tetrisBlock.blockType;
blockUnitBufs
=
tetrisBlock.getUnits(xx,
yy);
if
(father
!=
null)
{//
顯示出下一個要出現(xiàn)的方塊
father.setNextBlockView(blockUnitBufs,
(num_x
/
2)
*
BlockUnit.UNIT_SIZE);
}
}
/**
*
游戲的主線程
*
*
@sign
Created
by
wang.ao
on
2017年1月16日
*/
private
class
MainThread
implements
Runnable
{
@Override
public
void
run()
{
while
(gameStatus)
{
while
(runningStatus)
{
if
(BlockUnit.canMoveToDown(blockUnits,
max_y,
allBlockUnits))
{
//
判斷是否可以繼續(xù)下落,如果可以下落,則下落
BlockUnit.toDown(blockUnits,
max_y,
allBlockUnits);
yy
=
yy
+
BlockUnit.UNIT_SIZE;
}
else
{
/**
*
當(dāng)不可以繼續(xù)下落的時候,把當(dāng)前的方塊添加到allBlockUnits中,
*
并且判斷是否有需要消除的方塊,然后再產(chǎn)生一個新的方塊
*/
for
(BlockUnit
blockUnit
:
blockUnits)
{
blockUnit.y
=
blockUnit.y
+
BlockUnit.UNIT_SIZE;
allBlockUnits.add(blockUnit);
}
for
(BlockUnit
u
:
blockUnits)
{
//
更新map,即更新每行網(wǎng)格中靜止俄羅斯方塊單元的個數(shù)
int
index
=
(int)
((u.y
-
beginPoint)
/
50);
//
計算所在行數(shù)
map[index]++;
}
//
每行最大個數(shù)
int
end
=
(int)
((max_y
-
50
-
beginPoint)
/
BlockUnit.UNIT_SIZE);
int
full
=
(int)
((max_x
-
50
-
beginPoint)
/
BlockUnit.UNIT_SIZE)
+
1;
try
{
Thread.sleep(GameConfig.SPEED);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
for
(int
i
=
0;
i
<=
end;
i++)
{
/***
*
消除需要消除的方塊(觸發(fā)條件,某一行中被塞滿了方塊,沒有空白)
*
注意順序,先消除某一行,再移動這一行上邊的方塊
*/
if
(map[i]
>=
full)
{
BlockUnit.remove(allBlockUnits,
i);
score
+=
100;
map[i]
=
0;
for
(int
j
=
i;
j
>
0;
j--)
map[j]
=
map[j
-
1];
map[0]
=
0;
for
(BlockUnit
blockUnit
:
allBlockUnits)
{
if
(blockUnit.y
<
(i
*
BlockUnit.UNIT_SIZE
+
beginPoint))
{
blockUnit.y
=
blockUnit.y
+
BlockUnit.UNIT_SIZE;
}
}
}
}
father.runOnUiThread(new
Runnable()
{
@Override
public
void
run()
{
/**
*
刷新分?jǐn)?shù)
*/
father.score.setText(""
+
score);
invalidate();
}
});
try
{
Thread.sleep(GameConfig.SPEED
*
3);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
father.runOnUiThread(new
Runnable()
{
@Override
public
void
run()
{
getNewBlock();
score
+=
10;
father.score.setText(""
+
score);
}
});
}
father.runOnUiThread(new
Runnable()
{
@Override
public
void
run()
{
invalidate();
}
});
try
{
Thread.sleep(GameConfig.SPEED);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
}
}BlockUnit.java方塊的單元塊,大家都玩過俄羅斯方塊,每一個方塊由四個單元塊組成。單元快應(yīng)該有以下屬性:①大?。簡卧獕K的大小決定了主界面的容量(容納單元塊的數(shù)量);②顏色:每個單元塊都有一個顏色,美化游戲界面(可無);③坐標(biāo):包括X軸坐標(biāo)、Y軸坐標(biāo),在繪制方塊的時候,以單元塊的坐標(biāo)為起點繪制,即:單元塊的坐標(biāo)值應(yīng)該為單元塊在界面上的左上角的坐標(biāo)。此類的主要功能有:方塊的下落,左右移動,判斷是否可以旋轉(zhuǎn)等功能都在此類中,算是核心類。/**
*
俄羅斯方塊的單元快
*
*
@sign
Created
by
wang.ao
on
2017年1月13日
*/
public
class
BlockUnit
{
public
static
final
int
UNIT_SIZE
=
50;
public
static
final
int
BEGIN
=
10;
public
int
color;
//
單元塊
的坐標(biāo)
public
int
x,
y;
public
BlockUnit()
{
}
public
BlockUnit(int
x,
int
y,
int
color)
{
/*
*
@param
單元塊橫縱坐標(biāo)
構(gòu)造函數(shù)
*/
this.x
=
x;
this.y
=
y;
this.color
=
color;
}
/**
*
判斷方塊是否可以向左移動,1是否在邊緣,2是否會與其他方塊重合
*
@param
blockUnits
當(dāng)前正在下落的方塊
*
@param
max_x
游戲主界面X軸的最大值
,下同
*
@param
allBlockUnits
所有的方塊
*
@return
能移動true;不能移動false
*/
public
static
boolean
canMoveToLeft(List<BlockUnit>
blockUnits,
int
max_x,
List<BlockUnit>
allBlockUnits)
{
for
(BlockUnit
blockUnit
:
blockUnits)
{
int
x
=
blockUnit.x;
if
(x
-
UNIT_SIZE
<
BEGIN)
{
return
false;
}
int
y
=
blockUnit.y;
if
(isSameUnit(x
-
UNIT_SIZE,
y,
allBlockUnits))
{
return
false;
}
}
return
true;
}
/**
*
判斷方塊是否可以向右移動,1是否在邊緣,2是否會與其他方塊重合
*
@param
blockUnits
當(dāng)前正在下落的方塊
*
@param
max_x
游戲主界面X軸的最大值
,下同
*
@param
allBlockUnits
所有的方塊
*
@return
能移動true;不能移動false
*/
public
static
boolean
canMoveToRight(List<BlockUnit>
blockUnits,
int
max_x,
List<BlockUnit>
allBlockUnits)
{
for
(BlockUnit
blockUnit
:
blockUnits)
{
int
x
=
blockUnit.x;
if
(x
+
UNIT_SIZE
>
max_x
-
UNIT_SIZE)
{
return
false;
}
int
y
=
blockUnit.y;
if
(isSameUnit(x
+
UNIT_SIZE,
y,
allBlockUnits))
{
return
false;
}
}
return
true;
}
/**
*
判斷方塊是否可以向下移動,1是否在邊緣,2是否會與其他方塊重合
*
@param
blockUnits
當(dāng)前正在下落的方塊
*
@param
max_x
游戲主界面X軸的最大值
,下同
*
@param
allBlockUnits
所有的方塊
*
@return
能移動true;不能移動false
*/
public
static
boolean
canMoveToDown(List<BlockUnit>
blockUnits,
int
max_y,
List<BlockUnit>
allBlockUnits)
{
for
(BlockUnit
blockUnit
:
blockUnits)
{
int
x
=
blockUnit.x;
int
y
=
blockUnit.y
+
UNIT_SIZE
*
2;
if
(y
>
max_y
-
UNIT_SIZE)
{
return
false;
}
if
(isSameUnit(x,
y,
allBlockUnits))
{
return
false;
}
}
return
true;
}
public
static
boolean
canRoute(List<BlockUnit>
blockUnits,
List<BlockUnit>
allBlockUnits){
for
(BlockUnit
blockUnit:
blockUnits)
{
if(isSameUnit(blockUnit.x,
blockUnit.y,
allBlockUnits)){
return
false;
}
}
return
true;
}
/**
*
把當(dāng)前方塊向左移動一格
*
@param
blockUnits
*
@param
max_x
*
@param
allBlockUnits
*
@return
是否成功移動一格,是:true,否:false
*/
public
static
boolean
toLeft(List<BlockUnit>
blockUnits,
int
max_x,
List<BlockUnit>
allBlockUnits)
{
if
(canMoveToLeft(blockUnits,
max_x,
allBlockUnits))
{
for
(BlockUnit
blockUnit
:
blockUnits)
{
blockUnit.x
=
blockUnit.x
-
UNIT_SIZE;
}
return
true;
}
return
false;
}
/**
*
把當(dāng)前方塊向右移動一格
*
@param
blockUnits
*
@param
max_x
*
@param
allBlockUnits
*
@return
是否成功移動一格,是:true,否:false
*/
public
static
boolean
toRight(List<BlockUnit>
blockUnits,
int
max_x,
List<BlockUnit>
allBlockUnits)
{
if
(canMoveToRight(blockUnits,
max_x,
allBlockUnits))
{
for
(BlockUnit
blockUnit
:
blockUnits)
{
blockUnit.x
=
blockUnit.x
+
UNIT_SIZE;
}
return
true;
}
return
false;
}
/**
*
把當(dāng)前方塊下落一格
*
@param
blockUnits
*
@param
allBlockUnits
*
@return
是否成功移動一格,是:true,否:false
*/
public
static
void
toDown(List<BlockUnit>
blockUnits,
int
max_Y,
List<BlockUnit>
allBlockUnits)
{
for
(BlockUnit
blockUnit
:
blockUnits)
{
blockUnit.y
=
blockUnit.y
+
BlockUnit.UNIT_SIZE;
}
}
/**
*
判斷
方塊單元是否和所有方塊有重合
*
@param
x
*
@param
y
*
@param
allBlockUnits
*
@return
*/
public
static
boolean
isSameUnit(int
x,
int
y,
List<BlockUnit>
allBlockUnits)
{
for
(BlockUnit
blockUnit
:
allBlockUnits)
{
if
(Math.abs(x
-
blockUnit.x)
<
UNIT_SIZE
&&
Math.abs(y
-
blockUnit.y)
<
UNIT_SIZE)
{
return
true;
}
}
return
false;
}
/**
*
刪除在第j行上的方塊單元
*
@param
allBlockUnits
*
@param
j
需刪除行標(biāo)
*/
public
static
void
remove(List<BlockUnit>
allBlockUnits,
int
j)
{
for
(int
i
=
allBlockUnits.size()
-
1;
i
>=
0;
i--)
{
/*
*
①逆向遍歷
②根據(jù)y坐標(biāo)計算單元所在行,若為j行則從units中刪除
*/
if
((int)
((allBlockUnits.get(i).y
-
BEGIN)
/
50)
==
j)
allBlockUnits.remove(i);
}
}
}TetrisBlock.java用于產(chǎn)生不同形狀的方塊,共有其中類型。/**
*
方塊
*
*
@sign
Created
by
wang.ao
on
2017年1月13日
*/
public
class
TetrisBlock
{
private
static
final
int
TYPE_SUM
=
7;
public
int
blockType,
blockDirection;
//
方塊種類,方塊朝向
private
int
color;
//
方塊顏色
private
int
x,
y;
//
方塊坐標(biāo)
public
TetrisBlock()
{
}
public
TetrisBlock(int
x,
int
y)
{
this.x
=
x;
this.y
=
y;
}
public
List<BlockUnit>
getUnits(int
x,
int
y)
{
this.x
=
x;
this.y
=
y;
return
returnUnit();
}
/**
*
隨機產(chǎn)生一種方塊
*
@return
*/
public
List<BlockUnit>
returnUnit()
{
List<BlockUnit>
units
=
new
ArrayList<BlockUnit>();
//
方塊組成部分
blockType
=
(int)
(Math.random()
*
TYPE_SUM)
+
1;
//
隨機生成一個種類
blockDirection
=
1;
//
默認(rèn)初始方向
color
=
(int)
(Math.random()
*
4)
+
1;
//
隨機生成一個顏色
units.clear();
switch
(blockType)
{
case
1://
橫線
for
(int
i
=
0;
i
<
4;
i++)
{
units.add(new
BlockUnit(x
+
(-2
+
i)
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
case
2:
units.add(new
BlockUnit(x
+
(-1
+
1)
*
BlockUnit.UNIT_SIZE,
y
-
BlockUnit.UNIT_SIZE,
color));
for
(int
i
=
0;
i
<
3;
i++)
{
units.add(new
BlockUnit(x
+
(-1
+
i)
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
case
3:
for
(int
i
=
0;
i
<
2;
i++)
{
units.add(new
BlockUnit(x
+
(i
-
1)
*
BlockUnit.UNIT_SIZE,
y
-
BlockUnit.UNIT_SIZE,
color));
units.add(new
BlockUnit(x
+
(i
-
1)
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
case
4:
units.add(new
BlockUnit(x
+
(-1
+
0)
*
BlockUnit.UNIT_SIZE,
y
-
BlockUnit.UNIT_SIZE,
color));
for
(int
i
=
0;
i
<
3;
i++)
{
units.add(new
BlockUnit(x
+
(-1
+
i)
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
case
5:
units.add(new
BlockUnit(x
+
(-1
+
2)
*
BlockUnit.UNIT_SIZE,
y
-
BlockUnit.UNIT_SIZE,
color));
for
(int
i
=
0;
i
<
3;
i++)
{
units.add(new
BlockUnit(x
+
(-1
+
i)
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
case
6:
for
(int
i
=
0;
i
<
2;
i++)
{
units.add(new
BlockUnit(x
+
(-1
+
i)
*
BlockUnit.UNIT_SIZE,
y
-
BlockUnit.UNIT_SIZE,
color));
units.add(new
BlockUnit(x
+
i
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
case
7:
for
(int
i
=
0;
i
<
2;
i++)
{
units.add(new
BlockUnit(x
+
i
*
BlockUnit.UNIT_SIZE,
y
-
BlockUnit.UNIT_SIZE,
color));
units.add(new
BlockUnit(x
+
(-1
+
i)
*
BlockUnit.UNIT_SIZE,
y,
color));
}
break;
}
return
units;
}NextBlockView.java其實就是游戲主界面的一個縮減版,用于顯示下一個要出現(xiàn)的方塊的,玩家可以明確的知道下一個方塊的形狀和顏色。/**
*
下一個要展示的方塊
*
*
@sign
Created
by
wang.ao
on
2017年1月13日
*/
@SuppressLint("DrawAllocation")
public
class
NextBlockView
extends
View
{
/**
網(wǎng)格開始坐標(biāo)值,橫縱坐標(biāo)的開始值都是此值
*/
public
static
final
int
beginPoint
=
10;
/**
俄羅斯方塊的最大坐標(biāo)
*/
private
static
int
max_x,
max_y;
private
List<BlockUnit>
blockUnits
=
new
ArrayList<BlockUnit>();
/**
背景墻畫筆
*/
private
static
Paint
paintWall
=
null;
private
static
final
int
BOUND_WIDTH_OF_WALL
=
2;
private
static
Paint
paintBlock
=
null;
private
int
div_x
=
0;
//
俄羅斯方塊顏色數(shù)組
private
static
final
int
color[]
={
Color.parseColor("#FF6600"),
Color.BLUE,
Color.RED,
Color.GREEN,
Color.GRAY
};
public
NextBlockView(Context
context)
{
this(context,
null);
}
public
NextBlockView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
if
(paintWall
==
null)
{//
初始化化背景墻畫筆
paintWall
=
new
Paint();
paintWall.setColor(Color.LTGRAY);
paintWall.setStyle(Paint.Style.STROKE);
paintWall.setStrokeWidth(BOUND_WIDTH_OF_WALL
+
1);
}
if
(paintBlock
==
null)
{//
初始化化背景墻畫筆
paintBlock
=
new
Paint();
paintBlock.setColor(Color.parseColor("#FF6600"));
}
}
public
void
setBlockUnits(List<BlockUnit>
blockUnits,
int
div_x)
{
this.blockUnits
=
blockUnits;
this.div_x
=
div_x;
invalidate();
}
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
max_x
=
getWidth();
max_y
=
getHeight();
RectF
rel;
//
繪制網(wǎng)格
int
len
=
blockUnits.size();
//
繪制方塊
//
Toast.makeText(context,
""
+
len,
Toast.LENGTH_SHORT).show();
for
(int
i
=
0;
i
<
len;
i++)
{
paintBlock.setColor(color[blockUnits.get(i).color]);
int
x
=
blockUnits.get(i).x
-
div_x
+
BlockUnit.UNIT_SIZE
*
2;
int
y
=
blockUnits.get(i).y
+
BlockUnit.UNIT_SIZE
*
2;
rel
=
new
RectF(x
+
BOUND_WIDTH_OF_WALL,
y
+
BOUND_WIDTH_OF_WALL,
x
+
BlockUnit.UNIT_SIZE
-
BOUND_WIDTH_OF_WALL,
y
+
BlockUnit.UNIT_SIZE
-
BOUND_WIDTH_OF_WALL);
canvas.drawRoundRect(rel,
8,
8,
paintBlock);
rel
=
new
RectF(x,
y,
x
+
BlockUnit.UNIT_SIZE,
y
+
BlockUnit.UNIT_SIZE);
canvas.drawRoundRect(rel,
8,
8,
paintWall);
}
}
}GameConfig.java用于配置方塊的下落速度public
class
GameConfig
{
/**方塊下落的速度*/
public
static
final
int
SPEED
=
300;
}TetrisActivityAW.java主界面,包括游戲主界面和控制臺,很簡單,直接貼代碼。public
class
TetrisActivityAW
extends
Activity
{
private
NextBlockView
nextBlockView;
private
TetrisViewAW
tetrisViewAW;
private
TextView
gameStatusTip;
public
TextView
score;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tetris_activity_aw);
nextBlockView
=
(NextBlockView)
findViewById(R.id.nextBlockView1);
tetrisViewAW
=
(TetrisViewAW)
findViewById(R.id.tetrisViewAW1);
tetrisViewAW.setFather(this);
gameStatusTip
=
(TextView)
findViewById(R.id.game_staus_tip);
score
=
(TextView)
findViewById(R.id.score);
}
public
void
setNextBlockView(List<BlockUnit>
blockUnits,
int
div_x)
{
nextBlockView.setBlockUnits(blockUnits,
div_x);
}
/**
*
開始游戲
*
*
@param
view
*/
public
void
startGame(View
view)
{
tetrisViewAW.startGame();
gameStatusTip.setText("游戲運行中");
}
/**
*
暫停游戲
*/
public
void
pauseGame(View
view)
{
tetrisViewAW.pauseGame();
gameStatusTip.setText("游戲已暫停");
}
/**
*
繼續(xù)游戲
*/
public
void
continueGame(View
view)
{
tetrisViewAW.continueGame();
gameStatusTip.setText("游戲運行中");
}
/**
*
停止游戲
*/
public
void
stopGame(View
view)
{
tetrisViewAW.stopGame();
score.setText(""+0);
gameStatusTip.setText("游戲已停止");
}
/**
*
向左滑動
*/
public
void
toLeft(View
view)
{
tetrisViewAW.toLeft();
}
/**
*
向右滑動
*/
public
void
toRight(View
view)
{
tetrisViewAW.toRight();
}
/**
*
向右滑動
*/
public
void
toRoute(View
view)
{
tetrisViewAW.route();
}
}TetrisActivityAWactivity的xml文件<RelativeLayout
xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}"
>
<com.awang.media.minetetris.TetrisViewAW
android:id="@+id/tetrisViewAW1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="200dp"
android:layout_marginRight="120dp"
/>
<com.awang.media.minetetris.NextBlockView
android:id="@+id/nextBlockView1"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_alignParentRight="true"
/>
<LinearLayout
android:layout_width="110dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/nextBlockView1"
android:layout_marginTop="20dp"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分?jǐn)?shù)"
/>
<TextView
android:id="@+id/score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="1"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="等級"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_mar
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 創(chuàng)業(yè)合伙人簽訂合同范本
- 業(yè)務(wù)轉(zhuǎn)包合同范例
- 農(nóng)家樂入股合同范本
- 產(chǎn)品會展合同范本
- 不退不換合同范本
- 助聽器合同范本
- 勞務(wù)派遣合同范本6
- 借名辦證合同范本
- 倉庫租憑合同范本
- 勞動合同范本廣州
- 新概念英語第一冊期末測試試卷附答案
- 2023年青島港灣職業(yè)技術(shù)學(xué)院高職單招(數(shù)學(xué))試題庫含答案解析
- GB/T 21114-2007耐火材料X射線熒光光譜化學(xué)分析熔鑄玻璃片法
- GB/T 16823.3-2010緊固件扭矩-夾緊力試驗
- FZ/T 74001-2020紡織品針織運動護(hù)具
- 建筑工程上人屋面、不上人屋面工程施工方案及工藝方法
- 房建市政項目全過程工程咨詢招標(biāo)文件范本
- 整體形象設(shè)計課件
- 滅火器每月定期檢查記錄卡表格
- 一次函數(shù)的性質(zhì)說課課件
- 航空維修工程管理-第1章課件
評論
0/150
提交評論