年底了巍膘,各種事情糅合在一起厂财,不過還是磨磨嘰嘰的把Canvas學習的最后一部分寫完了,這一篇文章應該是Canvas學習的最后一篇文章了峡懈,也是整個小游戲的結束篇璃饱。
本篇文章包主要包含BOSS類,BOSS子彈類肪康,由于是終極BOSS所以不能像前面的敵機一樣簡單配置武器荚恶,所以這篇文章寫的有點多,如果沒有仔細看看前面子彈的實現磷支,這里看起來可能有點蒙圈谒撼,但是我可以明確的告訴大家本篇BOSS的武器類就是通過前面敵機簡單武器類的融合,最后才能實現出BOSS武器的炫酷效果雾狈。
1.首先創(chuàng)建BOSS類
package com.tangyx.game.holder;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import com.tangyx.game.util.ScreenUtils;
import java.util.Random;
/**
* Created by tangyx on 2017/1/10.
*
*/
public class DrawBoss extends DrawGame {
/**
* Boss資源
*/
public Bitmap mBoss;
/**
* Boss配置的僚機
*/
private Bitmap mTurn;
/**
* Boss特別武器
*/
private Bitmap bmpBossBulletC;
/**
* Boss生命值
*/
public int mLife = 100;
/**
* Boss的移動坐標
*/
public float mBossX, mBossY;
private int mSpeedX = 2;
private int mSpeedY = 3;
public boolean isCrazy;
private int mCountBoos;
private static int YTime = 1;
public boolean mAttackLaser;
/**
* 激光武器
*/
boolean mLaser;
private Random mRandom;
/**
* Boss旋轉設置
*/
private float mAngle, mTurnAngle;
private Matrix mMatrix;
private int mBossType;
private int mFireTime;
public boolean mFireBullet;
private int mRotaTime;
public DrawBoss(Context context, Bitmap bitmap,int cos) {
super(context);
this.mBoss = bitmap;
mBossX = ScreenUtils.getScreenWidth(getContext()) / 2 - mBoss.getWidth();
mBossY = -mBoss.getHeight()*2;
mRandom = new Random();
mMatrix = new Matrix();
this.mBossType = cos;
mLife = (cos+1)*50;
}
public DrawBoss(Context context, Bitmap bitmap,Bitmap turnmap,int cos) {
super(context);
this.mBoss = bitmap;
this.mTurn = turnmap;
mBossX = ScreenUtils.getScreenWidth(getContext()) / 2 - mBoss.getWidth()/2;
mBossY = -mBoss.getHeight()*2;
mRandom = new Random();
mMatrix = new Matrix();
this.mBossType = cos;
mLife = (cos+1)*50;
}
@Override
void onDraw(Canvas canvas) {
if(mLife <=0){
return;
}
Bitmap bm;
if(mBossType ==0){
canvas.drawBitmap(mBoss, mBossX, mBossY, mPaint);
bm = getTurnMax(mTurn,10);
float cx = mBossX - mTurn.getWidth();
float cy = mBossY;
if(mTurnAngle %90!=0){
cx = cx-13;
cy = cy-13;
}
canvas.drawBitmap(bm, cx, cy, mPaint);//左邊
canvas.drawBitmap(bm, cx+ mBoss.getWidth()+ mTurn.getWidth(), cy, mPaint);//右邊
}else if(mBossType ==2){
if(mFireBullet){
bm = getTurnMax(mBoss,2);
}else{
bm = getMatrixBitmap(mBoss);
}
canvas.drawBitmap(bm, mBossX, mBossY, mPaint);
}else{
canvas.drawBitmap(mBoss, mBossX, mBossY, mPaint);
}
}
@Override
void updateGame() {
if(mLife <=0|| mLaser){
return;
}
if(mBossType ==0){
mBossX += mSpeedX;
mBossY += mSpeedY;
if(mBossX + mBoss.getWidth()>=ScreenUtils.getScreenWidth(getContext())|| mBossX <=0){
mSpeedX =-mSpeedX;
}
if(mBossY >=ScreenUtils.getScreenHeight(getContext())/8){
mSpeedY = -mSpeedY;
}
if(mBossY + mBoss.getHeight()*2<=ScreenUtils.getScreenHeight(getContext())/16){
mSpeedY = -mSpeedY;
}
}else if(mBossType ==2){
if(!mFireBullet){
mFireTime++;
}
if(mFireTime %1000==0){
mFireBullet = true;
mFireTime =0;
}
MyLogic();
}else if(mBossType ==3){
if(!mFireBullet){
mFireTime++;
}
if(mFireTime %1000==0){
mFireBullet = true;
mFireTime =0;
}
if(mFireBullet){
mFireTime++;
if(mFireTime %100==0){
mFireBullet =false;
mFireTime =0;
}
}
MyLogic();
}else if(mBossType ==4){
MyLogic();
}else{
int crazyTime = 300;
if(mLife >30&& mLife <40){
crazyTime = 30;
}else{
crazyTime = 300;
}
if(!mFireBullet &&!mAttackLaser){
mFireTime++;
}
if (mFireTime % crazyTime ==0) {
mFireBullet = true;
mSpeedX = 10;
isCrazy = true;
mFireTime =0;
}
if (!isCrazy) {
mCountBoos++;
mBossX += mSpeedX;
if (mCountBoos % YTime == 0) {
mBossY += mSpeedY;
}
if ((mBossX + mBoss.getWidth() >= ScreenUtils.getScreenWidth(getContext())-bmpBossBulletC.getWidth() || mBossX <= 0)&&!mLaser) {
mSpeedX = -mSpeedX;
int mRandLaser = 10;
if(mRandom.nextInt(100)< mRandLaser){
mLaser =true;
mAttackLaser =true;
}
}
if (mBossY >= 100) {
mSpeedY = -1;
}
if (mBossY <= 0) {
mSpeedY = 1;
}
}else{
mSpeedX -= 1;
mBossY += mSpeedX;
if (mBossY <= 0) {
isCrazy = false;
mSpeedX = 4;
mCountBoos = 0;
}
}
}
}
/**
* 圖像旋轉
*/
private Bitmap getTurnMax(Bitmap bm,int rotaspeed){
mRotaTime++;
mMatrix.reset();
if(mRotaTime %rotaspeed==0){
mTurnAngle +=60;
}
mMatrix.postRotate(mTurnAngle);
if(mTurnAngle >=360){
mTurnAngle =0;
}
return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), mMatrix, true);
}
private void MyLogic(){
mCountBoos++;
mBossX += mSpeedX;
if (mCountBoos % YTime == 0) {
mBossY += mSpeedY;
}
if ((mBossX + mBoss.getWidth() >= ScreenUtils.getScreenWidth(getContext())-bmpBossBulletC.getWidth() || mBossX <= 0)) {
mSpeedX = -mSpeedX;
}
if (mBossY >= 100) {
mSpeedY = -1;
}
if (mBossY <= 0) {
mSpeedY = 1;
}
}
/**
* 圖片相對于主角方向旋轉
*/
private Bitmap getMatrixBitmap(Bitmap bmpMap){
if(mAngle ==0){
return bmpMap;
}
mMatrix.reset();
mMatrix.setRotate(mAngle);
Bitmap tb = Bitmap.createBitmap(bmpMap,0, 0, bmpMap.getWidth(), bmpMap.getHeight(), mMatrix, true);
return tb;
}
/**
* 面向主角方向 重新計算移動坐標
* isTack 是否需要去追殺主角
*/
public void getAngleRotate(float px,float py){
float cx = px- mBossX;
float cy = py- mBossY;
float k = Math.abs(cy/cx);//計算偏移量 斜率
mAngle = (float) (90-Math.toDegrees(Math.atan(k)));//把弧度轉換成角度
if(cx>0){
mAngle = -mAngle;
}
}
/**
*
* @return
*/
public boolean isCollisionWith(DrawPlayerBullet bullet) {
if(mBossY<0){
return false;
}
float bx = bullet.getBulletX();
float by = bullet.getBulletY();
int bw = bullet.getWidth();
int bh = bullet.getHeight();
if(mBossX + mBoss.getWidth()<bx|| mBossX >bx+bw){
return false;
}
if(mBossY + mBoss.getHeight()<by|| mBossY >by+bh){
return false;
}
return true;
}
public float getWidth(){
return mBoss.getWidth();
}
public float getHeight(){
return mBoss.getHeight();
}
public float getBossX(){
return mBossX;
}
public float getBossY(){
return mBossY;
}
public void setBmpBossBulletC(Bitmap bmpBossBulletC) {
this.bmpBossBulletC = bmpBossBulletC;
}
}
Boss類最特別的地方是特殊武器就是激光武器還有僚機廓潜,其中比較復雜一點的地方就是通過Boss的血量來判斷當前應該發(fā)射的武器和Boss移動動畫效果。實現移動動畫主要通過Matrix配合善榛,之前已經說過這個類很重要辩蛋,自行查看API。
2.Boss出場完畢移盆,需要給Boss配置常用武器悼院,創(chuàng)建Boss的武器類DrawBossBullet
package com.tangyx.game.holder;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import com.tangyx.game.util.ScreenUtils;
/**
* Created by tangyx on 2017/1/11.
*
*/
public class DrawBossBullet extends DrawGame {
/**
* 自由落體
*/
public final static int BULLET_A=2;
/**
* 跟蹤彈
*/
public final static int BULLET_C=3;
/**
* boss重型武器
*/
public final static int BULLET_BOOS=1;
/**
* 激光武器
*/
public final static int BULLET_D=4;
public final static int DIR_UP=5;
public final static int DIR_DOWN=6;
public final static int DIR_LEFT=7;
public final static int DIR_RIGHT=8;
public final static int DIR_UP_LEFT=9;
public final static int DIR_UP_RIGHT=10;
public final static int DIR_DOWN_LEFT=11;
public final static int DIR_DOWN_RIGHT=12;
/**
* 子彈資源
*/
private Bitmap mBullet;
private int mDir;
private float mBulletX, mBulletY;
private int mBulletType;
private Matrix mMatrix;
private float mSpeed;
private float mSpeedX;
private float mSpeedY;
private boolean isDead;
private float mScaleSy;
private float mSy =0.008f;
private int mLaserAlpha =220;
private int mAlpha =-10;
private int mLaserTime;
/**
* Boss重型活力
* @param bmpBullet
* @param bulletX
* @param bulletY
* @param bulletType
* @param dir
*/
public DrawBossBullet(Context context,Bitmap bmpBullet, float bulletX, float bulletY, int bulletType, int dir) {//boss子彈
super(context);
this.mBullet = bmpBullet;
this.mBulletX = bulletX;
this.mBulletY = bulletY;
this.mBulletType = bulletType;
this.mDir = dir;
mMatrix = new Matrix();
mSpeed = 16;
}
/**
* 普通子彈模式
*/
public DrawBossBullet(Context context,Bitmap bmpBullet,float x,float y,int bulletType){
super(context);
this.mBullet = bmpBullet;
this.mBulletX = x;
this.mBulletY = y;
this.mBulletType = bulletType;
mMatrix = new Matrix();
mSpeed =((float)ScreenUtils.getScreenHeight(context))/80;
};
/**
* 子彈自動追蹤模式
*/
public DrawBossBullet(Context context,Bitmap bmpBullet,DrawPlayer player,float ex,float ey,int bulletType) {
super(context);
this.mBullet = bmpBullet;
this.mBulletX = ex;
this.mBulletY =ey;
this.mBulletType = bulletType;
float cx = player.getPlayerX() - mBulletX;
float cy = player.getPlayerY() - mBulletY;
mSpeedY =((float)ScreenUtils.getScreenHeight(getContext()))/160;
if(cy<0){
mSpeedY =-mSpeedY;
}
float runTime = cy/ mSpeedY;
mSpeedX = cx / runTime;
if(cx>0&& mSpeedX >=5){
mSpeedX =1;
}else if(cx<0&& mSpeedX <=-5){
mSpeedX =-1;
}
mMatrix = new Matrix();
}
@Override
void onDraw(Canvas canvas) {
mPaint.setAlpha(255);
switch (mBulletType){
case BULLET_D:
mPaint.setAlpha(mLaserAlpha);
Bitmap bm = getBitmap();
canvas.drawBitmap(bm, mBulletX, mBulletY, mPaint);
break;
default:
canvas.drawBitmap(mBullet, mBulletX, mBulletY,mPaint);
break;
}
}
/**
* 激光長短變化
*/
private Bitmap getBitmap(){
mMatrix.reset();
mScaleSy += mSy;
float scaleSx = 1;
mMatrix.postScale(scaleSx, mScaleSy);
if(mScaleSy >=1){
mSy =0;
}
return Bitmap.createBitmap(mBullet, 0, 0, mBullet.getWidth(), mBullet.getHeight(), mMatrix, true);
}
@Override
void updateGame() {
switch (mBulletType){
case BULLET_A://自由落體軌跡
mBulletY += mSpeed;
if(mBulletY >ScreenUtils.getScreenHeight(getContext())){
isDead=true;
}
break;
case BULLET_C://跟蹤
mBulletY += mSpeedY;
mBulletX += mSpeedX;
if(mBulletY <0|| mBulletY >ScreenUtils.getScreenHeight(getContext())|| mBulletX >ScreenUtils.getScreenWidth(getContext())|| mBulletX <0){
isDead=true;
}
break;
case BULLET_D://激光武器
if(mSy ==0){
mLaserAlpha += mAlpha;
if(mLaserAlpha >220|| mLaserAlpha <=50){
mAlpha = -mAlpha;
}
mLaserTime++;
if(mLaserTime >=100){
mBulletY += mSpeed;
if(mBulletY >ScreenUtils.getScreenHeight(getContext())){
isDead = true;
}
}
}
case BULLET_BOOS:
switch (mDir) {
case DIR_UP:
mBulletY -= mSpeed;
break;
case DIR_DOWN:
mBulletY += mSpeed;
break;
case DIR_LEFT:
mBulletX -= mSpeed;
break;
case DIR_RIGHT:
mBulletX += mSpeed;
break;
case DIR_UP_LEFT:
mBulletY -= mSpeed;
mBulletX -= mSpeed;
break;
case DIR_UP_RIGHT:
mBulletY += mSpeed;
mBulletX += mSpeed;
break;
case DIR_DOWN_LEFT:
mBulletY += mSpeed;
mBulletX -= mSpeed /3;
break;
case DIR_DOWN_RIGHT:
mBulletY += mSpeed;
mBulletX += mSpeed /3;
break;
default:
mBulletY += mSpeed;
break;
}
if(mBulletY > ScreenUtils.getScreenHeight(getContext())|| mBulletY <0
|| mBulletX >ScreenUtils.getScreenWidth(getContext())|| mBulletX <0){
isDead = true;
}
break;
}
}
public float getBulletX() {
return mBulletX;
}
public float getBulletY() {
return mBulletY;
}
public float getWidth(){
return mBullet.getWidth();
}
public float getHeight(){
return mBullet.getHeight();
}
public int getBulletType() {
return mBulletType;
}
public boolean isDead() {
return isDead;
}
}
Boss武器類的邏輯和敵機武器類異曲同工,只是Boss武器類增加更多的效果以及針對主角的跟蹤設置咒循,因為在Boss出場后据途,整個畫布只有主角和Boss在對戰(zhàn)钮呀,所以邏輯處理上主需要針對彼此實現。
3.怎么去使用上面的兩個類昨凡?打開Level1類,如果看了之前的文章就知道在關卡有一個變量用來控制當前關卡敵機的出場次數哦蚁署。
/**
* 當前關卡最多出現多少波敵機
*/
private int maxEnemy=1;
這里為了直接演示便脊,我把敵機次數改成1,就是說一波敵機出現后就開始主角和Boss對戰(zhàn)光戈,在Level1中新增一個方法告訴畫布是否Boss出場哪痰。
/**
* 判斷關卡敵機出現的場次已經結束,如果結束 需要BOSS出場
* @return
*/
public boolean isEnemyArrayOver(){
return enemyArrayIndex>=maxEnemy;
}
4.根據最開始整理的思路久妆,模擬關卡晌杰,所以Boss類應該放到對應的關卡中去使用,不同的關卡出現的Boss不一樣筷弦。在Level1中新增初始化Boss的方法肋演。
/**
* 初始化當前關卡的Boss
* @param selectLevel
*/
public void initBoss(int selectLevel){
if(selectLevel==1||selectLevel==4){
bmpBossBulletA = BitmapUtils.ReadBitMap(getContext(), R.drawable.bullet3);
}else{
bmpBossBulletA = BitmapUtils.ReadBitMap(getContext(), R.drawable.bullet2);
}
bmpBossBulletB = BitmapUtils.ReadBitMap(getContext(), R.drawable.bossbullet1);
bmpBossBulletC = BitmapUtils.ReadBitMap(getContext(), R.drawable.bulletlaser);
bmpBossBulletC = BitmapUtils.getBitmap(getContext(),bmpBossBulletC, 4);
bmpBossBulletD = BitmapUtils.ReadBitMap(getContext(),"boss/bbullet1.png");
bmpBossBulletE = BitmapUtils.ReadBitMap(getContext(),"boss/bbullet2.png");
bmpBossBulletF = BitmapUtils.ReadBitMap(getContext(),"boss/bbullet3.png");
bmpBossBulletF = BitmapUtils.getBitmap(bmpBossBulletF, 0.3f, 0.3f);
//初始化boss
Bitmap mBoss = BitmapUtils.ReadBitMap(getContext(), getBoss(selectLevel));
bmpTurntable = BitmapUtils.ReadBitMap(getContext(), "boss/truntableyellow.png");
if(selectLevel==1){
mDrawBoss = new DrawBoss(getContext(),mBoss, bmpTurntable,selectLevel);
}else{
mDrawBoss = new DrawBoss(getContext(),mBoss,selectLevel);
}
mDrawBoss.setBmpBossBulletC(bmpBossBulletC);
mBulletBoss = new ArrayList<>();
}
selectLevel參數就是通過在進入游戲的時候一個左右滑動選擇場景的地方獲取選擇的某個場景的標示。
5.在Level1中新增一個增加Boss子彈的方法
/**
* 添加boss子彈攻擊
*/
public void addBossBullet(int selectLevel){
mCountBossBullet++;
if(mCountBossBullet % mAddBossBulletTime ==0&&getBoss().mLife >0&&!getBoss().isCrazy && getBoss().getBossY()>0){//添加一次boss子彈
if(selectLevel==2){
if(getBoss().mFireBullet){
isTurntable =true;
}else{
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletA,mPlayer, getBoss().mBossX +getBoss().getWidth()/2-bmpBossBulletA.getWidth()-bmpBossBulletA.getWidth()/2,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_C));//左邊
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletA,mPlayer, getBoss().mBossX +getBoss().getWidth()/2+bmpBossBulletA.getWidth()/2,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_C));//右邊
if(new Random().nextBoolean()){
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletF,getBoss().mBossX +getBoss().getWidth()/2-bmpBossBulletF.getWidth()/2,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_A));//中間
}
}
}else if(selectLevel==3){
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletE,mPlayer, getBoss().mBossX +getBoss().getWidth()/2-bmpBossBulletE.getWidth()*3,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_C));//左邊
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletE,mPlayer, getBoss().mBossX +getBoss().getWidth()/2+bmpBossBulletE.getWidth()*2,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_C));//右邊
if(getBoss().mLife <500&&new Random().nextInt(100)>50&&!isTurntable){
isTurntable =true;
}
}else{
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletA,mPlayer, getBoss().mBossX +getBoss().getWidth()/2-bmpBossBulletA.getWidth()/2,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_C));
}
if(getBoss().mBossY <0&&getBoss().mLife <(selectLevel*0.2)&&selectLevel==1){
if(new Random().nextInt(100)>30){
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletE, getBoss().mBossX +getBoss().getWidth()/2-bmpBossBulletD.getWidth()/2,getBoss().mBossY +getBoss().getHeight(), DrawBossBullet.BULLET_A));
}
}
if(mBulletBoss.size()>10){
mAddBossBulletTime = 100;
}else{
mAddBossBulletTime =15;
}
}
if(selectLevel==1&&!isTurntable &&mEnemyList.size()<=0){
mCountTurntableTime++;
if(mCountTurntableTime %1000==0){
isTurntable =true;
}
}
if(isTurntable){
mTurntableTime++;
int createFire=5;
if(selectLevel==2){
createFire=createFire*10;
if(mTurntableTime %createFire==0){
mEnemyList.add(new DrawEnemy(getContext(),mEnemyG, mPlayer.getPlayerX(), mPlayer.getPlayerY(), getBoss().mBossX, getBoss().mBossY, DrawEnemy.TYPE_V, 1));
mEnemyList.add(new DrawEnemy(getContext(),mEnemyG, mPlayer.getPlayerX(), mPlayer.getPlayerY(), getBoss().mBossX +getBoss().getWidth(), getBoss().mBossY, DrawEnemy.TYPE_W, 1));
}
}else if(selectLevel==3){
createFire=createFire*10;
if(mTurntableTime %createFire==0){
Bitmap temp = BitmapUtils.getBitmap(bmpTurntable,0.5f,0.5f);
mEnemyList.add(new DrawEnemy(getContext(),temp, mPlayer.getPlayerX(), mPlayer.getPlayerY(), getBoss().mBossX, getBoss().mBossY, DrawEnemy.TYPE_V, 1));
mEnemyList.add(new DrawEnemy(getContext(),temp, mPlayer.getPlayerX(), mPlayer.getPlayerY(), getBoss().mBossX +getBoss().getWidth(), getBoss().mBossY, DrawEnemy.TYPE_W, 1));
}
}else{
if(mTurntableTime %createFire==0){
Bitmap temp =BitmapUtils.getBitmap(bmpTurntable,0.5f,0.5f);
mEnemyList.add(new DrawEnemy(getContext(),temp, mPlayer.getPlayerX(), mPlayer.getPlayerY(), getBoss().mBossX, getBoss().mBossY, DrawEnemy.TYPE_V, 1));
mEnemyList.add(new DrawEnemy(getContext(),temp, mPlayer.getPlayerX(), mPlayer.getPlayerY(), getBoss().mBossX +getBoss().getWidth(), getBoss().mBossY, DrawEnemy.TYPE_W, 1));
}
}
if(mTurntableTime >=createFire*5){
mTurntableTime =0;
isTurntable =false;
getBoss().mFireBullet =false;
}
}
if(getBoss().mAttackLaser){
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletC,getBoss().mBossX +getBoss().getWidth()/6,getBoss().mBossY +getBoss().getHeight()/2,DrawBossBullet.BULLET_D));//左邊
mBulletBoss.add(new DrawBossBullet(getContext(),bmpBossBulletC,getBoss().mBossX +getBoss().getWidth()-getBoss().getWidth()/6-bmpBossBulletC.getWidth(),getBoss().mBossY +getBoss().getHeight()/2, DrawBossBullet.BULLET_D));//右邊
getBoss().mAttackLaser =false;
}
if(getBoss().mFireBullet){
if(selectLevel==1){
addBossBulletFire(selectLevel,bmpBossBulletB);
}else if(selectLevel==3){
addBossBulletFire(selectLevel,bmpBossBulletA);
}
}
}
Boss增加武器的方法通過不同場景出場不同Boss烂琴,Boos完全顯示爹殊,Boss血量大于0,Boss子彈增加的間隔時間各個值的判斷來決定Boss武器在畫布中的實現奸绷。
上面的方法除了增加Boss子彈還有實現了僚機增加梗夸,其實僚機也可以看做是武器的一部分,只是把子彈換成了敵機的模式來出現号醉,一樣具有殺傷力反症。
6.上面的方法有一段代碼用來實現Boss的暴力武器,有種火力全開的感覺畔派。
/**
* 增加Boss超級武器铅碍,火力全開
* @param selectLevel
* @param bitmap
*/
private void addBossBulletFire(int selectLevel,Bitmap bitmap){
float bx,by;
if(selectLevel==3){
bx = mDrawBoss.getBossX() + mDrawBoss.getWidth()/2-bitmap.getWidth()/2;
by = mDrawBoss.getBossY()+mDrawBoss.getHeight();
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx, by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_UP));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx, by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_UP_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx, by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx, by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_DOWN_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx,by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_DOWN));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx,by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_DOWN_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx, by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),bitmap,
bx, by,
DrawBossBullet.BULLET_BOOS,DrawBossBullet.DIR_UP_LEFT));
}else{
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_UP));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 3, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 1.5f, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_UP_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_UP_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY()-bitmap.getHeight()*2,
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY()-bitmap.getHeight()*3,
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN_LEFT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY(),
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY()-bitmap.getHeight()*2,
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN_RIGHT));
mBulletBoss.add(new DrawBossBullet(getContext(),
bitmap, getBoss().getBossX() + getBoss().getWidth() / 2, getBoss().getBossY()-bitmap.getHeight()*3,
DrawBossBullet.BULLET_BOOS, DrawBossBullet.DIR_DOWN_RIGHT));
getBoss().mFireBullet=false;
}
}
以上部分就是關卡類新增的邏輯和方法。
7.回到GameView中調用關卡中跟Boss相關的方法父虑。實例關卡類并且初始化Boss
//初始化關卡
mLevel = new Level1(getContext(),mPlayer);
mLevel.initBoss(mSelectLevel);
8.新增一個游戲狀態(tài)该酗,用來控制主角打敗Boss的時候游戲勝利。
private final static int WIN=4;//Boss死亡游戲結束士嚎。
9.在GameView類onGameDraw方法中調用Boss相關的邏輯方法呜魄。
其中需要新增一個方法用來處理Boss和主角之間對戰(zhàn)。
/**
* 繪制BOSS
* 判斷BOSS子彈是否失效 Boss子彈和主角碰撞
*/
private void drawBossBulletCollPlayerIsDecide(){
if(mSelectLevel ==2){
mLevel.getBoss().getAngleRotate(mPlayer.getPlayerX(),mPlayer.getPlayerY());
}
mLevel.getBoss().onDraw(mCanvas);//繪制boss
List<DrawBossBullet> mBulletBoss = mLevel.getBulletBoss();
for (int i = 0; i < mBulletBoss.size(); i++){
DrawBossBullet b = mBulletBoss.get(i);
if(mPlayer.isCollisionWith(b)){//主角和boss子彈碰撞 主角掉血 子彈失效
collPlayerLife(1);
if(b.getBulletType()!=DrawBossBullet.BULLET_D){
mBulletBoss.remove(b);
}
}
if(b.isDead()){//判斷boss子彈是否失效
mBulletBoss.remove(b);//清除
if(b.getBulletType() == DrawBossBullet.BULLET_D){//是否是激光
mLevel.getBoss().mLaser =false;
}
}else{
b.updateGame();
b.onDraw(mCanvas);
}
}
}
其實這個方法的邏輯處理和敵機處理的思路一致莱衩,只不過Boss的碰撞處理需要增加Boss特殊武器的處理爵嗅,比如激光武器。
Boss類暫時就簡單實現了4種模式模式笨蚁,更多的Boss效果就留給學習者去拓展了睹晒。
Canvas 以及畫布的學習就此告一段落趟庄,最后就是在回顧一下成長的道路,首先確定學習目標伪很,定下學習思路戚啥,其次將思路分割并且模塊化,然后分模塊學習锉试,最后分模塊去實現代碼猫十。
真正的游戲開發(fā)有對應的游戲框架,比如cocos2d跨平臺框架呆盖,或者一些java游戲框架拖云,肯定比我們這個高端多了,但是無論什么框架的底層核心或者底層邏輯思路都是最簡單的代碼累加起來的应又,只有把最簡單的東西寫好了宙项,最后才能組成一個趨近完美的東西。
最后還是要說一下我們的重點Canvas和SurfaceView畫布株扛,整個游戲都是在這個基礎上實現的,包括怎么去合理分配資源以及性能上的優(yōu)化都是基于畫布來完成席里,而canvas可以在這布上畫出你任何想要的東西叔磷,比如動畫,多張圖片組合效果奖磁。
說了這么多就是想讓大家知道你能玩轉canvas改基,那么在很多自定義需求對你來說都不再是讓你迷茫的感覺了,至少能為你的成神的路上增加一大段功力咖为。
<b>本文或者各主題文章都屬于原創(chuàng)秕狰,禁止商業(yè)用途,歡迎各路喜歡技術的初級躁染,中級鸣哀,高級,高高高...級的朋友一起分享學習吞彤。</b>
如果你喜歡請點擊喜歡告訴我我衬,后面將會帶來更多Android自己搭建的輕量級高效率框架以及更多實用,強大饰恕,高性能的自定義控件挠羔。
<a >源碼在此,不服來戰(zhàn)埋嵌。</a>
<a href="http://www.reibang.com/p/e77701c67f47">上一篇</a>
<a href="http://www.reibang.com/nb/8490176">Canvas打飛機成長主題</a>