Corona SDK - frame-by-frame animation and accelerometer problem
we are doing a game with moving objects around frame-by-frame and also using accelerometer.
We have hooked on two events - about drawing the frame and for th开发者_StackOverflow中文版e acc.
The problem is, after we receive the acc event, we immediately put the x value in a variable.
Then we use this variable to move an object on the screen, but there is CONSIDERABLE slow down. ( I turn the phone, and after a second the object is moving properly, but a second is just way too much for a game, I expect immediate response).
What am I doing wrong? Is there another workaround to do this, or can I give some params to the accelerometer?
Unfortunately this is a serious problem - a real blocker. If this does not work, I have to find another solution (not Corona) for implementing the game.
Thanks in advance!!! Danail
PS: here's some source:
local lastXGravity = 0
local function move(event)
eventTime=event.time
elapsedTime = eventTime - lastDrawTime
lastDrawTime = eventTime
xSpeed = lastXGravity
local xMoved = xSpeed * elapsedTime
object.x= object.x + xMoved
end
function acc(event)
lastXGravity = event.xGravity
end
Runtime:addEventListener("accelerometer", acc)
Runtime:addEventListener( "enterFrame", move )
I don't know anything about Corona development, but there are some general issues. First what is gravity containing? Just the gravity vector or total acceleration = gravity + userAcceleration? You will need to get userAcceleration = totalAcceleration - gravity or some member from event providing it directly, otherwise there is no chance.
If you have user acceleration, you need to integrate twice to get the position. See Equations of motion. In your case the code will be like:
velocity = userAcceleration * elapsedTime
position = 0.5*userAcceleration * elapsedTime^2
In general precise position detection by accelerometer and gyroscope is still an unresolved problem, so don't expect precise results. But if you are interested in just evaluating that there is an impulse in one direction, it might work. See for example Getting displacement from accelerometer data with Core Motion
The guys at Ansca's forum just got this out:
system.setAccelerometerInterval( 50 )
This didn't quite actually did the trick, but
system.setAccelerometerInterval( 100 )
-- warning - battery drainer!!
did it :)
I open-sourced my first Corona SDK-made game (which actually did really well) which uses Tilting in the same manner you describe (the more the tilt, the faster the movement and vice-versa).
It's called 'Tilt Monster' and you can download it here: http://developer.anscamobile.com/code/tilt-monster
local isSimulator = "simulator" == system.getInfo("environment")
-- Accelerator is not supported on Simulator
if isSimulator then -- Please display an Alert Box end
-- Text parameters local labelx = 50 local x = 220 local y = 95 local fontSize = 24
local frameUpdate = false
local xglabel = display.newText( "gravity x = ", labelx, y, native.systemFont, fontSize ) xglabel:setTextColor(255,255,255) local xg = display.newText( "0.0", x, y, native.systemFont, fontSize ) xg:setTextColor(255,255,255) y = y + 25 local yglabel = display.newText( "gravity y = ", labelx, y, native.systemFont, fontSize ) local yg = display.newText( "0.0", x, y, native.systemFont, fontSize ) yglabel:setTextColor(255,255,255) yg:setTextColor(255,255,255) y = y + 25 local zglabel = display.newText( "gravity z = ", labelx, y, native.systemFont, fontSize ) local zg = display.newText( "0.0", x, y, native.systemFont, fontSize ) zglabel:setTextColor(255,255,255) zg:setTextColor(255,255,255) y = y + 50 local xilabel = display.newText( "instant x = ", labelx, y, native.systemFont, fontSize ) local xi = display.newText( "0.0", x, y, native.systemFont, fontSize ) xilabel:setTextColor(255,255,255) xi:setTextColor(255,255,255) y = y + 25 local yilabel = display.newText( "instant y = ", labelx, y, native.systemFont, fontSize ) local yi = display.newText( "0.0", x, y, native.systemFont, fontSize ) yilabel:setTextColor(255,255,255) yi:setTextColor(255,255,255) y = y + 25 local zilabel = display.newText( "instant z = ", labelx, y, native.systemFont, fontSize ) local zi = display.newText( "0.0", x, y, native.systemFont, fontSize ) zilabel:setTextColor(255,255,255) zi:setTextColor(255,255,255)
-- Create a circle that moves with Accelerator events
local centerX = display.contentWidth / 2 local centerY = display.contentHeight / 2
Circle = display.newCircle(0, 0, 20) Circle.x = centerX Circle.y = centerY Circle:setFillColor( 0, 0, 255 ) -- blue
local textMessage = function( str, location, scrTime, size, color, font )
local x, t
size = tonumber(size) or 24
color = color or {255, 255, 255}
font = font or "Helvetica"
if "string" == type(location) then
if "Top" == location then
x = display.contentHeight/4
elseif "Bottom" == location then
x = (display.contentHeight/4)*3
else
-- Assume middle location
x = display.contentHeight/2
end
else
-- Assume it's a number -- default to Middle if not
x = tonumber(location) or display.contentHeight/2
end
scrTime = (tonumber(scrTime) or 3) * 1000 -- default to 3 seconds (3000) if no time given
t = display.newText(str, 0, 0, font, size )
t.x = display.contentWidth/2
t.y = x
t:setTextColor( color[1], color[2], color[3] )
-- Time of 0 = keeps on screen forever (unless removed by calling routine)
if scrTime ~= 0 then
-- Function called after screen delay to fade out and remove text message object
local textMsgTimerEnd = function()
transition.to( t, {time = 500, alpha = 0},
function() t.removeSelf() end )
end
-- Keep the message on the screen for the specified time delay
timer.performWithDelay( scrTime, textMsgTimerEnd )
end
return t -- return our text object in case it's needed
end -- textMessage()
local function xyzFormat( obj, value)
obj.text = string.format( "%1.3f", value )
-- Exit if not time to update text color
if not frameUpdate then return end
if value < 0.0 then
-- Only update the text color if the value has changed
if obj.positive ~= false then
obj:setTextColor( 255, 0, 0 ) -- red if negative
obj.positive = false
print("[---]")
end
else
if obj.positive ~= true then
obj:setTextColor( 255, 255, 255) -- white if postive
obj.positive = true
print("+++")
end
end
end
local function onAccelerate( event )
xyzFormat( xg, event.xGravity)
xyzFormat( yg, event.yGravity)
xyzFormat( zg, event.zGravity)
xyzFormat( xi, event.xInstant)
xyzFormat( yi, event.yInstant)
xyzFormat( zi, event.zInstant)
frameUpdate = false -- update done
-- Move our object based on the accelerator values
Circle.x = centerX + (centerX * event.xGravity)
Circle.y = centerY + (centerY * event.yGravity * -1)
-- Display message and sound beep if Shake'n
if event.isShake == true then
-- str, location, scrTime, size, color, font
textMessage( "Shake!", 400, 3, 52, {255, 255, 0} )
end
end
local function onFrame() frameUpdate = true end
-- Add runtime listeners Runtime:addEventListener ("accelerometer", onAccelerate); Runtime:addEventListener ("enterFrame", onFrame);
I hope, this code will help you.
精彩评论