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

Timer Lua/Corona SDK:循环中显示对象的位置差异,timer,lua,sdk,position,coronasdk,Timer,Lua,Sdk,Position,Coronasdk,因此,在使用Corona SDK构建手机游戏时,我偶尔会遇到一些问题。其中一个我似乎没有解决: 在循环中生成显示对象时,行中的两个对象之间似乎随机出现位置差异 起初,我认为这是由于在实际生成和转换开始之间执行了大量代码,但后来我设法在几行代码中重现了相同的问题: local rectangleLoopTimer; local counter = 0; local rectangleArray = {} local function rectangleLoop() counter =

因此,在使用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)

是否需要使用表来存储RECT?

如果不需要进一步引用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来存储rect吗?

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

这里的问题是,当前所用的时间是计算时的当前时间,而不是帧的时间。这意味着,如果你有很多转换,一帧内的第一个和最后一个转换之间可能需要几毫秒。这将导致同一帧中的不同位置

如果Corona需要帧时间[帧开始时的时间],它将使用相同的值来计算所有内容,并且无论有多少对象从A转换到B,所有对象都将在所有帧中显示在相同的位置

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

希望这有帮助

编辑: 根据您的附加代码和注释,我认为这应该可以按照您的要求工作。请原谅我的代码质量,我是从内存中编写的,没有在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)
重新编辑帖子后进行编辑:


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

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

这里的问题是,当前所用的时间是计算时的当前时间,而不是帧的时间。这意味着,如果你有很多转换,一帧内的第一个和最后一个转换之间可能需要几毫秒。这将导致同一帧中的不同位置

如果Corona需要帧时间[帧开始时的时间],它将使用相同的值来计算所有内容,并且无论有多少对象从A转换到B,所有对象都将在所有帧中显示在相同的位置

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

希望这有帮助

编辑: 根据您的附加代码和注释,我认为这应该可以按照您的要求工作。请原谅我的代码质量,我是从内存中编写的,没有在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)
重新编辑帖子后进行编辑:


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

已经谢谢你了。是的,在实际应用中,我需要表格,因为我在那里使用enterFrame。但是你的代码实际上产生了同样的问题。这个问题可能与电晕模拟器有关吗?您有时会看到矩形之间的空格,有时不会…谢谢。是的,在实际应用中,我需要表格,因为我在那里使用enterFrame。但是你的代码实际上产生了同样的问题。这个问题可能与电晕模拟器有关吗?您有时会看到矩形之间的空格,有时不会…谢谢您的回答!但奇怪的是:我实际上也尝试过使用enterFrame+合并deltaTime…但问题仍然存在!你对此有何看法?我将发布相关代码作为答案。无,这正是我写的。请记住,Corona SDK处理点的分数。因此,如果你的X计算为33.3,另一个计算为33.8,它们将