1. 效果
2.思路
点击豌豆射手卡片,生成卡片,并将触摸事件传递给卡片,以便卡片能移动
2.1 第1触摸事件
Activity 的触摸事件
package com.su.botanywarzombies;
public class MainActivity extends Activity {
private GameView mGameView;
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGameView.onTouchEvent(event);
}
2.2 第2触摸事件
mGameView 中的卡片选卡触摸事件
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
@Override
public boolean onTouchEvent(MotionEvent event) {
// 第一图层,背景图和放置状态栏的卡片
for (BaseModel model : gameLayout1) {
if (model instanceof TouchAble) {
if (((TouchAble) model).onTouch(event)) {
// true 表示触摸事件到此为止不再响应
return true;
}
}
}
2.3 第3触摸事件
豌豆射手卡片被点击事件
public class SeedPea extends BaseModel implements TouchAble {
@Override
public boolean onTouch(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 判断是否点击了卡片,根据是否焦点在触摸区域范围内
if (touchArea.contains(x, y)) {
Log.d("sufadi", "touch seed pea");
applyEmplacePea();
return true;
}
default:
break;
}
return false;
}
2.4 第4触摸事件
申请一张卡片,并且获取触摸事件,已方便位移操作
2.4.1 请求安放一个卡片
public class SeedPea extends BaseModel implements TouchAble {
// 请求安放一个卡片
private void applyEmplacePea() {
// 向 GameView图层加
GameView.getInstance().applyEmplacePea(locationX, locationY);
}
2.4.3 GameView 新增该卡片
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
public void applyEmplacePea(int locationX, int locationY) {
synchronized (mSurfaceHolder) {
// 顶层加入被安放状态的植物
Log.d("sufadi", "applyEmplacePea add EmplacePea");
gameLayout1.add(new EmplacePea(locationX, locationY));
}
}
2.4.3 GameView 绘制该卡片,见图层 gameLayout1
注意下面的图层是有先后顺序的
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private void onDrawing(Canvas mCanvas) {
for (BaseModel model : gameLayout2) {
model.drawSelf(mCanvas, mPaint);
}
// 后画的会覆盖先画的,故位置在gameLayout2下面
if (gameLayout1 != null && !gameLayout1.isEmpty()) {
for (BaseModel model : gameLayout1) {
model.drawSelf(mCanvas, mPaint);
}
}
}
2.4.4 GameView 传递触摸事件
注意下面的图层是有先后顺序的
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
@Override
public boolean onTouchEvent(MotionEvent event) {
// 第一图层,背景图和放置状态栏的卡片
for (BaseModel model : gameLayout1) {
if (model instanceof TouchAble) {
if (((TouchAble) model).onTouch(event)) {
// true 表示触摸事件到此为止不再响应
return true;
}
}
}
// 第二图层,安放卡片
for (BaseModel model : gameLayout2) {
if (model instanceof TouchAble) {
if (((TouchAble) model).onTouch(event)) {
// true 表示触摸事件到此为止不再响应
return true;
}
}
}
return false;
}
2.4.5 卡片的移动事件
public class EmplacePea extends BaseModel implements TouchAble {
// 触摸区域
private Rect touchArea;
@Override
public boolean onTouch(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if (touchArea.contains(x, y)) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
// 卡片位置更新
locationX = x - Config.peaFlames[0].getWidth() / 2;
locationY = y - Config.peaFlames[0].getHeight() / 2;
// 触摸点跟随,重新移到新的位置
touchArea.offsetTo(locationX, locationY);
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
}
return false;
}
2.4.6 上述步骤每60秒不断绘制,故图片顺利移动
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
@Override
public void run() {
while (gameRunFlag) {
// 这里需要考虑线程同步
synchronized (mSurfaceHolder) {
try {
// 锁住画布才能绘图
mCanvas = mSurfaceHolder.lockCanvas();
mCanvas.drawBitmap(Config.gameBg, 0, 0, mPaint);
// 放置卡片的起始 X 坐标是 (界面宽度-卡片宽度) / 2
mCanvas.drawBitmap(Config.seekBank, (Config.screenWidth - Config.seekBank.getWidth()) / 2, 0, mPaint);
onDrawing(mCanvas);
} catch (Exception e) {
// e.printStackTrace();
} finally {
// 解锁并提交
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
try {
Thread.sleep(60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}