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

时间:2016-12-06 16:58:32

标签: timer lua sdk position corona

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

如果有人执行此操作,那么我会看到我的意思,那么您认为为什么会这样?我很感激每一个答案!

问候,Nils

编辑:

这也会产生同样的问题:

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)

RE-编辑:

此代码也会产生相同的问题,尽管使用帧率独立动画。在增加循环速度时会强调这个问题,如下面的代码所示:

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

)

2 个答案:

答案 0 :(得分:0)

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

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)

您是否需要使用表来存储rects?

答案 1 :(得分:0)

这是转换的一个非常常见的问题,[对我来说]是Corona SDK中的一个错误。 需要注意的重要事项是过渡如何运作。 转换只不过是一个表,它引用了对象和每个帧应该对它们做什么的信息。 检索每个帧这样的对象,并使用当前时间来计算应该应用于对象值的差异,如转换本身中所指定的。 这基本上意味着,如果您要求Corona将对象从x = 0移动到x = 100中的time = 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)

在重新编辑帖子后编辑:

你有时间设置在enterFrame听众中,但你实际上并不知道它什么时候会被调用。我不会指望在enterFrame阶段调用的函数的顺序。