手势操作的Snake游戏_游戏视图分析之SnakeView

手势操作的Snake游戏_游戏视图分析之SnakeView

本文是snake on a phone 贪吃蛇游戏的项目解析系列文章之4,基于google sample code 改编而成项目链接接上一篇文章手势操作的Snake游戏_游戏视图分析之TileView

SnakeView继承自TileView,在TileView的基础上添加了具体游戏元素。涉及代码较多,我们去繁从简,跟着大体框架去剖析其流程。通过上篇文章我们知道,TileView有一组网格状态集合mTileGrid并提供了setTile的public方法去设置状态,那么子类SnakeView显然正是通过这个状态去表示当前游戏布局详情的。

新添加的主要成员

如下这些参数表示游戏的状态,作为setMode去设置游戏状态的参数。

private int mMode = READY;
public static final int PAUSE = 0;
public static final int READY = 1;
public static final int RUNNING = 2;
public static final int LOSE = 3;

如下是图片编号表示,作为视图元素中的红色方格、黄色方格、绿色方格。
会有对应的drawable资源表示,这个int数值用在TileView中的mTileArray[]数组中,分别对应1~3号,0号是空的,表示黑色的区域,绿色是外围的墙壁。红色表示蛇身,换色表示蛇头和苹果。

private static final int RED_STAR = 1;
private static final int YELLOW_STAR = 2;
private static final int GREEN_STAR = 3;

主体函数

SnakeView构造函数,layout加载的时候会调用,其中initSnakeView做了视图初始化的主要工作。

public SnakeView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initSnakeView();
}

initSnakeView加载了视图元素,如我们上面所说的图片资源,其中初始化gestureDetector的部分我们前面讲述过,属于我们改进的手势操作,这里不再讲述。

private void initSnakeView() {
    setFocusable(true);

    Resources r = this.getContext().getResources();

    resetTiles(4);//长度为4的数组 0黑色 1~3对应红黄绿
    loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
    loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
    loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));

    //初始化gestureDetector
    gestureDetector = new GestureDetector(getContext(), this);
}

当然SnakeView初始化的时候会先去初始化父类TileView,对应相关状态集合的初始化工作也都同时完成。

视图刷新的动态实现

前面数据已经初始化,那么游戏要跑起来,界面要不断刷新,程序通过handler和update函数的交互来实现。

首先看一下handler实现,handler收到消息后会update状态并调用invalidate通知系统需要再次绘制界面了,于是父类的onDraw就会被调用。

class RefreshHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        SnakeView.this.update();//更新网格状态
        SnakeView.this.invalidate();//绘制新界面
    }

    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
};

这是update函数的细节,如果当前是running的状态,则更新数据并向handler发送消息,告诉延迟一段时间再次执行更新操作。

public void update() {
    if (mMode == RUNNING) {
        long now = System.currentTimeMillis();

        if (now - mLastMove > mMoveDelay) {
            clearTiles();//所有网格归零
            updateWalls();//赋值墙壁 绿色标示
            updateSnake();//更新蛇的坐标
            updateApples();//更新苹果的坐标
            mLastMove = now;//记录最后一次运动时间
        }
        mRedrawHandler.sleep(mMoveDelay);
    }
}

至此应该明白视图变化的流程了,通过update更新状态,并利用mRedrawHandler进行消息传递,延迟一定时间后再次通过handlerMessage处理会再次调用update,于是整个游戏就跑起来了。这里的update函数中的updateSnake和updateApples则会根据当前状态以及运动方向动态地更新网格数据。游戏第一次启动update函数是由事件触发的,也就是我们游戏开始时提示的”press up to start”,是否还记得我们在第一节讲述的onKeyDown事件响应,对于dpad_up类型响应代码如下

        if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
        if (mMode == READY | mMode == LOSE) {
            initNewGame();
            setMode(RUNNING);
            update();
            return (true);
        }

setMode函数用于设置游戏状态标示,这里第一次调用了update函数,于是游运行起来了。
当然我们已经修改可以通过向上滑动来启动游戏。至于updateSnake()是如何变换状态,以及苹果随机生成方法,我们下节讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值