欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【quick-cocos2d-lua】 2048小游戏

程序员文章站 2024-03-18 19:58:40
...

玩法示例:

【quick-cocos2d-lua】 2048小游戏【quick-cocos2d-lua】 2048小游戏

图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

进入游戏加载完历史数据后,每次触摸前得判断游戏是否结束。每次触摸后则决定游戏是否结束。