# Path drawing

I want to make a game where player can control the characters by touch them and draw the path for them to follow. But I don’t know how to start. Can anyone suggest me or give me example?

Thank you

Hi @wave, May be this link could help you: http://twolivesleft.com/Codea/Talk/discussion/comment/13802#Comment_13802

@wave

Is this what you’re after. Just drag your finger on the screen to leave a trail. Once you lift your finger, the circle will follow the trail. After the circle stops, draw another trail somewhere on the screen and the circle will find the start of the trail and then follow it. I don’t like the way this works, but I don’t have the time to make it better right now, but this might give you a starting point.
If the points on the trail are close together, the circle gets kind of jerky, so the faster you draw the trail, the smoother it moves.

``````
displayMode(FULLSCREEN)
function setup()
mx=0
my=0
init()
end

function init()
tab1={}    -- table for points
offset=1
dx=0
dy=0
move=false
end

function draw()
background(40, 40, 50)
for z=2,#tab1-1 do
stroke(255)
strokeWidth(3)
line(tab1[z-1].x,tab1[z-1].y,tab1[z].x,tab1[z].y)
end
if move then    -- try to move at constant speed
a=math.sqrt(dx*dx+dy*dy)
b=5/a
mx = mx + dx*b
my = my + dy*b
end
fill(255)
ellipse(mx,my,20,20)
moveCircle()
end

function touched(t)
if t.state==BEGAN and not en then
if mx==0 and my==0 then
mx=t.x
my=t.y
end
elseif t.state==MOVING then
table.insert(tab1,vec2(t.x,t.y))    -- insert points in table
elseif t.state==ENDED then
dx=(tab1[offset].x-mx)
dy=(tab1[offset].y-my)
move=true
end
end

function moveCircle()
if move then
if offset==#tab1 then
init()
return
end
a=math.abs(tab1[offset].x-mx)    -- calc new x,y direction
b=math.abs(tab1[offset].y-my)
ab=math.sqrt(a*a+b*b)
if a<1 and b<1 or ab<5 then
offset = offset + 1
dx=tab1[offset].x-mx
dy=tab1[offset].y-my
end
end
end

``````

@dave1707

Thank you, this really help me getting start. But can you explain a moveCircle function? I’m quite confused. Thanks again for the help.

@wave

I added more comments to moveCircle(). Here is what’s happening. The circle moves from one position in the table to the next. When I reach a point in the table, I get the x,y difference to the next point. Based on that difference, I know how far I need to move in the x direction and the y direction. As the circle moves, I check if it reaches the next point, that’s the check a<1 and b<1. I also add code if the x,y distance is within 5 of the next point, that’s the ab<5. The circle didn’t always get within 1 of the next point and would leave the trail. Actually, you don’t need the a<1and b<1check, just the ab<5. Up in the draw function, I calculate the distance the circle needs to travel and try to move it at a constant speed. I hope that explains things better. Like I said earlier, I’m not satisfied with the way all this is working, but it works. I’m sure someone will come up with a better routine.

``````
function moveCircle()
if move then  -- if the circle is moving, then execute the following code

if offset==#tab1 then  -- circle reached end of trail, start over
init()
return
end

a=math.abs(tab1[offset].x-mx)  -- difference between circle x and table x position
b=math.abs(tab1[offset].y-my)  -- difference between circle y and table y position

ab=math.sqrt(a*a+b*b) -- distance between circle x,y and table x,y position

-- check if the circle reached the next point in the table
if a<1 and b<1 or ab<5 then -- if x,y difference less 1 or distance less than 5

offset = offset + 1  -- offset for the next position in the table

-- get the difference of where the circle is and where it needs to go
dx=tab1[offset].x-mx  -- difference between circle x and table x position
dy=tab1[offset].y-my  -- difference between circle y and table y position

end
end
end

``````

@wave

Here is another version. I limit the number of points in the table. If you drag your finger slow, I won’t insert a point unless it’s more than 20 away from the previous point. I also remove the trail as the circle moves along. And I removed the a<1 and the b< 1 from moveCircle. Still not very good, but better.

``````
displayMode(FULLSCREEN)
function setup()
mx=0
my=0
init()
end

function init()
tab1={}    -- table for points
offset=1
dx=0
dy=0
move=false
end

function draw()
local a; local b
local line=line
background(40, 40, 50)
for z=offset+1,#tab1-1 do
stroke(255)
strokeWidth(3)
line(tab1[z-1].x,tab1[z-1].y,tab1[z].x,tab1[z].y)
end
if move then    -- try to move at constant speed
a=math.sqrt(dx*dx+dy*dy)
b=5/a
mx = mx + dx*b
my = my + dy*b
end
fill(255)
ellipse(mx,my,20,20)
moveCircle()
end

function calcDist()-- don't draw points within 20 of the previous point
local t=#tab1
local a; local b
if t>1 then
a=hx-tab1[t].x
b=hy-tab1[t].y
if a*a+b*b>400 then
return true
end
return false
end
return true
end

function touched(t)
if t.state==BEGAN and not en then
if mx==0 and my==0 then
mx=t.x
my=t.y
end
elseif t.state==MOVING then
hx=t.x
hy=t.y
if calcDist() then -- limit points in the table
table.insert(tab1,vec2(t.x,t.y))    -- insert points in table
end
elseif t.state==ENDED then
dx=(tab1[offset].x-mx)
dy=(tab1[offset].y-my)
move=true
end
end

function moveCircle()
local a; local b; local ab
if move then
if offset==#tab1 then
init()
return
end
a=math.abs(tab1[offset].x-mx)    -- calc new x,y direction
b=math.abs(tab1[offset].y-my)
ab=math.sqrt(a*a+b*b)
if ab<5 then
offset = offset + 1
dx=tab1[offset].x-mx
dy=tab1[offset].y-my
end
end
end

``````

@dave1707

Thank you again. Your explanation help me understand much better.

(By the way, there is a crash when press a finger and lift it without moving)

.@dave1707
Thanks for your permanent help to us, I want to add a background image to this code in order to enable delineation of figures from it and to save them.

1. How to add a background image into this code ( sprite , setContext, …)

2. How to close this trail and fill the inside with a transparent color by playing on its alpha to verify that the region delineated is accurate.

Great thanks for your previous help to .@letaief

Hi @letaief

1. You want a sprite as the background. 2) You want to drag your finger to close an area and fill it with a transparent color. How close is this. This isn’t the greatest, but I’m not exactly sure what you’re trying to do. Drag your finger in a large circle on the sprite.
``````
displayMode(FULLSCREEN)
function setup()
count=0
tab={}
mtab={}
m=mesh()
end

function draw()
background(40, 40, 50)
sprite("Cargo Bot:Codea Icon",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
m.vertices=mtab
m:setColors(0,0,0,75)  -- transparent color
m.draw(m)
end

function touched(t)
if t.state==MOVING then
count = count + 1
table.insert(tab,t)
if count>1 then
table.insert(mtab,(vec2(tab.x,tab.y)))
table.insert(mtab,(vec2(tab[count-1].x,tab[count-1].y)))
table.insert(mtab,(vec2(tab[count].x,tab[count].y)))
end
end
end

``````

Hi @wave

The crash doesn’t surprise me. I don’t like the way the code is working, so eventually I’m going to re-write it and make it better. Glad the explanation helped.

@dave1707
I added my own code a bit to change the line to dot and make player to have to draw from the circle for it to follow. I also fix the crash too, it happens because when you touch and lift your finger, it won’t call the t.state == moving so no insert table. But later on the code calls that nil thing so it crash.

Here’s my version I would be very glad if you have anything to suggest about it.

``````displayMode(FULLSCREEN)
function setup()
mx=0
my=0
init()
end

function init()
tab1={}    -- table for points
offset=1
dx=0
dy=0
move=false
mx1 = 0
my1 = 0
insert = false
end

function draw()
local a; local b
local line=line
background(0, 0, 0, 255)
for z=offset+1,#tab1-1 do
stroke(255, 255, 255, 255)
strokeWidth(3)
--line(tab1[z-1].x,tab1[z-1].y,tab1[z].x,tab1[z].y)
if math.abs(tab1.x - mx1) < 30 and math.abs(tab1.y - my1) < 30 then
ellipse(tab1[z-1].x,tab1[z-1].y,3)
end
end
if move then    -- try to move at constant speed
a=math.sqrt(dx*dx+dy*dy)
b=5/a
mx = mx + dx*b
my = my + dy*b
end
fill(255, 255, 255, 255)
ellipse(mx,my,40,40)
moveCircle()
end

function calcDist()-- don't draw points within 20 of the previous point
local t=#tab1
local a; local b
if t>1 then
a=hx-tab1[t].x
b=hy-tab1[t].y
if a*a+b*b>400 then
return true
end
return false
end
return true
end

function touched(t)
if t.state==BEGAN and not en then
mx1=t.x
my1=t.y
if mx==0 and my==0 then
mx=t.x
my=t.y
end

elseif t.state==MOVING then
hx=t.x
hy=t.y
if calcDist() then -- limit points in the table
table.insert(tab1,vec2(t.x,t.y))    -- insert points in table
insert = true
end

elseif t.state==ENDED then
if insert then
if math.abs(tab1.x - mx) < 30 and math.abs(tab1.y - my) < 30 then
move=true
dx=(tab1[offset].x-mx)
dy=(tab1[offset].y-my)

else
init()
return
end
end
end
end

function moveCircle()
local a; local b; local ab
if move then
if offset==#tab1 then
init()
return
end
a=math.abs(tab1[offset].x-mx)    -- calc new x,y direction
b=math.abs(tab1[offset].y-my)
ab=math.sqrt(a*a+b*b)
if ab<5 then
offset = offset + 1
dx=tab1[offset].x-mx
dy=tab1[offset].y-my
end
end
end
``````

(Now I’m trying to make multiple circles and draw path for them individually. I think it will be done soon but again, any advice would be nice)

In order to have multiple circles and paths for them to follow, you’ll have to change the code to add tables to keep track of the circle/dot values for each one and the calculations. For example, tab1 will have to be a multiple table. Instead of tab1[z], it will have to be tab1[nbr][z] where nbr will be the number for the different circles. Each time you touch the screen to draw the points, nbr will have to be incremented. Will the circles start moving as soon as you lift your finger, or will you draw multiple paths and then start the circles. Post if you have questions.

You should also look at using a tween library for smooth motion or clean the code up by writing a function.

What or where is the tween library. A google search didn’t show anything useful, and it’s not mentioned in Codea. All of my coding is done on the iPad, so if it’s not in Codea, I can’t use it.

It will be in 1.5 release of Codea.

To .@dave1707

http://www.pcastuces.com/pratique/multimedia/photoshop/lasso.htm

The image pedro.bmp! Explains what I intend to do with this code.

I want to Draw any shape from anatomical images, from scintigraphic images or any other medical imaging file.

Thanks @Jmv38

Guess I should have skipped the Google search and did a forum search instead.

To @letaief

I guess you’re talking about a lasso tool that’s found in a lot of photo editors. Do you want something like that written in Codea or could you just download one of the free photo editors to do what you want.

I want it in Codea, if you remember I wrote in a previous post about ROI (region of interest) and you posted a code that I tried and worked but not as I needed, I let that in stand by and when I saw this post on path drawing I returned to this idea. I thought that the lasso is a French term thats why I didn’t use it. sorry for my bad English.

I can’t do multitouch and the code is not quite work. Can you help me fix it?

``````
displayMode(FULLSCREEN)
function setup()
init()
end

function init()
tab1={}
offset = {}
mx = {}
my = {}
dx = {}
dy = {}
move = {}
mxi = {}
myi = {}
ptouch = {}
insert = {}
touches = {}
for w = 1, 8 do
tab1[w] = {}
mxi[w] = 0
myi[w] = 0
move[w] = false
offset[w] = 1
dx[w] = 0
dy[w] = 0
ptouch[w] = false
mx[w] = 50*w*2
my[w] = 125
insert[w] = false
end
end

function draw()
background(0, 0, 0, 255)
fill(255, 255, 255, 255)
for w = 1, 8 do
local a; local b
for z=offset[w]+1,#tab1[w] - 1 do
stroke(255, 255, 255, 255)
strokeWidth(3)
if math.abs(tab1[w].x - mxi[w]) < 30 and math.abs(tab1[w].y - myi[w]) < 30 then
ellipse(tab1[w][z-1].x,tab1[w][z-1].y,3)
end
end
if move[w] then -- try to move at constant speed
a=math.sqrt(dx[w]*dx[w]+dy[w]*dy[w])
b=5/a
mx[w] = mx[w] + dx[w]*b
my[w] = my[w] + dy[w]*b
moveCircle(w)
end
ellipse(mx[w],my[w],40,40)
end
end

function calcDist() -- don't draw points within 20 of the previous point
for w = 1,8 do
local t=#tab1[w]
local a; local b
if t>1 then
a=hx-tab1[w][t].x
b=hy-tab1[w][t].y
if a*a+b*b>400 then
return true
end
return false
end
end
return true
end

function touched(touch)
if touch.state==BEGAN then
-- touches[touch.id] = touch
for w = 1, 8 do
if touch.x > (mx[w] - 40) and touch.x < (mx[w] + 40) and
touch.y > (my[w] - 40) and touch.y < (my[w] + 40) then
mxi[w] = touch.x
myi[w] = touch.y
ptouch[w] = true
else ptouch[w] = false end
end

elseif touch.state==MOVING then
-- touches[touch.id] = touch
hx=touch.x
hy=touch.y
if calcDist() then -- limit points in the table
for w = 1, 8 do
if ptouch[w] then
table.insert(tab1[w],vec2(touch.x,touch.y))    -- insert points in table
insert[w] = true
end
end
end

elseif touch.state==ENDED then
--   touches[touch.id] = nil
for w = 1, 8 do
if insert[w] == true then
if math.abs(tab1[w].x - mx[w]) < 30 and
math.abs(tab1[w].y - my[w]) < 30 then
move[w]=true
dx[w]=(tab1[w][offset[w]].x-mx[w])
dy[w]=(tab1[w][offset[w]].y-my[w])
else
return
end
end
end
end
end

function moveCircle(w)
local a; local b; local ab
if move[w] then
if offset[w]==#tab1[w] then
tab1[w] = {}
offset[w]=1
dx[w]=0
dy[w]=0
move[w]=false
mxi[w] = 0
myi[w] = 0
insert[w] = false
ptouch[w] = false
return
end
a=math.abs(tab1[w][offset[w]].x-mx[w])
b=math.abs(tab1[w][offset[w]].y-my[w])
ab=math.sqrt(a*a+b*b)
if ab<5 then
offset[w] = offset[w] + 1
dx[w]=tab1[w][offset[w]].x-mx[w]
dy[w]=tab1[w][offset[w]].y-my[w]
end
end
end
``````