手把手教你Unity开发俄罗斯方块

第四十一节 重玩游戏

2019-06-26  本文已影响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

上一篇 下一篇

猜你喜欢

热点阅读