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

第三十节 添加消除动画

2019-06-25  本文已影响0人  安静的程序员

其实也不是什么高深的动画,就是那种加个定时器,一个一个的消除像素点而已。

本节需要做两段动画:
01.消除动画
02.填补消除后的空行动画

01.消除的动画

目前消除是没有动画的,所有点会在一瞬间消除,我想要的动画是每次只消除一个点,用定时器控制,比如每0.1秒消除一个点,这样看起来就会给人连贯的感觉,而不是突然之间就完成了。

01.01 实现流程

其中,消除点是一个方法,由定时器反复调用。

01.02 添加成员,并收集需要消除的点
List<MyPoint> _needClearPoints;     // 存储需要消除的点

在InitGame()中初始化:

_needClearPoints = new List<MyPoint>();

在GameCore()中收集需要消除的点:

// 如有需要消除的行
if (_needClearLines.Count > 0)
{
    // 收集需要消除的点
    foreach (var line in _needClearLines)
    {
        for (int list = 0; list < 10; list++)
        {
            _needClearPoints.Add(new MyPoint(line, list));
        }
    }
...
01.03 添加消除点方法
// 消除一个点
void ClearOnePoint()
{
    // 如果有未处理完的点
    if (_needClearPoints.Count > 0)
    {
        // 取出第一个点
        MyPoint point = _needClearPoints[0];
        // 移除该点
        _defaultLayer.RemovePoint(point._line, point._list);
        // 删除处理完的点
        _needClearPoints.Remove(point);

        _screenMain.RefreshScreen();
    }
    else
    {
        // 先停止定时器
        CancelInvoke("ClearOnePoint");

        // 填补消除后的行
        FillUpClearedLine();
        // 创建新方块
        CreateNewBlock();

        // 启动核心逻辑
        InvokeRepeating("GameCore", 0, 1);
    }
}
01.04 修改核心逻辑
// 如有需要消除的行
if (_needClearLines.Count > 0)
{
    // 停止核心逻辑,进入消除阶段
    CancelInvoke("GameCore");

    // 收集需要消除的点
    foreach (var line in _needClearLines)
    {
        for (int list = 0; list < 10; list++)
        {
            _needClearPoints.Add(new MyPoint(line, list));
        }
    }

    // “消除点”启动
    InvokeRepeating("ClearOnePoint", 0, 0.1f);
}
else
{
    // 创建新方块
    CreateNewBlock();
}

修改完之后,运行游戏。如果没有问题,当有满行的时候,就会一个一个得消除点了。

02.填补空行的动画

同样,我们来添加一个方法:填补单行

// 填补一行被消除的
void FillUpOneLineByCleared()
{
    if (_needClearLines.Count > 0)
    {
        int line = _needClearLines[_needClearLines.Count - 1];
        List<MyPoint> fixedPoints = _defaultLayer.ViewData;
        for (int index = 0; index < fixedPoints.Count; index++)
        {
            // 将高于当前行的点下移一格
            if (fixedPoints[index]._line > line)
            {
                fixedPoints[index] = new MyPoint(fixedPoints[index]._line - 1, fixedPoints[index]._list);
            }
        }
        _needClearLines.RemoveAt(_needClearLines.Count - 1);

        _screenMain.RefreshScreen();
    }
    else
    {
        // 先停止定时器
        CancelInvoke("FillUpOneLineByCleared");

        // 创建新方块
        CreateNewBlock();
        // 启动核心逻辑
        InvokeRepeating("GameCore", 0, 1);
    }
}

修改ClearOnePoint()中的else块:

else
{
    // 先停止定时器
    CancelInvoke("ClearOnePoint");
    // “填补单行”启动
    InvokeRepeating("FillUpOneLineByCleared", 0, 0.1f);
}

再次运行游戏,你可以看到消除和填补都有了一个简单的过渡,至少看起来不像上一节那么生硬了。你可以把速度改快一点,看起来更流畅。
然后,上一节的两个方法已经没有作用了,删除即可:

关于游戏核心逻辑部分,除了重玩之外,几乎都完成了,但是重玩功能关系到许多数据的重置,现在还有许多核心逻辑外的东西没写,所以重玩放到后面再写。
接下来,我们需要好好整理一下代码和思路,准备下一阶段的开发。

代码链接:https://pan.baidu.com/s/10C0__VA0aadb6AF3Uli6zg
提取码:1nca

上一篇 下一篇

猜你喜欢

热点阅读