上一篇讲过游戏背景图的加载以及场景运动效果,如果还需要了解的请<a href="http://www.jianshu.com/p/a87a9ed6a8b2">移驾这里</a>
今天要研究的是游戏主角战机的运动以及逻辑的实现。
1.创建一个主角的类DrawPlayer。
package com.tangyx.game.holder;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import com.tangyx.game.R;
import com.tangyx.game.util.BitmapUtils;
import com.tangyx.game.util.ScreenUtils;
import com.tangyx.game.util.SizeUtils;
/**
* Created by tangyx on 2016/12/22.
*
*/
public class DrawPlayer extends DrawGame {
/**
* 主角
*/
private Bitmap mPlayer;
private float mPlayerX;
private float mPlayerY;
/**
* 主角的控制位置
*/
private Bitmap mCollect;
private float mCollectX;
private float mCollectY;
private int mCollectCount;
private Paint mCollectPaint;
/**
* 尾气喷气
*/
private Bitmap mPlayerBlow;
private float mSpeedAngle=0.05f;
private float mBlowAngle = 1;
private Matrix mBlowMatrix;
public DrawPlayer(Context context,int player) {
super(context,player);
}
@Override
void initialize(Object... objects) {
mPlayer = BitmapUtils.ReadBitMap(getContext(), (Integer) objects[0]);
int wh = SizeUtils.dp2px(getContext(),20);
mPlayer = BitmapUtils.getBitmap(mPlayer,wh,wh);
mPlayerBlow = BitmapUtils.ReadBitMap(getContext(), R.drawable.playblow0);
mPlayerBlow = BitmapUtils.getBitmap(mPlayerBlow,wh,wh);
mCollect = BitmapUtils.ReadBitMap(getContext(),R.drawable.collect);
wh = SizeUtils.dp2px(getContext(),30);
mCollect = BitmapUtils.getBitmap(mCollect,wh,wh);
int screenW = ScreenUtils.getScreenWidth(getContext());
int screenH = ScreenUtils.getScreenHeight(getContext());
//初始化战机的位置
mPlayerX = screenW/2-mPlayer.getWidth()/2;
mPlayerY = screenH-mPlayer.getHeight()-screenH/10;
mCollectX = screenW/2-mCollect.getWidth()/2;
mCollectY = mPlayerY+mPlayer.getHeight()+mCollect.getHeight()/2;
mBlowMatrix = new Matrix();
mCollectPaint = new Paint();
mCollectPaint.setAntiAlias(true);
}
@Override
void onDraw(Canvas canvas) {
mPaint.setAlpha(255);
canvas.drawBitmap(mPlayer,mPlayerX,mPlayerY,mPaint);
canvas.drawBitmap(getBlowAnimation(), (mPlayerX-mPlayerBlow.getWidth()/4),mPlayerY+mPlayerBlow.getHeight()/1.5f,mPaint);
}
/**
* 尾气喷气动画
*/
private Bitmap getBlowAnimation(){
mBlowAngle += mSpeedAngle;
float sx =1.5f;
float sy = mBlowAngle;
mBlowMatrix.reset();
mBlowMatrix.postScale(sx,sy);
if(mBlowAngle>=1.2||mBlowAngle<1){
mSpeedAngle=-mSpeedAngle;
}
return Bitmap.createBitmap(mPlayerBlow,0,0,mPlayerBlow.getWidth(),mPlayerBlow.getHeight(),mBlowMatrix,true);
}
/**
* 绘制操作的位置按钮
*/
public void onDrawCollect(Canvas canvas,String text){
if(mCollectCount==(Integer.MAX_VALUE-1)){
mCollectCount=0;
}
mCollectPaint.setTextSize(20f);
mCollectCount++;
if(mCollectCount%2==0){
mCollectPaint.setAlpha(0);
}else{
mCollectPaint.setAlpha(255);
}
mCollectX = mPlayerX-(mCollect.getWidth()-mPlayer.getWidth())/2;
mCollectY = mPlayerY+mPlayer.getHeight()+mCollect.getHeight()/2;
canvas.drawBitmap(mCollect,mCollectX,mCollectY,mCollectPaint);
String fire = getContext().getString(R.string.fire);
Rect rect = getTextRect(fire,mCollectPaint);
float tx = mCollectX+(mCollect.getWidth()-rect.width())/2;
float ty = mCollectY+mCollect.getHeight()/2+rect.height()/2;
//点击这个地方游戏继续
canvas.drawText(fire, tx, ty, mCollectPaint);
int w = ScreenUtils.getScreenWidth(getContext());
int h = ScreenUtils.getScreenHeight(getContext());
mPaint.setTextSize(SizeUtils.sp2px(getContext(),20));
//游戏暂停提示语
rect = getTextRect(text,mPaint);
canvas.drawText(text,(w-rect.width())/2 ,h/3, mPaint);
}
@Override
void updateGame() {
}
public void setPlayerX(float mPlayerX) {
this.mPlayerX = mPlayerX-mPlayer.getWidth()/1.5f;
}
public void setPlayerY(float mPlayerY) {
this.mPlayerY = mPlayerY-mPlayer.getHeight() * 2.5f;
}
public float getCollectX() {
return mCollectX;
}
public float getCollectY() {
return mCollectY;
}
public Bitmap getCollect() {
return mCollect;
}
}
主角战机组成部分:飞机+尾部喷气+手指操作按钮。
1.战机部分就跟简单,默认开始坐标在屏幕底部中心位置。
canvas.drawBitmap(mPlayer,mPlayerX,mPlayerY,mPaint);
2.因为是战机,肯定需要尾部火焰喷气效果嘛,不然不够炫。
火焰的位置就是位于战机的尾部,所以前面绘制完成战机以后,通过得到战机的x,y计算出喷气的位置。
canvas.drawBitmap(getBlowAnimation(), (mPlayerX-mPlayerBlow.getWidth()/4),mPlayerY+mPlayerBlow.getHeight()/1.5f,mPaint);
其中有一个getBlowAnimation的方法,通过它实时更改火焰图片的高度来给人一种喷射的感觉。
其中主要是通过Matrix类来完成一些特效,这个类也是非常非常非常的重要,在<a href="https://developer.android.google.cn/reference/android/graphics/Matrix.html">官网</a>有详细的介绍,可自行查看。
3.战机是通过我们用手按住屏幕来移动,所以我们需要提供一个可操控的位置,操控的位置也是一张图片,它的位置一直紧随着喷气的底部,而喷气是紧随战机,所以操作动作就是去移动战机在屏幕的位置。
操作按钮中心就是一个FIRE的字体,字体和按钮通过<a href="https://developer.android.google.cn/reference/android/graphics/Paint.html">Paint</a>设置透明度的变化产生一个闪烁的效果,并且手离开屏幕的时候操作按钮就会出现,并且提示游戏状态以及下一步操作,手按下屏幕的时候就按钮就会消失并且游戏继续。
---------我是分割线----------
这里只是把战机绘制出来,那怎么让战机跟随我的手指运动呢?
回到<b>GameView</b>类,既然是手势操作,你想到的是什么?我想到就是实现onTouchEvent。
1.暂时给游戏定义三个状态
2.默认是游戏加载到可操作状态READY。
当游戏可以操作的时候,这时候把手放到操作按钮的位置(上图的白色圆圈),就可以变更游戏状态为ING。点击其他位置不做任何变化。
3.手指移动变更战机的位置x,y。
4.手离开屏幕,游戏进入暂停状态。
5.在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:
break;
case READY:
mPlayer.onDrawCollect(mCanvas,getContext().getString(R.string.reading));
break;
case PAUSE:
mPlayer.onDrawCollect(mCanvas,getContext().getString(R.string.conution));
break;
}
}```
![player.gif](http://upload-images.jianshu.io/upload_images/3982371-222c5de5c612988b.gif?imageMogr2/auto-orient/strip)
主角战机的核心思路就是以上部分,最后是提供持续更新的源码。
<a href="https://github.com/tangyxgit/GameCanvas">源码传送门</a>
<a href="http://www.jianshu.com/p/a87a9ed6a8b2">上一篇</a> <a href="http://www.jianshu.com/p/966a3e9d8bdf">下一篇</a>