第四十一节 重玩游戏

作者: 安静的程序员 | 来源:发表于2019-06-26 07:24 被阅读0次

    加上重玩之后,游戏流程就完整了。我们抓紧开始吧。

    01.判断游戏失败

    我目前的设定是:方块下落完成后,扫描最顶端的一行,只要发现该行上有一个点,就认定游戏失败。
    下面是代码:

    // 检测游戏失败
    bool CheckGameOver()
    {
        for (int list = 0; list < 10; list++)
        {
            if (_defaultLayer.IsCanSee(new MyPoint(19, list)))
            {
                // 游戏失败
                return true;
            }
        }
    
        return false;
    }
    
    02.如何清屏

    记得砖块机上游戏失败后是如何清屏的吗?先从最底端向上一行一行填充,再从顶端向下一行一行消除,直到全部清除。
    为了实现这个动画,我们先添加两个方法,一个填充行,一个消除行:

    // 清屏 - 填充行
    void FillLineForClearScreen()
    {
    }
    // 清屏 - 消除行
    void ClearLineForClearScreen()
    {
    }
    

    这两个方法使用定时器驱动。
    关于什么时候检测游戏失败,我的设定是:方块固定之后,判断是否游戏失败。
    如果失败了,就启动定时器执行FillLineForClearScreen(),为了依次处理每一行,需要一个成员变量来记录已经处理到哪一行了,本次就接着上一次继续处理,如果发现所有行都填满了,那就停止执行填充行,然后启动定时器执行消除行。所有行都消除后,重置游戏数据(分数、关卡)后,开始执行核心逻辑。

    03.实现清屏

    先添加一个成员变量并初始化为0:

    int _lineOfClearScreen;     // 清屏 - 正在处理的行号
    

    在核心逻辑中驱动清屏:

    // 检测游戏失败
    if (CheckGameOver())
    {
        InvokeRepeating("FillLineForClearScreen", 0, 0.02f);
        return;
    }
    

    实现填充与消除两个方法:

    // 清屏 - 填充行
    void FillLineForClearScreen()
    {
        // 填充当前行
        List<MyPoint> line = new List<MyPoint>();
        for (int list = 0; list < 10; list++)
        {
            line.Add(new MyPoint(_lineOfClearScreen, list));
        }
        _defaultLayer.AddViewData(line);
        _screenMainScript.RefreshScreen();
    
        // 判断是否处理到顶行
        if (_lineOfClearScreen < 19)
        {
            _lineOfClearScreen++;
        }
        else
        {
            // 如果已经处理到顶行,则开始消除行
            CancelInvoke("FillLineForClearScreen");
            InvokeRepeating("ClearLineForClearScreen", 0.02f, 0.02f);
        }
    }
    
    // 清屏 - 消除行
    void ClearLineForClearScreen()
    {
        // 消除当前行
        for (int list = 0; list < 10; list++)
        {
            _defaultLayer.RemovePoint(_lineOfClearScreen, list);
        }
        _screenMainScript.RefreshScreen();
    
        // 判断是否已处理到底端
        if (_lineOfClearScreen > 0)
        {
            _lineOfClearScreen--;
        }
        else
        {
            CancelInvoke("ClearLineForClearScreen");
            // 重置分数
            _currentScore = 0;
            _currentScoreScript.SetScore(_currentScore);
            // 重置关卡
            _level = 1;
            _levelScript.SetLevel(0, _level);
            // 清空所有屏幕
            _blockLayer.ViewData.Clear();
            _defaultLayer.ViewData.Clear();
            _screenAttachedScript.GetLayer("DefaultLayer").ViewData.Clear();
            // 添加初始方块
            _blockLayer.Point = new MyPoint(20, 4);
            EBlockType blockType = BlockCreator.GetInstance().RandomBlockType();
            _blockLayer.ViewData = BlockCreator.GetInstance().CreateBlock(blockType);
            // 生成下一个方块
            _nextBlockType = BlockCreator.GetInstance().RandomBlockType();
            _screenAttachedScript.GetLayer("DefaultLayer").ViewData = BlockCrea-tor.GetInstance().CreateBlock(_nextBlockType);
            // 刷新屏幕
            _screenMainScript.RefreshScreen();
            _screenAttachedScript.RefreshScreen();
    
            // 启动GameCore
            CancelInvoke("GameCore");
            InvokeRepeating("GameCore", 1 - (_level - 1) * 0.1f, 1 - (_level - 1) * 0.1f);
        }
    }
    
    04.处理重复点

    经过测试发现:在清屏的第二步(消除行)中,会有重置游戏前残留的方块数据:



    这主要是因为,在添加显示数据至固定方块层时,添加了重复的点,我们需要修改图层类的添加显示数据方法,把重复的剔除掉:

    // 添加显示数据
    public void AddViewData(List<MyPoint> points)
    {
        foreach (var point in points)
        {
            if (ViewData.Contains(point)) continue;
            ViewData.Add(point);
        }
    }
    

    添加一行判断元素是否已存在的代码,就可以剔除重复了,下面是测试效果:


    代码链接:https://pan.baidu.com/s/1e5AdR3bu9fSPejguEkB0kg
    提取码:nmzt

    相关文章

      网友评论

        本文标题:第四十一节 重玩游戏

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