上一篇的主角已经登场,如果你还没见过,可以通过这里进行查看<a href="//www.greatytc.com/p/8b65e7e73f70">主角秀</a>
主角登场没有武器是不行的,所以这一篇的核心就是给主角进行武器装备。
1.创建一个子弹的类DrawPlayerBullet
package com.tangyx.game.holder;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import com.tangyx.game.util.ScreenUtils;
/**
* Created by tangyx on 2016/12/24.
*
*/
public class DrawPlayerBullet extends DrawGame {
/**
* 子弹样式
*/
private Bitmap mBullet;
private float mBulletX;
private float mBulletY;
/**
* 子弹模式
*/
public final static int PLAYER_BULLET_A=1;//垂直中间发出
public final static int PLAYER_BULLET_B=2;//左边发出
public final static int PLAYER_BULLET_C=3;//右边发出
public final static int PLAYER_BULLET_D=4;//双重子弹
private int mBulletType=0;
/**
* 子弹运行速度
*/
private float mBulletSpeed=0;
/**
* 子弹是否有效,当子弹飞出屏幕不可见的时候,这时候子弹已经失效。
*/
private boolean isDead;
public DrawPlayerBullet(Context context, Object... objects) {
super(context);
initialize(objects);
}
@Override
void initialize(Object... objects) {
mBulletX = (float) objects[0];
mBulletY = (float) objects[1];
mBullet = (Bitmap) objects[2];
mBulletType = (int) objects[3];
}
@Override
void onDraw(Canvas canvas) {
canvas.drawBitmap(mBullet,mBulletX,mBulletY,mPaint);
}
@Override
void updateGame() {
onSetSpeed();
switch (mBulletType){
case PLAYER_BULLET_D:
case PLAYER_BULLET_A:
mBulletY -=mBulletSpeed;
break;
case PLAYER_BULLET_B://左边倾斜飞行
mBulletY -=mBulletSpeed;
mBulletX -=mBulletSpeed/4;
break;
case PLAYER_BULLET_C://右边倾斜飞行
mBulletY -=mBulletSpeed;
mBulletX +=mBulletSpeed/4;
break;
}
if(mBulletY<0){
isDead = true;
}
}
/**
* 根据屏幕高度计算子弹飞行的速度
*/
private void onSetSpeed(){
float screenHeight = ScreenUtils.getScreenHeight(getContext());
switch (mBulletType){
case PLAYER_BULLET_B:
case PLAYER_BULLET_C:
case PLAYER_BULLET_D:
case PLAYER_BULLET_A:
mBulletSpeed = screenHeight / 48f;
break;
}
}
public boolean isDead() {
return isDead;
}
}
2.目前主要实现了三种武器模式,普通武器,双重武器以及散弹武器。
<b>普通武器:</b>子弹出发的位置位于战机当前位置的中心(黄色子弹)
<b>双重武器:</b>子弹出发的位置位于战机当前位置的两边,每次发出由两组子弹出现,一边一组子弹对称(红色子弹)
<b>散弹武器:</b>每次生成三组子弹,位于战机当前位置,一边一组和中心一组(月牙形子弹)
每一颗子弹我们也可以看做一个对象,这个对象就是DrawPlayerBullet。DrawPlayerBullet根据不同的子弹类型来实现不同的逻辑,其实每一颗子弹都是自己一个单独的运行逻辑,和其他子弹没有关系,只需要按照顺序绘制出来就能产生一体的感觉。
<b>子弹类的使用方式:</b>
3.回到GameView类,定义子弹相关的参数
4.在GameView类中自定义一个添加主角子弹的方法并且实现逻辑
/**
* 添加主角子弹
*/
private void addPlayerBullet(){
mCountPlayerBullet++;
int mCreatePlayerBullet = 7;//间接性循环加入子弹
if(mCountPlayerBullet % mCreatePlayerBullet ==0){
int bullet = mPlayer.getBulletType();
float playerX = mPlayer.getPlayerX();
float playerY = mPlayer.getPlayerY();
float bulletX;
switch (bullet){
case DrawPlayerBullet.PLAYER_BULLET_A:
bulletX = playerX+(mPlayer.getWidth()-mPlayerBulletA.getWidth())/2;
mPlayerBullets.add(new DrawPlayerBullet(getContext(),bulletX, playerY,mPlayerBulletA,bullet));
break;
case DrawPlayerBullet.PLAYER_BULLET_B:
case DrawPlayerBullet.PLAYER_BULLET_C:
//中间
bulletX = playerX+(mPlayer.getWidth()-mPlayerBulletC.getWidth())/2;
mPlayerBullets.add(new DrawPlayerBullet(getContext(),bulletX, playerY,mPlayerBulletC,DrawPlayerBullet.PLAYER_BULLET_A));
//左边
bulletX = playerX - mPlayerBulletC.getWidth();
mPlayerBullets.add(new DrawPlayerBullet(getContext(),bulletX, playerY,mPlayerBulletC,DrawPlayerBullet.PLAYER_BULLET_B));
//右边
bulletX = playerX + mPlayer.getWidth();
mPlayerBullets.add(new DrawPlayerBullet(getContext(),bulletX, playerY,mPlayerBulletC,DrawPlayerBullet.PLAYER_BULLET_C));
break;
case DrawPlayerBullet.PLAYER_BULLET_D:
//左边
bulletX = playerX;
mPlayerBullets.add(new DrawPlayerBullet(getContext(),bulletX,playerY,mPlayerBulletB,bullet));
//右边
bulletX = playerX+mPlayer.getWidth()-mPlayerBulletB.getWidth();
mPlayerBullets.add(new DrawPlayerBullet(getContext(),bulletX, playerY,mPlayerBulletB,bullet));
break;
}
}
for (int i=0;i<mPlayerBullets.size();i++) {
DrawPlayerBullet bullet = mPlayerBullets.get(i);
if(bullet.isDead()){//如果有子弹已经飞出屏幕直接移除。
mPlayerBullets.remove(bullet);
}else{
bullet.updateGame();
bullet.onDraw(mCanvas);
}
}
//模拟子弹类型变化
mTempBulletType++;
if(mTempBulletType == 50){
mPlayer.setBulletType(DrawPlayerBullet.PLAYER_BULLET_D);
}else if(mTempBulletType == 100){
mPlayer.setBulletType(DrawPlayerBullet.PLAYER_BULLET_C);
}
}```
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3982371-3fe6f1397fe9c730.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
类型PLAYER_BULLET_B,PLAYER_BULLET_C是一起使用的,因为他就是双重子弹武器。
<b>实现思路:</b>
通过得到当前战机的位置X,Y。并且得到当前主角子弹的设置的类型。<b>DrawPlayer</b>中新增了一个参数
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3982371-7884131682b0a628.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
根据子弹类型进入不同的分子设置子弹X的坐标。
Y为什么不需要设置?因为Y就是战机的位置,子弹肯定是从飞机的位置发射的。
除了普通武器,其他武器为了保证子弹的合理性所以需要设置好每一组子弹的x坐标位置,并且传入子弹的类型,然后去<b>DrawPlayerBullet</b>类中进行对应逻辑计算。
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3982371-42f475b1d729936e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
######5.为了保证游戏的流畅性和性能,肯定不能一直都在加入子弹,每一个子弹都是一个新生成的对象,会占用内存,所以我们需要处理子弹是否失效,如果失效就需要移除对象。
子弹失效的判断通过子弹Y的坐标是否小于0,因为子弹是往上运动, 所以Y坐标在减小,小于0肯定就飞出顶部屏幕了,所以直接就在<b>DrawPlayerBullet</b>中判断失效后,移除集合。
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3982371-77c0ba5a6846bb1d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3982371-3a991ba887ba4861.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
######6.在GameView的onGameDraw方法中调用子弹类,只有在游戏运行状态才执行子弹的逻辑处理。
/**
* 绘制内容以及更新内容
*/
private void onGameDraw(){
if(mCanvas==null)return;
mCanvas.drawColor(Color.WHITE);
//背景
mDrawBackground.onDraw(mCanvas);
mDrawBackground.updateGame();
//主角
mPlayer.onDraw(mCanvas);
mPlayer.updateGame();
//判断当前游戏状态
switch (GAME_STATE){
case ING:
addPlayerBullet();
break;
case READY:
mPlayer.onDrawCollect(mCanvas,getContext().getString(R.string.reading));
break;
case PAUSE:
mPlayer.onDrawCollect(mCanvas,getContext().getString(R.string.conution));
break;
}
}```
其他更多的思路就需要自己通过源码去了解。
<b>实践才是唯一的真理。</b>
<a href="https://github.com/tangyxgit/GameCanvas">源码传送门</a>
<a href="//www.greatytc.com/p/8b65e7e73f70">上一篇</a> <a href="//www.greatytc.com/p/1114eca3393b">下一篇</a>