Drawing and following a line

I have wrote very inefficient code to draw and follow line as below

local tale={} local c=0 local xc,yc,w,h=display.contentCenterX,display.contentCenterY,display.contentWidth,display.contentHeight local blue=display.newRect(xc,yc+300,160,160) blue:setFillColor( 1,0,1 ) local function play(id) transition.to( blue,{x=tale[id].x,y=tale[id].y,time=100,onComplete=function() c=c-1 if c\>0 then play(id+1) end end}) end local function start(event) play(1) return true end local function draw(event) local xa=display.newCircle(event.x,event.y,20) xa:setFillColor( 0,1,1 ) c=c+1 table.insert( tale,c,xa) end local x=display.newRect(xc,yc,100,100) x:setFillColor( 1,0,0 ) local bg=display.newRect(xc,yc,10000,10000) bg:setFillColor( 0,1,0 ) x:toFront() bg:addEventListener( "touch", draw ) x:addEventListener( "touch",start ) blue:toFront( ) --Touch screen to draw..touch red to start

It is very inefficient and doesn’t work as expected…

How to make a line follower efficiently??

One of the guys in my team actually created a system like this a long time ago. It was used in one of our games, but we’ve taken it off the app stores since. It would take me a day or so to dig up its source code and clean that bit up. I’m sure that there are plenty of tutorials for this thing, just chilling around. Probably one such example might be in Roaming Gamer’s GitHub folder, but that’s just a guess. :stuck_out_tongue:

Here are some general points for how you can improve upon what you’ve already created:

  1. You are currently drawing a lot of “tale” entries and using them as is for the coordinates. I would recommend that you pick only a certain number of those points, such as the first and last points, and N number of points in between. You can then use these N+2 points to draw a bezier curve. This’ll give you fewer points to transition from and smoother curves. Or, if you want, you can also draw a bezier line with more points.

  2. You are currently setting all transitions to use 100ms time, however, since the distance between two adjacent points can vary, your transitions will end up looking odd as the object will speed up and slow down between points. In order to address this, you’d need to calculate the pixel distance between two adjacent points, i.e. the transition distance in pixels, and then apply a pixel based time. For instance, if you have two points that are 3px apart and another set of points that are 9px apart, then consider multiplying that pixel count by some time value. If you give both 100ms transition times, then the 3px distance will be covered 3 times slower.

  3. The object seems to be backtracking. Add “print(id)” to the top of the function play, i.e. row 7. You’ll see that the function runs through every id twice, i.e. it first jerks the object back to the previous point and then moves on. This is why the transition looks to bumpy.

your “biggest” problem is not checking the event.phase, fe:

local function start(event) if (event.phase=="began") then play(1) end return true end

because you’re actually running two (phase==“ended”, or more, phase==“moved”) sets of timers.  that’ll eliminate your “double-stepping”, and allow it to traverse the entire line (instead of just half of it)

other things tho:  you should probably “filter” the draw events - if a new point is less than some trivial distance from last point then don’t add it.

then, as per XeduR 2), time should be relative to distance if you wish to maintain a constant velocity.

I looked through my AskEd folder in my Free Stuff archive here: https://github.com/roaminggamer/RG_FreeStuff/

I found two examples that are related to this question:

I combined and tweaked them:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/10/draw_follow_path.zip

End result:

https://www.youtube.com/watch?v=AMzN1e5m44M&feature=youtu.be

If you have a mechanics question, odds are I’ve answered it before and coded it up in either of these archives:

Seems like my guess was spot on. :smiley:

Thanks  RG dave and xedur for your guidance!

Yes!

One of the guys in my team actually created a system like this a long time ago. It was used in one of our games, but we’ve taken it off the app stores since. It would take me a day or so to dig up its source code and clean that bit up. I’m sure that there are plenty of tutorials for this thing, just chilling around. Probably one such example might be in Roaming Gamer’s GitHub folder, but that’s just a guess. :stuck_out_tongue:

Here are some general points for how you can improve upon what you’ve already created:

  1. You are currently drawing a lot of “tale” entries and using them as is for the coordinates. I would recommend that you pick only a certain number of those points, such as the first and last points, and N number of points in between. You can then use these N+2 points to draw a bezier curve. This’ll give you fewer points to transition from and smoother curves. Or, if you want, you can also draw a bezier line with more points.

  2. You are currently setting all transitions to use 100ms time, however, since the distance between two adjacent points can vary, your transitions will end up looking odd as the object will speed up and slow down between points. In order to address this, you’d need to calculate the pixel distance between two adjacent points, i.e. the transition distance in pixels, and then apply a pixel based time. For instance, if you have two points that are 3px apart and another set of points that are 9px apart, then consider multiplying that pixel count by some time value. If you give both 100ms transition times, then the 3px distance will be covered 3 times slower.

  3. The object seems to be backtracking. Add “print(id)” to the top of the function play, i.e. row 7. You’ll see that the function runs through every id twice, i.e. it first jerks the object back to the previous point and then moves on. This is why the transition looks to bumpy.

your “biggest” problem is not checking the event.phase, fe:

local function start(event) if (event.phase=="began") then play(1) end return true end

because you’re actually running two (phase==“ended”, or more, phase==“moved”) sets of timers.  that’ll eliminate your “double-stepping”, and allow it to traverse the entire line (instead of just half of it)

other things tho:  you should probably “filter” the draw events - if a new point is less than some trivial distance from last point then don’t add it.

then, as per XeduR 2), time should be relative to distance if you wish to maintain a constant velocity.

I looked through my AskEd folder in my Free Stuff archive here: https://github.com/roaminggamer/RG_FreeStuff/

I found two examples that are related to this question:

I combined and tweaked them:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/10/draw_follow_path.zip

End result:

https://www.youtube.com/watch?v=AMzN1e5m44M&feature=youtu.be

If you have a mechanics question, odds are I’ve answered it before and coded it up in either of these archives:

Seems like my guess was spot on. :smiley:

Thanks  RG dave and xedur for your guidance!

Yes!