Android植物大战僵尸小游戏

Android植物大战僵尸小游戏全部内容如下:

相关下载:Android植物大战僵尸小游戏

具体代码如下所示:

package com.example.liu.mygame;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.tools.DeviceTools;
import com.example.liu.mygame.view.GameView;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.MotionEvent;
public class MainActivity extends Activity {
 private GameView gameview;
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  init();
  gameview = new GameView(this);
  setContentView(gameview);
 }
 // 初始化游戏资源
 private void init() {
  // TODO Auto-generated method stub
  // 获取屏幕大小尺寸
  Config.deviceWidth = DeviceTools.getDeviceInfo(this)[0];
  Config.deviceHeight = DeviceTools.getDeviceInfo(this)[1];
  // 得到原始图片
  Config.gameBK = BitmapFactory.decodeResource(getResources(),
    R.drawable.bk);
  // 获取缩放比
  Config.scaleWidth = Config.deviceWidth
    / (float) Config.gameBK.getWidth();
  Config.scaleHeight = Config.deviceHeight
    / (float) Config.gameBK.getHeight();
  // 处理图片让它成为目标图片
  Config.gameBK = DeviceTools.resizeBitmap(Config.gameBK);
  Config.seedBank = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.seedbank));
  // 绘制出卡片,不能进行等比缩放要进行目标大小的输入控制
  Config.seedFlower = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.seed_flower),
    Config.seedBank.getWidth() / 10,
    Config.seedBank.getHeight() * 8 / 10);
  Config.seedPea = DeviceTools.resizeBitmap(BitmapFactory.decodeResource(
    getResources(), R.drawable.seed_pea), Config.seedBank
    .getWidth() / 10, Config.seedBank.getHeight() * 8 / 10);
  // 初始化阳光图片
  Config.sun = DeviceTools.resizeBitmap(BitmapFactory.decodeResource(
    getResources(), R.drawable.sun));
  // 初始化子弹图片
  Config.bullet = DeviceTools.resizeBitmap(BitmapFactory.decodeResource(
    getResources(), R.drawable.bullet));
  // 初始化gameOver图片
  Config.gameOver = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.gameover));
  // 初始化动态图片帧
  Config.flowerFrames[0] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_01));
  Config.flowerFrames[1] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_02));
  Config.flowerFrames[2] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_03));
  Config.flowerFrames[3] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_04));
  Config.flowerFrames[4] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_05));
  Config.flowerFrames[5] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_06));
  Config.flowerFrames[6] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_07));
  Config.flowerFrames[7] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_1_08));
  Config.peaFrames[0] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_01));
  Config.peaFrames[1] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_02));
  Config.peaFrames[2] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_03));
  Config.peaFrames[3] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_04));
  Config.peaFrames[4] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_05));
  Config.peaFrames[5] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_06));
  Config.peaFrames[6] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_07));
  Config.peaFrames[7] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.p_2_08));
  Config.zombieFrames[0] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_01));
  Config.zombieFrames[1] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_02));
  Config.zombieFrames[2] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_03));
  Config.zombieFrames[3] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_04));
  Config.zombieFrames[4] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_05));
  Config.zombieFrames[5] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_06));
  Config.zombieFrames[6] = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.z_1_07));
 }
 // 重写onTouch触摸响应事件,返回值为gameview中生成的onTouch事件值
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // TODO Auto-generated method stub
  return gameview.onTouchEvent(event);
 }
 // 销毁
 @Override
 protected void onDestroy() {
  super.onDestroy();
 }
 // 停止
 @Override
 protected void onPause() {
  super.onPause();
 }
 // 重启
 @Override
 protected void onResume() {
  super.onResume();
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
public class Bullet extends BaseModel {
 // 位置
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 子弹产生时间
 private long birthTime = 0l;
 // X方向上的速度分量
 // 根据帧数,确定移动时间,然后来确定移动方式
 private float SpeedX = 10;
 public Bullet(int locationX, int locationY) {
  this.locationX = locationX + 40;
  this.locationY = locationY + 20;
  this.isAlife = true;
  // 获取系统时间
  birthTime = System.currentTimeMillis();
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   // 移动
   locationX += SpeedX;
   // 如果图片的Y轴坐标移动到超出屏幕或者说移动到与屏幕齐平,那么生命周期结束
   if (locationX > Config.deviceWidth) {
    // 去除子弹
    isAlife = false;
   }
  }
  canvas.drawBitmap(Config.bullet, locationX, locationY, paint);
 }
 @Override
 public int getModelWidth() {
  // TODO Auto-generated method stub
  return Config.bullet.getWidth();
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.TouchAble;
import com.example.liu.mygame.view.GameView;
public class EmplaceFlower extends BaseModel implements TouchAble {
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 触摸区域(矩形)
 private Rect touchArea;
 public EmplaceFlower(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化触摸响应矩形区域,与整体屏幕一致大小
  touchArea = new Rect(0, 0, Config.deviceWidth, Config.deviceHeight);
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   canvas.drawBitmap(Config.flowerFrames[0], locationX, locationY,
     paint);
  }
 }
 @Override
 public boolean onTouch(MotionEvent event) {
  // TODO Auto-generated method stub
  int x = (int) event.getX();
  int y = (int) event.getY();
  // 如果点击的地方是在矩形区域内,那么开始设置跟随
  if (touchArea.contains(x, y)) {
   // 图标跟随
   // switch中需要相应三个事件:按下、抬起、拖动
   switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    break;
   case MotionEvent.ACTION_MOVE:
    // drawSelf方法已定,那么我们需要改变表示位置的两个变量,同时也要改变响应点击的区域touchArea
    locationX = x - Config.flowerFrames[0].getWidth() / 2;
    locationY = y - Config.flowerFrames[0].getHeight() / 2;
    break;
   case MotionEvent.ACTION_UP:
    // 放手以后此移动中的实例的生命周期结束并在特定点产生新的固定的实例
    isAlife = false;
    // 交由GameView处理
    GameView.getInstance().applay4Plant(locationX, locationY, this);
    break;
   }
  }
  return false;
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.TouchAble;
import com.example.liu.mygame.view.GameView;
public class EmplacePea extends BaseModel implements TouchAble {
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 触摸区域(矩形)
 private Rect touchArea;
 public EmplacePea(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化触摸响应矩形区域
  touchArea = new Rect(0, 0, Config.deviceWidth, Config.deviceHeight);
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   canvas.drawBitmap(Config.peaFrames[0], locationX, locationY, paint);
  }
 }
 @Override
 public boolean onTouch(MotionEvent event) {
  // TODO Auto-generated method stub
  int x = (int) event.getX();
  int y = (int) event.getY();
  // 如果点击的地方是在矩形区域内,那么开始设置跟随
  if (touchArea.contains(x, y)) {
   // 图标跟随
   // switch中需要相应三个事件:按下、抬起、拖动
   switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    break;
   case MotionEvent.ACTION_MOVE:
    // drawSelf方法已定,那么我们需要改变表示位置的两个变量,同时也要改变响应点击的区域touchArea
    locationX = x - Config.peaFrames[0].getWidth() / 2;
    locationY = y - Config.peaFrames[0].getHeight() / 2;
    break;
   case MotionEvent.ACTION_UP:
    // 放手以后此移动中的实例的生命周期结束并在特定点产生新的固定的实例
    isAlife = false;
    // 交由GameView处理
    GameView.getInstance().applay4Plant(locationX, locationY, this);
    break;
   }
  }
  return false;
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.Plant;
import com.example.liu.mygame.view.GameView;
//豌豆射手实体类
public class Flower extends BaseModel implements Plant {
 private int locationX;
 private int locationY;
 private boolean isAlife;
 // 图片帧数组的下标
 private int frameIndex = 0;
 // 一个标记通过此标记确定此处是否有植物
 private int mapIndex;
 // 控制产生阳光的时间
 private long lastBirthTime;
 // 摆动速度控制,两帧一动
 private boolean swingSpeed;
 public Flower(int locationX, int locationY, int mapIndex) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.mapIndex = mapIndex;
  isAlife = true;
  // 初始化时间用来确保初试时间与花的创造时间一致
  lastBirthTime = System.currentTimeMillis();
  swingSpeed = false;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   // 这里绘入的bitmap就需要在绘制自己的时候换自己的帧动画以形成动态效果
   // 这个组在Config中已经初始化好了
   canvas.drawBitmap(Config.flowerFrames[frameIndex], locationX,
     locationY, paint);
   // 用此变量让数组变化
   // 通过这样的取模方法,可以让这个frameIndex值不超过7
   // 当frameIndex为8时会变为0,避免数组越界
   if (!swingSpeed) {
    frameIndex = (++frameIndex) % 8;
    swingSpeed = false;
   } else {
    swingSpeed = true;
   }
   // 用此处判断来确定每10秒一个阳光的产生
   if (System.currentTimeMillis() - lastBirthTime > 10000) {
    lastBirthTime = System.currentTimeMillis();
    giveBirth2Sun();
   }
  }
 }
 // 产生阳光
 // 阳光具有生命,然后两种情况,被点击则转换状态,移动到上方阳光的标志处,过一段时间不点击则死亡消失
 // 产生在花的位置上
 private void giveBirth2Sun() {
  // 首先要有阳光的图层集合,处于第三层,那么就需要操作集合,就需要调用GameView.getInstance
  GameView.getInstance().giveBrith2Sun(locationX, locationY);
 }
 @Override
 public int getModelWidth() {
  // TODO Auto-generated method stub
  return Config.flowerFrames[0].getWidth();
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
 @Override
 public int getmapIndex() {
  // TODO Auto-generated method stub
  return mapIndex;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.Plant;
import com.example.liu.mygame.view.GameView;
//豌豆射手实体类
public class Pea extends BaseModel implements Plant {
 private int locationX;
 private int locationY;
 private boolean isAlife;
 // 图片帧数组的下标
 private int frameIndex = 0;
 // 一个标记通过此标记确定此处是否有植物
 private int mapIndex;
 // 控制产生子弹的时间
 private long lastBirthTime;
 // 摆动速度控制,两帧一动
 private boolean swingSpeed;
 public Pea(int locationX, int locationY, int mapIndex) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.mapIndex = mapIndex;
  isAlife = true;
  swingSpeed = false;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   // 这里绘入的bitmap就需要在绘制自己的时候换自己的帧动画以形成动态效果
   // 这个组在Config中已经初始化好了
   canvas.drawBitmap(Config.peaFrames[frameIndex], locationX,
     locationY, paint);
   // 用此变量让数组变化
   // 通过这样的取模方法,可以让这个frameIndex值不超过7
   // 当frameIndex为8时会变为0,避免数组越界
   if (!swingSpeed) {
    frameIndex = (++frameIndex) % 8;
    swingSpeed = false;
   } else {
    swingSpeed = true;
   }
   // 用此处判断来确定每10秒一个子弹的产生
   if (System.currentTimeMillis() - lastBirthTime > 10000) {
    lastBirthTime = System.currentTimeMillis();
    giveBirth2Bullet();
   }
  }
 }
 // 产生子弹
 // 子弹具有生命,然后两种情况,被点击则转换状态,移动到上方子弹的标志处,过一段时间不点击则死亡消失
 // 产生在花的位置上
 private void giveBirth2Bullet() {
  // 首先要有子弹的图层集合,处于第三层,那么就需要操作集合,就需要调用GameView.getInstance
  GameView.getInstance().giveBirth2Bullet(locationX, locationY);
 }
 @Override
 public int getModelWidth() {
  // TODO Auto-generated method stub
  return Config.peaFrames[0].getWidth();
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
 @Override
 public int getmapIndex() {
  // TODO Auto-generated method stub
  return mapIndex;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.TouchAble;
import com.example.liu.mygame.view.GameView;
public class SeedFlower extends BaseModel implements TouchAble {
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 触摸区域(矩形)
 private Rect touchArea;
 public SeedFlower(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化触摸响应矩形区域
  touchArea = new Rect(locationX, locationY, locationX
    + Config.seedFlower.getWidth(), locationY
    + Config.seedFlower.getHeight());
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   canvas.drawBitmap(Config.seedFlower, locationX, locationY, paint);
  }
 }
 @Override
 public boolean onTouch(MotionEvent event) {
  // TODO Auto-generated method stub
  // 获取并传入触摸的X,Y坐标,getX() getY()获取到的数据都是float型
  int x = (int) event.getX();
  int y = (int) event.getY();
  if (touchArea.contains(x, y)) {
   // 当触摸点落在区域内则响应
   // 生成安置状态的花(优先级最高)
   if (Config.sunlight >= 50) {
    applay4EmplaceFlower();
    return true;
   }
  }
  return false;
 }
 // 通过GameView来请求生成一个安置状态的花(优先级最高)
 private void applay4EmplaceFlower() {
  // TODO Auto-generated method stub
  GameView.getInstance().applay4EmplacePlant(locationX, locationY, this);
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.TouchAble;
import com.example.liu.mygame.view.GameView;
public class SeedPea extends BaseModel implements TouchAble {
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 触摸区域(矩形)
 private Rect touchArea;
 public SeedPea(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化触摸响应矩形区域
  touchArea = new Rect(locationX, locationY, locationX
    + Config.seedPea.getWidth(), locationY
    + Config.seedPea.getHeight());
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   canvas.drawBitmap(Config.seedPea, locationX, locationY, paint);
  }
 }
 @Override
 public boolean onTouch(MotionEvent event) {
  // TODO Auto-generated method stub
  // 获取并传入触摸的X,Y坐标,getX() getY()获取到的数据都是float型
  int x = (int) event.getX();
  int y = (int) event.getY();
  if (touchArea.contains(x, y)) {
   // 当触摸点落在区域内则响应
   // 生成安置状态的豌豆(优先级最高)
   if (Config.sunlight >= 100) {
    applay4EmplacePea();
    return true;
   }
  }
  return false;
 }
 // 通过GameView来请求生成一个安置状态的豌豆(优先级最高)
 private void applay4EmplacePea() {
  // TODO Auto-generated method stub
  GameView.getInstance().applay4EmplacePlant(locationX, locationY, this);
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.TouchAble;
public class Sun extends BaseModel implements TouchAble {
 // 位置
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 可触摸区域
 private Rect touchArea;
 // 阳光产生时间
 private long birthTime;
 // 标示阳光的状态
 private SunState state;
 // 移动距离
 private int DirectionDistanceX;
 private int DirectionDistanceY;
 // XY方向上的速度分量
 // 根据帧数,确定移动时间,然后来确定移动方式
 private float SpeedX;
 private float SpeedY;
 // 用此枚举来标示阳光的状态
 // 两个状态:静止、移动
 // 移动过程中生命周期对阳光无效,静止时生命周期有效
 public enum SunState {
  SHOW, MOVE
 }
 public Sun(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化触摸响应矩形区域
  // 对于每个阳光来说能出没的地方只有他这张图片大小的区域
  touchArea = new Rect(locationX, locationY, locationX
    + Config.sun.getWidth(), locationY + Config.sun.getHeight());
  // 获取系统时间
  birthTime = System.currentTimeMillis();
  // 初始实例化为SHOW状态
  state = SunState.SHOW;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   if (state == SunState.SHOW) {
    // 判断当前系统时间如果比出生时间大5000毫秒那么阳光生命结束,消失
    if (System.currentTimeMillis() - birthTime > Config.lifeTime) {
     isAlife = false;
    }
   } else {// 对于move状态的阳光的处理
    // 移动
    locationX -= SpeedX;
    locationY -= SpeedY;
    // 如果图片的Y轴坐标移动到超出屏幕或者说移动到与屏幕齐平,那么生命周期结束
    if (locationY <= 0) {
     // 去除阳光
     isAlife = false;
     // 改变阳光值
     Config.sunlight += 25;
    }
   }
   canvas.drawBitmap(Config.sun, locationX, locationY, paint);
  }
 }
 // 触摸事件响应
 @Override
 public boolean onTouch(MotionEvent event) {
  // TODO Auto-generated method stub
  // 获取触摸点
  int x = (int) event.getX();
  int y = (int) event.getY();
  // 如果触摸点在可触摸区域内
  if (touchArea.contains(x, y)) {
   // 开始运动并且不可被点击,同时可能会与上边框产生碰撞事件
   // 移动过程中也需要时间,如果这个收集时间中用了超过阳光生命值5秒的时间
   // 那么我们需要在点击以后改变阳光的状态并删除原本的静态阳光
   state = SunState.MOVE;
   // 改变状态以后,那么就要开始移动,移动的起点不一定,但是终点是一定的
   // 移动的终点可以认为是条形框(seedBank)的左上角点
   // 起始点就是此阳光图片的左上角
   // XY方向上的移动距离
   DirectionDistanceX = locationX - Config.seedBankLocationX;
   DirectionDistanceY = locationY;
   // 移动速度分量的计算,具体帧数需要项目分析,这里设置为20帧
   SpeedX = DirectionDistanceX / 20f;
   SpeedY = DirectionDistanceY / 20f;
   return true;
  }
  return false;
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.view.GameView;
public class Zombie extends BaseModel {
 private int locationX;
 private int locationY;
 private boolean isAlife;
 // 僵尸位于的跑道,因为此僵尸只跟其所在的跑道内的植物、子弹等进行碰撞检测
 private int raceWay;
 // 因为僵尸是移动中的 所以他要有动画帧的下标
 private int frameIndex = 0;
 // 移动速度,每一帧移动3像素
 private int peedX = 3;
 public Zombie(int locationX, int locationY, int raceWay) {
  this.locationX = locationX;
  this.locationY = locationY;
  isAlife = true;
  this.raceWay = raceWay;
 }
 // 在某跑道随机产生僵尸,同时间隔一段时间出现一只僵尸
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (locationX < 0) {
   Config.game = false;
  }
  if (isAlife) {
   canvas.drawBitmap(Config.zombieFrames[frameIndex], locationX,
     locationY, paint);
   frameIndex = (++frameIndex) % 7;
   locationX -= peedX;
   // 碰撞检测,僵尸发起的此碰撞检测
   GameView.getInstance().checkCollision(this, raceWay);
  }
 }
 @Override
 public int getModelWidth() {
  // TODO Auto-generated method stub
  return Config.zombieFrames[0].getWidth();
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.entity;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.view.GameView;
public class ZombieManager extends BaseModel {
 // 一般需要显示出现在屏幕上的实体才需要继承BaseModel
 // 所以此处的僵尸控制器其实不需要继承BaseModel
 // 但是为了与之前的flower和pea产生器相统一
 // 效仿以前的模式减少工作量
 // 在这里也进行继承
 private boolean isAlife;
 // 最后一只僵尸的产生时间
 private long lastBirthTime;
 public ZombieManager() {
  lastBirthTime = System.currentTimeMillis();
  isAlife = true;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  // 此处不需要绘制出图片,所以不需要draw,但是可以进行逻辑上的处理
  if (System.currentTimeMillis() - lastBirthTime > 15000) {
   lastBirthTime = System.currentTimeMillis();
   giveBirth2Zombie();
  }
 }
 private void giveBirth2Zombie() {
  // 与GameView请求加入僵尸
  GameView.getInstance().apply4AddZombie();
 }
}
package com.example.liu.mygame.global;
import java.util.HashMap;
import android.graphics.Bitmap;
import android.graphics.Point;
//常量
public class Config {
 public static float scaleWidth;
 public static float scaleHeight;
 public static int deviceWidth;
 public static int deviceHeight;
 public static Bitmap gameBK;
 public static Bitmap seedBank;
 public static Bitmap gameOver;
 // seedBank的位置X坐标
 public static int seedBankLocationX;
 public static Bitmap seedFlower;
 public static Bitmap seedPea;
 // 阳光
 public static Bitmap sun;
 // 阳光的生存时间5000毫秒
 public static long lifeTime = 5000;
 // 现在的阳光值
 public static int sunlight = 200;
 // 僵尸和植物图片的高度差
 public static int heightYDistance;
 // 子弹
 public static Bitmap bullet;
 // 将图片帧放入数组
 public static Bitmap[] flowerFrames = new Bitmap[8];
 public static Bitmap[] peaFrames = new Bitmap[8];
 public static Bitmap[] zombieFrames = new Bitmap[7];
 // 放置植物的点
 public static HashMap<Integer, Point> plantPoints = new HashMap<Integer, Point>();
 // 跑道
 public static int[] raceWayYpoints = new int[5];
 // 输赢判断标志
 public static boolean game = true;
}
package com.example.liu.mygame.model;
import android.graphics.Canvas;
import android.graphics.Paint;
public class BaseModel {
 // 基础类,对于所有能展示在屏幕上的动态对象都要继承自此类
 // 位置
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 绘制自己,即移动
 public void drawSelf(Canvas canvas, Paint paint) {
 }
 public int getModelWidth() {
  return 0;
 }
 public int getLocationX() {
  return locationX;
 }
 public void setLocationX(int locationX) {
  this.locationX = locationX;
 }
 public int getLocationY() {
  return locationY;
 }
 public void setLocationY(int locationY) {
  this.locationY = locationY;
 }
 public boolean isAlife() {
  return isAlife;
 }
 public void setAlife(boolean isAlife) {
  this.isAlife = isAlife;
 }
}
package com.example.liu.mygame.model;
// 所有需要种植在地上保持静止的植物都要有这个接口
public interface Plant {
 // 用于key
 public int getmapIndex();
}
package com.example.liu.mygame.model;
import android.view.MotionEvent;
public interface TouchAble {
 // 对于能接受触摸事件的对象的一个公用接口
 // 传入MotionEvent事件
 public boolean onTouch(MotionEvent event);
}
package com.example.liu.mygame.tools;
import com.example.liu.mygame.global.Config;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.util.DisplayMetrics;
import android.util.Log;
public class DeviceTools {
 private static int[] deviceWidthHeight = new int[2];
 // 重新设置Bitmap的大小
 public static Bitmap resizeBitmap(Bitmap bitmap) {
  if (bitmap != null) {
   int width = bitmap.getWidth();
   int height = bitmap.getHeight();
   Log.i("info", width + "," + height);
   Matrix matrix = new Matrix();
   matrix.postScale(Config.scaleWidth, Config.scaleHeight);
   Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width,
     height, matrix, true);
   return resizedBitmap;
  } else {
   return null;
  }
 }
 // 重载
 // 原因是找到的素材需要进行处理来适应手机屏幕,等比操作,但是如果合成的两张材料图不成比例 那么就不得不用这种重载来适应
 // 首先传入一个bitmap和期望的宽高
 public static Bitmap resizeBitmap(Bitmap bitmap, int w, int h) {
  if (bitmap != null) {
   // 获取传入的图片宽高
   int width = bitmap.getWidth();
   int height = bitmap.getHeight();
   // 传入期望的宽高
   int newWidth = w;
   int newHeight = h;
   // 缩放比
   float scaleWidth = ((float) newWidth) / width;
   float scaleHeight = ((float) newHeight) / height;
   // 图片矩阵对象,3X3矩阵
   Matrix matrix = new Matrix();
   // 把缩放比传入期望矩阵
   matrix.postScale(scaleWidth, scaleHeight);
   // 生成期望的图片
   Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, width,
     height, matrix, true);
   return resizeBitmap;
  } else {
   return null;
  }
 }
 // 获取屏幕的宽高
 // 在DisplayMetrics类中可以获取屏幕的亮度,宽高,刷新率等相关信息
 public static int[] getDeviceInfo(Context context) {
  if ((deviceWidthHeight[0] == 0) && (deviceWidthHeight[1] == 0)) {
   DisplayMetrics metrics = new DisplayMetrics();
   ((Activity) context).getWindowManager().getDefaultDisplay()
     .getMetrics(metrics);
   deviceWidthHeight[0] = metrics.widthPixels;
   deviceWidthHeight[1] = metrics.heightPixels;
  }
  return deviceWidthHeight;
 }
}
package com.example.liu.mygame.view;
import java.util.ArrayList;
import com.example.liu.mygame.R;
import com.example.liu.mygame.entity.*;
import com.example.liu.mygame.global.Config;
import com.example.liu.mygame.model.BaseModel;
import com.example.liu.mygame.model.Plant;
import com.example.liu.mygame.model.TouchAble;
import android.R.bool;
import android.R.integer;
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.Point;
import android.graphics.Typeface;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
//对于这种有赛道的游戏可以用以下方法
//对于那种可以上下移动的游戏可以把所有精灵放在一个集合里 不用分图层 每次绘制的时候要按照Y坐标进行排序
//对于先画出来的肯定是排在前面的 所以Y最小的排在前面即离屏幕上边缘最近的精灵
//那种游戏肯定会通过游戏引擎来进行开发
public class GameView extends SurfaceView implements SurfaceHolder.Callback,
  Runnable {
 private Canvas canvas;
 private Paint paint;
 private SurfaceHolder surfaceHolder;
 private boolean gameRunFlag;
 private Context context;// 用于存放图片地址
 // 把GameView当做总管理,所有的实体都向这里发送请求并处理
 private static GameView gameView;
 private ArrayList<BaseModel> deadList;// 存放已消亡的实体,在拖动放手后实体会不显示,但是还存在所以要进行清理
 private ArrayList<BaseModel> gameLayout3;// 存放第三图层中的实体;
 private ArrayList<BaseModel> gameLayout2;// 存放第二图层中的实体
 private ArrayList<BaseModel> gameLayout1;// 存放第一图层中的实体
 // 跑道从上至下
 // 这些可以做一个封装,放入一个for循环进行创建即可
 private ArrayList<BaseModel> gameLayout4plant0;
 private ArrayList<BaseModel> gameLayout4plant1;
 private ArrayList<BaseModel> gameLayout4plant2;
 private ArrayList<BaseModel> gameLayout4plant3;
 private ArrayList<BaseModel> gameLayout4plant4;
 // 定义僵尸跑道
 private ArrayList<BaseModel> gamelayout4zombie0;
 private ArrayList<BaseModel> gamelayout4zombie1;
 private ArrayList<BaseModel> gamelayout4zombie2;
 private ArrayList<BaseModel> gamelayout4zombie3;
 private ArrayList<BaseModel> gamelayout4zombie4;
 // 定义僵尸控制器,通过此控制器来使僵尸实现移动
 private ZombieManager zombieManager;
 public GameView(Context context) {
  super(context);
  // TODO GameView
  this.context = context;
  paint = new Paint();
  surfaceHolder = getHolder();
  surfaceHolder.addCallback(this);
  gameRunFlag = true;
  gameView = this;
  if (Config.game == false) {
   canvas.drawBitmap(Config.gameOver, 0, 0, paint);
  }
 }
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  // TODO surfaceCreated
  // 加载bitmap(图片)
  createElement();
  new Thread(this).start();
 }
 private void createElement() {
  // TODO createElement
  // 给植物与僵尸的高度差赋值
  Config.heightYDistance = Config.zombieFrames[0].getHeight()
    - Config.flowerFrames[0].getHeight();
  // 给seedBank的X坐标赋初值
  Config.seedBankLocationX = (Config.deviceWidth - Config.seedBank
    .getWidth()) / 2;
  // 初始化第三图层
  gameLayout3 = new ArrayList<BaseModel>();
  // 当此方法被触发时便会创建卡片对象
  gameLayout2 = new ArrayList<BaseModel>();
  SeedFlower seedFlower = new SeedFlower(
    (Config.deviceWidth - Config.seedBank.getWidth()) / 2
      + Config.seedFlower.getWidth() / 3
      + Config.seedBank.getWidth() / 7,
    Config.seedBank.getHeight() / 10);
  SeedPea seedPea = new SeedPea(
    (Config.deviceWidth - Config.seedBank.getWidth()) / 2
      + Config.seedFlower.getWidth() / 7
      + Config.seedBank.getWidth() / 7 * 2,
    Config.seedBank.getHeight() / 10);
  gameLayout2.add(seedFlower);
  gameLayout2.add(seedPea);
  // 添加安置状态中的植物
  gameLayout1 = new ArrayList<BaseModel>();
  deadList = new ArrayList<BaseModel>();
  gameLayout4plant0 = new ArrayList<BaseModel>();
  gameLayout4plant1 = new ArrayList<BaseModel>();
  gameLayout4plant2 = new ArrayList<BaseModel>();
  gameLayout4plant3 = new ArrayList<BaseModel>();
  gameLayout4plant4 = new ArrayList<BaseModel>();
  // 僵尸跑道初始化
  gamelayout4zombie0 = new ArrayList<BaseModel>();
  gamelayout4zombie1 = new ArrayList<BaseModel>();
  gamelayout4zombie2 = new ArrayList<BaseModel>();
  gamelayout4zombie3 = new ArrayList<BaseModel>();
  gamelayout4zombie4 = new ArrayList<BaseModel>();
  // 初始化僵尸控制器
  zombieManager = new ZombieManager();
  // 放置植物的合适位置
  for (int i = 0; i < 5; i++) {
   for (int j = 0; j < 9; j++) {
    Config.plantPoints.put(i * 10 + j, new Point(
      (j + 2) * Config.deviceWidth / 11 - Config.deviceWidth
        / 11 / 2, (i + 1) * Config.deviceHeight / 6));
    if (j == 0) {
     Config.raceWayYpoints[i] = (i + 1) * Config.deviceHeight
       / 6;
    }
   }
  }
 }
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
   int height) {
  // TODO surfaceChanged
 }
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  // TODO surfaceDestroyed
 }
 // 所有的动画帧都由这个run方法来控制
 // 控制动画帧的时候要注意首先进行数据更新 然后在更新图像
 @Override
 public void run() {
  // TODO run
  while (gameRunFlag) {
   synchronized (surfaceHolder) {
    try {
     // 为了形成动画效果首先需要清理屏幕
     // 加锁避免很多线程同时绘制
     canvas = surfaceHolder.lockCanvas();
     // 绘入背景,最底层图层
     canvas.drawBitmap(Config.gameBK, 0, 0, paint);
     // 绘入上方植物栏,倒数第二层图层,仅覆盖于背景之上
     canvas.drawBitmap(Config.seedBank,
       Config.seedBankLocationX, 0, paint);
     // 数据更改操作
     updateData();
     // 绘入植物卡片(第二层)
     ondraw(canvas);
    } catch (Exception e) {
     // TODO: handle exception
    } finally {
     // 解锁并提交
     surfaceHolder.unlockCanvasAndPost(canvas);
     // CanvasAndPost必须要进行解锁 不管程序有什么问题必须给用户直观完整的显示过程
     // 以防万一的话 加入try catch
    }
   }
   // 加入以下语句每次循环中休眠50毫秒减少一直循环的系统资源浪费
   // 使用50毫秒的原因是在42帧及以上肉眼就会认为是流畅的,即1秒42张图片,每次循环休眠50毫秒即20帧
   // 如果把sleep放在synchronized中的话会出现程序每次遍历完立刻睡眠然后再次遍历没有给其他进程事件运行会造成卡死
   try {
    Thread.sleep(40);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 private void updateData() {
  // 在此方法中进行数据更新
  // 清除deadList
  deadList.clear();
  // 遍历第一图层
  for (BaseModel model : gameLayout1) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  // 遍历第二图层
  for (BaseModel model : gameLayout2) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  // 遍历第三图层
  for (BaseModel model : gameLayout3) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  // 遍历五条跑道上的僵尸
  for (BaseModel model : gamelayout4zombie0) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gamelayout4zombie1) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gamelayout4zombie2) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gamelayout4zombie3) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gamelayout4zombie4) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  // 遍历五条跑道上的植物
  for (BaseModel model : gameLayout4plant0) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gameLayout4plant1) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gameLayout4plant2) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gameLayout4plant3) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  for (BaseModel model : gameLayout4plant4) {
   if (!model.isAlife()) {
    deadList.add(model);
   }
  }
  // 遍历deadList集合
  for (BaseModel model : deadList) {
   // 在各个图层列表中把它们移除
   gameLayout1.remove(model);
   gameLayout2.remove(model);
   gameLayout3.remove(model);
   gamelayout4zombie0.remove(model);
   gamelayout4zombie1.remove(model);
   gamelayout4zombie2.remove(model);
   gamelayout4zombie3.remove(model);
   gamelayout4zombie4.remove(model);
  }
 }
 private void ondraw(Canvas canvas) {
  // TODO ondraw
  // 在此方法中进行绘图作业
  // 按照游戏的层次进行绘制,先画游戏层次最下方的精灵
  // 按照已经写好的分层顺序
  // 绘制出阳光值
  Paint paint2 = new Paint();
  paint2.setTypeface(Typeface.DEFAULT_BOLD);
  paint2.setTextSize(15);
  canvas.drawText(Config.sunlight + "", Config.deviceWidth * 2 / 7,
    Config.deviceHeight / 8, paint2);
  // 僵尸控制器中的drawSelf实现僵尸移动
  zombieManager.drawSelf(canvas, paint);
  // 跑道应该处于第四层故放在上方先绘制出来
  // 遍历五条跑道调用drawSelf方法进行绘制植物
  // 此处也可以进行方法的抽象 或者说应该把这些重复的代码抽象为一个方法调用不同的值进去
  for (BaseModel model : gameLayout4plant0) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gameLayout4plant1) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gameLayout4plant2) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gameLayout4plant3) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gameLayout4plant4) {
   model.drawSelf(canvas, paint);
  }
  // 第三层(阳光)
  for (BaseModel model : gameLayout3) {
   model.drawSelf(canvas, paint);
  }
  // 第二层
  for (BaseModel model : gameLayout2) {
   model.drawSelf(canvas, paint);
  }
  // 遍历五条跑道调用drawSelf方法进行绘制僵尸
  // 此处也可以进行方法的抽象 或者说应该把这些重复的代码抽象为一个方法调用不同的值进去
  // 第二层是植物卡片,僵尸在经过第一行的时候应该可以挡住植物卡片
  for (BaseModel model : gamelayout4zombie0) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gamelayout4zombie1) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gamelayout4zombie2) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gamelayout4zombie3) {
   model.drawSelf(canvas, paint);
  }
  for (BaseModel model : gamelayout4zombie4) {
   model.drawSelf(canvas, paint);
  }
  // 第一层
  // gameLayout1比gameLayout2的层次要高故放在后面
  for (BaseModel model : gameLayout1) {
   model.drawSelf(canvas, paint);
  }
  /*
   * private m=200; Paint paint3 = new Paint(); paint3.setAlpha(100);
   * canvas.drawRect(100, 100, 200, m, paint3); m-=5; 设置半透明效果
   * m的作用是可以让这个半透明效果逐步消去, m的变化大小就可以理解为此植物的冷却时间
   */
 }
 // 在这里重写触摸响应事件
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // TODO onTouchEvent
  // 对于相应来说gameLayout1的优先级最高故放在gameLayout2上方
  for (BaseModel model : gameLayout1) {
   // 判定是否为touchAble的子类,只有是touchAble的子类才能响应
   if (model instanceof TouchAble) {
    // 然后进行onTouch事件,查看是否被点击,如果点击那么返回true
    if (((TouchAble) model).onTouch(event)) {
     return true;
    }
   }
  }
  // 遍历第二层中的全部实体
  for (BaseModel model : gameLayout2) {
   // 判定是否为touchAble的子类,只有是touchAble的子类才能响应
   if (model instanceof TouchAble) {
    // 然后进行onTouch事件,查看是否被点击,如果点击那么返回true
    if (((TouchAble) model).onTouch(event)) {
     return true;
    }
   }
  }
  // 遍历第三层中的全部实体
  for (BaseModel model : gameLayout3) {
   // 判定是否为touchAble的子类,只有是touchAble的子类才能响应
   if (model instanceof TouchAble) {
    // 然后进行onTouch事件,查看是否被点击,如果点击那么返回true
    if (((TouchAble) model).onTouch(event)) {
     return true;
    }
   }
  }
  return false;
 }
 // 获取GameView的方法,让GameView编程所有实体的总桥梁
 public static GameView getInstance() {
  return gameView;
 }
 // 添加EmplacePlant植物(优先级最高)
 public void applay4EmplacePlant(int locationX, int locationY,
   BaseModel model) {
  // TODO applay4EmplacePlant
  // 相当于在进行数据更新,在onDraw中会从这里取出一个个元素进行绘制,绘制过程中如果这里还会有更新那么会产生冲突,所以需要在这里加入一个同步锁
  // 所有对于集合的操作都要加入同步锁,锁对象用surfaceHolder当得到此surfaceHolder锁对象的时候才能够进行操作
  synchronized (surfaceHolder) {
   // gameLayout1放的是正在安放状态的植物,没有放下
   // new一个处于安置状态的实体
   // gameLayout1中只能有0~1个实例
   if (gameLayout1.size() < 1) {
    if (model instanceof SeedPea) {
     gameLayout1.add(new EmplacePea(locationX, locationY));
    } else {
     gameLayout1.add(new EmplaceFlower(locationX, locationY));
    }
   }
  }
 }
 public void applay4Plant(int locationX, int locationY, BaseModel baseModel) {
  // TODO applay4Plant
  // 安放静态植物
  // 以空间换时间,因为植物、子弹、僵尸、都在第四层所以对于这些来说把它们分为五个赛道从上至下五层
  // 每条赛道上有两个集合,一个是僵尸的集合,另一个是植物与子弹的集合,这样分是为了碰撞检测
  // 为了减少碰撞检测事件去除部分不必要的运算,故而分成很多层
  // 循环这个可安放植物的HashMap,目的是拿出每个元素与locationX和locationY进行比较
  // key的作用是让每个Paint的标示不同
  synchronized (surfaceHolder) {// 加锁
   Point point;
   for (Integer key : Config.plantPoints.keySet()) {
    // 找距离locationX与locationY最近而且处于目标地域上
    point = Config.plantPoints.get(key);
    if ((Math.abs(locationX - point.x) < Config.deviceWidth / 11 / 2)
      && (Math.abs(locationY - point.y) < Config.deviceHeight / 6 / 2)) {
     // 跑道标示
     int raceWayIndex = 6;
     for (int i = 0; i < Config.raceWayYpoints.length; i++) {
      // 遍历跑道的Y值
      if (point.y == Config.raceWayYpoints[i]) {
       // 如果Y值相等那么跑道确定
       raceWayIndex = i;
      }
     }
     if (isPlantExist(key, raceWayIndex)) {
      // 跑道数出发事件
      switch (raceWayIndex) {
      case 0:
       if (baseModel instanceof EmplacePea) {
        gameLayout4plant0.add(new Pea(point.x, point.y,
          key));
        Config.sunlight -= 100;
       } else {
        gameLayout4plant0.add(new Flower(point.x,
          point.y, key));
        Config.sunlight -= 50;
       }
       break;
      case 1:
       if (baseModel instanceof EmplacePea) {
        gameLayout4plant1.add(new Pea(point.x, point.y,
          key));
        Config.sunlight -= 100;
       } else {
        gameLayout4plant1.add(new Flower(point.x,
          point.y, key));
        Config.sunlight -= 50;
       }
       break;
      case 2:
       if (baseModel instanceof EmplacePea) {
        gameLayout4plant2.add(new Pea(point.x, point.y,
          key));
        Config.sunlight -= 100;
       } else {
        gameLayout4plant2.add(new Flower(point.x,
          point.y, key));
        Config.sunlight -= 50;
       }
       break;
      case 3:
       if (baseModel instanceof EmplacePea) {
        gameLayout4plant3.add(new Pea(point.x, point.y,
          key));
        Config.sunlight -= 100;
       } else {
        gameLayout4plant3.add(new Flower(point.x,
          point.y, key));
        Config.sunlight -= 50;
       }
       break;
      case 4:
       if (baseModel instanceof EmplacePea) {
        gameLayout4plant4.add(new Pea(point.x, point.y,
          key));
        Config.sunlight -= 100;
       } else {
        gameLayout4plant4.add(new Flower(point.x,
          point.y, key));
        Config.sunlight -= 50;
       }
       break;
      default:
       break;
      }
     }
    }
   }
  }
 }
 // 判断此处是否已经有植物的方法
 // key是标示,raceWayIndex用于确定应查哪一个跑道
 private boolean isPlantExist(int key, int raceWayIndex) {
  switch (raceWayIndex) {
  case 0:
   for (BaseModel model : gameLayout4plant0) {
    // 首先 如果这个区域是继承了Plant接口的子类(因为子弹和阳光不继承Plant做以区别)
    if (model instanceof Plant) {
     // 然后此处的key与传入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此处不能种植植物
      return false;
     }
    }
   }
   break;
  case 1:
   for (BaseModel model : gameLayout4plant1) {
    // 首先 如果这个区域是继承了Plant接口的子类(因为子弹和阳光不继承Plant做以区别)
    if (model instanceof Plant) {
     // 然后此处的key与传入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此处不能种植植物
      return false;
     }
    }
   }
   break;
  case 2:
   for (BaseModel model : gameLayout4plant2) {
    // 首先 如果这个区域是继承了Plant接口的子类(因为子弹和阳光不继承Plant做以区别)
    if (model instanceof Plant) {
     // 然后此处的key与传入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此处不能种植植物
      return false;
     }
    }
   }
   break;
  case 3:
   for (BaseModel model : gameLayout4plant3) {
    // 首先 如果这个区域是继承了Plant接口的子类(因为子弹和阳光不继承Plant做以区别)
    if (model instanceof Plant) {
     // 然后此处的key与传入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此处不能种植植物
      return false;
     }
    }
   }
   break;
  case 4:
   for (BaseModel model : gameLayout4plant4) {
    // 首先 如果这个区域是继承了Plant接口的子类(因为子弹和阳光不继承Plant做以区别)
    if (model instanceof Plant) {
     // 然后此处的key与传入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此处不能种植植物
      return false;
     }
    }
   }
   break;
  default:
   break;
  }
  return true;
 }
 // 被Flower请求,用于产生阳光
 public void giveBrith2Sun(int locationX, int locationY) {
  // TODO giveBrith2Sun
  // 先设置锁住
  synchronized (surfaceHolder) {
   gameLayout3.add(new Sun(locationX, locationY));
  }
 }
 // 被Pea请求,用于产生子弹
 public void giveBirth2Bullet(int locationX, int locationY) {
  // TODO Auto-generated method stub
  // 先设置锁住
  synchronized (surfaceHolder) {// 加锁
   Point point;
   for (Integer key : Config.plantPoints.keySet()) {
    // 找距离locationX与locationY最近而且处于目标地域上
    point = Config.plantPoints.get(key);
    if ((Math.abs(locationX - point.x) < Config.deviceWidth / 11 / 2)
      && (Math.abs(locationY - point.y) < Config.deviceHeight / 6 / 2)) {
     // 跑道标示
     int raceWayIndex = 6;
     for (int i = 0; i < Config.raceWayYpoints.length; i++) {
      // 遍历跑道的Y值
      if (point.y == Config.raceWayYpoints[i]) {
       // 如果Y值相等那么跑道确定
       raceWayIndex = i;
      }
     }
     switch (raceWayIndex) {
     case 0:
      gameLayout4plant0.add(new Bullet(locationX, locationY));
      break;
     case 1:
      gameLayout4plant1.add(new Bullet(locationX, locationY));
      break;
     case 2:
      gameLayout4plant2.add(new Bullet(locationX, locationY));
      break;
     case 3:
      gameLayout4plant3.add(new Bullet(locationX, locationY));
      break;
     case 4:
      gameLayout4plant4.add(new Bullet(locationX, locationY));
      break;
     default:
      break;
     }
    }
   }
  }
 }
 // 僵尸控制器产生相应,加入僵尸
 public void apply4AddZombie() {
  // TODO apply4AddZombie
  // 先解锁
  synchronized (surfaceHolder) {
   int raceWay = 0;
   // 0~4的随机数来进行跑到初始化
   // Math.random()产生的是0~1的不包括1的随机double型数字
   raceWay = (int) (Math.random() * 5);
   // Config.deviceWidth + 20是为了让僵尸逐步走入屏幕
   // Config.raceWayYpoints[raceWay] - Config.heightYDistance
   // 是为了让僵尸与植物的底对齐
   switch (raceWay) {
   case 0:
    gamelayout4zombie0
      .add(new Zombie(Config.deviceWidth + 20,
        Config.raceWayYpoints[raceWay]
          - Config.heightYDistance, raceWay));
    break;
   case 1:
    gamelayout4zombie1
      .add(new Zombie(Config.deviceWidth + 20,
        Config.raceWayYpoints[raceWay]
          - Config.heightYDistance, raceWay));
    break;
   case 2:
    gamelayout4zombie2
      .add(new Zombie(Config.deviceWidth + 20,
        Config.raceWayYpoints[raceWay]
          - Config.heightYDistance, raceWay));
    break;
   case 3:
    gamelayout4zombie3
      .add(new Zombie(Config.deviceWidth + 20,
        Config.raceWayYpoints[raceWay]
          - Config.heightYDistance, raceWay));
    break;
   case 4:
    gamelayout4zombie4
      .add(new Zombie(Config.deviceWidth + 20,
        Config.raceWayYpoints[raceWay]
          - Config.heightYDistance, raceWay));
    break;
   default:
    break;
   }
  }
 }
 // 处理碰撞检测,碰撞检测的发起者是僵尸
 public void checkCollision(Zombie zombie, int raceWay) {
  // TODO Auto-generated method stub
  synchronized (surfaceHolder) {
   switch (raceWay) {
   case 0:
    for (BaseModel model : gameLayout4plant0) {
     if (Math.abs((model.getLocationX() + model.getModelWidth() / 2)
       - (zombie.getLocationX() + zombie.getModelWidth() / 2)) < Math
       .abs((model.getModelWidth() + zombie
         .getModelWidth()) / 2)) {
      if (model instanceof Plant) {
       // 植物死
       model.setAlife(false);
      } else if (model instanceof Bullet) {
       // 子弹死
       model.setAlife(false);
       // 僵尸死
       zombie.setAlife(false);
       model.setAlife(true);
      }
     }
    }
    break;
   case 1:
    for (BaseModel model : gameLayout4plant1) {
     if (Math.abs((model.getLocationX() + model.getModelWidth() / 2)
       - (zombie.getLocationX() + zombie.getModelWidth() / 2)) < Math
       .abs((model.getModelWidth() + zombie
         .getModelWidth()) / 2)) {
      if (model instanceof Plant) {
       // 植物死
       model.setAlife(false);
      } else if (model instanceof Bullet) {
       // 子弹死
       model.setAlife(false);
       // 僵尸死
       zombie.setAlife(false);
       model.setAlife(true);
      }
     }
    }
    break;
   case 2:
    for (BaseModel model : gameLayout4plant2) {
     if (Math.abs((model.getLocationX() + model.getModelWidth() / 2)
       - (zombie.getLocationX() + zombie.getModelWidth() / 2)) < Math
       .abs((model.getModelWidth() + zombie
         .getModelWidth()) / 2)) {
      if (model instanceof Plant) {
       // 植物死
       model.setAlife(false);
      } else if (model instanceof Bullet) {
       // 子弹死
       model.setAlife(false);
       // 僵尸死
       zombie.setAlife(false);
       model.setAlife(true);
      }
     }
    }
    break;
   case 3:
    for (BaseModel model : gameLayout4plant3) {
     if (Math.abs((model.getLocationX() + model.getModelWidth() / 2)
       - (zombie.getLocationX() + zombie.getModelWidth() / 2)) < Math
       .abs((model.getModelWidth() + zombie
         .getModelWidth()) / 2)) {
      if (model instanceof Plant) {
       // 植物死
       model.setAlife(false);
      } else if (model instanceof Bullet) {
       // 子弹死
       model.setAlife(false);
       // 僵尸死
       zombie.setAlife(false);
       model.setAlife(true);
      }
     }
    }
    break;
   case 4:
    for (BaseModel model : gameLayout4plant4) {
     if (Math.abs((model.getLocationX() + model.getModelWidth() / 2)
       - (zombie.getLocationX() + zombie.getModelWidth() / 2)) < Math
       .abs((model.getModelWidth() + zombie
         .getModelWidth()) / 2)) {
      if (model instanceof Plant) {
       // 植物死
       model.setAlife(false);
      } else if (model instanceof Bullet) {
       // 子弹死
       model.setAlife(false);
       // 僵尸死
       zombie.setAlife(false);
       model.setAlife(true);
      }
     }
    }
    break;
   default:
    break;
   }
  }
 }
}

(0)

相关推荐

  • Android实现完整游戏循环的方法

    本文实例讲述了Android实现完整游戏循环的方法.分享给大家供大家参考.具体如下: 1. DroidzActivity.java: package net.obviam.droidz; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Window; import android.view.WindowManager; public class

  • 图片拼图记忆力测试游戏,网页+JS版

    记忆力测试游戏,网页+JS版,规则:图被分割成15块. 每次随机给出一块,在问号区域中找到它的位置并单击该位置.每选对一个区域得一分,得15分才算获胜,每次游戏只有15次机会. 记忆测试 .20pt{font-size:20pt;color:#de3076} "; } if (N) { Styl=" ID="+divId+" top="+divY+" left="+divX+" width="+divW+"

  • Android游戏开发学习①弹跳小球实现方法

    本文实例讲述了Android游戏开发学习①弹跳小球实现方法.分享给大家供大家参考.具体如下: 在学习了一点点Android之后,觉得有必要记录下来,于是就开了这个新坑,慢慢来填吧. 1.运动体Movable类 本例主要模拟了一组大小不一的球以一定的水平初速度从高处落下的运动轨迹.其中的小球为一个可移动物体Movable对象,该类中除了包含小球图片对象之外,还包括了如位置坐标.水平速度.垂直速度等一系列用于模拟小球运动的成员变量和一些方法. Movable类: package com.ball;

  • Java制作智能拼图游戏原理及代码

    今天突发奇想,想做一个智能拼图游戏来给哄女友. 需要实现这些功能 第一图片自定义 第二宫格自定义,当然我一开始就想的是3*3 4*4 5*5,没有使用3*5这样的宫格. 第三要实现自动拼图的功能,相信大家知道女人耍游戏都不是很厉害,所以这个自动拼图功能得有. 其他什么暂停.排行就不写了! 现在重点问题出来了 要实现自动拼图功能似乎要求有点高哦!计算机有可不能像人一样只能: 先追究下本质 拼图游戏其实就是排列问题: 排列有这么一个定义:在一个1,2,...,n的排列中,如果一对数的前后位置与大小顺

  • Android实现美女拼图游戏详解

    先来看看效果: 图片切分很多份,点击交换拼成一张完整的:这样关卡也很容易设计,3 3:4 4:5 5:6 6:一直下去 加了个切换动画,效果还是不错的,其实游戏就是自定义了一个控件,下面我们开始自定义之旅. 游戏的设计 首先我们分析下如何设计这款游戏: 1.我们需要一个容器,可以放这些图片的块块,为了方便,我们准备使用RelativeLayout配合addRule实现 2.每个图片的块块,我们准备使用ImageView 3.点击交换,我们准备使用传统的TranslationAnimation来实

  • Android 游戏开发之Canvas画布的介绍及方法

    Canvas,在英语中,这个单词的意思是帆布.在Android中,则把Canvas当做画布,只要我们借助设置好的画笔(Paint类)就可以在画布上绘制我们想要的任何东西:另外它也是显示位图(Bitmap类)的核心类.随用户的喜好,Canvas还可设置一些关于画布的属性,比如,画布的颜色.尺寸等.Canvas提供了如下一些方法:    Canvas(): 创建一个空的画布,可以使用setBitmap()方法来设置绘制具体的画布.    Canvas(Bitmap bitmap): 以bitmap对

  • JS 拼图游戏 面向对象,注释完整。

    在线演示 http://img.jb51.net/online/pintu/pintu.htm 复制代码 代码如下: <html> <head> <title>JS拼图游戏</title> <style>     body{         font-size:9pt;     } table{ border-collapse: collapse; } input{     width:20px; } </style> </he

  • Android游戏源码分享之2048

    引言 程序猿们,是否还在为你的老板辛辛苦苦的打工而拿着微薄的薪水呢,还是不知道如何用自己的应用或游戏来赚钱呢! 在这里IQuick将教您如何同过自己的应用来赚取自己的第一桶金! 你是说自己的应用还没有做出来? 不,在這里已经为你提供好了一个完整的游戏应用了,在文章的下面有源码的地址哦.你只要稍做修改就可以变成一个完全属于自己的应用了,比如将4*4换成5*5,甚至是其它的.如果你实在是慵懒至极的话,你只要将本应用的包名及广告换成自己的,就可以上传到市场上轻轻松松赚取自己的第一桶金了. 如果你觉得本

  • Android游戏开发实践之人物移动地图的平滑滚动处理

    如图所示为程序效果动画图 地图滚动的原理 在本人之前博客的文章中介绍过人物在屏幕中的移动方式,因为之前拼的游戏地图是完全填充整个手机屏幕的,所以无需处理地图的平滑滚动.这篇文章我着重的向 大家介绍一下控制人物移动后地图滚动的处理方式.举个例子 如上图所示 比如人物向右移动,如果地图贴在屏幕左边边界 将先移动人物在地图的坐标,当人物在屏幕中超过三分之二后 则将地图向人物行走的反方向移动给玩家一种人物还在向右移动的假象,其实这时候人物只是播放向右行走的动画 在屏幕中的坐标不变 ,当地图向人物行走反方

  • jQuery制作拼图小游戏

    源代码思路分析: [一]如何生成图片网格,我想到两种方法: (1)把这张大图切成16张小图,然后用img标签的src (2)只有一张大图,然后每个元素的背景图用css的background-position进行切割定位,这样就需要16个数组[0,0],[-150,0],[-300,0]..........(我采用这种) [二]图片背景定位数组与布局定位数组 在选择了使用CSS定位切图,就需要生成数据. 需要的css背景 定位数组为:[0,0],[-150,0],[-300,0],[-450,0]

随机推荐