![](/img/trans.png)
[英]Lua / Corona SDK / Loop Spawning / Positional Difference / Framerate independent animation
[英]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
)
如果您不需要進一步參考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嗎?
轉換是一個非常常見的問題,[對我來說]是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
階段調用的函數的順序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.