第二十六节 实现旋转方块

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

    想到我开发的第一版俄罗斯方块,处理旋转的代码也是非常粗暴,就是所有方块的旋转都单独写一段代码来处理,而不像现在的,使用一个通用的算法就搞定所有方块的旋转。

    01.旋转图形算法

    最出名的就是矩阵旋转,看了下介绍和实现流程后,果断放弃了,我相信绝对有超级简单的几行代码就能搞定方块旋转的算法。毕竟我只是旋转90度,根本用不到矩阵里面的各种角度计算。然后,我就寻找到了一段旋转数组的代码,经过几个小时的探索后,成功敲出了属于我这个项目的旋转方块代码:

    // 旋转方块
    void RotateBlock()
    {
        // 获取方块宽
        int blockWidth = _blockLayer.Size._width;
        // 存储旋转后的方块数据
        List<MyPoint> rotatedBlockData = new List<MyPoint>();
        // 开始旋转
        foreach (var item in _blockLayer.ViewData)
        {
            MyPoint rotated = new MyPoint();
            rotated._list = item._line;
            rotated._line = blockWidth - item._list - 1;
            rotatedBlockData.Add(rotated);
        }
        // 替换成旋转后的方块数据
        _blockLayer.ViewData = rotatedBlockData;
    
        _screenMain.RefreshScreen();
    }
    

    添加按键处理代码:

    // 按键 - 上方向键
    if (Input.GetKeyDown(KeyCode.UpArrow))
    {
        // 立即旋转一次
        RotateBlock();
        InvokeRepeating("RotateBlock", 0.2f, 0.2f);
    }
    if (Input.GetKeyUp(KeyCode.UpArrow))
    {
        CancelInvoke("RotateBlock");
    }
    

    不出意外的话,你可以成功看到方块的旋转效果。顺便提一下,我的方块旋转后都是停靠在左下角的,就是说,旋转后的图形,坐标是没有任何变化的(为了说明这个问题,我打了很多字,后来感觉还不如用图片解释方便):



    如图所示,左侧的是我目前的旋转方式,旋转完成后,方块依然是以左下角对齐的。而右侧的旋转方式会导致方块的纵坐标下降。
    之所以我使用左侧的方式是因为:屏幕本来就很小,如果因旋转而导致方块被迫下降的话,感觉对玩家不公平,当然,你可以旋转完成之后调整纵坐标,这些都是很灵活的修改的。我主要目的还是为了说明我是如何旋转方块的。

    02.旋转算法原理

    其实上面代码中,核心代码就是那两行调整坐标的代码:

    rotated._list = item._line;
    rotated._line = blockWidth - item._list - 1;
    

    我觉得有必要来解释下转换的原理。



    第一行代码是计算旋转之后的列号。如上图所示,旋转后的方块(右侧)的第一列(从左往右数)就是旋转前的方块(左侧)的第一行(从下往上数),第二列就是旋转前的方块的第二行。



    第二行代码是计算旋转之后的行号。如上图所示,第一、二、三列分别转换为第三、二、一行。可能第一眼看过去,不知道如何找到一个通用的公式来转换,其实很简单:红色点与左侧的偏移为0,旋转后,红色点与顶端的偏移为0;黄色点与左侧的偏移为1,旋转后与顶端的偏移为1;绿色点与左侧偏移为2,旋转后与顶端偏移为2。旋转之后,方块的宽则变成高度,左侧方块的列号 = 方块的宽 - 列偏移,旋转之后,行号 = 方块高 - 行偏移,因为方块高与旋转前的方块宽一样,行偏移与旋转前的列偏移一样,所以公式为:

    旋转后的行号 = 方块的宽度 - 列偏移距离

    红色点列偏移为0,旋转后,与顶端的偏移就是3 - 0 = 3
    黄色点列偏移为1,旋转后,与顶端的偏移就是3 - 1 = 2
    绿色点列偏移为2,旋转后,与顶端的偏移就是3 - 2 = 1
    当然,这是错误的结果,因为下标是从0开始,所以最终还要再减1,那么最终公式就是:

    旋转后的行号 = 方块的宽度 - 列偏移距离 - 1

    怎么样,是不是很简单。好了,下一节,来处理旋转的碰撞。

    代码链接:https://pan.baidu.com/s/1XJgOGIbBGIeD3_cDwhfUoQ
    提取码:uloj

    相关文章

      网友评论

        本文标题:第二十六节 实现旋转方块

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