欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android植物大戰(zhàn)僵尸小游戲

 更新時(shí)間:2015年12月16日 10:03:21   作者:蔡都平  
植物大戰(zhàn)僵尸小游戲,無(wú)論老少皆愛(ài),非常有意思,具有挑戰(zhàn)性,那么基于代碼是怎么實(shí)現(xiàn)的呢?下面通過(guò)本文給大家介紹Android植物大戰(zhàn)僵尸小游戲,感興趣的朋友一起學(xué)習(xí)吧

Android植物大戰(zhàn)僵尸小游戲全部?jī)?nèi)容如下:

相關(guān)下載:Android植物大戰(zhàn)僵尸小游戲

具體代碼如下所示:

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();
  // 處理圖片讓它成為目標(biāo)圖片
  Config.gameBK = DeviceTools.resizeBitmap(Config.gameBK);
  Config.seedBank = DeviceTools.resizeBitmap(BitmapFactory
    .decodeResource(getResources(), R.drawable.seedbank));
  // 繪制出卡片,不能進(jìn)行等比縮放要進(jìn)行目標(biāo)大小的輸入控制
  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);
  // 初始化陽(yáng)光圖片
  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));
  // 初始化動(dòng)態(tài)圖片幀
  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));
 }
 // 重寫(xiě)onTouch觸摸響應(yīng)事件,返回值為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;
 // 子彈產(chǎn)生時(shí)間
 private long birthTime = 0l;
 // X方向上的速度分量
 // 根據(jù)幀數(shù),確定移動(dòng)時(shí)間,然后來(lái)確定移動(dòng)方式
 private float SpeedX = 10;
 public Bullet(int locationX, int locationY) {
  this.locationX = locationX + 40;
  this.locationY = locationY + 20;
  this.isAlife = true;
  // 獲取系統(tǒng)時(shí)間
  birthTime = System.currentTimeMillis();
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   // 移動(dòng)
   locationX += SpeedX;
   // 如果圖片的Y軸坐標(biāo)移動(dòng)到超出屏幕或者說(shuō)移動(dòng)到與屏幕齊平,那么生命周期結(jié)束
   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;
 // 觸摸區(qū)域(矩形)
 private Rect touchArea;
 public EmplaceFlower(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化觸摸響應(yīng)矩形區(qū)域,與整體屏幕一致大小
  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();
  // 如果點(diǎn)擊的地方是在矩形區(qū)域內(nèi),那么開(kāi)始設(shè)置跟隨
  if (touchArea.contains(x, y)) {
   // 圖標(biāo)跟隨
   // switch中需要相應(yīng)三個(gè)事件:按下、抬起、拖動(dòng)
   switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    break;
   case MotionEvent.ACTION_MOVE:
    // drawSelf方法已定,那么我們需要改變表示位置的兩個(gè)變量,同時(shí)也要改變響應(yīng)點(diǎn)擊的區(qū)域touchArea
    locationX = x - Config.flowerFrames[0].getWidth() / 2;
    locationY = y - Config.flowerFrames[0].getHeight() / 2;
    break;
   case MotionEvent.ACTION_UP:
    // 放手以后此移動(dòng)中的實(shí)例的生命周期結(jié)束并在特定點(diǎn)產(chǎn)生新的固定的實(shí)例
    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;
 // 觸摸區(qū)域(矩形)
 private Rect touchArea;
 public EmplacePea(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化觸摸響應(yīng)矩形區(qū)域
  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();
  // 如果點(diǎn)擊的地方是在矩形區(qū)域內(nèi),那么開(kāi)始設(shè)置跟隨
  if (touchArea.contains(x, y)) {
   // 圖標(biāo)跟隨
   // switch中需要相應(yīng)三個(gè)事件:按下、抬起、拖動(dòng)
   switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    break;
   case MotionEvent.ACTION_MOVE:
    // drawSelf方法已定,那么我們需要改變表示位置的兩個(gè)變量,同時(shí)也要改變響應(yīng)點(diǎn)擊的區(qū)域touchArea
    locationX = x - Config.peaFrames[0].getWidth() / 2;
    locationY = y - Config.peaFrames[0].getHeight() / 2;
    break;
   case MotionEvent.ACTION_UP:
    // 放手以后此移動(dòng)中的實(shí)例的生命周期結(jié)束并在特定點(diǎn)產(chǎn)生新的固定的實(shí)例
    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;
//豌豆射手實(shí)體類
public class Flower extends BaseModel implements Plant {
 private int locationX;
 private int locationY;
 private boolean isAlife;
 // 圖片幀數(shù)組的下標(biāo)
 private int frameIndex = 0;
 // 一個(gè)標(biāo)記通過(guò)此標(biāo)記確定此處是否有植物
 private int mapIndex;
 // 控制產(chǎn)生陽(yáng)光的時(shí)間
 private long lastBirthTime;
 // 擺動(dòng)速度控制,兩幀一動(dòng)
 private boolean swingSpeed;
 public Flower(int locationX, int locationY, int mapIndex) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.mapIndex = mapIndex;
  isAlife = true;
  // 初始化時(shí)間用來(lái)確保初試時(shí)間與花的創(chuàng)造時(shí)間一致
  lastBirthTime = System.currentTimeMillis();
  swingSpeed = false;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   // 這里繪入的bitmap就需要在繪制自己的時(shí)候換自己的幀動(dòng)畫(huà)以形成動(dòng)態(tài)效果
   // 這個(gè)組在Config中已經(jīng)初始化好了
   canvas.drawBitmap(Config.flowerFrames[frameIndex], locationX,
     locationY, paint);
   // 用此變量讓數(shù)組變化
   // 通過(guò)這樣的取模方法,可以讓這個(gè)frameIndex值不超過(guò)7
   // 當(dāng)frameIndex為8時(shí)會(huì)變?yōu)?,避免數(shù)組越界
   if (!swingSpeed) {
    frameIndex = (++frameIndex) % 8;
    swingSpeed = false;
   } else {
    swingSpeed = true;
   }
   // 用此處判斷來(lái)確定每10秒一個(gè)陽(yáng)光的產(chǎn)生
   if (System.currentTimeMillis() - lastBirthTime > 10000) {
    lastBirthTime = System.currentTimeMillis();
    giveBirth2Sun();
   }
  }
 }
 // 產(chǎn)生陽(yáng)光
 // 陽(yáng)光具有生命,然后兩種情況,被點(diǎn)擊則轉(zhuǎn)換狀態(tài),移動(dòng)到上方陽(yáng)光的標(biāo)志處,過(guò)一段時(shí)間不點(diǎn)擊則死亡消失
 // 產(chǎn)生在花的位置上
 private void giveBirth2Sun() {
  // 首先要有陽(yáng)光的圖層集合,處于第三層,那么就需要操作集合,就需要調(diào)用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;
//豌豆射手實(shí)體類
public class Pea extends BaseModel implements Plant {
 private int locationX;
 private int locationY;
 private boolean isAlife;
 // 圖片幀數(shù)組的下標(biāo)
 private int frameIndex = 0;
 // 一個(gè)標(biāo)記通過(guò)此標(biāo)記確定此處是否有植物
 private int mapIndex;
 // 控制產(chǎn)生子彈的時(shí)間
 private long lastBirthTime;
 // 擺動(dòng)速度控制,兩幀一動(dòng)
 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就需要在繪制自己的時(shí)候換自己的幀動(dòng)畫(huà)以形成動(dòng)態(tài)效果
   // 這個(gè)組在Config中已經(jīng)初始化好了
   canvas.drawBitmap(Config.peaFrames[frameIndex], locationX,
     locationY, paint);
   // 用此變量讓數(shù)組變化
   // 通過(guò)這樣的取模方法,可以讓這個(gè)frameIndex值不超過(guò)7
   // 當(dāng)frameIndex為8時(shí)會(huì)變?yōu)?,避免數(shù)組越界
   if (!swingSpeed) {
    frameIndex = (++frameIndex) % 8;
    swingSpeed = false;
   } else {
    swingSpeed = true;
   }
   // 用此處判斷來(lái)確定每10秒一個(gè)子彈的產(chǎn)生
   if (System.currentTimeMillis() - lastBirthTime > 10000) {
    lastBirthTime = System.currentTimeMillis();
    giveBirth2Bullet();
   }
  }
 }
 // 產(chǎn)生子彈
 // 子彈具有生命,然后兩種情況,被點(diǎn)擊則轉(zhuǎn)換狀態(tài),移動(dòng)到上方子彈的標(biāo)志處,過(guò)一段時(shí)間不點(diǎn)擊則死亡消失
 // 產(chǎn)生在花的位置上
 private void giveBirth2Bullet() {
  // 首先要有子彈的圖層集合,處于第三層,那么就需要操作集合,就需要調(diào)用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;
 // 觸摸區(qū)域(矩形)
 private Rect touchArea;
 public SeedFlower(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化觸摸響應(yīng)矩形區(qū)域
  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坐標(biāo),getX() getY()獲取到的數(shù)據(jù)都是float型
  int x = (int) event.getX();
  int y = (int) event.getY();
  if (touchArea.contains(x, y)) {
   // 當(dāng)觸摸點(diǎn)落在區(qū)域內(nèi)則響應(yīng)
   // 生成安置狀態(tài)的花(優(yōu)先級(jí)最高)
   if (Config.sunlight >= 50) {
    applay4EmplaceFlower();
    return true;
   }
  }
  return false;
 }
 // 通過(guò)GameView來(lái)請(qǐng)求生成一個(gè)安置狀態(tài)的花(優(yōu)先級(jí)最高)
 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;
 // 觸摸區(qū)域(矩形)
 private Rect touchArea;
 public SeedPea(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化觸摸響應(yīng)矩形區(qū)域
  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坐標(biāo),getX() getY()獲取到的數(shù)據(jù)都是float型
  int x = (int) event.getX();
  int y = (int) event.getY();
  if (touchArea.contains(x, y)) {
   // 當(dāng)觸摸點(diǎn)落在區(qū)域內(nèi)則響應(yīng)
   // 生成安置狀態(tài)的豌豆(優(yōu)先級(jí)最高)
   if (Config.sunlight >= 100) {
    applay4EmplacePea();
    return true;
   }
  }
  return false;
 }
 // 通過(guò)GameView來(lái)請(qǐng)求生成一個(gè)安置狀態(tài)的豌豆(優(yōu)先級(jí)最高)
 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;
 // 可觸摸區(qū)域
 private Rect touchArea;
 // 陽(yáng)光產(chǎn)生時(shí)間
 private long birthTime;
 // 標(biāo)示陽(yáng)光的狀態(tài)
 private SunState state;
 // 移動(dòng)距離
 private int DirectionDistanceX;
 private int DirectionDistanceY;
 // XY方向上的速度分量
 // 根據(jù)幀數(shù),確定移動(dòng)時(shí)間,然后來(lái)確定移動(dòng)方式
 private float SpeedX;
 private float SpeedY;
 // 用此枚舉來(lái)標(biāo)示陽(yáng)光的狀態(tài)
 // 兩個(gè)狀態(tài):靜止、移動(dòng)
 // 移動(dòng)過(guò)程中生命周期對(duì)陽(yáng)光無(wú)效,靜止時(shí)生命周期有效
 public enum SunState {
  SHOW, MOVE
 }
 public Sun(int locationX, int locationY) {
  this.locationX = locationX;
  this.locationY = locationY;
  this.isAlife = true;
  // 初始化觸摸響應(yīng)矩形區(qū)域
  // 對(duì)于每個(gè)陽(yáng)光來(lái)說(shuō)能出沒(méi)的地方只有他這張圖片大小的區(qū)域
  touchArea = new Rect(locationX, locationY, locationX
    + Config.sun.getWidth(), locationY + Config.sun.getHeight());
  // 獲取系統(tǒng)時(shí)間
  birthTime = System.currentTimeMillis();
  // 初始實(shí)例化為SHOW狀態(tài)
  state = SunState.SHOW;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  if (isAlife) {
   if (state == SunState.SHOW) {
    // 判斷當(dāng)前系統(tǒng)時(shí)間如果比出生時(shí)間大5000毫秒那么陽(yáng)光生命結(jié)束,消失
    if (System.currentTimeMillis() - birthTime > Config.lifeTime) {
     isAlife = false;
    }
   } else {// 對(duì)于move狀態(tài)的陽(yáng)光的處理
    // 移動(dòng)
    locationX -= SpeedX;
    locationY -= SpeedY;
    // 如果圖片的Y軸坐標(biāo)移動(dòng)到超出屏幕或者說(shuō)移動(dòng)到與屏幕齊平,那么生命周期結(jié)束
    if (locationY <= 0) {
     // 去除陽(yáng)光
     isAlife = false;
     // 改變陽(yáng)光值
     Config.sunlight += 25;
    }
   }
   canvas.drawBitmap(Config.sun, locationX, locationY, paint);
  }
 }
 // 觸摸事件響應(yīng)
 @Override
 public boolean onTouch(MotionEvent event) {
  // TODO Auto-generated method stub
  // 獲取觸摸點(diǎn)
  int x = (int) event.getX();
  int y = (int) event.getY();
  // 如果觸摸點(diǎn)在可觸摸區(qū)域內(nèi)
  if (touchArea.contains(x, y)) {
   // 開(kāi)始運(yùn)動(dòng)并且不可被點(diǎn)擊,同時(shí)可能會(huì)與上邊框產(chǎn)生碰撞事件
   // 移動(dòng)過(guò)程中也需要時(shí)間,如果這個(gè)收集時(shí)間中用了超過(guò)陽(yáng)光生命值5秒的時(shí)間
   // 那么我們需要在點(diǎn)擊以后改變陽(yáng)光的狀態(tài)并刪除原本的靜態(tài)陽(yáng)光
   state = SunState.MOVE;
   // 改變狀態(tài)以后,那么就要開(kāi)始移動(dòng),移動(dòng)的起點(diǎn)不一定,但是終點(diǎn)是一定的
   // 移動(dòng)的終點(diǎn)可以認(rèn)為是條形框(seedBank)的左上角點(diǎn)
   // 起始點(diǎn)就是此陽(yáng)光圖片的左上角
   // XY方向上的移動(dòng)距離
   DirectionDistanceX = locationX - Config.seedBankLocationX;
   DirectionDistanceY = locationY;
   // 移動(dòng)速度分量的計(jì)算,具體幀數(shù)需要項(xiàng)目分析,這里設(shè)置為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;
 // 僵尸位于的跑道,因?yàn)榇私┦桓渌诘呐艿纼?nèi)的植物、子彈等進(jìn)行碰撞檢測(cè)
 private int raceWay;
 // 因?yàn)榻┦且苿?dòng)中的 所以他要有動(dòng)畫(huà)幀的下標(biāo)
 private int frameIndex = 0;
 // 移動(dòng)速度,每一幀移動(dòng)3像素
 private int peedX = 3;
 public Zombie(int locationX, int locationY, int raceWay) {
  this.locationX = locationX;
  this.locationY = locationY;
  isAlife = true;
  this.raceWay = raceWay;
 }
 // 在某跑道隨機(jī)產(chǎn)生僵尸,同時(shí)間隔一段時(shí)間出現(xiàn)一只僵尸
 @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;
   // 碰撞檢測(cè),僵尸發(fā)起的此碰撞檢測(cè)
   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 {
 // 一般需要顯示出現(xiàn)在屏幕上的實(shí)體才需要繼承BaseModel
 // 所以此處的僵尸控制器其實(shí)不需要繼承BaseModel
 // 但是為了與之前的flower和pea產(chǎn)生器相統(tǒng)一
 // 效仿以前的模式減少工作量
 // 在這里也進(jìn)行繼承
 private boolean isAlife;
 // 最后一只僵尸的產(chǎn)生時(shí)間
 private long lastBirthTime;
 public ZombieManager() {
  lastBirthTime = System.currentTimeMillis();
  isAlife = true;
 }
 @Override
 public void drawSelf(Canvas canvas, Paint paint) {
  // TODO Auto-generated method stub
  // 此處不需要繪制出圖片,所以不需要draw,但是可以進(jìn)行邏輯上的處理
  if (System.currentTimeMillis() - lastBirthTime > 15000) {
   lastBirthTime = System.currentTimeMillis();
   giveBirth2Zombie();
  }
 }
 private void giveBirth2Zombie() {
  // 與GameView請(qǐng)求加入僵尸
  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坐標(biāo)
 public static int seedBankLocationX;
 public static Bitmap seedFlower;
 public static Bitmap seedPea;
 // 陽(yáng)光
 public static Bitmap sun;
 // 陽(yáng)光的生存時(shí)間5000毫秒
 public static long lifeTime = 5000;
 // 現(xiàn)在的陽(yáng)光值
 public static int sunlight = 200;
 // 僵尸和植物圖片的高度差
 public static int heightYDistance;
 // 子彈
 public static Bitmap bullet;
 // 將圖片幀放入數(shù)組
 public static Bitmap[] flowerFrames = new Bitmap[8];
 public static Bitmap[] peaFrames = new Bitmap[8];
 public static Bitmap[] zombieFrames = new Bitmap[7];
 // 放置植物的點(diǎn)
 public static HashMap<Integer, Point> plantPoints = new HashMap<Integer, Point>();
 // 跑道
 public static int[] raceWayYpoints = new int[5];
 // 輸贏判斷標(biāo)志
 public static boolean game = true;
} 
package com.example.liu.mygame.model;
import android.graphics.Canvas;
import android.graphics.Paint;
public class BaseModel {
 // 基礎(chǔ)類,對(duì)于所有能展示在屏幕上的動(dòng)態(tài)對(duì)象都要繼承自此類
 // 位置
 private int locationX;
 private int locationY;
 // 生命
 private boolean isAlife;
 // 繪制自己,即移動(dòng)
 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;
// 所有需要種植在地上保持靜止的植物都要有這個(gè)接口
public interface Plant {
 // 用于key
 public int getmapIndex();
} 
package com.example.liu.mygame.model;
import android.view.MotionEvent;
public interface TouchAble {
 // 對(duì)于能接受觸摸事件的對(duì)象的一個(gè)公用接口
 // 傳入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];
 // 重新設(shè)置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;
  }
 }
 // 重載
 // 原因是找到的素材需要進(jìn)行處理來(lái)適應(yīng)手機(jī)屏幕,等比操作,但是如果合成的兩張材料圖不成比例 那么就不得不用這種重載來(lái)適應(yīng)
 // 首先傳入一個(gè)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;
   // 圖片矩陣對(duì)象,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類中可以獲取屏幕的亮度,寬高,刷新率等相關(guān)信息
 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;
//對(duì)于這種有賽道的游戲可以用以下方法
//對(duì)于那種可以上下移動(dòng)的游戲可以把所有精靈放在一個(gè)集合里 不用分圖層 每次繪制的時(shí)候要按照Y坐標(biāo)進(jìn)行排序
//對(duì)于先畫(huà)出來(lái)的肯定是排在前面的 所以Y最小的排在前面即離屏幕上邊緣最近的精靈
//那種游戲肯定會(huì)通過(guò)游戲引擎來(lái)進(jìn)行開(kāi)發(fā)
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當(dāng)做總管理,所有的實(shí)體都向這里發(fā)送請(qǐng)求并處理
 private static GameView gameView;
 private ArrayList<BaseModel> deadList;// 存放已消亡的實(shí)體,在拖動(dòng)放手后實(shí)體會(huì)不顯示,但是還存在所以要進(jìn)行清理
 private ArrayList<BaseModel> gameLayout3;// 存放第三圖層中的實(shí)體;
 private ArrayList<BaseModel> gameLayout2;// 存放第二圖層中的實(shí)體
 private ArrayList<BaseModel> gameLayout1;// 存放第一圖層中的實(shí)體
 // 跑道從上至下
 // 這些可以做一個(gè)封裝,放入一個(gè)for循環(huán)進(jìn)行創(chuàng)建即可
 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;
 // 定義僵尸控制器,通過(guò)此控制器來(lái)使僵尸實(shí)現(xiàn)移動(dòng)
 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坐標(biāo)賦初值
  Config.seedBankLocationX = (Config.deviceWidth - Config.seedBank
    .getWidth()) / 2;
  // 初始化第三圖層
  gameLayout3 = new ArrayList<BaseModel>();
  // 當(dāng)此方法被觸發(fā)時(shí)便會(huì)創(chuàng)建卡片對(duì)象
  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);
  // 添加安置狀態(tài)中的植物
  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
 }
 // 所有的動(dòng)畫(huà)幀都由這個(gè)run方法來(lái)控制
 // 控制動(dòng)畫(huà)幀的時(shí)候要注意首先進(jìn)行數(shù)據(jù)更新 然后在更新圖像
 @Override
 public void run() {
  // TODO run
  while (gameRunFlag) {
   synchronized (surfaceHolder) {
    try {
     // 為了形成動(dòng)畫(huà)效果首先需要清理屏幕
     // 加鎖避免很多線程同時(shí)繪制
     canvas = surfaceHolder.lockCanvas();
     // 繪入背景,最底層圖層
     canvas.drawBitmap(Config.gameBK, 0, 0, paint);
     // 繪入上方植物欄,倒數(shù)第二層圖層,僅覆蓋于背景之上
     canvas.drawBitmap(Config.seedBank,
       Config.seedBankLocationX, 0, paint);
     // 數(shù)據(jù)更改操作
     updateData();
     // 繪入植物卡片(第二層)
     ondraw(canvas);
    } catch (Exception e) {
     // TODO: handle exception
    } finally {
     // 解鎖并提交
     surfaceHolder.unlockCanvasAndPost(canvas);
     // CanvasAndPost必須要進(jìn)行解鎖 不管程序有什么問(wèn)題必須給用戶直觀完整的顯示過(guò)程
     // 以防萬(wàn)一的話 加入try catch
    }
   }
   // 加入以下語(yǔ)句每次循環(huán)中休眠50毫秒減少一直循環(huán)的系統(tǒng)資源浪費(fèi)
   // 使用50毫秒的原因是在42幀及以上肉眼就會(huì)認(rèn)為是流暢的,即1秒42張圖片,每次循環(huán)休眠50毫秒即20幀
   // 如果把sleep放在synchronized中的話會(huì)出現(xiàn)程序每次遍歷完立刻睡眠然后再次遍歷沒(méi)有給其他進(jìn)程事件運(yùn)行會(huì)造成卡死
   try {
    Thread.sleep(40);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 private void updateData() {
  // 在此方法中進(jìn)行數(shù)據(jù)更新
  // 清除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) {
   // 在各個(gè)圖層列表中把它們移除
   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
  // 在此方法中進(jìn)行繪圖作業(yè)
  // 按照游戲的層次進(jìn)行繪制,先畫(huà)游戲?qū)哟巫钕路降木`
  // 按照已經(jīng)寫(xiě)好的分層順序
  // 繪制出陽(yáng)光值
  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實(shí)現(xiàn)僵尸移動(dòng)
  zombieManager.drawSelf(canvas, paint);
  // 跑道應(yīng)該處于第四層故放在上方先繪制出來(lái)
  // 遍歷五條跑道調(diào)用drawSelf方法進(jìn)行繪制植物
  // 此處也可以進(jìn)行方法的抽象 或者說(shuō)應(yīng)該把這些重復(fù)的代碼抽象為一個(gè)方法調(diào)用不同的值進(jìn)去
  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);
  }
  // 第三層(陽(yáng)光)
  for (BaseModel model : gameLayout3) {
   model.drawSelf(canvas, paint);
  }
  // 第二層
  for (BaseModel model : gameLayout2) {
   model.drawSelf(canvas, paint);
  }
  // 遍歷五條跑道調(diào)用drawSelf方法進(jìn)行繪制僵尸
  // 此處也可以進(jìn)行方法的抽象 或者說(shuō)應(yīng)該把這些重復(fù)的代碼抽象為一個(gè)方法調(diào)用不同的值進(jìn)去
  // 第二層是植物卡片,僵尸在經(jīng)過(guò)第一行的時(shí)候應(yīng)該可以擋住植物卡片
  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; 設(shè)置半透明效果
   * m的作用是可以讓這個(gè)半透明效果逐步消去, m的變化大小就可以理解為此植物的冷卻時(shí)間
   */
 }
 // 在這里重寫(xiě)觸摸響應(yīng)事件
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // TODO onTouchEvent
  // 對(duì)于相應(yīng)來(lái)說(shuō)gameLayout1的優(yōu)先級(jí)最高故放在gameLayout2上方
  for (BaseModel model : gameLayout1) {
   // 判定是否為touchAble的子類,只有是touchAble的子類才能響應(yīng)
   if (model instanceof TouchAble) {
    // 然后進(jìn)行onTouch事件,查看是否被點(diǎn)擊,如果點(diǎn)擊那么返回true
    if (((TouchAble) model).onTouch(event)) {
     return true;
    }
   }
  }
  // 遍歷第二層中的全部實(shí)體
  for (BaseModel model : gameLayout2) {
   // 判定是否為touchAble的子類,只有是touchAble的子類才能響應(yīng)
   if (model instanceof TouchAble) {
    // 然后進(jìn)行onTouch事件,查看是否被點(diǎn)擊,如果點(diǎn)擊那么返回true
    if (((TouchAble) model).onTouch(event)) {
     return true;
    }
   }
  }
  // 遍歷第三層中的全部實(shí)體
  for (BaseModel model : gameLayout3) {
   // 判定是否為touchAble的子類,只有是touchAble的子類才能響應(yīng)
   if (model instanceof TouchAble) {
    // 然后進(jìn)行onTouch事件,查看是否被點(diǎn)擊,如果點(diǎn)擊那么返回true
    if (((TouchAble) model).onTouch(event)) {
     return true;
    }
   }
  }
  return false;
 }
 // 獲取GameView的方法,讓GameView編程所有實(shí)體的總橋梁
 public static GameView getInstance() {
  return gameView;
 }
 // 添加EmplacePlant植物(優(yōu)先級(jí)最高)
 public void applay4EmplacePlant(int locationX, int locationY,
   BaseModel model) {
  // TODO applay4EmplacePlant
  // 相當(dāng)于在進(jìn)行數(shù)據(jù)更新,在onDraw中會(huì)從這里取出一個(gè)個(gè)元素進(jìn)行繪制,繪制過(guò)程中如果這里還會(huì)有更新那么會(huì)產(chǎn)生沖突,所以需要在這里加入一個(gè)同步鎖
  // 所有對(duì)于集合的操作都要加入同步鎖,鎖對(duì)象用surfaceHolder當(dāng)?shù)玫酱藄urfaceHolder鎖對(duì)象的時(shí)候才能夠進(jìn)行操作
  synchronized (surfaceHolder) {
   // gameLayout1放的是正在安放狀態(tài)的植物,沒(méi)有放下
   // new一個(gè)處于安置狀態(tài)的實(shí)體
   // gameLayout1中只能有0~1個(gè)實(shí)例
   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
  // 安放靜態(tài)植物
  // 以空間換時(shí)間,因?yàn)橹参?、子彈、僵尸、都在第四層所以?duì)于這些來(lái)說(shuō)把它們分為五個(gè)賽道從上至下五層
  // 每條賽道上有兩個(gè)集合,一個(gè)是僵尸的集合,另一個(gè)是植物與子彈的集合,這樣分是為了碰撞檢測(cè)
  // 為了減少碰撞檢測(cè)事件去除部分不必要的運(yùn)算,故而分成很多層
  // 循環(huán)這個(gè)可安放植物的HashMap,目的是拿出每個(gè)元素與locationX和locationY進(jìn)行比較
  // key的作用是讓每個(gè)Paint的標(biāo)示不同
  synchronized (surfaceHolder) {// 加鎖
   Point point;
   for (Integer key : Config.plantPoints.keySet()) {
    // 找距離locationX與locationY最近而且處于目標(biāo)地域上
    point = Config.plantPoints.get(key);
    if ((Math.abs(locationX - point.x) < Config.deviceWidth / 11 / 2)
      && (Math.abs(locationY - point.y) < Config.deviceHeight / 6 / 2)) {
     // 跑道標(biāo)示
     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)) {
      // 跑道數(shù)出發(fā)事件
      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;
      }
     }
    }
   }
  }
 }
 // 判斷此處是否已經(jīng)有植物的方法
 // key是標(biāo)示,raceWayIndex用于確定應(yīng)查哪一個(gè)跑道
 private boolean isPlantExist(int key, int raceWayIndex) {
  switch (raceWayIndex) {
  case 0:
   for (BaseModel model : gameLayout4plant0) {
    // 首先 如果這個(gè)區(qū)域是繼承了Plant接口的子類(因?yàn)樽訌椇完?yáng)光不繼承Plant做以區(qū)別)
    if (model instanceof Plant) {
     // 然后此處的key與傳入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此處不能種植植物
      return false;
     }
    }
   }
   break;
  case 1:
   for (BaseModel model : gameLayout4plant1) {
    // 首先 如果這個(gè)區(qū)域是繼承了Plant接口的子類(因?yàn)樽訌椇完?yáng)光不繼承Plant做以區(qū)別)
    if (model instanceof Plant) {
     // 然后此處的key與傳入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此處不能種植植物
      return false;
     }
    }
   }
   break;
  case 2:
   for (BaseModel model : gameLayout4plant2) {
    // 首先 如果這個(gè)區(qū)域是繼承了Plant接口的子類(因?yàn)樽訌椇完?yáng)光不繼承Plant做以區(qū)別)
    if (model instanceof Plant) {
     // 然后此處的key與傳入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此處不能種植植物
      return false;
     }
    }
   }
   break;
  case 3:
   for (BaseModel model : gameLayout4plant3) {
    // 首先 如果這個(gè)區(qū)域是繼承了Plant接口的子類(因?yàn)樽訌椇完?yáng)光不繼承Plant做以區(qū)別)
    if (model instanceof Plant) {
     // 然后此處的key與傳入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此處不能種植植物
      return false;
     }
    }
   }
   break;
  case 4:
   for (BaseModel model : gameLayout4plant4) {
    // 首先 如果這個(gè)區(qū)域是繼承了Plant接口的子類(因?yàn)樽訌椇完?yáng)光不繼承Plant做以區(qū)別)
    if (model instanceof Plant) {
     // 然后此處的key與傳入的key相等
     if (key == ((Plant) model).getmapIndex()) {
      // 那么返回此處不能種植植物
      return false;
     }
    }
   }
   break;
  default:
   break;
  }
  return true;
 }
 // 被Flower請(qǐng)求,用于產(chǎn)生陽(yáng)光
 public void giveBrith2Sun(int locationX, int locationY) {
  // TODO giveBrith2Sun
  // 先設(shè)置鎖住
  synchronized (surfaceHolder) {
   gameLayout3.add(new Sun(locationX, locationY));
  }
 }
 // 被Pea請(qǐng)求,用于產(chǎn)生子彈
 public void giveBirth2Bullet(int locationX, int locationY) {
  // TODO Auto-generated method stub
  // 先設(shè)置鎖住
  synchronized (surfaceHolder) {// 加鎖
   Point point;
   for (Integer key : Config.plantPoints.keySet()) {
    // 找距離locationX與locationY最近而且處于目標(biāo)地域上
    point = Config.plantPoints.get(key);
    if ((Math.abs(locationX - point.x) < Config.deviceWidth / 11 / 2)
      && (Math.abs(locationY - point.y) < Config.deviceHeight / 6 / 2)) {
     // 跑道標(biāo)示
     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;
     }
    }
   }
  }
 }
 // 僵尸控制器產(chǎn)生相應(yīng),加入僵尸
 public void apply4AddZombie() {
  // TODO apply4AddZombie
  // 先解鎖
  synchronized (surfaceHolder) {
   int raceWay = 0;
   // 0~4的隨機(jī)數(shù)來(lái)進(jìn)行跑到初始化
   // Math.random()產(chǎn)生的是0~1的不包括1的隨機(jī)double型數(shù)字
   raceWay = (int) (Math.random() * 5);
   // Config.deviceWidth + 20是為了讓僵尸逐步走入屏幕
   // Config.raceWayYpoints[raceWay] - Config.heightYDistance
   // 是為了讓僵尸與植物的底對(duì)齊
   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;
   }
  }
 }
 // 處理碰撞檢測(cè),碰撞檢測(cè)的發(fā)起者是僵尸
 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;
   }
  }
 }
}

相關(guān)文章

最新評(píng)論