【quick-cocos2d-lua】 2048小游戏
程序员文章站
2024-03-18 19:58:40
...
玩法示例:
图1为初始游戏场景(只有一个游戏场景),4x4个格子上随机产生两个数,数字2或4。
图2:玩家向左滑动屏幕,整体向左移动,相邻相同数字进行相加,并再随机产生2或4的数字。当16个格子充满数字且滑动屏幕无法进行数字相加时,游戏失败。当最大数为2048时,游戏胜利。
场景:一个游戏场景
界面UI:游戏标题标签,游戏最高分和当前游戏分数标签,重新开始游戏的button
代码分析:
首先,背景,标签,按钮的添加,
4X4的格子逻辑实现:
function initGrid(m,n)
local grid = {}
for i=1,m do
if not grid[i] then
grid[i] = {}
end
for j=1,n do
grid[i][j] = 0
end
end
randomNum(grid) --随机产生一个初始数
randomNum(grid)
return grid
end
初始随机数的产生:
local function randomNum(grid)
local i,j = getRandomZeroPos(grid)
if i and j then
local r = math.random()
if r<0.9 then
grid[i][j] = 2
else
grid[i][j] = 4
end
return i,j
end
end
local function getRandomZeroPos(grid) --随机获得初始数的位置
local m = #grid
local n = #grid[1]
local zeros = {}
for i=1,m do
for j=1,n do
if grid[i][j]==0 then
table.insert(zeros,{i=i,j=j})
end
end
end
if #zeros>0 then
local r = math.random(1,#zeros)
return zeros[r].i,zeros[r].j
end
end
格子的展示:
function MainScene:createGridShow()
gridShow = {}
for tmp=0,15 do
local i,j = math.floor(tmp/4)+1,math.floor(tmp%4)+1
local num = grid[i][j]
local s = tostring(num)
--s = s.."("..i..","..j..")"
if s=='0' then
s=''
end
if not gridShow[i] then
gridShow[i] = {}
end
local cell = {
backgroundsize = 140,
background = cc.LayerColor:create(colors[-1], 140, 140),
num = cc.ui.UILabel.new({
text = s,
size = 40,
color = numcolors[0],
}),
}
gridShow[i][j] = cell
self:show(gridShow[i][j],i,j)
end
function MainScene:show(cell,mx,my)
local x,y = getPosFormIdx(mx,my)
local bsz = cell.backgroundsize/2
cell.background:setPosition(cc.p(x-bsz,y-bsz))
self:addChild(cell.background)
cell.num:align(display.CENTER,x,y):addTo(self)
end
function getPosFormIdx(mx,my)
local cellsize=150 -- cell size
local cdis = 2*cellsize-cellsize/2
local origin = {x=display.cx-cdis,y=display.cy+cdis}
local x = (my-1)*cellsize+origin.x
local y = -(mx-1)*cellsize+origin.y - 100
return x,y
end
读取历史数据,若有历史数据(grid,最高分,当前分的记录),则重新加载游戏:
function MainScene:loadStatus()
if io.exists(configFile) then
local str = io.readfile(configFile)
if str then
local f = loadstring(str)
local _grid,_bestScore,_totalScore,_WINSTR,_isOver = f()
if _grid and _bestScore and _totalScore and _WINSTR then
grid,bestScore,totalScore,WINSTR,isOver = _grid,_bestScore,_totalScore,_WINSTR,_isOver
end
end
end
self:reLoadGame()
end
添加触摸层,注册触摸监听(进入游戏场景时):
layer:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
return self:onTouch(event.name, event.x, event.y)
end)
判断滑动方向:可根据触摸开始和结束的坐标判断,△y/△x在-1~1且△x>0则往右,其他类推。
相邻相同的数字进行相加,整体在该方向上移动,例向左滑动:
local function moveLeft(grid)
print("==============moveLeft===============")
local score = 0
local win = false
local m = #grid
local n = #grid[1]
for i=1,m do
local line = {}
for j=1,n do
if grid[i][j]~=0 then
table.insert(line,grid[i][j])
end
end
local k=#line
for j=1,n do
if j<=k then
grid[i][j] = line[j]
else
grid[i][j] = 0
end
end
for j=1,k-1 do
if grid[i][j]==grid[i][j+1] then
grid[i][j+1] = grid[i][j] + grid[i][j+1]
if grid[i][j+1]==2048 then
win = true
end
score = score + grid[i][j+1]
for x=j,n-1 do
grid[i][x] = grid[i][x+1]
end
grid[i][n] = 0
end
end
end
return score,win
end
并再随机产生一个2或4,
界面更新:将滑动前和滑动完成后的grid进行比较,不同的部分则记录到一个表,记录滑动后的在grid中的位置及数字,遍历其表,使界面更新。
进行最高分和当前得分的更新,若当前得分高于最高分,则最高分更新为当前得分。
记录当前状态的数据。
function saveStatus()
local gridstr = serialize(grid)
local isOverstr = "false"
if isOver then isOverstr = "true" end
local str = string.format("do local grid,bestScore,totalScore,WINSTR,isOver \
=%s,%d,%d,\'%s\',%s return grid,bestScore,totalScore,WINSTR,isOver end",
gridstr,bestScore,totalScore,WINSTR,isOverstr)
io.writefile(configFile,str)
end
进入游戏加载完历史数据后,每次触摸前得判断游戏是否结束。每次触摸后则决定游戏是否结束。