[Updated Jul 30, 2020]
Using transition.to() for animation is one of the most awesome things about Solar2D. It makes simple animation quick and easy. However, it’s based on time — move the object from Point A to Point B over a specified amount of time. Which means if you want to move something different distance at the same speed, it’s not automatic.
But it’s also not rocket science.
Here’s a sample project that shows how it’s done. Create a main.lua file and paste in the following code. Then run it in the simulator and you’ll see a dot show on the screen. Tap anywhere else on the screen and the dot will move to that location. Tap close and tap far — the dot will always move at the same speed, no matter how far away you tap.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
local player local mSqrt = math.sqrt local function distanceBetween( pos1, pos2 ) local factor = { x = pos2.x - pos1.x, y = pos2.y - pos1.y } return mSqrt( ( factor.x * factor.x ) + ( factor.y * factor.y ) ) end local function movePlayer(event) transition.cancel ( player.trans ) local totDist = distanceBetween(player, event) local travTime = totDist / player.speed player.trans = transition.to ( player, {time=travTime, x=event.x, y=event.y} ) end player = display.newCircle( 50, 50, 15 ) player.speed = .1 -- bigger numbers are faster Runtime:addEventListener("tap", movePlayer) |
The secret is the distanceBetween() function and two lines inside the movePlayer() function. To determine the time it should take to go from point A to Point B we need to know how far between the two points.
The distance between() function takes two parameters — tables that contain x and y properties. Which means you can pass in a display object since it’s (under the hood) a Lua table and all objects have x and y properties. Your second parameter can be the event record that’s passed to a listener from the Runtime listener — event records are also Lua tables and they have x and y properties that tell where the tap took place.
So inside movePlayer() we call distanceBetween() and pass the current location of the dot on the screen as well as the location of the tap. It passes back the distance between the two in pixels (not technically pixels, but it’s okay to think of them that way) and then all it takes to get the time we need is to divide the distance by our player speed.
1 |
local travTime = totDist / player.speed |
The player.speed is set to .1 right after we create the player (dot) and by choosing a larger number we can make the dot move faster.
Now we have a variable called travTime that can be used for the time parameter in transition.to() and our player dot will always move the same speed, no matter whether it’s going 10 pixels or 500.
Previously published referencing Corona SDK, the old name of Solar2D.