package game.project;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Region.Op;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class SurfaceView01 extends SurfaceView implements Callback, Runnable {
SurfaceHolder holder;
Canvas canvas;
Paint paint;
boolean isGame;
TestCollisionActivity activity;
final int UP = 1;
final int DOWN = 0;
final int LEFT = 2;
final int RIGHT = 3;
int playerX,playerY,playerW,playerH;
boolean isMove;
int direction = DOWN;
int speed;
int frameIndex;
Bitmap role;
Bitmap mapImg;
int tileW ,tileH,tileNum;
int mapX,mapY;
int mapW,mapH;
int map[][] ={
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
//在View的构造函数中是拿不到view有关的任何信息的,因为它还没有构建好
public SurfaceView01(Context context) {
super(context);
activity=(TestCollisionActivity)context;
holder=getHolder();
paint=new Paint();
paint.setAntiAlias(true);
// 获取当前SurfaceHolder 并且把它加到CallBack回调函数中
holder.addCallback(this);
role = BitmapFactory.decodeResource(getResources(), R.drawable.role);
mapImg = BitmapFactory.decodeResource(getResources(), R.drawable.map);
playerW = 27;
playerH = 50;
playerX = 90;
playerY = 220;
speed = 5;
tileW = 16;
tileH = 16;
tileNum = mapImg.getWidth()/tileW;
mapW = tileW*map[0].length;
mapH = tileH*map.length;
}
public void run() {
// TODO Auto-generated method stub
while(isGame){
move(); //人物行走(改变人物的坐标+动作帧坐标)
render();//画图
//这段代码是不理智的,每一次绘画完成都要停顿100ms,见下run01
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**每30帧刷新一次屏幕**/
public static final int TIME_IN_FRAME = 30;
public void run01() {
while (isGame) {
/**取得更新游戏之前的时间**/
long startTime = System.currentTimeMillis();
/**在这里加上线程安全锁**/
synchronized (holder) {
move(); //人物行走(改变人物的坐标+动作帧坐标)
render();//画图
}
/**取得更新游戏结束的时间**/
long endTime = System.currentTimeMillis();
/**计算出游戏一次更新的毫秒数**/
int diffTime = (int)(endTime - startTime);
/**确保每次更新时间为30帧**/
while(diffTime <=TIME_IN_FRAME) {
diffTime = (int)(System.currentTimeMillis() - startTime);
/**线程等待**/
Thread.yield();
}
}
}
// 通过callBack接口监听SurfaceView的状态
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
//在surfaceview被创建的时候开启游戏的主线程
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
isGame=true;
new Thread(this).start();
}
//在surfaceview结束的时候销毁activity
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
isGame=false;
activity.finish();
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
isMove = true;
direction = LEFT;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
isMove = true;
direction = RIGHT;
break;
case KeyEvent.KEYCODE_DPAD_UP:
isMove = true;
direction = UP;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
isMove = true;
direction = DOWN;
break;
}
return super.onKeyDown(keyCode, event);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
//frameIndex = 0;只要停止按键后,动作都停在第一帧
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
isMove = false;
frameIndex = 0;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
isMove = false;
frameIndex = 0;
break;
case KeyEvent.KEYCODE_DPAD_UP:
isMove = false;
frameIndex = 0;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
isMove = false;
frameIndex = 0;
break;
}
return super.onKeyUp(keyCode, event);
}
/**人物行走
*
*/
void move(){
if(isMove){
frameIndex=(frameIndex==3? 0:frameIndex+1);
switch (direction) {
case UP:
if(playerY>getHeight()/2){ //人走无需滚屏,所以用了1/2屏幕做分界(考虑滚屏)
playerY-=speed; //往上走,屏幕左上角原点(向下向右正轴)
}else if(mapY<=-speed){ //人物不动滚屏,而且还能滚屏
mapY+=speed;
}else if(playerY>=speed){ //不能滚屏了,人物必须动了,但是还能走不出边界
playerY-=speed;
}
break;
case DOWN:
if(playerY< getHeight()/2)
playerY += speed;
else if(mapY > getHeight()-mapH+speed)
mapY -= speed;
else if(playerY <= getHeight()-playerH-speed)
{
playerY += speed;
}
break;
case LEFT:
if(playerX>getWidth()/2)
playerX -= speed;
else if(mapX<-speed)
mapX += speed;
else if(playerX >= speed)
playerX -= speed;
break;
case RIGHT:
if(playerX<getWidth()/2)
playerX += speed;
else if(mapX > getWidth()-mapW+speed)
mapX -= speed;
else if(playerX <= getWidth()-playerW-speed)
playerX += speed;
break;
}
}
}
/**整个游戏的画图都封装在这(地图+人物[包括动态动作])
*
* @param canvas
*/
void drawGame(Canvas canvas){
canvas.drawColor(Color.RED);
//画出地图
drawMap(canvas, mapImg, tileW, tileH, mapX, mapY, tileNum, map);
//将人物抠出来
canvas.clipRect(playerX, playerY, playerX+playerW, playerY+playerH,Op.REPLACE);
//将人物画到map上,跟动画帧结合了
canvas.drawBitmap(role, playerX-frameIndex*playerW, playerY-direction*playerH, paint);
}
/**
* 绘制地图
* @param canvas
* @param mapImg 地图原图图片
* @param tileW 每个tile的宽
* @param tileH 每个tile的高
* @param mapX 地图的X位置
* @param mapY 地图的Y位置
* @param tileNum 地图原图图片上的一行 tile的总个数
* @param map 地图数组
*/
void drawMap(Canvas canvas,Bitmap mapImg, int tileW,int tileH, int mapX,int mapY,int tileNum,int map[][])
{
for (int i = 0; i <map.length; i++) {
for (int j = 0; j <map[i].length; j++) {
if(map[i][j]!=0)
{
canvas.save();
canvas.clipRect(j*tileW+mapX, i*tileH+mapY, (j+1)*tileW+mapX, i*tileH+tileH+mapY,Op.REPLACE);
canvas.drawBitmap(mapImg, j*tileW+mapX-((map[i][j]-1)%tileNum)*tileW,
i*tileH+mapY-((map[i][j]-1)/tileNum)*tileH, paint);
canvas.restore();
}
}
}
}
/**
* 封装surfaceView中著名的三步走
* 锁住canvas
* 画图
* 释放锁然后将图呈现到屏幕上
*/
void render()
{
canvas = holder.lockCanvas();
drawGame(canvas);
holder.unlockCanvasAndPost(canvas);
}
/**矩阵碰撞检测
*
* @param x
* @param y
* @param w
* @param h
* @param x1
* @param y1
* @param w1
* @param h1
* @return
*/
boolean collisionWith(int x,int y,int w,int h,int x1,int y1,int w1,int h1)
{
if(((x>=x1 && x<=x1+w1)|| (x+w>=x1 && x+w<=x1+w1))&&
((y>=y1 && y<=y1+h1)||( y+h>=y1 &&y+h<= y1+h1)))
return true;
else
return false;
}
}
<pre name="code" class="java">package game.project;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class TestCollisionActivity extends Activity {
/** Called when the activity is first created. */
GameSurfaceView surfaceView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
surfaceView = new GameSurfaceView(this);
setContentView(surfaceView);
surfaceView.setFocusable(true);
}
}