問題描述
Corona 中的 iPad 式慣性滾動 (iPad-style inertial scrolling in Corona)
I'm trying to imitate an iPad-style inertia scroll in Corona, using the touch
event and the enterFrame
event. In short, I should be able to drag and "throw" an object to a certain extent, similar to scrolling on the iPad. I'm fairly new to Corona, but I've used other languages before. (This is my second day.)
This is the code I've got so far:
local bg = display.newImage("cloud.jpg");
bg:setReferencePoint(bg.TopLeftReferencePoint);
bg.x = 0;
bg.y = 0;
function bg:touch (event)
print("event", event)
for i,v in pairs(event) do
print("**: ",i,v)
end
bg.x = event.x;
bg.y = event.y;
bg.xStart = event.xStart;
bg.yStart = event.yStart;
if (event.phase == "ended")
then
bg.xdelta = bg.xStart + bg.x;
bg.ydelta = bg.yStart + bg.y;
Runtime.addEventListener("enterFrame", bg);
end
end
function bg:enterFrame(event)
bg.x = bg.x + bg.xdelta;
bg.y = bg.y + bg.ydelta;
// TODO: Add code to decrease delta so that object gradually stops.
end
bg:addEventListener("touch");
This is throwing an error in the compiler. What am I doing wrong? I tried making the enterFrame function a local function instead of a table function, but I ran into the same issue. I'm sure that the answer is VERY simple, but I'm not familiar enough with Corona to see it immediately.
Edit: I've done some reading and I've realized that this is closer to what I want:
local bg = display.newImage("cloud.jpg");
bg:setReferencePoint(bg.TopLeftReferencePoint);
bg.x = 0;
bg.y = 0;
bg.xdelta = 0;
bg.ydelta = 0;
local function onEveryFrame(event)
bg.x = bg.x + (bg.oldx - bg.x);
bg.y = bg.y + (bg.oldy - bg.y);
end
function bg:touch (event)
if (event.phase == "ended")
then
print("ended")
bg.oldx = bg.x;
bg.oldy = bg.y;
bg.x = event.x;
bg.y = event.y;
Runtime.addEventListener("enterFrame", onEveryFrame)
end
print("event", event)
for i,v in pairs(event) do
print("**: ",i,v)
end
bg.oldx = bg.x;
bg.oldy = bg.y;
bg.x = event.x;
bg.y = event.y;
print("bg.x:", bg.x)
print("bg.oldx:", bg.oldx)
print("bg.y:", bg.y)
print("bg.oldy:", bg.oldy)
end
bg:addEventListener("touch");
This is no longer erroring out, but I'm not getting the desired result either...
參考解法
方法 1:
I have not attempted to solve this problem in Corona, but encountered it a lot in Director when implementing smooth scrolling.
While dragging, capture a velocity that measures speed over several touch events, comparing position differences to timestamp differences. Use a table or a linked list for the individual measuring points, and average the velocity over the stored values.
Then the "ended" event in the same position as the last "moved" event will only slightly decrease speed, preserving inertia. In absence of dragging events, subtract a value from the velocity for friction.
方法 2:
Actually, you have a syntax error.
It is Runtime:AddEventListener (pay attention to the : instead of .)
EDIT:
Now about your math:
Your logic do: during a moved event, it sets the bg.p (p for position, both x and y) to event.p
During the ended event you set bg.olp to bg.p and then bg.p to event.p and then you try to every frame do bg.p+=(bg.oldp-bg.p)
This maybe would work IF you did the olp logic on "moved" because the result is this:
Users move finger: moved event triggers, and bg.p changed (thus you see it moving). Users attempt to remove finger: This trigger a "ended" event, that has a very high change that it will trigger in the same place as the last "moved" event (you would need to move the finger VERY, VERY, VERY fast to trigger a "ended" far from the last "moved"). This will make your bg.oldp be the same as bg.p and thus you do bg.p+=(bg.olp-bg.p) the result is bg.p+=0
(by jedd.ahyoung、Knutopia、speeder)