Android植物大戰(zhàn)僵尸小游戲
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)文章
android實(shí)現(xiàn)文本復(fù)制到剪切板功能(ClipboardManager)
Android也有剪切板(ClipboardManager),可以復(fù)制一些有用的文本到剪貼板,以便用戶可以粘貼的地方使用,下面是使用方法2014-02-02Android自定義RecyclerView Item頭部懸浮吸頂
這篇文章主要為大家詳細(xì)介紹了Android自定義RecyclerView Item頭部懸浮吸頂,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08關(guān)于android studio升級(jí)4.1 某些插件使用不了的問(wèn)題(Mac)
這篇文章主要介紹了關(guān)于android studio升級(jí)4.1 某些插件使用不了的問(wèn)題(Mac),本文給大家分享解決方法供大家參考,感興趣的朋友跟隨小編一起看看吧2020-10-10android自定義按鈕示例(重寫(xiě)imagebutton控件實(shí)現(xiàn)圖片按鈕)
由于項(xiàng)目這種類型的圖片按鈕比較多,所以重寫(xiě)了ImageButton類,現(xiàn)在把代碼分享給大家,需要的朋友可以參考下2014-03-03Android系統(tǒng)的五種數(shù)據(jù)存儲(chǔ)形式實(shí)例(二)
Android系統(tǒng)有五種數(shù)據(jù)存儲(chǔ)形式,分別是文件存儲(chǔ)、SP存儲(chǔ)、數(shù)據(jù)庫(kù)存儲(chǔ)、contentprovider 內(nèi)容提供者、網(wǎng)絡(luò)存儲(chǔ)。本文介紹了Android系統(tǒng)的五種數(shù)據(jù)存儲(chǔ)形式,有興趣的可以了解一下。2016-12-12Android 仿摩拜單車共享單車進(jìn)度條實(shí)現(xiàn)StepView效果
這篇文章主要介紹了android 仿摩拜單車共享單車進(jìn)度條實(shí)現(xiàn)StepView效果的實(shí)例,通過(guò)定義五個(gè)狀態(tài),分別為:為完成、正在進(jìn)行、已完成、終點(diǎn)完成、終點(diǎn)未完成。具體實(shí)現(xiàn)代碼,大家參考下2017-03-03Android 自定義ProgressDialog進(jìn)度條對(duì)話框用法詳解
ProgressDialog為進(jìn)度對(duì)話框。android手機(jī)自帶的對(duì)話框顯得比較單一,我們可以通過(guò)ProgressDialog來(lái)自己定義對(duì)話框中將要顯示出什么東西2016-01-01