Android Canvas打飞机之主角秀

作者: Galaxy北爱 | 来源:发表于2016-12-23 12:12 被阅读0次

    上一篇讲过游戏背景图的加载以及场景运动效果,如果还需要了解的请<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.战机部分就跟简单,默认开始坐标在屏幕底部中心位置。

    Paste_Image.png
    canvas.drawBitmap(mPlayer,mPlayerX,mPlayerY,mPaint);
    

    2.因为是战机,肯定需要尾部火焰喷气效果嘛,不然不够炫。
    火焰的位置就是位于战机的尾部,所以前面绘制完成战机以后,通过得到战机的x,y计算出喷气的位置。

    canvas.drawBitmap(getBlowAnimation(), (mPlayerX-mPlayerBlow.getWidth()/4),mPlayerY+mPlayerBlow.getHeight()/1.5f,mPaint);
    

    其中有一个getBlowAnimation的方法,通过它实时更改火焰图片的高度来给人一种喷射的感觉。

    Paste_Image.png

    其中主要是通过Matrix类来完成一些特效,这个类也是非常非常非常的重要,在<a href="https://developer.android.google.cn/reference/android/graphics/Matrix.html">官网</a>有详细的介绍,可自行查看。
    3.战机是通过我们用手按住屏幕来移动,所以我们需要提供一个可操控的位置,操控的位置也是一张图片,它的位置一直紧随着喷气的底部,而喷气是紧随战机,所以操作动作就是去移动战机在屏幕的位置。

    Paste_Image.png

    操作按钮中心就是一个FIRE的字体,字体和按钮通过<a href="https://developer.android.google.cn/reference/android/graphics/Paint.html">Paint</a>设置透明度的变化产生一个闪烁的效果,并且手离开屏幕的时候操作按钮就会出现,并且提示游戏状态以及下一步操作,手按下屏幕的时候就按钮就会消失并且游戏继续。

    device-2016-12-23-105428.png

    ---------我是分割线----------
    这里只是把战机绘制出来,那怎么让战机跟随我的手指运动呢?
    回到<b>GameView</b>类,既然是手势操作,你想到的是什么?我想到就是实现onTouchEvent。
    1.暂时给游戏定义三个状态

    Paste_Image.png

    2.默认是游戏加载到可操作状态READY。
    当游戏可以操作的时候,这时候把手放到操作按钮的位置(上图的白色圆圈),就可以变更游戏状态为ING。点击其他位置不做任何变化。

    Paste_Image.png

    3.手指移动变更战机的位置x,y。

    Paste_Image.png

    4.手离开屏幕,游戏进入暂停状态。

    Paste_Image.png

    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](https://img.haomeiwen.com/i3982371/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>

    相关文章

      网友评论

        本文标题:Android Canvas打飞机之主角秀

        本文链接:https://www.haomeiwen.com/subject/nnckvttx.html