美文网首页game
CocosLua3.10 消除类游戏(主要游戏玩法,只用Text

CocosLua3.10 消除类游戏(主要游戏玩法,只用Text

作者: 叫我29就好啦 | 来源:发表于2019-11-20 09:35 被阅读0次

参考文章:https://blog.csdn.net/hiwoshixiaoyu/article/details/78705965

检查附近的项是否与自己选取得所相同。

local Row = 8  -- 行
local Column = 8  -- 列

local Offset_X = 100
local Offset_Y = display.height - 80

local Interval = 60  -- 间距

local Text_Click_Color = cc.c3b(255, 0, 0)
local Text_Default_Color = cc.c3b(255, 255, 255)

local MarkName = 'Text_'  -- 标记名字

local Math_Count = 3  -- 数字个数

local Time_FadeOut = 0.2  -- 淡出时间
local Time_Drow = 0.05

local Is_Add_Math = true  -- 点击后补充

local AddNew_Offset_Y = 4

function event:ctor()
    self._sameAsSender = {}
    self._sameAsTable = {}  -- 标记已经查找过的表
    self._currentClickName = nil  -- 一个相同的标记
    self._isCanClick = true
    self._isDropingMath = false
    self._isReloadingMath = false

    self:createLayout()
    self:createReload()
end

function event:createLayout()
    self._items = {}
    for i = 1, Row do
        self._items[i] = {}
        for j = 1, Column do
            local node = self:createItem(i, j)
            self._items[i][j] = node
        end
    end
end

function event:createReload()
    local text = ccui.Text:create()
    text:setPositionX(display.width - 120)
    text:setPositionY(display.height - 80)
    text:setFontSize(32)
    self:addChild(text)
    text:setString('Reload')
    text:setTouchEnabled(true)

    local function clickEvent(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            self:reloadMath()
        end
    end
        
    text:addTouchEventListener(clickEvent)    
end

function event:createItem(i, j)
    -- text
    local text = ccui.Text:create()
    local x, y = self:getPositionByIdx(i, j)
    text:setPositionX(x)
    text:setPositionY(y)
    text:setFontSize(32)
    self:addChild(text)
    text:setTouchEnabled(true)
    text:setString(math.random(1, Math_Count))
    text:setName(MarkName..text:getString())

    local function clickEvent(sender, eventType)
        if not self:getIsCanClick() then
            return
        end

        if eventType == ccui.TouchEventType.ended then
            -- self._isCanClick = false
            self:clearTheSameTable()
            self:addTheSameNode(sender)
            self._currentClick = sender:getName()
            local idx_i, idx_j = self:getIdxByPosition(sender)
            self:checkNearBy(idx_i ,idx_j)  -- 不使用ij是因为可能ij会改变,所以通过坐标来获取。或者可以记录一下当前的ij和改变后的
            self:showSameTable()
        end
    end
        
    text:addTouchEventListener(clickEvent)

    return text
end

function event:getPositionByIdx(i, j)
    return Offset_X + i * Interval, Offset_Y - j * Interval
end

function event:getIdxByPosition(node)
    if not node then
        return 0, 0
    end

    local i, j = 0, 0
    local pos = cc.p(node:getPositionX(), node:getPositionY())
    i = (pos.x - Offset_X) / Interval
    j = (Offset_Y - pos.y) / Interval

    return i, j
end

function event:checkNearBy(i, j)
    local indexStr = string.format('%s_%s', i, j)
    if self._sameAsTable[indexStr] then
        return false
    end

    self._sameAsTable[indexStr] = true

    local temp = {cc.p(i, j-1), cc.p(i, j+1), cc.p(i-1, j), cc.p(i+1, j)}

    for i, v in ipairs(temp) do
        if v.x > 0 and v.x <= Row and v.y > 0 and v.y <= Column then
            local node = self._items[v.x][v.y]
            if node and node:getName() == self._currentClick then
                if self:checkNearBy(v.x, v.y) then
                    self:addTheSameNode(node)
                end
            end
        end
    end

    return true
end

function event:clearTheSameTable()
    for i, v in ipairs(self._sameAsSender) do
        self:changeFontColor(v, false)
    end

    self._sameAsSender = {}
    self._sameAsTable = {}
end

function event:addTheSameNode(node)
    if node then
        table.insert(self._sameAsSender, node)
    end
end

function event:showSameTable()
    print('\n')
    print(string.format('同值表内个数是%d', #self._sameAsSender))
    dump(self._sameAsSender)
    if not self._sameAsSender or not next(self._sameAsSender) then
        return
    end

    for i, v in ipairs(self._sameAsSender) do
        -- text
        self:changeFontColor(v, true)
        self:fadeOutNode(v, i == #self._sameAsSender)
    end
end

-- 改颜色(测试)
function event:changeFontColor(node, isChange)
    local isChange = isChange or false
    node:setColor(isChange and Text_Click_Color or Text_Default_Color)
end

function event:fadeOutNode(node, isEnd)
    if not node then
        return
    end

    local fadeOut = cc.FadeOut:create(Time_FadeOut)
    local callfunc = cc.CallFunc:create(function()
        node:setVisible(false)

        if isEnd then
            self:endFadeOutCallfunc()
        end
    end)

    local seq = cc.Sequence:create(fadeOut, callfunc)
    node:runAction(seq)
end

function event:endFadeOutCallfunc()
    self:reloadMath()
    -- self._sameAsSender = {}
end

function event:reloadMath()
    if #self._sameAsSender > 0 then
        for i, v in ipairs(self._sameAsSender) do
            v:stopAllActions()
            v:setVisible(false)
        end
    end

    self:checkDownIsEmpty()
    self:clearTheSameTable()

    if Is_Add_Math then
        print('补充数字')
        -- 补充
        local addTable = {}  -- 插入表格式为{node(节点), pos(坐标) addCount(当前列补充个数)}     
        local runActionCount = 0
        local emptyCountTable, emptyPosTable = self:getEmptyCountInColumn()
        for i, v in ipairs(emptyCountTable) do
            if v > 0 then
                for j, pos in ipairs(emptyPosTable[i]) do
                    local node = self:createItem(pos.x, pos.y - AddNew_Offset_Y)
                    table.insert(addTable, {node = node, pos = cc.p(pos.x, pos.y - AddNew_Offset_Y), addCount = v})
                end
            end
        end

        if #addTable > 0 then
            self._isReloadingMath = true
            for idx, v in ipairs(addTable) do
                local node, i, j, addCount = v.node, v.pos.x, v.pos.y, v.addCount
                local x, y = self:getPositionByIdx(i, j + AddNew_Offset_Y)
                local seq = cc.Sequence:create(
                    cc.MoveTo:create((addCount * Time_Drow), cc.p(x, y)),
                    cc.CallFunc:create(function()
                        self._items[i][j + AddNew_Offset_Y]:removeFromParent()
                        self._items[i][j + AddNew_Offset_Y] = node
                        if idx == #addTable then
                            self._isReloadingMath = false
                        end
                    end)
                )
                node:runAction(seq)
            end
        end
    end
end

function event:clearNodeByPos(i, j)
    if not i or not j then
        return
    end

    if self._items[i][j] then
        self._items[i][j]:removeFromParent()
        self._items[i][j] = nil
    end
end

function event:checkDownIsEmpty()
    local function checkIsEmpty(node, nextPos)
        if nextPos.y <= Column then
            local nextNode = self._items[nextPos.x][nextPos.y]
            if nextNode and nextNode:isVisible() then
                return checkIsEmpty(nextNode, cc.p(nextPos.x, nextPos.y + 1))
            else
                return checkIsEmpty(nextNode, cc.p(nextPos.x, nextPos.y + 1)) + 1
            end
        else
            return 0
        end
    end

    -- 移动
    local emptyTable = {}  -- 插入表格式为{node(节点), pos(坐标) nextCount(下面空格的个数)}
    for j = Column, 1, -1 do
        for i = Row, 1, -1 do
            local pos = cc.p(i, j + 1)  -- 下面那个
            if pos.y <= Column then
                local node = self._items[i][j]
                if node and node:isVisible() then
                    local nextCount = checkIsEmpty(node, pos)
                    if nextCount > 0 then
                        table.insert(emptyTable, {node = node, pos = cc.p(i, j), nextCount = nextCount})
                    end
                end
            end
        end
    end

    if #emptyTable > 0 then
        self._isDropingMath = true
        for idx, v in ipairs(emptyTable) do
            local node, i, j, nextCount = v.node, v.pos.x, v.pos.y, v.nextCount
            local x, y = self:getPositionByIdx(i, j + nextCount)
            self._items[i][j + nextCount], self._items[i][j] = self._items[i][j], self._items[i][j + nextCount]  -- 这里做交换,因为如果删除会把原有的表改变

            local seq = cc.Sequence:create(
                cc.MoveTo:create(nextCount * Time_Drow, cc.p(x, y)),
                cc.CallFunc:create(function()
                    if idx == #emptyTable then
                        self._isDropingMath = false
                    end
                end)
            )
            node:runAction(seq)
        end
    end
end

function event:getEmptyCountInColumn()
    local temp = {}  -- 需补充个数表
    local tempPos = {}  -- 需补充位置表

    for i, v in ipairs(self._items) do
        local count = 0
        tempPos[i] = {}
        for j, node in ipairs(v) do
            if not node or not node:isVisible() then
                count = count + 1
                table.insert(tempPos[i], cc.p(i, j))
            end
        end
        table.insert(temp, count)
    end

    return temp, tempPos
end

function event:getIsCanClick()
    return self._isCanClick and not self._isDropingMath and not self._isReloadingMath
end
图中'Reload'一开始用来测试填充的,不要理他
参考图,红色区域是刚点击准备消失掉的.png

ε≡٩(๑>₃<)۶ 请大家多多评论一起讨论讨论

相关文章

网友评论

    本文标题:CocosLua3.10 消除类游戏(主要游戏玩法,只用Text

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