Moving Objects in Tiny Increments
Motion pictures are actually a series of still images. They only appear to be moving because the frames are flashing in front of you very fast, and the incremental movement from one frame to the next is very small.
You can use this same strategy in Wild Pockets. If you use setPosition to move an object just one millimeter each frame, and repeat this for 1000 frames, it will appear that the object is gliding smoothly across a one-meter distance. In reality, it is moving in 1000 discrete, millimeter steps. But since the steps are so tiny, the user will not see them and will only see the continuous motion.
This is the basic recipe for all procedurally-controlled movement: create a function or background job whose responsibility is to keep moving the object, over and over, in tiny increments.
Straightforward Example: Keyboard-Driven Movement
Here is a function that lets you drive an object around using keyboard keys. It very straighforwardly uses the idea of tiny, incremental movements adding up when applied over multiple frames:
function drive(obj)
while true do
if (EventHandler.keyIsDown("w")) then
obj:setPosition(0,0.1,0, obj)
end
if (EventHandler.keyIsDown("s")) then
obj:setPosition(0,-0.1,0, obj)
end
if (EventHandler.keyIsDown("a")) then
obj:setHeading(3, obj)
end
if (EventHandler.keyIsDown("d")) then
obj:setHeading(-3, obj)
end
obj:setUpright()
Timer.sleep(0)
end
end
You can test this in the development environment by loading this into the debugging window, then typing:
s = SceneManager.getObject("small box")
Coroutines.schedule(drive, s)
Then, use the w,a,s,d keys to drive the small box around.
The way it works is: the function checks the keyboard key "w" and if it is pressed, it moves the object a tiny bit forward. The "s" key causes a tiny backward movement, the "a" key a tiny left-turn, and the "d" key a tiny right-turn. Then, the routine sleeps for one frame. Although the movements are very small, they occur inside a while-loop which causes them to be repeated every frame, so they add up to significant movement.
A More Subtle Example
Here is a piece of code which will cause one object to stay within two meters of another:
function stayClose(obj, other)
while true do
local dist = obj:distance(other)
if dist > 2.0 then
local direction = obj:getPosition() - other:getPosition()
direction = direction:normalize()
obj:setPosition(other:getPosition() + direction * 2.0)
end
Timer.sleep(0)
end
end
You can test this in the development environment by loading this into the debugging window, then typing:
s = SceneManager.getObject("small box")
l = SceneManager.getObject("large box")
Coroutines.schedule(stayClose, l, s)
Then, drag the small box around and watch the large box follow it.
The way it works is that the subroutine measures the distance between the two. If it's more than two meters, it uses vector mathematics to determine how to move the large box to within two meters of the small one.
This function can move the large box rapidly. If the large box is 100 meters from the small one, this function will move the large box 98 meters in a single frame. But more likely, assuming the small box is moving in gradual, tiny amounts, the large box will only need to move in gradual, tiny amounts to keep up. So even though this function is not explicitly programmed to move the large box a small amount every frame, it will effectively do just that, moving the large box just exactly the amount necessary to keep up, and no more. This is usually a very small amount, so the large box's movement usually appears quite smooth.
- Printer-friendly version
- Login or register to post comments
-



