俄罗斯方块源码

网上源码,下下来读的,这个游戏木键盘就玩不了。。
我比较喜欢欢迎页面的线程部分。。
GameThread.java

package com.android.tetris;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class GameThread extends Thread{
boolean stop=false;
boolean pause=false;
private GameView gv;
private SurfaceHolder holder;
int sleepSpan=200;//200毫秒重新绘制一次
// private SimpleDateFormat sDateFormat;
public GameThread(GameView gv,SurfaceHolder holder){
this.gv=gv;
this.holder=holder;
}

public void run(){
Canvas canvas=null;
//sDateFormat=new SimpleDateFormat("hh:mm:ss");
while(!stop){
try{
canvas=holder.lockCanvas(null);
synchronized(holder){
gv.doDraw(canvas);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(canvas!=null){
holder.unlockCanvasAndPost(canvas);
}
}
try {
Thread.sleep(sleepSpan);
//gv.time=sDateFormat.format(new Date());
if(!pause){
if(!gv.shape_flag){
gv.shape_flag=true;
}else{
gv.shapeView.DetectDownY();
}//检测是否碰到下面的方块
}
} catch (InterruptedException e) {
stop=true;
}
}
}
}

GameView.java

package com.android.tetris;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Shader;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView implements SurfaceHolder.Callback{

private Paint paint;
private Paint mPaint;//菜单画笔
GameThread gameThread;
KeyThread keyThread;
String time="0";//时间
int score=0;//分数
int level=0;//级别
ShapeView shapeView;
boolean game_over;
boolean shape_flag;//开始绘制方块标志
boolean menu_show=false;//绘制菜单
boolean back_show=false;//绘制返回选项
private int INFO_BEGIN;
private int INFO_WIDTH;
int MENU_BEGIN;
int ITEM_BEGIN;

private RectF gamerect;
private RectF next_rect;
private RectF score_rect;
private RectF level_rect;
private RectF timerect;
private RectF mrect;
private LinearGradient lGradient;
private LinearGradient infoGradient;
private LinearGradient mGradient;
private int FONT_SIZE;
Tetris tetris;
public GameView(Tetris tetris) {
super(tetris);
this.tetris=tetris;
this.getHolder().addCallback(this);
initPaint();
initGame();
INFO_BEGIN=tetris.GAME_WIDTH+tetris.BITMAP_WIDTH;
INFO_WIDTH=tetris.GAME_WIDTH+tetris.BITMAP_WIDTH*5+tetris.HALF_BITMAP;
MENU_BEGIN=(tetris.VIEW_ROWS-11)/2*tetris.BITMAP_WIDTH+tetris.HALF_BITMAP;
ITEM_BEGIN=tetris.BITMAP_WIDTH*3;
}
//初始化变量
public void initGame(){
shapeView=new ShapeView(this);
shape_flag=false;//开始绘制方块标志
game_over=false;
score=0;
level=0;
gameThread=new GameThread(this,getHolder());
keyThread=new KeyThread(this);
}
public void initPaint(){
paint=new Paint();
lGradient=new LinearGradient(0,0,100,100,new int[]{Color.LTGRAY,Color.argb(255,198,226,255)},null,Shader.TileMode.MIRROR);
FONT_SIZE=(int) paint.getTextSize();
infoGradient=new LinearGradient(20,20,80,80,new int[]{Color.BLACK,Color.BLUE,Color.MAGENTA},null,Shader.TileMode.MIRROR);
}
public void doDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
/*
*以下是游戏界面网格
*/
paint.setStrokeWidth(tetris.HALF_BITMAP/2);
paint.setShader(lGradient);
paint.setAntiAlias(true);
paint.setStyle(Style.STROKE);
//画四周稍宽的边框
gamerect=new RectF(tetris.HALF_BITMAP,tetris.HALF_BITMAP,tetris.GAME_WIDTH+tetris.HALF_BITMAP,tetris.GAME_HEIGHT+tetris.HALF_BITMAP);
canvas.drawRoundRect(gamerect,5,5,paint);
paint.setStrokeWidth(1);
//画网格线
for(int i=1;i<tetris.VIEW_ROWS;++i){
canvas.drawLine(tetris.HALF_BITMAP,i*tetris.BITMAP_WIDTH+tetris.HALF_BITMAP,tetris.HALF_BITMAP+tetris.GAME_WIDTH,i*tetris.BITMAP_WIDTH+tetris.HALF_BITMAP, paint);
}
for(int i=1;i<tetris.VIEW_COLUMNS;++i){
canvas.drawLine(i*tetris.BITMAP_WIDTH+tetris.HALF_BITMAP,tetris.HALF_BITMAP,i*tetris.BITMAP_WIDTH+tetris.HALF_BITMAP,tetris.GAME_HEIGHT+tetris.HALF_BITMAP,paint);
}
/*
*绘制已经存在的方块
*/
for(int i=0;i<tetris.VIEW_ROWS;++i){
for(int j=0;j<tetris.VIEW_COLUMNS;++j){
if(tetris.Enable[i][j]){
canvas.drawBitmap(tetris.bitmaps[tetris.ColorKind[i][j]],
tetris.HALF_BITMAP+j*tetris.BITMAP_WIDTH,
tetris.HALF_BITMAP+i*tetris.BITMAP_WIDTH,
paint);
}
}
}
/*
*以下是右边显示栏
*
*/




paint.setShader(infoGradient);
///////////下一个要显示的图形///////////////
canvas.drawText("下一个:",INFO_BEGIN,tetris.BITMAP_WIDTH,paint);
next_rect=new RectF(INFO_BEGIN,tetris.BITMAP_WIDTH+FONT_SIZE,INFO_WIDTH,tetris.BITMAP_WIDTH*6+FONT_SIZE);
canvas.drawRoundRect(next_rect, 5, 5, paint);
/////分数显示////////////////////////////
canvas.drawText("分数:",INFO_BEGIN,tetris.BITMAP_WIDTH*7+FONT_SIZE, paint);
score_rect=new RectF(INFO_BEGIN,tetris.BITMAP_WIDTH*7+FONT_SIZE*2,INFO_WIDTH,tetris.BITMAP_WIDTH*9+FONT_SIZE*2);
canvas.drawRoundRect(score_rect, 5,5, paint);
canvas.drawText(score+"",INFO_BEGIN+tetris.BITMAP_WIDTH,tetris.BITMAP_WIDTH*8+FONT_SIZE*2,paint);
//////玩家级别///////////////////////////
canvas.drawText("级别:",INFO_BEGIN,tetris.BITMAP_WIDTH*10+FONT_SIZE*2,paint);
level_rect=new RectF(INFO_BEGIN,tetris.BITMAP_WIDTH*10+FONT_SIZE*3,INFO_WIDTH,tetris.BITMAP_WIDTH*12+FONT_SIZE*3);
canvas.drawRoundRect(level_rect, 5,5, paint);
canvas.drawText(level+"",INFO_BEGIN+tetris.BITMAP_WIDTH,tetris.BITMAP_WIDTH*11+FONT_SIZE*3,paint);
///////玩家所玩时间////////////////////////
canvas.drawText("时间(s):",INFO_BEGIN,tetris.BITMAP_WIDTH*13+FONT_SIZE*3, paint);
timerect=new RectF(INFO_BEGIN,tetris.BITMAP_WIDTH*13+FONT_SIZE*4,INFO_WIDTH,tetris.BITMAP_WIDTH*15+FONT_SIZE*4);
canvas.drawRoundRect(timerect, 5, 5, paint);
canvas.drawText(time+"",INFO_BEGIN+tetris.BITMAP_WIDTH,tetris.BITMAP_WIDTH*14+FONT_SIZE*4, paint);
//绘制方块
if(shape_flag){
shapeView.draw(canvas);
}
if(game_over){
pauseGame();
tetris.menuStart=true;
}
//绘制菜单
if(menu_show||tetris.menuStart){
gameThread.pause=true;
gameThread.stop=true;
drawMenu(canvas);
}

if(back_show){
gameThread.pause=true;
gameThread.stop=true;
drawBackMenu(canvas);
}
}

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){//重写的方法,返回的是此View的大小
setMeasuredDimension(tetris.VIEW_WIDTH,tetris.VIEW_HEIGHT);
}


public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

public void surfaceCreated(SurfaceHolder holder) {
if(!gameThread.isAlive()){
gameThread.start();
}
}

public void surfaceDestroyed(SurfaceHolder holder) {
gameThread.stop=true;
gameThread=null;
keyThread.stop=true;
keyThread=null;
}
//绘制Menu菜单
private void drawMenu(Canvas canvas){
mPaint=new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
mPaint.setAlpha(33);
mPaint.setStrokeWidth(3);
mrect=new RectF(tetris.BITMAP_WIDTH+tetris.HALF_BITMAP,MENU_BEGIN-tetris.BITMAP_WIDTH,9*tetris.BITMAP_WIDTH,MENU_BEGIN+7*tetris.BITMAP_WIDTH);
canvas.drawRoundRect(mrect,15,15,mPaint);
//绘制菜单
mPaint.setTextSize(tetris.BITMAP_WIDTH);
mGradient=new LinearGradient(20,20,40,30,new int[]{Color.BLUE,Color.RED},null,Shader.TileMode.MIRROR);
mPaint.setShader(mGradient);
mPaint.setAlpha(255);
if(tetris.menuStart){
canvas.drawText("新建游戏",ITEM_BEGIN,MENU_BEGIN+tetris.BITMAP_WIDTH,mPaint);
}else{
canvas.drawText("继续游戏",ITEM_BEGIN,MENU_BEGIN+tetris.BITMAP_WIDTH,mPaint);
canvas.drawText("重新开始",ITEM_BEGIN,MENU_BEGIN+tetris.BITMAP_WIDTH*3,mPaint);
}
canvas.drawText("退出游戏",ITEM_BEGIN,MENU_BEGIN+tetris.BITMAP_WIDTH*5,mPaint);
}
//绘制back按键菜单
private void drawBackMenu(Canvas canvas){
mPaint=new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
mPaint.setAlpha(33);
mPaint.setStrokeWidth(3);
mrect=new RectF(tetris.BITMAP_WIDTH+tetris.HALF_BITMAP,MENU_BEGIN,9*tetris.BITMAP_WIDTH+tetris.HALF_BITMAP,MENU_BEGIN+5*tetris.BITMAP_WIDTH);
canvas.drawRoundRect(mrect,15,15,mPaint);
mPaint.setAlpha(200);
mGradient=new LinearGradient(20,20,40,30,new int[]{Color.BLUE,Color.RED},null,Shader.TileMode.MIRROR);
mPaint.setShader(mGradient);
mPaint.setTextSize(tetris.BITMAP_WIDTH);
canvas.drawText("你确定要退出吗",2*tetris.BITMAP_WIDTH,MENU_BEGIN+tetris.BITMAP_WIDTH, mPaint);
canvas.drawText("确定",2*tetris.BITMAP_WIDTH,MENU_BEGIN+4*tetris.BITMAP_WIDTH,mPaint);
canvas.drawText("取消",7*tetris.BITMAP_WIDTH,MENU_BEGIN+4*tetris.BITMAP_WIDTH,mPaint);
}
public void pauseGame(){
keyThread.pause=true;
gameThread.pause=true;
gameThread.stop=true;
keyThread.stop=true;
}
public void startGame(){
gameThread=new GameThread(this,this.getHolder());
keyThread=new KeyThread(this);
gameThread.start();
keyThread.start();
}

}

KeyThread.java

package com.android.tetris;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.util.Log;

public class KeyThread extends Thread{
/*
*
* 键盘监听线程
*/
private GameView gv;
boolean stop=false;
boolean pause=false;
private ShapeView shapeView;
private static int SLEEP_SPAN=10;
private SimpleDateFormat sDateFormat;
public KeyThread(GameView gameview){
this.gv=gameview;
shapeView=gv.shapeView;
}

public void run(){
sDateFormat=new SimpleDateFormat("hh:mm:ss");
while(!stop){
gv.time=sDateFormat.format(new Date());
if(!pause){
try{
Thread.sleep(SLEEP_SPAN);
}catch(Exception e){
stop=true;
}
HandleKeyEvent();//按键事件
}
}
}
//处理键盘事件
public void HandleKeyEvent(){
//上
if(Tetris.up_flag){
shapeView.changeShape();
Tetris.up_flag=false;
}
//下 下降两格
if(Tetris.down_flag){
shapeView.DetectDownY();
shapeView.DetectDownY();
Tetris.down_flag=false;
}
//左
if(Tetris.left_flag){
shapeView.DetectLeftX();
Tetris.left_flag=false;
}
//右
if(Tetris.right_flag){
shapeView.DetectRightX();
Tetris.right_flag=false;
}
}

//改变形状

}

ShapeView.java

package com.android.tetris;

import java.util.Random;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;


public class ShapeView {
/*
* 方块类
*
*/

private int [][]currentCoord;//当前网格坐标
private int [][]nextCoord;//下一个要显示的网格坐标
private int []currentKind;//当前方块类型;类型 、状态、颜色
private int []nextKind;//下一个方块类型:同上
private GameView gv;
private Random r;
private Tetris tetris;
public ShapeView(GameView gameview){
this.gv=gameview;
this.tetris=gv.tetris;
r=new Random();
nextKind=GenerateKinds();
nextCoord=GenerateCoordinate(4,0,nextKind[0],nextKind[1]);
Reset();
}

//当前网格坐标
//g_x-当前的x网格坐标
//g_y-当前的y网格坐标
//pKind-当前的方块类型(共七种)
//cKind-当前的方块形状
//isNext-是否赋值标志
public int[][] GenerateCoordinate(int g_x,int g_y,int pKind,int cKind){
Log.i("****",g_x+"--"+g_y+"--"+pKind+"--"+cKind);
int coord[][] = null;
switch(pKind){
case 0:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x-1,g_y},{g_x+1,g_y},{g_x+1,g_y-1}};
}else if(cKind==1){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x,g_y-2},{g_x-1,g_y-2}};
}else if(cKind==2){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x+1,g_y-1},{g_x+2,g_y-1}};
}else if(cKind==3){
coord=new int[][]{{g_x,g_y},{g_x+1,g_y},{g_x,g_y-1},{g_x,g_y-2}};
}
break;
case 1:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x-1,g_y},{g_x+1,g_y},{g_x,g_y-1}};
}else if(cKind==1){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x-1,g_y-1},{g_x,g_y-2}};
}else if(cKind==2){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x-1,g_y-1},{g_x+1,g_y-1}};
}else if(cKind==3){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x+1,g_y-1},{g_x,g_y-2}};
}
break;
case 2:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x-1,g_y},{g_x,g_y-1},{g_x+1,g_y-1}};
}else if(cKind==1){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x-1,g_y-1},{g_x-1,g_y-2}};
}
break;
case 3:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x+1,g_y},{g_x-1,g_y-1},{g_x,g_y-1}};
}else if(cKind==1){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x+1,g_y-1},{g_x+1,g_y-2}};
}
break;
case 4:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x-1,g_y},{g_x+1,g_y},{g_x-1,g_y-1}};
}else if(cKind==1){
coord=new int[][]{{g_x,g_y},{g_x-1,g_y},{g_x,g_y-1},{g_x,g_y-2}};
}else if(cKind==2){
coord=new int[][]{{g_x,g_y},{g_x-2,g_y-1},{g_x-1,g_y-1},{g_x,g_y-1}};
}else if(cKind==3){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x,g_y-2},{g_x+1,g_y-2}};
}
break;
case 5:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x-1,g_y},{g_x-2,g_y},{g_x+1,g_y}};
}else if(cKind==1){
coord=new int[][]{{g_x,g_y},{g_x,g_y-1},{g_x,g_y-2},{g_x,g_y-3}};
}
break;
case 6:
if(cKind==0){
coord=new int[][]{{g_x,g_y},{g_x+1,g_y},{g_x,g_y-1},{g_x+1,g_y-1}};
}
break;
default:break;
}
return coord;
}
/*
* 绘制方块
*/
public void draw(Canvas canvas){
Paint paint=new Paint();
/*
* 绘制方块和右边显示栏上的方块
*/
for(int i=0;i<4;++i){
//绘制方块
canvas.drawBitmap(gv.tetris.bitmaps[currentKind[2]],tetris.HALF_BITMAP+currentCoord[i][0]*tetris.BITMAP_WIDTH,
tetris.HALF_BITMAP+currentCoord[i][1]*tetris.BITMAP_WIDTH,paint);
//绘制右边显示栏下一个方块
canvas.drawBitmap(gv.tetris.bitmaps[nextKind[2]],
(nextCoord[i][0]-1)*tetris.BITMAP_WIDTH+tetris.GAME_WIDTH,(nextCoord[i][1]+5)*tetris.BITMAP_WIDTH,paint);
}


}
/*
* 向左移动
*/
public void DetectLeftX(){
boolean stop_flag=false;
for(int i=0;i<4;++i){
if(currentCoord[i][0]<=0||currentCoord[i][1]<0){
stop_flag=true;
break;
}
if(tetris.Enable[currentCoord[i][1]][currentCoord[i][0]-1]){
stop_flag=true;
break;
}
}
//Log.i("***","left--"+stop_flag);
if(!stop_flag){
for(int i=0;i<4;++i){

--currentCoord[i][0];
}
}
}
/*
*向右移动
*/
public void DetectRightX(){
boolean stop_flag=false;
for(int i=0;i<4;++i){
if(currentCoord[i][0]<0||currentCoord[i][1]<0||
currentCoord[i][0]>=tetris.VIEW_COLUMNS-1){
stop_flag=true;
break;
}
if(tetris.Enable[currentCoord[i][1]][currentCoord[i][0]+1]){
stop_flag=true;
break;
}
}
//Log.i("***","right--"+stop_flag);
if(!stop_flag){
for(int i=0;i<4;++i){
++currentCoord[i][0];
}
}
}
/*
*
*向下移动
*/
public void DetectDownY(){
boolean stop_flag=false;
int y=0;//网格x坐标
int x=0;//网格y坐标
for(int i=0;i<4;++i){
x=currentCoord[i][0];
y=currentCoord[i][1];
if(x<0||y<0){
break;
}
if(y==tetris.VIEW_ROWS-1){
stop_flag=true;
break;
}
//判断当前小方块下面的位置是否已经有小方块了,若有则代表已经碰到底,小方块不能再下降
if(tetris.Enable[y+1][x]){
stop_flag=true;
break;
}
}
if(stop_flag){//碰底停止
////////////////////////////////////
for(int i=0;i<4;++i){
x=currentCoord[i][0];
y=currentCoord[i][1];

++tetris.NumPreLine[y];//这一行上的方块数加1
tetris.Enable[y][x]=true;//将这个位置标识为已经有方块存在了。
tetris.ColorKind[y][x]=currentKind[2];//得到该位置处方块的颜色。
/*
*游戏结束检测 (方块已经在游戏屏幕的最顶端,game over)
*/
if(y==0){
gv.game_over=true;
return;
}
}
//检测是否有全行的

int lines[]=new int[4];//因为最多就能一次销毁4行,所以长度为4
boolean isFull=false;
for(int i=0;i<4;++i){
//currentCoord中存放的是每个图形组成的四个小方块的坐标
y=currentCoord[i][1];
if(tetris.NumPreLine[y]==10){//此处为10是因为绘制网格的时候一共就10列 tetris.VIEW_COLUMNS=10
lines[i]=y;
isFull=true;
}
}
if(isFull){//有全行的
clearLines(lines);
}
Reset();
}else{//如果没到底,那么将小方块下移一个位置
for(int i=0;i<4;++i){
++currentCoord[i][1];
}
}
}


//消行函数
public void clearLines(int []lines){
//消除相同数,并且排序(按照行数的降序排序)
//因为lines是根据每个图形的四个小方块中每个小方块全行的行数,
//就有可能出现这四小方块中有两个小方块是同一行的,并且这行为全行导致lines中有重复行
int temp;
for(int i=0;i<3;++i){
for(int j=i+1;j<4;++j){
if(lines[i]<lines[j]){
temp=lines[i];
lines[i]=lines[j];
lines[j]=temp;
}else if(lines[i]==lines[j]){
lines[j]=0;
}
}
}
int line=0;//总共需要消除的行数
for(int i=0;i<4;++i){
if(lines[i]==0){//因为已经按照降序排过序了,所以只要遇到为0就直接退出不需要继续
break;
}
for(int j=lines[i]-1;j>=0;--j){
tetris.Enable[j+1]=tetris.Enable[j].clone();
tetris.ColorKind[j+1]=tetris.ColorKind[j].clone();
tetris.NumPreLine[j+1]=tetris.NumPreLine[j];
}
//首行为零
// tetris.Enable[0]=new boolean[tetris.VIEW_COLUMNS];
// tetris.ColorKind[0]=new int[tetris.VIEW_COLUMNS];
// tetris.NumPreLine[0]=0;

/*
*现象:注释掉这段话后,当消除多行时,会出现问题。而只消除一行的时候没有这个问题
*因为上面将每行的方块依次下移一行,所以lines也要跟着改变,否则消除不掉其他行
*/
for(int j=i+1;j<4;++j){
if(lines[j]==0){
break;
}
++lines[j];
}
++line;
}
gv.score+=line*line*100;
gv.level=gv.score/10000+1;
gv.gameThread.sleepSpan=(6-gv.level)*50;
}


//重置,新一个方块
public void Reset(){
currentKind=nextKind.clone();//克隆,不能直接赋值
nextKind=GenerateKinds();
currentCoord=nextCoord.clone();
nextCoord=GenerateCoordinate(4,0,nextKind[0],nextKind[1]);//可换一个算法,直接操
}
//随机生成方块类型、颜色以及状态
public int[] GenerateKinds(){
int ppKind;//类型
int ccKind;//状态
int bbKind;//颜色
ppKind=r.nextInt(7);
if(ppKind==0||ppKind==1||ppKind==4){
ccKind=r.nextInt(4);
}else if(ppKind==2||ppKind==3||ppKind==5){
ccKind=r.nextInt(2);
}else{
ccKind=0;
}
//这个是根据drawable中小方块颜色个数确实的
bbKind=r.nextInt(6);
return new int[]{ppKind,ccKind,bbKind};
}
//改变方块的状态
public int ChangeKind(boolean flag){
int ccKind=currentKind[1];
int pKind=currentKind[0];
if(pKind==0||pKind==1||pKind==4){
++ccKind;
ccKind=ccKind>3?0:ccKind;
}else if(pKind==2||pKind==3||pKind==5){
++ccKind;
ccKind=ccKind>1?0:ccKind;
}else if(pKind==6){
ccKind=0;
}
if(flag){
currentKind[1]=ccKind;
}
return ccKind;
}
/*
* 改变形状
* /
*/
public void changeShape(){

int [][]ACoord=GenerateCoordinate(currentCoord[0][0],currentCoord[0][1],currentKind[0],ChangeKind(false));
boolean change_flag=true;
//检测变形后的方块是否越界
try{
for(int i=0;i<4;++i){
if(ACoord[i][0]<0||ACoord[i][0]>9||ACoord[i][1]<0||tetris.Enable[ACoord[i][1]][ACoord[i][0]]){
change_flag=false;
break;
}
}
}catch(Exception e){
change_flag=false;
}
if(change_flag){
currentCoord=GenerateCoordinate(currentCoord[0][0],currentCoord[0][1],currentKind[0],ChangeKind(true));
}
}
//数组赋值
}

Tetris.java

package com.android.tetris;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;

public class Tetris extends Activity {
int VIEW_WIDTH;//游戏view宽度
int VIEW_HEIGHT;//游戏view高度
int VIEW_ROWS;//view行数
int VIEW_COLUMNS;//view列数
int GAME_WIDTH;//网格界面宽度
int BITMAP_WIDTH;//每个图片宽度
int GAME_HEIGHT;//网格界面高度
int HALF_BITMAP;//半个图片的宽度
static boolean up_flag=false;//上键
static boolean down_flag=false;//下键
static boolean left_flag=false;//左键
static boolean right_flag=false;//右键
GameView gameview=null;//游戏主界面
private WelcomeView welcomeview;//欢迎界面
boolean [][]Enable;//坐标上是否有方块
int [][]ColorKind;//方块颜色种类
int []NumPreLine;//每一行的方块数
Bitmap []bitmaps;//图片
boolean welcomeStart=true;//欢迎界面标志
boolean menuStart=false;//初始游戏界面
private WelcomeThread wvThread;//欢迎界面刷新线程
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
initConstants();//初始化变量
initBitmap(this.getResources());//初始化图片
/*
* 欢迎界面
*/
welcomeview=new WelcomeView(this);
wvThread=new WelcomeThread(this,welcomeview);
setContentView(welcomeview);
wvThread.start();
/*
* 后台初始化gameview
*
*/
new Thread(){
public void run(){
Looper.prepare();
System.out.println("----------------后台进行初始化操作!!!!!");
menuStart=true;
gameview=new GameView(Tetris.this);
Looper.loop();
}
}.start();
}
/*
*handle
*/
Handler myHandler=new Handler(){
public void handleMessage(Message msg){
if(msg.what==0){
System.out.println("================= handle message!!!");
if(gameview==null){
System.out.println("已经初始化过了!!!!!!!");
gameview=new GameView(Tetris.this);
}
setContentView(gameview);
welcomeview=null;
}
}
};
/*
*初始化变量
*
*/
public void initBitmap(Resources r){
bitmaps=new Bitmap[6];
bitmaps[0]=BitmapFactory.decodeResource(r,R.drawable.icon_blue);
bitmaps[1]=BitmapFactory.decodeResource(r,R.drawable.icon_cyan);
bitmaps[2]=BitmapFactory.decodeResource(r,R.drawable.icon_lark);
bitmaps[3]=BitmapFactory.decodeResource(r,R.drawable.icon_purple);
bitmaps[4]=BitmapFactory.decodeResource(r,R.drawable.icon_yellow);
bitmaps[5]=BitmapFactory.decodeResource(r,R.drawable.ingigo);

}
public void initConstants(){
DisplayMetrics dm=new DisplayMetrics();
getWindow().getWindowManager().getDefaultDisplay().getMetrics(dm);
VIEW_WIDTH=dm.widthPixels;
VIEW_HEIGHT=dm.heightPixels;
if(VIEW_WIDTH>300&&VIEW_WIDTH<400){
BITMAP_WIDTH=20;
}
else{
BITMAP_WIDTH=30;
}
VIEW_COLUMNS=10;
VIEW_ROWS=(VIEW_HEIGHT-BITMAP_WIDTH)/BITMAP_WIDTH;
GAME_WIDTH=VIEW_COLUMNS*BITMAP_WIDTH;
GAME_HEIGHT=VIEW_ROWS*BITMAP_WIDTH;
HALF_BITMAP=BITMAP_WIDTH/2;
Enable=new boolean[VIEW_ROWS][VIEW_COLUMNS];
ColorKind=new int[VIEW_ROWS][VIEW_COLUMNS];
NumPreLine=new int[VIEW_ROWS];
}
/*
*按键处理
*/
public boolean onKeyDown(int keyCode, KeyEvent event) {

if(welcomeStart){//在欢迎界面时只有back键有效
if(keyCode==KeyEvent.KEYCODE_BACK){
Tetris.this.finish();
}
return false;
}
//Log.i("*****",keyCode+"");
switch(keyCode){
case KeyEvent.KEYCODE_DPAD_DOWN://下
down_flag=true;
break;
case KeyEvent.KEYCODE_DPAD_UP://上
up_flag=true;
break;
case KeyEvent.KEYCODE_DPAD_LEFT://左
left_flag=true;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT://右
right_flag=true;
break;
case KeyEvent.KEYCODE_MENU://菜单
if(!gameview.menu_show&&!gameview.game_over){
gameview.keyThread.pause=true;
gameview.keyThread.stop=true;
gameview.menu_show=true;
//gameview.startGame();
}
break;
case KeyEvent.KEYCODE_BACK://返回
if(!gameview.back_show&&!gameview.game_over){
gameview.keyThread.pause=true;
gameview.keyThread.stop=true;
gameview.back_show=true;
}
break;
default:break;
}
return false;
}

/*
*触屏处理,可放在GameView类中
*/
public boolean onTouchEvent(MotionEvent event) {
if(welcomeStart){
return false;
}
float x=event.getX();
float y=event.getY();
if(gameview.menu_show||menuStart){


if(x<gameview.ITEM_BEGIN||x>gameview.ITEM_BEGIN+BITMAP_WIDTH*4||
y<gameview.MENU_BEGIN||y>gameview.MENU_BEGIN+5*BITMAP_WIDTH){
return false;
}

//继续游戏
if(y<gameview.MENU_BEGIN+BITMAP_WIDTH){
if(menuStart){
menuStart=false;
restartGame();
return false;
}
gameview.menu_show=false;
gameview.startGame();
}
//重新开始游戏
else if(!menuStart&&y>gameview.MENU_BEGIN+BITMAP_WIDTH*2&&y<gameview.MENU_BEGIN+BITMAP_WIDTH*3){
gameview.menu_show=false;
restartGame();
}
//退出游戏
else if(y>gameview.MENU_BEGIN+BITMAP_WIDTH*4&&y<gameview.MENU_BEGIN+5*BITMAP_WIDTH){
Tetris.this.finish();
}

}
else if(gameview.back_show){

//确定
if(x>2*BITMAP_WIDTH&&x<4*BITMAP_WIDTH&&
y>gameview.MENU_BEGIN+3*BITMAP_WIDTH&&y<gameview.MENU_BEGIN+4*BITMAP_WIDTH){
Tetris.this.finish();
}
//取消
else if(x>7*BITMAP_WIDTH&&x<9*BITMAP_WIDTH&&
y>gameview.MENU_BEGIN+3*BITMAP_WIDTH&&y<gameview.MENU_BEGIN+4*BITMAP_WIDTH){
gameview.back_show=false;
gameview.startGame();
}
}
return false;
}
//重新开始游戏
public void restartGame(){
Enable=new boolean[VIEW_ROWS][VIEW_COLUMNS];
ColorKind=new int[VIEW_ROWS][VIEW_COLUMNS];
NumPreLine=new int[VIEW_ROWS];
gameview.initGame();//重新设置
gameview.gameThread.start();
gameview.keyThread.start();
}


}

WelcomeThread.java

package com.android.tetris;

import android.os.Looper;

public class WelcomeThread extends Thread{

private WelcomeView wv;
private static final int sleepSpan=100;
boolean stop=false;
private Tetris tetris;
public WelcomeThread(Tetris tetris,WelcomeView wv){
this.wv=wv;
this.tetris=tetris;
}

public void run(){
try {
Thread.sleep(1000);//先休眠一秒
} catch (InterruptedException e1) {
stop=true;
}
int i = 0 ;
while(!stop){
// System.out.println("循环次数:" + ++i);
try {
Thread.sleep(sleepSpan);
System.out.println("VIEW-ROWS : " + (wv.tetris.VIEW_ROWS/2+3));
if(wv.count<=6&&wv.index[wv.count-1]<wv.tetris.VIEW_ROWS/2+3){
System.out.println("wv.index = " + wv.index[wv.count-1] + ",wv.count = " + (wv.count-1));
//这里wv.index[i]被循环赋值wv.tetris.VIEW_ROWS/2+3次,
//目的是为了使WelcomeView重绘wv.tetris.VIEW_ROWS/2+3次,
//而形成小方块从上一点一点落下的效果
++wv.index[wv.count-1];
}else if(wv.count<6){//这里的count是WelcomeView中落下的小方块个数
System.out.println("+++++++++++++");
++wv.count;
}

if(wv.show){//使欢迎页面 的文字从模糊变真实
System.out.println("welcome alpha = " + wv.alpha);
wv.alpha+=20;
}//0 - 255
if(wv.alpha>=250){//这个地方是用来控制显示文字后多长时间停止线程。
System.out.println("welcome thread stop!!!");
stop=true;
}
wv.postInvalidate();
if(stop){
stop=true;
tetris.welcomeStart=false;
//向主线程发送消息通知其进入游戏界面结束欢迎界面
tetris.myHandler.sendEmptyMessage(0);

}
} catch (InterruptedException e) {
stop=true;
}

}
}
}

WelcomeView.java

package com.android.tetris;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.Shader;
import android.view.View;

public class WelcomeView extends View {
Tetris tetris;
int count=1;
int []index;
boolean show=false;
int alpha;
private Paint paint;
public WelcomeView(Tetris tetris) {
super(tetris);
this.tetris=tetris;
index=new int[6];
index[0]=-1;
paint=new Paint();
}

@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.WHITE);
paint.setAlpha(250);
for(int i=0;i<count;++i){
System.out.println("WelcomeView draw count " + i);
canvas.drawBitmap(tetris.bitmaps[i],(5+i)*tetris.BITMAP_WIDTH,tetris.BITMAP_WIDTH*index[i],paint);
}

if(show){
LinearGradient gradient=new LinearGradient(30,30,40,40,new int[]{Color.RED,Color.CYAN,Color.TRANSPARENT},null,Shader.TileMode.MIRROR);
paint.setShader(gradient);
paint.setTextSize(tetris.BITMAP_WIDTH*2);
paint.setAlpha(alpha);
canvas.drawText("经典俄罗斯方块",tetris.BITMAP_WIDTH,tetris.BITMAP_WIDTH*(tetris.VIEW_ROWS/2-4),paint);
}
if(!show&&index[5]==tetris.VIEW_ROWS/2+3){//当6个小方块都已经显示完
System.out.println("welcome text is show !!!");
show=true;
}
}

}

string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">俄罗斯方块</string>
<string name="nextstatus">下一个</string>
<string name="score">分数</string>
<string name="time">时间(s)</string>
<string name="level">关卡</string>
</resources>

color.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable name="white">#C9C9C9</drawable>

</resources>

方便理解的图例
俄罗斯方块源码 - 无尘 - 无尘的博客
 
俄罗斯方块源码 - 无尘 - 无尘的博客
 
俄罗斯方块源码 - 无尘 - 无尘的博客
 
俄罗斯方块源码 - 无尘 - 无尘的博客
 
俄罗斯方块源码 - 无尘 - 无尘的博客
 
俄罗斯方块源码 - 无尘 - 无尘的博客
 
俄罗斯方块源码 - 无尘 - 无尘的博客
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值