移动互联网开发教学案例学习-2

2021SC@SDUSC


目录

案例——Flappybird

一、代码思路分析

Gamebird类 

重写onTouchEvent()方法

logic()方法

initPos()方法

checkGameOver()方法


案例——Flappybird

一、代码思路分析

Gamebird类 

(1)首先需要绘制背景、鸟、管道、地板。这里需要做的就是用Bird、Floor、Pipe类中的相关方法实现。具体步骤在上一个博客中分析过。

(2)游戏状态变量的设置和记录:WAITING,RUNNING,OVER;

//游戏状态枚举变量
    private enum GameStatus
    {
        WAITING, RUNNING, OVER
    }
    //记录游戏的状态*/
    private GameStatus gameStatus = GameStatus.WAITING;

(3)声音

//声音
    private AudioRecordDemo audioRecordDemo=new AudioRecordDemo();

(4)在游戏过程中,鸟的触摸上升、自动下落 ,管道的移动、移除。

相关变量:

//触摸上升的距离,因为是上升,所以为负值
    private static final int TOUCH_UP_SIZE = -16;
    //将上升的距离转化为px;这里多存储一个变量,变量在run中计算
    private final int mBirdUPDirs = Util.dp2px(getContext(), TOUCH_UP_SIZE);
    //用于计算的变量
    private int mTmpBirdDis;
    // 鸟自动下落的距离
    private final int mAutoDownSpeed = Util.dp2px(getContext(), 2);
    // 记录需要移除的管道
    private List<Pipe> mNeedRemovePipe=new ArrayList<Pipe>();
    private int mRemovedPipe = 0;
    // 两个管道间的距离
    private final int PIPE_DIS_BETWEEN_TWO=Util.dp2px(getContext(),100);
    //管道移动的距离
    private int mTmpMoveDistance;

重写onTouchEvent()方法

在触屏时如果游戏状态是WAITING的话,说明用户还没有正式开始游戏,相当于处于准备阶段,这个时候管道是不移动的,触屏后改为RUNNING状态,管道、背景、地板开始移动,声音加载。

如果触屏时的状态时RUNNING,则会让鸟的高度升高,升高的值在上面变量中声明。

 @Override
    public boolean onTouchEvent(MotionEvent event){
        int action=event.getAction();

        if(action==MotionEvent.ACTION_DOWN){
            switch (gameStatus){
                //触屏时如果是WAITTING转为RUNNING
                case WAITING:
                    //声音开始加载
                    gameStatus= GameStatus.RUNNING;
                    audioRecordDemo=new AudioRecordDemo();
                    audioRecordDemo.getNoiseLevel();
                    break;
                //触屏时如果是RUNNING让鸟的高度升高
                case RUNNING:
                    mTmpBirdDis=mBirdUPDirs;
                    break;
            }
        }
        return true;
    }

logic()方法

是用于一些逻辑上的计算

1)在RUNNING状态下:

1>管道在移出屏幕时需要被移除,操作是将该管道加入到移出管道的List中, 同时让移除的管道数+1;

2>当管道移动距离>=管道间距离的时候,生成一个新管道(实例化新管道,并将其加入到管道List中);

3>鸟的高度处理,并检查时候结束游戏。

2)在OVER状态下:

1>如果鸟在空中,就让它掉下来,加上它自动下落的距离;

2>否则更改游戏状态为WAITING。

    private void logic(){
        switch (gameStatus){
            case RUNNING:

                for(Pipe pipe:mPipes){
                    //当管道移出屏幕时,移除管道
                    if(pipe.getX()<-mPipeWidth){
                        mNeedRemovePipe.add(pipe);
                        mRemovedPipe++;
                        continue;
                    }
                    //管道移动
                    pipe.setX(pipe.getX()-mSpeed);
                }
                //现存管道中出去可以删除的管道
                mPipes.removeAll(mNeedRemovePipe);
                Log.e("TAG","现存管道数量"+mPipes.size());

                //管道移动的距离
                mTmpMoveDistance+=mSpeed;

                //生成一个管道
                if(mTmpMoveDistance>=PIPE_DIS_BETWEEN_TWO){
                    Pipe pipe=new Pipe(getContext(),getWidth(),getHeight(),
                            mPipeTop,mPipeBottom);
                    mPipes.add(pipe);
                    mTmpMoveDistance=0;
                }
                //在这里处理鸟的高度
                int volume=audioRecordDemo.getMvolume();
//                mTmpBirdDis+=mAutoDownSpeed;
                bird.setY(bird.getY()-(volume-40)+mTmpBirdDis);
                Log.e("TAG",volume+"");
                //默认下落,点击时瞬间上升
//                mTmpBirdDis+=mAutoDownSpeed;
//                bird.setY(bird.getY()+mTmpBirdDis);
                checkGameOver();
                break;
            case OVER:
                //鸟落下
                //如果鸟在空中,让他掉下来
                if (bird.getY() < mHeight)
                {
                    mTmpBirdDis += mAutoDownSpeed;
                    bird.setY(bird.getY() + mTmpBirdDis);
                } else
                {
                    gameStatus = GameStatus.WAITING;
                    initPos();
                }
                break;
            default:
                break;
        }
    }

(5)用于重置鸟的位置等数据:

initPos()方法

  private void initPos()
    {
        mPipes.clear();
        mNeedRemovePipe.clear();
        //重置鸟的位置
        bird.setY(mHeight * 1 / 3);
        //重置下落速度
        mTmpBirdDis = 0;
        mTmpMoveDistance = 0 ;
        mRemovedPipe=0;
        audioRecordDemo=null;

    }

(6)用于检验游戏是否结束:

checkGameOver()方法

如果鸟触碰到地板,或者撞到管道,游戏均结束;顺利穿过则游戏继续。

碰到地板:bird.getY()>mHeight;

撞到管道:wall.touchBird(bird),用了Pipe类中的touchBird()方法;

顺利通过:wall.getX()+mPipeWidth < bird.getX();

 private void checkGameOver()
    {

        // 如果触碰地板,gg
        if (bird.getY() > mHeight)
        {
            gameStatus = GameStatus.OVER;
        }
        // 如果撞到管道
        for (Pipe wall : mPipes)
        {
            //已经穿过的
            if (wall.getX() + mPipeWidth < bird.getX())
            {
                continue;
            }
            if (wall.touchBird(bird))
            {
                gameStatus = GameStatus.OVER;
                break;
            }
        }
    }

(7)重写surfaceCreated(SurfaceHolder holder)方法,开启线程;

        重写   surfaceDestoryed(SurfaceHolder holder)方法通知关闭线程;

        run()方法控制线程sleep的时间

(8) draw()方法调用drawBg(),drawBird(),drawPipes()方法来绘制背景、鸟、管道;

        重写onSizeChanged(int w,int h,int oldw,int oldh)方法用于改变尺寸大小。

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh){
        super.onSizeChanged(w, h, oldw, oldh);

        mWidth = w;
        mHeight = h;
        mGamePanelRect.set(0, 0, w, h);
        // 初始化mBird
        bird = new Bird(getContext(), mWidth, mHeight, mBird_bitmap);
        // 初始化速度
        mSpeed = Util.dp2px(getContext(), 2);
        // 初始化管道范围
        mPipeRect = new RectF(0, 0, mPipeWidth, mHeight);
//        Pipe pipe = new Pipe(getContext(), w, h, mPipeTop, mPipeBottom);
//        mPipes.add(pipe);
    }

管道和鸟的运行演示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值