ssRender+Lua开发小游戏<俄罗斯方块>(三)

引言:

本篇文章是本人使用ssRender引擎,配合使用Lua脚本语言,开发一个俄罗斯方块小游戏的案例合集的第三篇文章(也是最后一篇文章)。本篇文章将会详细介绍如下功能:详细介绍方块的消除逻辑、得分功能、游戏结束检测、以及其他功能的细节处理等等。

本合集的第一篇介绍了开发初期的构想、前端界面的布局、各个按钮的功能和(界面渲染、方块初始化、左移、右移等功能的实现。

本合集的第二篇详细介绍了方块的下落检测、方块的下落、显示下一个方块、方块的旋转逻辑等。

一:方块满行消除功能实现

本小章主要介绍俄罗斯方块下落结束后,插入主Bg表时进行满行删除的功能实现


(一)满行消除

function Remove()
    local temp = {}
    for i = 20, 1, -1 do
        sum = 0
        for j = 1, 10 do
            if bg[i][j] ==1 then sum = sum + 1 end
        end

        if sum == 10 then
            table.insert(temp,i)------当前的行数加到temp表中
        end
    end
    

    --根据消除的行数更新分数
    

    --将添加到temp表中对应的行数覆盖掉
    if tempLen > 0 then
        for i = 1,#temp do
            ----拷贝当前行以上的所有行 到下一行,第一行没有上一行,所以到2结束
            for j = temp[i] + (i-1), 2, -1 do
            Clone(bg[j-1], bg[j])
            end
            ----清空第一行
            for j = 1, #bg[1] do
                bg[1][j] = 0
            end
        end
    end
    return tempLen
end

此功能的逻辑不难理解,遍历一次主BG表,从下到上,检查每一行的元素是否全为1;若全为1则说明此行满,需要覆盖,将其行数插入到临时待覆盖表temp中;遍历结束,所有待覆盖行数均添加到temp表中。

之后再遍历temp表的长度次,将其所在行数的上方所有BG行对下一行进行覆盖,直到全部覆盖结束。

Tips:此方法的覆盖部分有优化空间,只需遍历一遍BG表即可

具体方法如下:类似于在不改变原有顺序的情况下,对一维数组内部删除某一重复元素的优化算法将二维表看做一维数组,每一行当做一个元素,BG表上均为1的某一行视为重复元素;我们要从下往上遍历这个一维数组(二维表),因为不改变原有的顺序,所以要将上方的行覆盖到下方的行,所以数组头部为二维表的尾行,数组尾部为二维表的首行。这时,需要一个临时变量存储当前需要覆盖的行数跨度(当前遍历的行数每小于temp表的一个元素时,覆盖跨度加一),在遇到满行时,将(当前行数-覆盖的行数跨度)所在的一行,通过Clone方法对行进行覆盖,时间复杂度由O(n³)变为O(n²)。具体实现方式大家可以自行尝试。

此函数将会在当前俄罗斯方块触底后调用

更新Down函数(具体Down函数请见第二篇的方块下落功能实现)

--方块触底
    if CheckGround(currentBlock['curRow'],currentBlock['curColumn']) then
        --插入方块到主BG表中
        InsertBlockToBG()

        --调用方块移除的函数,满行的给移除掉
        Remove()

        --根据主BG表渲染主page
        RenderBG()

        --取消当前的nextBlock
        CancelNextBlock()

        --更新当前的俄罗斯方块(先把next赋值给current, 再重新再生成一个随机的next)
        CopyNextBlock()

        --渲染next方块
        RenderNextBlock()

        --更新分数


    else
            currentBlock['curRow'] = row
            
    end

方块满行消除功能测试:

 

普通消除,与复杂的隔行消除效果均正确,没有显示问题,功能测试通过。

二:方块消除得分功能实现

本小节内容将会对方块满行消除后的得分功能进行实现。


(一)全局变量Score与分数表

-- 分数配置表 消除行数对应所获得的分数
ScoreList = {
    [1] = 10,
    [2] = 30,
    [3] = 60,
    [4] = 100,
}

Score = 0

Score代表总分,初值值为0;ScoreList为分数表,满行消除时记录消除的行数,直接通过行数获取对应的得分即可

(二)添加得分逻辑

需要再上一节中Remove方法中的备注处,对总分Score进行更新;

--根据消除的行数更新分数
    local tempLen = #temp
    if tempLen ~= 0 then
        Score = Score + ScoreList[tempLen]
    end

(三)更新界面的显示分数

--更新得分(满行消除时调用)
function UpdateScore()
    
    local textNode = ssr.getText("Layer0//Score//num")
    textNode:setText(tostring(Score))
end

--清空得分(重新开始时调用)
function ClearScore()
    Score = 0
    local textNode = ssr.getText("Layer0//Score//num")
    textNode:setText(tostring(Score))
end

调用ssRender引擎所封装的接口,获取Text节点,将总分以String的形式传递给界面的Text节点。

此函数需要在下落函数中的--更新分数注解处调用

得分功能效果测试:

如图,消除一行和两行时,分数将会同步更新,消除三行四行时显示同样正确,测试通过。

三:Game Over 检测

本小节内容主要是介绍游戏结束显示效果的实现。

(一)检查Game Over下降阻拦

function CheckGameOver()
    --检查bg第一行,check当前block的正下方bg有无阻拦
    local row = currentBlock['curRow']
    if row >= 1 then 
        return false
    end

    local column = currentBlock['curColumn']
    local block = currentBlock['block']

    if row < 1 then
        for i = #block, 1, -1 do--从下往上
            for j = 1, #block[i] do--从zuo向you,
                if block[i][j] == 1 then  --每检测到一个格子,就做一次比较
                    --当前的行数+有方块的行数 == 有方块的行数的下一行的行数
                    if row + i > 1 then
                        ------行是下一行,列是本一列
                        if bg[row + i ][column + j -1] == 1 then
                            return true
                        end

                    end
                end

            end
        end
    end

end

本函数其实和落地检测CheckGround基本一致,检测到阻拦即返回True,其他的逻辑判断写在了Down函数中。

(二)Game Over检测与同步

--Down的时候先检查是否GameOver  --即当前方块的当前行能否落到第一行,如果落不到,则说明满了,就GameOver
    if currentBlock['curRow'] < 1 then
        if CheckGameOver() then
            print("Game Over")
            
            local setPropertyTable = {}
            setPropertyTable["LayerStartOver//stopPage//Visible"] = "1"
	        ssr.setNodeProperty(setPropertyTable)
        end
        
    end

执行方块下落函数Down方法的一开始就要判断,当当前行数小于1时需要判断:当前方块下方有无阻拦,若无阻拦则当前方块下降一行,直到当前行数>=1;若当前方块下方有阻拦,则说明方块无法下降,不能全部显示,代表游戏结束。

游戏结束的后续处理就是将游戏结束界面的Visible弹出,遮挡住游戏界面。

(三)工具端Game Over处理

  

如图,工具端的Game Over界面如图

Text0与分数进行绑定:

当前界面额外添加了一个事件:界面显示时,停止Down函数的Timer调用控制,实现停止下落的效果。

而重新开始的按钮添加了一个点击事件:点击按钮,当前界面消失,游戏界面显示,并且调用了重新开始的Lua脚本ReStart。

ReStart脚本如下:初始化Bg,重新渲染BG,清空分数,重新生成方块(包括当前方块与下一方块的生成)

游戏结束功能效果测试:

方块下落正常,列满判断正常,最终的GameOver效果显示正常,符合GameOver效果预期,测试通过。

四:其他功能&优化

(一)暂停功能实现:

暂停功能,点击如图暂停按钮,显示暂停界面,Down的Timer控制停止,类比Game Over界面效果的实现。

                     

(二)优化

通过Gif图片可见,方块降落和左右横移时会出现闪烁的效果,是因为:方法执行的前期,对当前方块取消渲染,再进行其他逻辑处理(例如下降、横移、旋转等),再重新渲染逻辑处理过后的当前方块,在取消与重新渲染的过程中就会产生消失->出现->消失->出现的闪烁效果。

解决办法:将渲染和取消渲染合并为一个函数,对当前状态的方块和下一状态的方块在图形上进行对比,对重合的部分不做处理,对不重合的部分进行更改即可消除闪烁。

(即对当前的Block和下一状态的Block二维表取交集,交集部分不做改变,改变非交集的部分)

更多的功能大家可以试着自己实现一下,比如:历史得分记录、得分排行榜、关卡设置(不同关卡有不同的降落速度、时间限制、得分要求等)、或者尝试优化部分算法,感兴趣的伙伴可以在下方留言。最后附上时间稍长一些的最终实机演示:

小结:本篇文章是使用ssRender引擎与Lua脚本开发俄罗斯方块小游戏的收官之战!之后还会继续分享其他学习心得!感兴趣的话,留个关注再走吧~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值