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));
}
// 重寫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),那么開始設(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),那么開始設(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)畫以形成動(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)畫以形成動(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)) {
// 開始運(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)以后,那么就要開始移動(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)畫幀的下標(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ì)于先畫出來(lái)的肯定是排在前面的 所以Y最小的排在前面即離屏幕上邊緣最近的精靈
//那種游戲肯定會(huì)通過(guò)游戲引擎來(lái)進(jìn)行開發(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)畫幀都由這個(gè)run方法來(lái)控制
// 控制動(dòng)畫幀的時(shí)候要注意首先進(jìn)行數(shù)據(jù)更新 然后在更新圖像
@Override
public void run() {
// TODO run
while (gameRunFlag) {
synchronized (surfaceHolder) {
try {
// 為了形成動(dòng)畫效果首先需要清理屏幕
// 加鎖避免很多線程同時(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)行繪制,先畫游戲?qū)哟巫钕路降木`
// 按照已經(jīng)寫好的分層順序
// 繪制出陽(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í)間
*/
}
// 在這里重寫觸摸響應(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-02
Android自定義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-10
android自定義按鈕示例(重寫imagebutton控件實(shí)現(xiàn)圖片按鈕)
由于項(xiàng)目這種類型的圖片按鈕比較多,所以重寫了ImageButton類,現(xiàn)在把代碼分享給大家,需要的朋友可以參考下2014-03-03
Android系統(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-12
Android 仿摩拜單車共享單車進(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-03
Android 自定義ProgressDialog進(jìn)度條對(duì)話框用法詳解
ProgressDialog為進(jìn)度對(duì)話框。android手機(jī)自帶的對(duì)話框顯得比較單一,我們可以通過(guò)ProgressDialog來(lái)自己定義對(duì)話框中將要顯示出什么東西2016-01-01

