Hi!
Let’s say I want to make an object move across the screen in a random way (like an irritating fly!). It’s pretty easy to figure out how to get some random movement with transitions and random values for the x and y each time. Fair enough. Easy.
But what if I wanted to add some flair to everything, and make the object move in a more natural circular/bezier way (again… like a fly!). Basically having a path that is a continous bezier, so that the motion of an object is continously smooth, instead of just jagged jumping to different points. How would I accomplish this?
I found Carlos code for bezier movement and played around with it a bit just to see what I could come up with, and managed to create something barely functional - the object flies according to a bezier path that gets re-created at random every time the object reaches the end of it. I have attached the code block if anyone is interested - but be warned, the code is not pretty, and except for the glaring things like graphics being there but just hidden, the major gripe with this code is that the bezier path is not continous, and therefore the “turns” at every end is jittery and too quick. Smooth movement would be the ideal here, following a continous bezier path!
So – I just wanted to throw out an open question to the community, because I imagine more people like me being on the lookout for this. Has anyone accomplished smooth random movement using a bezier curve? What would be your ideas for accomplishing it?
[code]
module(…, package.seeall)
– Main function - MUST return a display.newGroup()
– Director function, we set up the scene
function new()
– Set up group
local localGroup = display.newGroup()
– Abstract: Bezier Handle Manipulation in Corona SDK
– Sample code is MIT licensed, see http://developer.anscamobile.com/code/license
– Copyright © 2010 ANSCA Inc. All Rights Reserved.
– Demonstrates how to create bezier segment.
– Not optmized. Just done. Feel free to modify at your hearts content.
local segMents = {};
local bezierSegment = {x,y};
local endCaps = {};
local tempCaps = {};
local tempBG = {};
local handleDot = {};
local FALSE = 0;
local TRUE = 1;
local moved = FALSE;
local numPoints = 0;
local NUMPOINTS = 200;
local gSegments;
local PIE = 3.14159265358
local line;
local speedFactor = 2
local bbg = nil;
–
local function destroyBezierSegment()
segMents = nil;
segMents = {};
handleDot = nil
handleDot = {};
end
–
local function drawBezierSegment(granularity,r,g,b)
if line then
line:removeSelf()
end
line = display.newLine(bezierSegment[1].x,bezierSegment[1].y,bezierSegment[2].x,bezierSegment[2].y);
localGroup:insert(line)
for i = 3, granularity, 1 do
line:append( bezierSegment[i].x,bezierSegment[i].y);
end
line:setColor(r,g,b, 0);
line.width=2;
end
–
local function setupBezierSegment(granularity)
local inc = (1.0 / granularity);
for i = 1, #endCaps,4 do
local t = 0;
local t1 = 0;
local i = 1;
for j = 1, granularity do
t1 = 1.0 - t;
local t1_3 = t1*t1*t1
local t1_3a = (3*t)*(t1*t1)
local t1_3b = (3*(t*t))*t1;
local t1_3c = (t * t * t )
local p1 = endCaps[i];
local p2 = endCaps[i+1];
local p3 = endCaps[i+2];
local p4 = endCaps[i+3];
local x = t1_3 * p1.x;
x = x + t1_3a * p2.x;
x = x + t1_3b * p3.x;
x = x + t1_3c * p4.x
local y = t1_3 * p1.y;
y = y + t1_3a * p2.y;
y = y + t1_3b * p3.y;
y = y + t1_3c * p4.y;
bezierSegment[j].x = x;
bezierSegment[j].y = y;
t = t + inc;
end
end
end
–
–[[
local function drawBezierHandles()
if ( gSegments ) then
gSegments:removeSelf()
end
gSegments = display.newGroup()
for i = 1,#endCaps,2 do
local line = display.newLine(endCaps[i].x,endCaps[i].y,endCaps[i+1].x,endCaps[i+1].y);
line:setColor(128,128,128, 0);
line.width=1;
gSegments:insert( line )
table.insert(segMents,line);
end
end
–]]
–
– moveAlongThesegment self explanatory
–
local prevX = 1;
local prevY = 1;
local prevAngle = 1;
local bFirst = true;
local object = nil;
local function createObject()
local objectGroup = display.newImageRect(“f15.png”,100,100);
return objectGroup
end
local function moveAlongThesegment( inc )
if (bFirst == true ) then
object = createObject();
localGroup:insert(object)
prevX = bezierSegment[1].x;
prevY = bezierSegment[1].y;
bFirst = false;
return;
end
local p = {};
p.x = bezierSegment[inc].x;
p.y = bezierSegment[inc].y;
local angle = math.atan2( p.y - prevY, p.x - prevX)
angle = angle * 180 / PIE
object.x = p.x;
object.y = p.y;
object:rotate(angle-prevAngle);
prevAngle = angle;
prevY = p.y;
prevX = p.x;
end
–
local function setupBezier(granularity,r,g,b)
– 1st draw anchor points and handles
–drawBezierHandles();
– 2nd setupBezierSegment
setupBezierSegment(granularity);
– 3rd draw the segment
drawBezierSegment(granularity,r,g,b);
– 4th destroy the segment
destroyBezierSegment();
end
–
local pointInc = 2;
local function randomizeBezierPoints()
for i=1,#endCaps,1 do
if i == 1 then
– print(endCaps[i].x … " blir " … endCaps[4].x)
endCaps[i].x = endCaps[4].x
endCaps[i].y = endCaps[4].y;
else
endCaps[i].x = math.random(screenWidth);
endCaps[i].y = math.random(screenHeight);
end
end
pointInc = 2;
moved = FALSE;
bFirst = false;
setupBezier(100,128,128,128)
end
local function draw (event )
if ( moved == TRUE ) then
setupBezier(50,128,128,128)
pointInc = 2;
bFirst = false;
return true;
elseif (moved == FALSE ) then
if ( pointInc < #bezierSegment ) then
moveAlongThesegment(pointInc);
pointInc = pointInc + speedFactor;
– print(pointInc)
if (pointInc >= #bezierSegment) then
– print(“moved”)
randomizeBezierPoints()
–randomizePositionPoints()
end
end
end
end
–
–[[
local function dragHandles(event)
local t = event.target
local phase = event.phase
if “began” == phase then
– Make target the top-most object
local parent = t.parent
parent:insert( t )
display.getCurrentStage():setFocus( t )
t.isFocus = true
t.x0 = event.x - t.x
t.y0 = event.y - t.y
elseif t.isFocus then
if “moved” == phase then
– Make object move (we subtract t.x0,t.y0 so that moves are
– relative to initial grab point, rather than object “snapping”).
t.x = event.x - t.x0
t.y = event.y - t.y0
moved = TRUE;
elseif “ended” == phase or “cancelled” == phase then
display.getCurrentStage():setFocus( nil )
t.isFocus = false
moved = FALSE;
setupBezier(100,255,128,0);
end
end
return true
end
–]]
–
–[[
local function addListeners()
for i = 1 , #endCaps, 1 do
endCaps[i]:addEventListener(“touch”,dragHandles);
end
end
–]]
–
–[[
local function addPoints (event )
numPoints = numPoints + 1;
if ( numPoints <= 4) then
local point = {}
point.x = event.x;
point.y = event.y;
–local c = display.newCircle(point.x, point.y,10);
–c:setFillColor(255,0,0);
local c = display.newText(#endCaps+1, 0, 0, native.systemFont, 16)
table.insert (endCaps,c);
end
if (numPoints == 4 ) then
Runtime:removeEventListener(“tap”,addPoints)
addListeners()
setupBezier(100,255,128,0);
Runtime:addEventListener(“enterFrame”,draw);
end
end
–]]
–
– MW RANDOM POSITIONS OF POINTS
local function randomizePositionPointsStart()
for i=1,4,1 do
numPoints = numPoints + 1;
if ( numPoints <= 4) then
local point = {}
point.x = math.random(screenWidth);
point.y = math.random(screenHeight);
local c = display.newCircle(point.x, point.y,0);
c:setFillColor(255,0,0,0);
– local c = display.newText(#endCaps+1, 0, 0, native.systemFont, 16)
table.insert (endCaps,c);
end
if (numPoints == 4 ) then
– Runtime:removeEventListener(“tap”,addPoints)
– addListeners()
setupBezier(100,255,128,0);
Runtime:addEventListener(“enterFrame”,draw);
end
end
end
–
local function initBezierSegment()
for j = 1, 100, 1 do
local pt = {};
pt.x = 0;
pt.y = 0;
table.insert(bezierSegment,pt);
end
end
–
local function main()
–[[
for i = 0, display.contentWidth, 20 do
local ll = display.newLine(i,0,i,display.contentHeight);
ll:setColor(98,98,98)
ll.width = 1;
end
for i = 0, display.contentHeight, 20 do
local ll = display.newLine(0,i,display.contentWidth,i);
ll:setColor(98,98,98)
ll.width = 1;
end
–]]
initBezierSegment()
randomizePositionPointsStart()
end
–
main();
return localGroup
end
[/code] [import]uid: 13935 topic_id: 11605 reply_id: 311605[/import]