Lua / Corona SDK : 循环显示对象的位置差异

Lua / Corona SDK : Positional difference of display objects in loop

因此,在使用 Corona SDK 构建手机游戏时,我时不时会遇到一些问题。其中一个我似乎没有解决:

在循环中生成显示对象时,一行中的两个对象之间似乎随机出现位置差异。

起初,我认为这是由于在实际生成和过渡开始之间执行了大量代码,但后来我设法在几行中重现了同样的问题:

local rectangleLoopTimer;
local counter = 0;
local rectangleArray = {}

local function rectangleLoop()

    counter = counter + 1

    local thisRectangle = display.newRect(1, 1, 216, 400)
    thisRectangle.anchorX = 0

    table.insert(rectangleArray, thisRectangle)

    transition.to(

        thisRectangle,

        {

            time = 5000,
            x = thisRectangle.x + 1080,

            onComplete = function()

                display.remove(thisRectangle)
                table.remove(rectangleArray, counter)

            end

        }

    )

end

rectangleLoopTimer = timer.performWithDelay(985, rectangleLoop, 0)

如果执行此操作,那么就会明白我的意思,那么您认为为什么会这样?我感谢每一个答案!

你好,尼尔斯

编辑:

这也会产生同样的问题:

local rectangleLoopTimer;
local counter = 0
local rectangleArray = {}
local thisRectangle

local function rectangleLoop()

    counter = counter + 1

    thisRectangle = display.newRect(1, 1, 216, 400)
    thisRectangle.anchorX = 0
    thisRectangle.lastTime = 0
    thisRectangle.rate = 216
    table.insert(rectangleArray, thisRectangle)
    thisRectangle.lastTime = system.getTimer()

    thisRectangle.enterFrame = function(self, event)

        local curTime = system.getTimer()
        local dt = curTime - self.lastTime
        self.lastTime = curTime
        local dx = self.rate * dt / 1000
        self.x = self.x + dx

    end

    Runtime:addEventListener("enterFrame", thisRectangle)

end

rectangleLoopTimer = timer.performWithDelay(1000, rectangleLoop, 0)

重新编辑:

此代码也会产生相同的问题,尽管使用的是独立于帧率的动画。如以下代码所示,在提高循环速度时,问题变得越来越突出:

local loopSpeed =  306
local loopTimerSpeed = 1000
local gapTable = {}
local gapLoopTimer
local frameTime
local gap

--enterFrame for time only

    local function frameTime(event)

        frameTime = system.getTimer()

    end

--enterFrame

    local function enterFrame(self, event)

        local deltaTime = frameTime - self.time
        print(deltaTime/1000)
        self.time = frameTime
        local speed = self.rate * deltaTime / 1000
        self:translate(speed, 0)

    end

--loop speed function

local function setLoopSpeed(factor)

    loopSpeed = loopSpeed * factor
    loopTimerSpeed = loopTimerSpeed / factor

end

--set the loop speed

    setLoopSpeed(3)

--loop to create gaps

local function createGap()

    gap = display.newRect(1, 1, 308, 442)
    gap.time = system.getTimer()
    gap.anchorX = 1
    gap.anchorY = 0

    --animation

        gap.rate = loopSpeed
        gap.enterFrame = enterFrame
        Runtime:addEventListener("enterFrame", gap)

    --fill table for cleaning up

        table.insert(gapTable, gap)

    --cleaning up

        for i = #gapTable, 1, -1 do

            local thisGap = gapTable[i]

            if thisGap.x > display.contentWidth + 500 then

                display.remove(thisGap)
                table.remove(gapTable, i)
                Runtime:removeEventListener("enterFrame", thisGap)

            end

            thisGap = nil

        end

end

Runtime:addEventListener("enterFrame", frameTime)

gapLoopTimer = timer.performWithDelay(

    loopTimerSpeed,
    createGap,
    0

)

如果您不需要进一步参考 rect,请使用下面的代码

local rand = math.random

local function rectangleLoop() 
    local thisRectangle = display.newRect(1, 1, 216, 400)
    thisRectangle.anchorX = 0
    thisRectangle:setFillColor(rand(), rand(), rand())

    transition.to(thisRectangle, {time=5000,x=thisRectangle.x + 1080, onComplete=display.remove})
end

rectangleLoopTimer = timer.performWithDelay(985, rectangleLoop, 0)

您需要使用table来存储矩形吗?

这是一个非常常见的转换问题,[对我来说] 是 Corona SDK 中的一个错误。 需要注意的重要一点是过渡是如何工作的。 过渡只不过是一个 table ,其中包含对对象的引用以及关于每帧应该对它们执行的操作的信息。 检索此类对象的每一帧,并使用当前时间计算应应用于对象值的差异,如转换本身所指定。 这基本上意味着,如果您要求 Corona 在 time = 100 中将对象从 x = 0 移动到 x = 100。每一帧,Corona 都会获取该信息,获取当前时间,并计算对象的 x 值。

这里的问题是,当前拍摄的时间是计算时的当前时间,而不是帧的时间。这意味着,如果你有很多过渡,那么一帧内的第一个和最后一个过渡之间可能会有几毫秒的时间。这将导致同一帧内的不同位置。

如果 Corona 需要帧时间 [所以帧开始的时间],它会使用相同的值来计算所有内容,并且无论您要从 A 过渡到 B 多少对象,所有对象都会出现在所有帧中的相同位置。

解决此问题的最简单方法是在 enterFrame 中手动处理转换或使用为您处理的库,例如:AKTween.

希望对您有所帮助。

编辑: 根据您的附加代码和评论,我认为这应该可以按您的意愿工作。请原谅我的代码质量,我是凭记忆写的,没有在 Corona 中测试。

local rectangleLoopTimer;

local allRectangles = display.newGroup()


local lastTime = system.getTimer()

local function enterFrame()

    local curTime = system.getTimer()
    local dt = curTime - lastTime
    lastTime = curTime

    for i = allRectangles.numChildren, 1 do
        local rect = allRectangles[i]
        local dx = rect.rate * dt / 1000
        rect.x = rect.x + dx
    end
end

Runtime:addEventListener("enterFrame", enterFrame)


local function createRectangle()

    local thisRectangle = display.newRect(1, 1, 216, 400)
    thisRectangle.anchorX = 0
    thisRectangle.lastTime = 0
    thisRectangle.rate = 216
    allRectangles:insert(thisRectangle)
end

timer.performWithDelay(1000, createRectangle, 0)

重新编辑 post 后编辑:

您在 enterFrame 侦听器中设置了时间,但您实际上并不知道何时调用它。我不会指望在 enterFrame 阶段调用函数的顺序。