Android SurfaceView实战 带你玩切水果1.0

1、概述

最近开发一个智能项目,项目对象是某智能早教机器人,这个产品主要定位是儿童益智玩的游戏,并且可以从中学习到相关历史知识等相关知识,其中有个游戏关卡就是去到不同国家,可以玩不同的游戏。领导说要用Android原生做游戏,卧槽,我当时就懵逼,原生做游戏,我就试试开撸吧。

好吧,先上个效果图
这里写图片描述

思路分析

1、水果
2、背景
3、水果篮子
4、分数
5、时间
6、水果刀
7、当用户touch屏幕时,水果刀跟着移动,水果刀碰到水果,被切成两半

3、SurfaceView模板

我先创建一个类为FruitGameSurfaceView 继承SurfaceView,上代码。


/**
 * @author Tim
 */
@SuppressWarnings("ALL")
public class FruitGameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private SurfaceHolder mHolder;
    private final Surface surface;
    public Thread getT() {
        return t;
    }

    public void setT(Thread t) {
        this.t = t;
    }

    public Canvas getCanvas() {
        return canvas;
    }

    public void setCanvas(Canvas canvas) {
        this.canvas = canvas;
    }

    public SurfaceHolder getmHolder() {
        return mHolder;
    }

    public void setmHolder(SurfaceHolder mHolder) {
        this.mHolder = mHolder;
    }

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean running) {
        isRunning = running;
    }

    /**
     * 线程控制开关
     */

    private boolean isRunning;
    private Thread t;
    private Canvas canvas;

    public FruitGameSurfaceView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        mHolder = getHolder();
        mHolder.addCallback(this);
        //可获得焦点
        setFocusable(true);
        setFocusableInTouchMode(true);
        //设置常亮
        setKeepScreenOn(true);
        surface = mHolder.getSurface();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        isRunning = true;
        t = new Thread(this);
        t.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        isRunning=false;
    }

    protected void myDraw(Canvas canvas) {

    }



    @Override
    public void run() {
        //不断绘制
            while (isRunning){
                long start = System.currentTimeMillis();
                draw();
                long end = System.currentTimeMillis();
                try
                {
                    if (end - start < 50)
                    {
                        Thread.sleep(50 - (end - start));
                    }
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
    }

    private void draw() {
        if(mHolder != null) {
            canvas = mHolder.lockCanvas();
        }
        try {
            if (canvas != null && mHolder != null &&surface != null && surface.isValid()) {
                myDraw(canvas);
            }
        } catch (Exception e) {
                e.printStackTrace();

        }finally {
            if (canvas!=null){
                mHolder.unlockCanvasAndPost(canvas);
            }
        }

    }
}

这个模板类,在HongYang前辈哪里已经学习过来的,可以直接拷贝,在此类基础上编写。

4、绘制相关

我再创建一个类继承我的FruitGameSurfaceView,这个类叫MyGameView专注于刷新绘制。

 //专用于绘制屏幕
    @Override
    protected void myDraw(Canvas canvas) {
        super.myDraw(canvas);
        //用户画背景
        drawBg(canvas);
        //画水果篮子
        drawFruitBox(canvas);
        //画刀光
        drawBlade(canvas);
        if (isOpen) {
            //到了计算好的时间就生成精灵
            if (mNextTime < System.currentTimeMillis()) {
                generateSpirit();
//          mSoundPool.play(mExplodeSoundId, 1, 1, 1, 0, 1);
                nextGenTime();
            }
        }
//      if(mNextTimeBoom<System.currentTimeMillis()){
//          //画炸弹
//          drawBoom();
//          nextGenTimeBoom();
//      }
        //绘制时间
        drawTime(canvas);
        //检查精灵是否还在屏幕内,不在屏幕内则移除
        checkSpirites();
        //画水果
        drawSpirites(canvas);
        //初始化切到水果
        isHit();
//      //初始化撞击炸弹
//      isHitBomb();
//      //绘制分数
        drawGrades(canvas);
    }

1、绘制相关代码

  /**
     * 绘制背景
     */
    private void drawBg(Canvas canvas) {
        //初始化图片
        canvas.drawBitmap(mBg, null, mGamePanelRect, null);
    }

    /**
     * 画水果篮子
     *
     * @param canvas
     */
    private void drawFruitBox(Canvas canvas) {
        canvas.drawBitmap(mIcon_fruit_all, null, mRectFFruitAll, null);
    }
/**
     * 画刀光到画布上,可以扩展
     *
     * @param canvas
     */
    private void drawBlade(Canvas canvas) {
        synchronized (mTrack) {
            Path path = new Path();
            Float startX, startY;
            Float controlX, controlY;
            Float endX, endY;
            int strokeWidth = 1;
            if (mTrack.size() > 1) {
                endX = mTrack.get(0).x;
                endY = mTrack.get(0).y;
                for (int i = 0; i < mTrack.size() - 1; i++) {
                    startX = endX;
                    startY = endY;
                    controlX = mTrack.get(i).x;
                    controlY = mTrack.get(i).y;
                    endX = (controlX + mTrack.get(i + 1).x) / 2;
                    endY = (controlY + mTrack.get(i + 1).y) / 2;
                    path.moveTo(startX, startY);
                    path.quadTo(controlX, controlY, endX, endY);
                    paintBlade.setColor(mBladeColor);
                    paintBlade.setStrokeWidth(strokeWidth++);
                    canvas.drawPath(path, paintBlade);
                    path.reset();
                }
                startX = endX;
                startY = endY;
                endX = mTrack.get(mTrack.size() - 1).x;
                endY = mTrack.get(mTrack.size() - 1).y;
                path.moveTo(startX, startY);
                path.lineTo(endX, endY);
                paintBlade.setStrokeWidth(strokeWidth++);
                paintBlade.setColor(mBladeColor);
                canvas.drawPath(path, paintBlade);
                mTrack.remove(0);
            }
        }
    }
/**
     * 倒计时,右上角时间和页面判断跳转
     *
     * @param canvas
     */
    private void drawTime(Canvas canvas) {
        if (System.currentTimeMillis() - mTimeCount > 1000) {
            mTimeCount = System.currentTimeMillis();
            count--;
            if (count == 0) {
                isOpen = false;
//              Intent intent = new Intent(mContext, GameStopActivity.class);
//              intent.putExtra("Score", ""+ scroe);
//              mContext.startActivity(intent);
            } else {

            }
        }
        if (count <= 0) {
            canvas.drawText("Time:" + 0, width - 250, 130, timePaint);
        } else {
            canvas.drawText("Time:" + count, width - 250, 120, timePaint);
        }

    }
/**
     * 画精灵到画布上
     *
     * @param canvas
     */
    private void drawSpirites(Canvas canvas) {
        for (int i = 0; i < mSpirits.size(); i++) {
            mSpirits.get(i).draw(canvas);
        }
//      for(int i=0;i<mBooms.size();i++){
//          mBooms.get(i).draw(canvas);
//      }
    }
 /**
     * 初始化切到水果的时候
     */
    private void isHit() {
        synchronized (mTrack) {
            for (int i = 0; i < mTrack.size(); i++) {
                for (int z = 0; z < mSpirits.size(); z++) {
                    if (mTrack.get(i).x > mSpirits.get(z).mCoord.x && mTrack.get(i).x < mSpirits.get(z).mCoord.x + mSpirits.get(z).mDimention.x) {
                        if (mTrack.get(i).y > mSpirits.get(z).mCoord.y && mTrack.get(i).y < mSpirits.get(z).mCoord.y + mSpirits.get(z).mDimention.y) {
                            switch (mSpirits.get(z).getmType()) {
                                case R.drawable.icon_orange:
                                    initCutCake(mIcon_orange1, mIcon_orange2, z);
                                    Log.e("m", "icon_orange");
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_pineapple:
                                    Log.e("m", "icon_pineapple");
                                    initCutCake(mIcon_pineapple2, mIcon_pineapple1, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_banana:
                                    Log.e("m", "icon_banana");
                                    initCutCake(mIcon_banana2, mIcon_banana1, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_lemon:
                                    Log.e("m", "icon_lemon");
                                    initCutCake(mIcon_lemon1, mIcon_lemon2, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_mango:
                                    Log.e("m", "icon_mango");
                                    initCutCake(mIcon_mango1, mIcon_mango2, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_watermelon:
                                    Log.e("m", "icon_watermelon");
                                    initCutCake(mIcon_watermelon2, mIcon_watermelon1, z);
                                    scroe += 1;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }
        }
    }
  /**
     * 绘制分数2
     */
    @SuppressLint("WrongConstant")
    private void drawGrades(Canvas canvas) {
        String grade = scroe + "";
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
//        canvas.translate(width / 2 - grade.length() * mSingleGradeWidth / 2,
//                1f / 8 * height);
        canvas.translate(mIcon_fruit_all.getWidth() / 2 - 40, mIcon_fruit_all.getHeight() + 50);
        // 一个一个地画一个数字
        for (int i = 0; i < grade.length(); i++) {
            String numStr = grade.substring(i, i + 1);
            int num = Integer.valueOf(numStr);
            canvas.drawBitmap(mNumBitmap[num], null, mSingleNumRectF, null);
            canvas.translate(mSingleGradeWidth, 0);
        }
        canvas.restore();
    }

2、构造函数初始化相关

   public MyGameView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        mContext = context;
        initSomeObjectList();
        initTimePaint();
        initScorePaint();
        initBladePaint();
        initBitmaps();
        initPlayer(context);
        initSoundPool(context);
    }

初始化相关水果对象、炸弹和点容器List

   private void initSomeObjectList() {
        mTrack = new ArrayList<PointF>();
        //实例化容纳精灵的列表,请自行做好管理精灵的工作
        mSpirits = new ArrayList<Spirite>();
        mBooms = new ArrayList<Spirite>();
    }

初始化声音

  private void initSoundPool(Context context) {
        SoundPool mSoundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 100);
        mExplodeSoundId = mSoundPool.load(context, R.raw.bomb_explode, 1);
    }

    private void initPlayer(Context context) {
        MediaPlayer mPlayer = MediaPlayer.create(context, R.raw.music_menu);
        mPlayer.setLooping(true);
    }

初始化一堆画笔

    private void initBladePaint() {
        paintBlade = new Paint();
        paintBlade.setColor(Color.WHITE);
        paintBlade.setStyle(Style.STROKE);
    }

    private void initScorePaint() {
        paintScore = new Paint();
        paintScore.setColor(Color.WHITE);
        paintScore.setTextSize(60);
    }

    private void initTimePaint() {
        timePaint = new Paint();
        timePaint.setColor(Color.WHITE);
        timePaint.setTextSize(60);
    }

初始化图片

 /**
     * 初始化图片
     */
    private void initBitmaps() {
        //背景
        mBg = loadImageByResId(R.drawable.icon_fruit_bg1);
        //切掉后水果图片
        mIcon_orange1 = loadImageByResId(R.drawable.icon_orange1);
        mIcon_orange2 = loadImageByResId(R.drawable.icon_orange2);
        mIcon_pineapple2 = loadImageByResId(R.drawable.icon_pineapple2);
        mIcon_pineapple1 = loadImageByResId(R.drawable.icon_pineapple1);
        mIcon_banana1 = loadImageByResId(R.drawable.icon_banana1);
        mIcon_banana2 = loadImageByResId(R.drawable.icon_banana2);
        mIcon_lemon2 = loadImageByResId(R.drawable.icon_lemon2);
        mIcon_lemon1 = loadImageByResId(R.drawable.icon_lemon1);
        mIcon_mango1 = loadImageByResId(R.drawable.icon_mango1);
        mIcon_mango2 = loadImageByResId(R.drawable.icon_mango2);
        mIcon_orange = loadImageByResId(R.drawable.icon_orange);
        mIcon_pineapple = loadImageByResId(R.drawable.icon_pineapple);
        mIcon_banana = loadImageByResId(R.drawable.icon_banana);
        mIcon_lemon = loadImageByResId(R.drawable.icon_lemon);
        mIcon_mango = loadImageByResId(R.drawable.icon_mango);
        mBoom = loadImageByResId(R.drawable.boom);
        mIcon_watermelon = loadImageByResId(R.drawable.icon_watermelon);
        mIcon_watermelon1 = loadImageByResId(R.drawable.icon_watermelon1);
        mIcon_watermelon2 = loadImageByResId(R.drawable.icon_watermelon2);
        mIcon_fruit_all = loadImageByResId(R.drawable.icon_fruit_all);
        mNumBitmap = new Bitmap[mNums.length];
        for (int i = 0; i < mNumBitmap.length; i++) {
            mNumBitmap[i] = loadImageByResId(mNums[i]);
        }
    }

3、生成水果对象

   if (isOpen) {
            //到了计算好的时间就生成水果精灵
            if (mNextTime < System.currentTimeMillis()) {
                generateSpirit();
//          mSoundPool.play(mExplodeSoundId, 1, 1, 1, 0, 1);
                nextGenTime();
            }
        }
 /**
     * 生成精灵,并添加到精灵管理列表
     */
    private void generateSpirit() {
        //请修改此方法,使精灵从更多方向抛出
        Spirite spirite = new Spirite(mContext);
//      spirite.loadBitmap(R.drawable.ic_launcher);
        Random rand = new Random();
        int randNum = 1 + rand.nextInt(6);
        int cakeId;
        switch (randNum) {
            case 1:
                cakeId = R.drawable.icon_orange;
                spirite.loadBitmap(mIcon_orange);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 2:
                cakeId = R.drawable.icon_pineapple;
                spirite.loadBitmap(mIcon_pineapple);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 3:
                cakeId = R.drawable.icon_banana;
                spirite.loadBitmap(mIcon_banana);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 4:
                cakeId = R.drawable.icon_lemon;
                spirite.loadBitmap(mIcon_lemon);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 5:
                cakeId = R.drawable.icon_mango;
                spirite.loadBitmap(mIcon_mango);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 6:
                cakeId = R.drawable.icon_watermelon;
                spirite.loadBitmap(mIcon_watermelon);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            default:
        }
        Random r = new Random();
        //随机坐标
        spirite.mCoord.x = width / (35 / 10) + r.nextInt(width / (35 / 10)) - 30;
        spirite.mCoord.y = r.nextInt(100);
        //设置抛物线向下速度
//      spirite.mV.x = 5+r.nextInt(5);
//      spirite.mV.y = -(30 + (r.nextInt(20)+10));
        //添加向上抛
        spirite.mV.y = -(30 + (r.nextInt(20) + 10));
        /*mSpirits.get(0).setmType(mType);*/
        mSpirits.add(spirite);
    }

4、切到水果


    /**
     * 初始化切到水果的时候
     */
    private void isHit() {
        synchronized (mTrack) {
            for (int i = 0; i < mTrack.size(); i++) {
                for (int z = 0; z < mSpirits.size(); z++) {
                    if (mTrack.get(i).x > mSpirits.get(z).mCoord.x && mTrack.get(i).x < mSpirits.get(z).mCoord.x + mSpirits.get(z).mDimention.x) {
                        if (mTrack.get(i).y > mSpirits.get(z).mCoord.y && mTrack.get(i).y < mSpirits.get(z).mCoord.y + mSpirits.get(z).mDimention.y) {
                            switch (mSpirits.get(z).getmType()) {
                                case R.drawable.icon_orange:
                                    initCutCake(mIcon_orange1, mIcon_orange2, z);
                                    Log.e("m", "icon_orange");
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_pineapple:
                                    Log.e("m", "icon_pineapple");
                                    initCutCake(mIcon_pineapple2, mIcon_pineapple1, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_banana:
                                    Log.e("m", "icon_banana");
                                    initCutCake(mIcon_banana2, mIcon_banana1, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_lemon:
                                    Log.e("m", "icon_lemon");
                                    initCutCake(mIcon_lemon1, mIcon_lemon2, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_mango:
                                    Log.e("m", "icon_mango");
                                    initCutCake(mIcon_mango1, mIcon_mango2, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_watermelon:
                                    Log.e("m", "icon_watermelon");
                                    initCutCake(mIcon_watermelon2, mIcon_watermelon1, z);
                                    scroe += 1;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }
        }
    }
  /**
     * 切到水果后加载2个图片
     *
     * @param bitmap1
     * @param bitmap2
     * @param z
     */
    private void initCutCake(Bitmap bitmap1, Bitmap bitmap2, int z) {
        Spirite spirite_left = new Spirite(mContext);
        Spirite spirite_right = new Spirite(mContext);
        spirite_left.loadBitmap(bitmap1);
        spirite_left.mCoord.x = mSpirits.get(z).mCoord.x + 60;
        spirite_left.mCoord.y = mSpirits.get(z).mCoord.y;
        mSpirits.add(spirite_left);
        spirite_right.loadBitmap(bitmap2);
        spirite_right.mCoord.x = mSpirits.get(z).mCoord.x - 60;
        spirite_right.mCoord.y = mSpirits.get(z).mCoord.y;
        mSpirits.add(spirite_right);
        mSpirits.remove(z);
    }

5、初始化尺寸相关

 /**
     * 初始化尺寸相关
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = getWidth();
        height = getHeight();
        mGamePanelRect.set(0, 0, width, height);
        // 初始化分数
        mSingleGradeHeight = (int) (h * RADIO_SINGLE_NUM_HEIGHT);
        mSingleGradeWidth = (int) (mSingleGradeHeight * 1.0f
                / mNumBitmap[0].getHeight() * mNumBitmap[0].getWidth());
        mSingleNumRectF = new RectF(0, 0, mSingleGradeWidth, mSingleGradeHeight);
        //初始化水果篮子
        mRectFFruitAll = new RectF(50, 50, mIcon_fruit_all.getWidth(), mIcon_fruit_all.getHeight());
    }

6、手势触摸处理

  /**
     * 屏幕点击事件的响应方法
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            handleActionDown(event);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            handleActionMove(event);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            handleActionUp();
        }
        return true;
    }

    //手指按下的响应方法
    private void handleActionDown(MotionEvent event) {
        PointF point = new PointF(event.getX(), event.getY());
        synchronized (mTrack) {
            if (mTrack.size() >= POINT_LIMIT) {
                mTrack.remove(0);
            }
            mTrack.add(point);
        }
    }

    //手指拖动的响应方法
    private void handleActionMove(MotionEvent event) {
        PointF point = new PointF(event.getX(), event.getY());
        synchronized (mTrack) {
            if (mTrack.size() >= POINT_LIMIT) {
                mTrack.remove(0);
            }
            mTrack.add(point);
        }
    }

    //手指抬起的响应方法
    private void handleActionUp() {
        synchronized (mTrack) {
            mTrack.clear();
        }
    }

所有源码

package com.example.tim.myapplication;

import java.util.ArrayList;
import java.util.Random;

import android.annotation.SuppressLint;
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.Path;
import android.graphics.PointF;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class MyGameView extends FruitGameSurfaceView {

    private Context mContext;
    private ArrayList<PointF> mTrack;
    private final static int POINT_LIMIT = 5;
    private int scroe = 0;
    //此变量用于修改刀光的颜色
    private int mBladeColor = 0xFFFFFFFF;

    //用于容纳精灵
    private ArrayList<Spirite> mSpirits;
    private ArrayList<Spirite> mBooms;

    //计算下次生成精灵的时间
    private long mNextTime = 0L;
    private long mNextTimeBoom = 0L;

    //显示右上角时间
    private long mTimeCount;
    public int count = 30;

    //声明播放器


    private int mExplodeSoundId;
    private int width;
    private int height;
    private Paint timePaint;
    private Paint paintScore;
    private Paint paintBlade;
    //背景
    private Bitmap mBg;
    private boolean isOpen = true;
    /**
     * 当前View的尺寸
     */
    private RectF mGamePanelRect = new RectF();
    /**
     * 分数
     */
    private final int[] mNums = new int[]{R.drawable.n0, R.drawable.n1,
            R.drawable.n2, R.drawable.n3, R.drawable.n4, R.drawable.n5,
            R.drawable.n6, R.drawable.n7, R.drawable.n8, R.drawable.n9};
    private Bitmap[] mNumBitmap;
    private int mGrade = 0;
    private int mRemovedPipe = 0;
    private static final float RADIO_SINGLE_NUM_HEIGHT = 1 / 15f;
    private int mSingleGradeWidth;
    private int mSingleGradeHeight;
    private RectF mSingleNumRectF;

    /**
     * 水果图片
     */
    private Bitmap mIcon_orange;
    private Bitmap mIcon_pineapple;
    private Bitmap mIcon_banana;
    private Bitmap mIcon_lemon;
    private Bitmap mIcon_mango;
    private Bitmap mIcon_watermelon;
    /**
     * 水果被切后效果
     */
    private Bitmap mIcon_orange1;
    private Bitmap mIcon_orange2;
    private Bitmap mIcon_pineapple2;
    private Bitmap mIcon_pineapple1;
    private Bitmap mIcon_banana1;
    private Bitmap mIcon_banana2;
    private Bitmap mIcon_lemon2;
    private Bitmap mIcon_lemon1;
    private Bitmap mIcon_mango1;
    private Bitmap mIcon_mango2;
    private Bitmap mIcon_watermelon1;
    private Bitmap mIcon_watermelon2;
    /**
     * 炸弹
     */
    private Bitmap mBoom;
    private Bitmap mIcon_fruit_all;
    private RectF mRectFFruitAll;

    public MyGameView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        mContext = context;
        initSomeObjectList();
        initTimePaint();
        initScorePaint();
        initBladePaint();
        initBitmaps();
        initPlayer(context);
        initSoundPool(context);
    }

    private void initSomeObjectList() {
        mTrack = new ArrayList<PointF>();
        //实例化容纳精灵的列表,请自行做好管理精灵的工作
        mSpirits = new ArrayList<Spirite>();
        mBooms = new ArrayList<Spirite>();
    }

    private void initSoundPool(Context context) {
        SoundPool mSoundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 100);
        mExplodeSoundId = mSoundPool.load(context, R.raw.bomb_explode, 1);
    }

    private void initPlayer(Context context) {
        MediaPlayer mPlayer = MediaPlayer.create(context, R.raw.music_menu);
        mPlayer.setLooping(true);
    }

    private void initBladePaint() {
        paintBlade = new Paint();
        paintBlade.setColor(Color.WHITE);
        paintBlade.setStyle(Style.STROKE);
    }

    private void initScorePaint() {
        paintScore = new Paint();
        paintScore.setColor(Color.WHITE);
        paintScore.setTextSize(60);
    }

    private void initTimePaint() {
        timePaint = new Paint();
        timePaint.setColor(Color.WHITE);
        timePaint.setTextSize(60);
    }

    /**
     * 初始化尺寸相关
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = getWidth();
        height = getHeight();
        mGamePanelRect.set(0, 0, width, height);
        // 初始化分数
        mSingleGradeHeight = (int) (h * RADIO_SINGLE_NUM_HEIGHT);
        mSingleGradeWidth = (int) (mSingleGradeHeight * 1.0f
                / mNumBitmap[0].getHeight() * mNumBitmap[0].getWidth());
        mSingleNumRectF = new RectF(0, 0, mSingleGradeWidth, mSingleGradeHeight);
        //初始化水果篮子
        mRectFFruitAll = new RectF(50, 50, mIcon_fruit_all.getWidth(), mIcon_fruit_all.getHeight());
    }

    //专用于绘制屏幕
    @Override
    protected void myDraw(Canvas canvas) {
        super.myDraw(canvas);
        //用户画背景
        drawBg(canvas);
        //画水果篮子
        drawFruitBox(canvas);
        //画刀光
        drawBlade(canvas);
        if (isOpen) {
            //到了计算好的时间就生成水果精灵
            if (mNextTime < System.currentTimeMillis()) {
                generateSpirit();
//          mSoundPool.play(mExplodeSoundId, 1, 1, 1, 0, 1);
                nextGenTime();
            }
        }
//      if(mNextTimeBoom<System.currentTimeMillis()){
//          //画炸弹
//          drawBoom();
//          nextGenTimeBoom();
//      }
        //绘制时间
        drawTime(canvas);
        //检查精灵是否还在屏幕内,不在屏幕内则移除
        checkSpirites();
        //画水果
        drawSpirites(canvas);
        //初始化切到水果
        isHit();
//      //初始化撞击炸弹
//      isHitBomb();
//      //绘制分数
        drawGrades(canvas);
    }

    /**
     * 画水果篮子
     *
     * @param canvas
     */
    private void drawFruitBox(Canvas canvas) {
        canvas.drawBitmap(mIcon_fruit_all, null, mRectFFruitAll, null);
    }

    /**
     * 下一次生成精灵的时间
     */
    private void nextGenTime() {
        mNextTime = System.currentTimeMillis();
        Random r = new Random();
        int interval = 700 + r.nextInt(100);
        mNextTime += interval;
    }

    private void nextGenTimeBoom() {
        mNextTimeBoom = System.currentTimeMillis() + 1000;
        Random r = new Random();
        int interval = 3000 + r.nextInt(2000);
        mNextTimeBoom += interval;
    }

    /**
     * 生成精灵,并添加到精灵管理列表
     */
    private void generateSpirit() {
        //请修改此方法,使精灵从更多方向抛出
        Spirite spirite = new Spirite(mContext);
//      spirite.loadBitmap(R.drawable.ic_launcher);
        Random rand = new Random();
        int randNum = 1 + rand.nextInt(6);
        int cakeId;
        switch (randNum) {
            case 1:
                cakeId = R.drawable.icon_orange;
                spirite.loadBitmap(mIcon_orange);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 2:
                cakeId = R.drawable.icon_pineapple;
                spirite.loadBitmap(mIcon_pineapple);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 3:
                cakeId = R.drawable.icon_banana;
                spirite.loadBitmap(mIcon_banana);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 4:
                cakeId = R.drawable.icon_lemon;
                spirite.loadBitmap(mIcon_lemon);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 5:
                cakeId = R.drawable.icon_mango;
                spirite.loadBitmap(mIcon_mango);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            case 6:
                cakeId = R.drawable.icon_watermelon;
                spirite.loadBitmap(mIcon_watermelon);
                spirite.setmType(cakeId);
                //t_num=randNum;
                break;
            default:
        }
        Random r = new Random();
        //随机坐标
        spirite.mCoord.x = width / (35 / 10) + r.nextInt(width / (35 / 10)) - 30;
        spirite.mCoord.y = r.nextInt(100);
        //设置抛物线向下速度
//      spirite.mV.x = 5+r.nextInt(5);
//      spirite.mV.y = -(30 + (r.nextInt(20)+10));
        //添加向上抛
        spirite.mV.y = -(30 + (r.nextInt(20) + 10));
        /*mSpirits.get(0).setmType(mType);*/
        mSpirits.add(spirite);
    }

    /**
     * 画炸弹
     */
    private void drawBoom() {
        Spirite spirite = new Spirite(mContext);
        spirite.loadBitmap(mBoom);
        Random r = new Random();
        spirite.mCoord.x = 50 + r.nextInt(300);
        spirite.mCoord.y = 480;
        spirite.mV.x = 5 + r.nextInt(5);
        spirite.mV.y = -(30 + (r.nextInt(20) + 10));
        /*mSpirits.get(0).setmType(mType);*/
        mBooms.add(spirite);
    }

    //开始和停止背景音乐
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        super.surfaceCreated(holder);
//      mPlayer.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        super.surfaceDestroyed(holder);
//      mPlayer.stop();
//      mSoundPool.release();
    }

    /**
     * 画精灵到画布上
     *
     * @param canvas
     */
    private void drawSpirites(Canvas canvas) {
        for (int i = 0; i < mSpirits.size(); i++) {
            mSpirits.get(i).draw(canvas);
        }
//      for(int i=0;i<mBooms.size();i++){
//          mBooms.get(i).draw(canvas);
//      }
    }

    /**
     * 检查精灵是否还在屏幕内,不在屏幕内则移除
     */
    private void checkSpirites() {
        for (int i = 0; i < mSpirits.size(); i++) {
            if (isSpiriteValidate(i)) {
                mSpirits.remove(i);
                i -= 1;
            }
        }
    }

    //具体检查精灵是否在屏幕内的方法
    private boolean isSpiriteValidate(int i) {
        PointF coord = mSpirits.get(i).mCoord;
        if (coord.x < -mSpirits.get(i).mDimention.x || coord.x > width || coord.y > height) {
            return true;
        }

        return false;
    }

    /**
     * 绘制分数1
     * @param canvas
     */
    private void drawScore(Canvas canvas) {
        canvas.drawText("Score:" + scroe, 50, 50, paintScore);
    }

    /**
     * 初始化切到水果的时候
     */
    private void isHit() {
        synchronized (mTrack) {
            for (int i = 0; i < mTrack.size(); i++) {
                for (int z = 0; z < mSpirits.size(); z++) {
                    if (mTrack.get(i).x > mSpirits.get(z).mCoord.x && mTrack.get(i).x < mSpirits.get(z).mCoord.x + mSpirits.get(z).mDimention.x) {
                        if (mTrack.get(i).y > mSpirits.get(z).mCoord.y && mTrack.get(i).y < mSpirits.get(z).mCoord.y + mSpirits.get(z).mDimention.y) {
                            switch (mSpirits.get(z).getmType()) {
                                case R.drawable.icon_orange:
                                    initCutCake(mIcon_orange1, mIcon_orange2, z);
                                    Log.e("m", "icon_orange");
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_pineapple:
                                    Log.e("m", "icon_pineapple");
                                    initCutCake(mIcon_pineapple2, mIcon_pineapple1, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_banana:
                                    Log.e("m", "icon_banana");
                                    initCutCake(mIcon_banana2, mIcon_banana1, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_lemon:
                                    Log.e("m", "icon_lemon");
                                    initCutCake(mIcon_lemon1, mIcon_lemon2, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_mango:
                                    Log.e("m", "icon_mango");
                                    initCutCake(mIcon_mango1, mIcon_mango2, z);
                                    scroe += 1;
                                    break;
                                case R.drawable.icon_watermelon:
                                    Log.e("m", "icon_watermelon");
                                    initCutCake(mIcon_watermelon2, mIcon_watermelon1, z);
                                    scroe += 1;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 切到炸弹的时候
     */
    private void isHitBomb() {
        synchronized (mTrack) {
            for (int i = 0; i < mTrack.size(); i++) {
                for (int z = 0; z < mBooms.size(); z++) {
                    if (mTrack.get(i).x > mBooms.get(z).mCoord.x && mTrack.get(i).x < mBooms.get(z).mCoord.x + mBooms.get(z).mDimention.x) {
                        if (mTrack.get(i).y > mBooms.get(z).mCoord.y && mTrack.get(i).y < mBooms.get(z).mCoord.y + mBooms.get(z).mDimention.y) {
                            if (scroe >= 10) {
                                scroe -= 10;
                            } else {
                                scroe = 0;
                            }
                            mBooms.remove(z);
                            mSpirits.removeAll(mSpirits);
                        }
                    }
                }
            }
        }
    }

    /**
     * 切到水果后加载2个图片
     *
     * @param bitmap1
     * @param bitmap2
     * @param z
     */
    private void initCutCake(Bitmap bitmap1, Bitmap bitmap2, int z) {
        Spirite spirite_left = new Spirite(mContext);
        Spirite spirite_right = new Spirite(mContext);
        spirite_left.loadBitmap(bitmap1);
        spirite_left.mCoord.x = mSpirits.get(z).mCoord.x + 60;
        spirite_left.mCoord.y = mSpirits.get(z).mCoord.y;
        mSpirits.add(spirite_left);
        spirite_right.loadBitmap(bitmap2);
        spirite_right.mCoord.x = mSpirits.get(z).mCoord.x - 60;
        spirite_right.mCoord.y = mSpirits.get(z).mCoord.y;
        mSpirits.add(spirite_right);
        mSpirits.remove(z);
    }


    /**
     * 画刀光到画布上,可以扩展
     *
     * @param canvas
     */
    private void drawBlade(Canvas canvas) {
        synchronized (mTrack) {
            Path path = new Path();
            Float startX, startY;
            Float controlX, controlY;
            Float endX, endY;
            int strokeWidth = 1;
            if (mTrack.size() > 1) {
                endX = mTrack.get(0).x;
                endY = mTrack.get(0).y;
                for (int i = 0; i < mTrack.size() - 1; i++) {
                    startX = endX;
                    startY = endY;
                    controlX = mTrack.get(i).x;
                    controlY = mTrack.get(i).y;
                    endX = (controlX + mTrack.get(i + 1).x) / 2;
                    endY = (controlY + mTrack.get(i + 1).y) / 2;
                    path.moveTo(startX, startY);
                    path.quadTo(controlX, controlY, endX, endY);
                    paintBlade.setColor(mBladeColor);
                    paintBlade.setStrokeWidth(strokeWidth++);
                    canvas.drawPath(path, paintBlade);
                    path.reset();
                }
                startX = endX;
                startY = endY;
                endX = mTrack.get(mTrack.size() - 1).x;
                endY = mTrack.get(mTrack.size() - 1).y;
                path.moveTo(startX, startY);
                path.lineTo(endX, endY);
                paintBlade.setStrokeWidth(strokeWidth++);
                paintBlade.setColor(mBladeColor);
                canvas.drawPath(path, paintBlade);
                mTrack.remove(0);
            }
        }
    }

    /**
     * 倒计时,右上角时间和页面判断跳转
     *
     * @param canvas
     */
    private void drawTime(Canvas canvas) {
        if (System.currentTimeMillis() - mTimeCount > 1000) {
            mTimeCount = System.currentTimeMillis();
            count--;
            if (count == 0) {
                isOpen = false;
//              Intent intent = new Intent(mContext, GameStopActivity.class);
//              intent.putExtra("Score", ""+ scroe);
//              mContext.startActivity(intent);
            } else {

            }
        }
        if (count <= 0) {
            canvas.drawText("Time:" + 0, width - 250, 130, timePaint);
        } else {
            canvas.drawText("Time:" + count, width - 250, 120, timePaint);
        }

    }

    /**
     * 屏幕点击事件的响应方法
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            handleActionDown(event);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            handleActionMove(event);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            handleActionUp();
        }
        return true;
    }

    //手指按下的响应方法
    private void handleActionDown(MotionEvent event) {
        PointF point = new PointF(event.getX(), event.getY());
        synchronized (mTrack) {
            if (mTrack.size() >= POINT_LIMIT) {
                mTrack.remove(0);
            }
            mTrack.add(point);
        }
    }

    //手指拖动的响应方法
    private void handleActionMove(MotionEvent event) {
        PointF point = new PointF(event.getX(), event.getY());
        synchronized (mTrack) {
            if (mTrack.size() >= POINT_LIMIT) {
                mTrack.remove(0);
            }
            mTrack.add(point);
        }
    }

    //手指抬起的响应方法
    private void handleActionUp() {
        synchronized (mTrack) {
            mTrack.clear();
        }
    }

    /**
     * 根据resId加载图片
     *
     * @param resId
     * @return
     */
    private Bitmap loadImageByResId(int resId) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;
        return BitmapFactory.decodeResource(getResources(), resId);
    }


    /**
     * 绘制背景
     */
    private void drawBg(Canvas canvas) {
        //初始化图片
        canvas.drawBitmap(mBg, null, mGamePanelRect, null);
    }

    /**
     * 初始化图片
     */
    private void initBitmaps() {
        //背景
        mBg = loadImageByResId(R.drawable.icon_fruit_bg1);
        //切掉后水果图片
        mIcon_orange1 = loadImageByResId(R.drawable.icon_orange1);
        mIcon_orange2 = loadImageByResId(R.drawable.icon_orange2);
        mIcon_pineapple2 = loadImageByResId(R.drawable.icon_pineapple2);
        mIcon_pineapple1 = loadImageByResId(R.drawable.icon_pineapple1);
        mIcon_banana1 = loadImageByResId(R.drawable.icon_banana1);
        mIcon_banana2 = loadImageByResId(R.drawable.icon_banana2);
        mIcon_lemon2 = loadImageByResId(R.drawable.icon_lemon2);
        mIcon_lemon1 = loadImageByResId(R.drawable.icon_lemon1);
        mIcon_mango1 = loadImageByResId(R.drawable.icon_mango1);
        mIcon_mango2 = loadImageByResId(R.drawable.icon_mango2);
        mIcon_orange = loadImageByResId(R.drawable.icon_orange);
        mIcon_pineapple = loadImageByResId(R.drawable.icon_pineapple);
        mIcon_banana = loadImageByResId(R.drawable.icon_banana);
        mIcon_lemon = loadImageByResId(R.drawable.icon_lemon);
        mIcon_mango = loadImageByResId(R.drawable.icon_mango);
        mBoom = loadImageByResId(R.drawable.boom);
        mIcon_watermelon = loadImageByResId(R.drawable.icon_watermelon);
        mIcon_watermelon1 = loadImageByResId(R.drawable.icon_watermelon1);
        mIcon_watermelon2 = loadImageByResId(R.drawable.icon_watermelon2);
        mIcon_fruit_all = loadImageByResId(R.drawable.icon_fruit_all);
        mNumBitmap = new Bitmap[mNums.length];
        for (int i = 0; i < mNumBitmap.length; i++) {
            mNumBitmap[i] = loadImageByResId(mNums[i]);
        }
    }

    /**
     * 绘制分数2
     */
    @SuppressLint("WrongConstant")
    private void drawGrades(Canvas canvas) {
        String grade = scroe + "";
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
//        canvas.translate(width / 2 - grade.length() * mSingleGradeWidth / 2,
//                1f / 8 * height);
        canvas.translate(mIcon_fruit_all.getWidth() / 2 - 40, mIcon_fruit_all.getHeight() + 50);
        // 一个一个地画一个数字
        for (int i = 0; i < grade.length(); i++) {
            String numStr = grade.substring(i, i + 1);
            int num = Integer.valueOf(numStr);
            canvas.drawBitmap(mNumBitmap[num], null, mSingleNumRectF, null);
            canvas.translate(mSingleGradeWidth, 0);
        }
        canvas.restore();
    }
}

到这里了可能会看得比较懵逼,但是我觉得把demo跑起来,根据思路来结合代码来研究会理解得比较快。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/u013933720/article/details/80207883
今日推荐