引言:
本篇文章是本人使用ssRender引擎,配合使用Lua脚本语言,开发一个俄罗斯方块小游戏的案例。本篇文章将会详细介绍如下功能:方块的下落检测、方块的下落、显示下一个方块、方块的旋转逻辑等等。
上一篇介绍了开发初期的构想、前端界面的布局、各个按钮的功能和(界面渲染、方块初始化、左移、右移等功能的实现(蓝色字体直达)。
下一篇将会详细介绍方块的消除逻辑、得分功能、游戏结束检测、以及其他功能的细节处理。
大家可以使用其他游戏引擎对此游戏的功能进行扩展!不要拘泥于工具与引擎,功能逻辑实现的思想是共通的!
话不多说,发车!
一:方块下落功能实现
本小章主要介绍俄罗斯方块当前方块下落功能的实现,包括“下落前障碍”的检测,以及方块下落实现。
(一)下落障碍检测
function CheckGround(row,column)
local block = currentBlock['block']
--遍历当前方块的所有节点,
for i = #block, 1, -1 do--从下往上
for j = 1, #block[i] do--从zuo向you,
if block[i][j] == 1 then --每检测到一个格子,就做一次比较
--到底了,就停止
if row + i -1 >= 20 then
return true
end
--当前的行数+有方块的行数 == 有方块的行数的下一行的行数
if row + i > 1 then
----------------------------有问题,需要雕琢,curRow和curColumn具体是是1,1点位置
------行是下一行,列是本一列
if bg[row + i ][column + j -1] == 1 then
return true
end
end
end
end
end
return false
end
此逻辑很简单,就是将当前方块表(currentBlock['block'])从下向上,从左到右依次遍历(如果当前的俄罗斯方块的下方有障碍物时,从下方物块开始检测能更提早结束check函数)。当检测到currentBlock['block']存在方块时,就同时检测主方格bg表,若当前方块的正下方超过第20行,或者检测到正下方有方块存在,则说明当前方格遇到障碍,返回true(表示有障碍);
若遍历完毕,并未发现障碍,则返回false(表示没有障碍)
(二)结束下落插入主表
------当前的currentBlock插入到主表bg中
function InsertBlockToBG()
local row = currentBlock['curRow']
local column = currentBlock['curColumn']
local block = currentBlock['block']
for i = 1, #block do
for j = 1, #block[1] do
if block[i][j] == 1 then
bg[row + i - 1][column + j - 1] = 1
end
end
end
--删除当前的方块信息
currentBlock = {['blockListID'] = 1, ['subID'] = 1, ['curRow'] = 1, ['curColumn'] = 1, ['block'] = {}}
end
首先获取到当前方块的数据,主需要获取当前行列值和当前方块形状即可;遍历当前方块,检测到方格存在,即根据行列值算出当前方格在bg表的位置,当对应bg表位置的值改为“1”即可。再全部插入完毕的时候,清楚当前方块的数据(也可以调用将下一方格复制给当前方格的函数,但是本人在此只是简单的将当前方块清空);此函数在发现“触底”之后调用。
(三)下落功能实现
function Down()
CancelCurrentBlock()
local row = currentBlock['curRow'] + 1
--触底之后操作
if CheckGround(currentBlock['curRow'],currentBlock['curColumn']) then
--当前方块插入到主bg表中
InsertBlockToBG()
--满行检测
--重新渲染主bg表
--取消渲染nextBlock(下一方块)
--nextBlock复制给currentblock
--重新生成nextBlock
--渲染下一方块nextBlock
--更新得分
else
currentBlock['curRow'] = row
end
RenderCurrentBlock()
end
再执行下降函数的一开始,先取消当前方块的渲染,然后再确定方块能否下落,再根据最终的结果重新渲染当前方块!(若未检测到地面,则允许方快下落,即currentBlock['curRow']增加一行)(若检测到地面,则将当前方块插入到主bg表,以及一系列其他操作)
方块下降功能测试
1.在ssRender工具端创建下落按钮
2.再新建一个Lua脚本,命名为Down,双击打开
调用上面编写好的Down方法
3.将下降按钮的click事件触发调用Down脚本
4.点击按钮,检查效果
效果达到预期,接下来我们实现方块旋转的功能
二:方块旋转功能实现(顺时针)
本人实现的旋转方式在上一篇有过简单的介绍,本章内容将会对旋转功能进行详细的实现。
(一)旋转检测
function CanRotateBlock(row,column,rotateID,rotateSubID)
--取得旋转后的方块形状
local block = BlockList[rotateID][rotateSubID]
--检测左右墙体 边缘障碍
for i =1, #block do
for j = 1, #block[1] do
if block[i][j] ==1 then
local newRow = row + i -1 -- == 1 的方块所在的行
local newColumn = column +j -1 -- == 1 的方块所在的列
if newColumn < 1 or newColumn > #bg[1] then
return false
elseif newRow < 1 or newRow > #bg then
return false
elseif bg[newRow][newColumn] == 1 then
return false
end
end
end
end
return true
end
旋转检测函数,参数有当前方块的行数、列数、旋转后的方块在形状表的位置rotateID(形状)、旋转后的方块在旋转表的位置rotateSubID(旋转角度)。
遍历旋转后的方块,检查旋转后的方块行列数是否出界,是否与主表bg固有的方格发生冲突,发现以上任一情况则返回false,表示不能旋转;遍历检查无误后,返回ture,表示能旋转。
(二)旋转实现
function RotaUp()
local blockid = currentBlock['blockListID'] -- 控制方块的形状
local subid = currentBlock['subID'] -- 控制方块地旋转角度 1 2 3 4
local len = #BlockList[blockid]
local nextSubid = subid + 1
if nextSubid == 5 then nextSubid = 1 end
--旋转判定
if CanRotateBlock(currentBlock['curRow'],currentBlock['curColumn'],blockid,nextSubid) == true then
currentBlock['subID'] = nextSubid
currentBlock['block'] = {}
Clone(BlockList[blockid][nextSubid], currentBlock['block'])
end
end
首先获取当前方块的形状(即形状表的位置ID:currentBlock['blockListID'])与旋转角度(即旋转表的ID:currentBlock['subID']);获取到顺时针旋转的下一角度的ID值(nextSubid = subid + 1,一共四种形状);再进行旋转检测,检测通过后改变现在方块的形状ID和对应的具体形状。
此旋转方法不用复杂的找中心点,根据中心点设计复杂的旋转方法(由于中心点可能不是整数,所以设计及实现会比较复杂;此设计方法简化了操作)。
方块旋转功能测试
1.在ssRender工具端创建下落按钮
2.再新建一个Lua脚本,命名为RotaUp,双击打开
调用上面编写好的旋转方法
3.将下降按钮的click事件触发调用Down脚本
4.点击按钮,检查旋转效果
效果达到预期,发现有边缘限制以及方块阻拦时,均不能旋转!接下来我们实现下一方块提示功能
三:NextBlock下一方块提示功能实现
首先现在游戏界面的右上角按照上一篇讲过的创建方法和命名方式,创建一个4*4大小的方格区域,用于显示下一个方块。
下一个方块的·存储方法·如下,只需要记录位置即可,‘下一方块’没有旋转等操作,所以不用担心其他操作会污染数据表。
(一)渲染与取消
function RenderNextBlock()
local setPropertyTable = {}
local block = BlockList[nextBlock['blockListID']][nextBlock['subID']]
for i = 1, #block do
for j = 1, #block[1] do
if block[i][j] == 1 then
setPropertyTable["Layer0//NextBlock//Row"..i.."//Item"..j.."//Visible"] = "1"
end
end
end
ssr.setNodeProperty(setPropertyTable)
end
function CancelNextBlock()
local setPropertyTable = {}
local block = BlockList[nextBlock['blockListID']][nextBlock['subID']]
for i = 1, #block do
for j = 1, #block[1] do
setPropertyTable["Layer0//NextBlock//Row"..i.."//Item"..j.."//Visible"] = "0"
end
end
ssr.setNodeProperty(setPropertyTable)
end
此方法大家应该不陌生,渲染当前方块,取消渲染当前方块,渲染bg表都有过提及,方法类似,不再赘述(此方法调用了ssRender引擎有关Lua的相应接口,大家如果使用其他工具、引擎,要根使用对应的渲染方法!)。
(二)更改CreatNewBlock函数
创建新俄罗斯方块时,只需要在游戏开始时调用一次,所以我们要将creat方块和nextBlock覆盖currentBlock方法分开
math.randomseed(os.time())
function CreatNewBlock()
nextBlock = {['blockListID'] = math.random(1,7), ['subID'] = math.random(1,4)}
currentBlock['blockListID'] = math.random(1,7)
currentBlock['subID'] = math.random(1,4)
currentBlock['curRow'] = -3
currentBlock['curColumn'] = 4
--currentBlock['block'] = BlockList[currentBlock['blockListID']][currentBlock['subID']]
Clone(BlockList[currentBlock['blockListID']][currentBlock['subID']], currentBlock['block'])
end
一起创建两个方块(此函数只在初始化时调用一次,当前俄罗斯方块触底之后则调用其他方法克隆下一方块给当前方块,并生成下一方块)
(三)下一方块nextBlock覆盖当前方块currentBlock
function CopyNextBlock()
currentBlock['blockListID'] = nextBlock['blockListID']
currentBlock['subID'] = nextBlock['subID']
currentBlock['curRow'] = -3
currentBlock['curColumn'] = 4
Clone(BlockList[nextBlock['blockListID']][nextBlock['subID']], currentBlock['block'])
nextBlock = {['blockListID'] = math.random(1,7), ['subID'] = math.random(1,4)}
end
新建的currentBlock所对应的初始行数设为固定值-3(currentBlock['curRow'] = -3 )初始列数设为固定值4( currentBlock['curColumn'] = 4);为了防止当前方块的旋转操作污染初始的方块表,所以要将方块表的数据拷贝(Clone)到currentBlock的形状中。
同时还要再生成一个新的nextBlock;
现在我们就可以给更新下降函数Down的注释处的逻辑处理啦:
function Down()
CancelCurrentBlock()
local row = currentBlock['curRow'] + 1
--触底之后操作
if CheckGround(currentBlock['curRow'],currentBlock['curColumn']) then
--当前方块插入到主bg表中
InsertBlockToBG()
--满行检测
--重新渲染主bg表
RenderBG()
--取消渲染nextBlock(下一方块)
CancelNextBlock()
--nextBlock复制给currentblock & 重新生成nextBlock
CopyNextBlock()
--渲染下一方块nextBlock
RenderNextBlock()
--更新得分
else
currentBlock['curRow'] = row
end
next方块提示功能测试
生成新的nextBlock我们集成到了Down方法中,在方块触底后自动调用,所以我们无需额外的处理。直接看当前方块触底后新方块的生成情况即可。
注意观察下一方块与新出现的当前方块图案对应,说明功能实现成功。满足预期。
小结:本篇文章是本人在使用ssRender引擎中的Lua脚本相关内容来制作俄罗斯方块的创作记录,本篇主要记录了方块下落功能、方块旋转功能和下一方块提示功能的实现!下一篇文章将会主要实现方块的消除逻辑、得分功能、游戏结束检测、以及其他功能的细节处理!若大家感兴趣,还请持续关注哦!