Draw line on screen with swipe

Anybody know how to:

  • Draw a line on the screen when you swipe your finger across the screen, and then convert that line into a static physics body?

Basic idea: object drops from top to bottom, you swipe a line across the screen, and that object interacts with that line.

[import]uid: 50459 topic_id: 9644 reply_id: 309644[/import]

Here’s what I did. It doesn’t work too well and I’m looking for something better.

I created an eventListener on the background that created a small circle/rectangle of about 8px at the spot and added a physics body around it.

That doesn’t produce a solid line, however. It’s full of holes, especially when you move your finger quickly.

I hope that’s good enough! I’m looking forward to seeing if anybody else has a better solution!
[import]uid: 49205 topic_id: 9644 reply_id: 35165[/import]

not exactly as you want but might help

[lua] local prevPoints = {}
local canDraw = 1
local function callMe(e)
if “began” == e.phase then
prevPoints[1] = e.x
prevPoints[2] = e.y
elseif “moved” == e.phase then
if canDraw == 5 then
prevPoints[#prevPoints + 1] = e.x
prevPoints[#prevPoints + 1] = e.y
end
canDraw = canDraw + 1
if canDraw >5 then
canDraw = 1
end
elseif “ended” == e.phase then
for i=1,#prevPoints,2 do
local myRect = display.newLine(prevPoints[i],prevPoints[i+1],prevPoints[i+2],prevPoints[i+3])
local myRect = display.newLine(prevPoints[i +2],prevPoints[i+3],prevPoints[i+4],prevPoints[i+5])
end
for i =1,#prevPoints do
prevPoints[i] = nil
end
end

end
Runtime:addEventListener(“touch”,callMe)[/lua] [import]uid: 12482 topic_id: 9644 reply_id: 35170[/import]

Have a look at Martian Control by BeeBee games (Code exchange). [import]uid: 51516 topic_id: 9644 reply_id: 35181[/import]

Hey,

I’m drawing a line for my app, how can i limit the amount of line drawn? If you draw about 2 inches of line, a table pops of and you are only allowed to draw 3 inches. If you draw more than 3 inches then you can’t draw any more. Also, Show how much is drawn at the moment.
Thanks.

local i = 1
local tempLine
local ractgangle_hit = {}
local prevX , prevY
local function runTouch(event)
if(event.phase==“began”) then
if(tempLine==nil) then
tempLine=display.newLine(event.x, event.y, event.x, event.y)
tempLine:setColor(255,255,255,255)
tempLine.width=4
prevX = event.x
prevY = event.y
end
elseif(event.phase==“moved”) then
tempLine:append(event.x,event.y-2)
tempLine.width=tempLine.width+0.000001
ractgangle_hit[i] = display.newLine(prevX, prevY, event.x, event.y)
ractgangle_hit[i]:append(event.x,event.y)
ractgangle_hit[i].width=2
ractgangle_hit[i].alpha = 0

local Width = ractgangle_hit[i].width * 0.3
local Height = ractgangle_hit[i].height * 0.3
local lineShape = {-Width,-Height,Width,-Height,Width,Height,-Width,Height}

physics.addBody(ractgangle_hit[i], “static”, { density=0.3, friction=0.001, shape = lineShape})
prevX = event.x
prevY = event.y
i = i + 1
elseif(event.phase==“ended”) then
tempLine.parent.remove(tempLine)
tempLine=nil
end
end
Runtime:addEventListener(“touch”, runTouch) [import]uid: 66985 topic_id: 9644 reply_id: 39829[/import]

This is where I am now. I can’t seem to get the physics body to join the points correctly though. Definitely a work a progress and pretty messy. I took it out of my game and put it into its own main.lua file if you want to have a go at making it work.

[code]
–main.lua

require “physics”

obj = {}
obj.drawing = {}

distanceBetween = function(point1, point2)
local deltaX = point1.x - point2.x
local deltaY = point1.y - point2.y
return math.ceil(math.sqrt(deltaX * deltaX + deltaY * deltaY))
end

draw = function(e)

local function disallowErase(platform)
platform.allowErase = false
end
function clickListener(e)
if obj.touchMode == “erase” then
platformTouch = e.target
platform = e.target.platform
if platform.allowErase then
obj.playerInk = obj.playerInk + platform.distance
obj:updateInkCount()
platform:removeSelf()
platformTouch:removeSelf()
end
end
end

– print(e.phase)
if e.phase == “began” then
obj.drawing.points = {}
obj.drawing.count = 0
obj.drawing.phys = {}
local xCoord, yCoord = e.x, e.y
local point = {x = xCoord, y = yCoord }
obj.drawing.points[obj.drawing.count] = point
obj.drawing.phys[obj.drawing.count] = { one = point, two = point }

elseif e.phase == “moved” then
if not obj.drawing.count then
obj.drawing.count = 0
obj.drawing.points = {}
end
– print(“Count: " … obj.drawing.count)
local xCoord, yCoord = e.x, e.y
local newPoint = { x = xCoord, y = yCoord }
local oldPoint = obj.drawing.points[obj.drawing.count]
local distance = distanceBetween(oldPoint, newPoint)
if distance < 10 then
return false
end
print(”-" … obj.drawing.count)

obj.drawing.count = obj.drawing.count + 1
obj.drawing.points[obj.drawing.count] = {x = xCoord, y = yCoord }

local platform = display.newLine(oldPoint.x, oldPoint.y, newPoint.x, newPoint.y)
platform.width = 9
platform.alpha = .2
local halfDeltaX = math.abs((newPoint.x - oldPoint.x)) * .5
local halfDeltaY = math.abs((newPoint.y - oldPoint.y)) * .5
local halfWidth = platform.width / 9

local phyX, phyY = halfDeltaX, halfDeltaY
if phyX < 3 then
phyX = 3
end
if phyY < 3 then
phyY = 3
end
local x1, y1 = -phyX, -phyY – -halfDeltaX, -halfWidth
local x2, y2 = phyX, -phyY – halfDeltaX, -halfWidth
local x3, y3 = phyX, phyY – halfDeltaX, halfWidth
local x4, y4 = -phyX, phyY – -halfDeltaX, halfWidth

–local platformShape = { x1,y1,x2,y2,x3,y3,x4,y4 }
–local platformFilter = { categoryBits = 1, maskBits = 6}
–physics.addBody(platform, “static”, { shape = platformShape, friction = .15, bounce = .1, filter = platformFilter })
obj.drawing.points[obj.drawing.count].segment = platform
local x2,y2 = platform:localToContent(x2,y2)
local x4,y4 = platform:localToContent(x4,y4)
local pointOne = { x = x2, y = y2 }
local pointTwo = { x = x4, y = y4 }
obj.drawing.phys[obj.drawing.count] = { one = pointOne, two = pointTwo }

return true

– print(drawing.points[drawing.count].x … " " … drawing.points[drawing.count].y)
– print(drawing.points[drawing.count-1].x … " " … drawing.points[drawing.count-1].y)

elseif e.phase == “ended” then
local physicsShape = {}
local segment = obj.drawing.points[1].segment
print("Number of points " … #obj.drawing.points)
for i=1, #obj.drawing.points do
local x, y = segment:contentToLocal(obj.drawing.phys[i].one.x, obj.drawing.phys[i].one.y)
table.insert(physicsShape, x)
table.insert(physicsShape, y)
local a,b = segment:localToContent(x,y)
local test = display.newCircle(a,b,2,2)
test:setFillColor(255,0,0)

– print("{"…x…", “…y…”)")
end

–print("---------")
local number = #obj.drawing.points

for i=0, number -1 do
local x, y = segment:contentToLocal(obj.drawing.phys[i].two.x, obj.drawing.phys[i].two.y)
table.insert(physicsShape, x)
table.insert(physicsShape, y)
local a,b = segment:localToContent(x,y)
local test = display.newCircle(a,b,2,2)
test:setFillColor(0,0,255)

–print("{"…x…", “…y…”)")
end
–for k,v in pairs(physicsShape) do print(k,v) end
–print("Physics points " … #physicsShape/2)
physics.addBody(segment, “static”, { shape = physicsShape })

end

end

local function main()
physics.start()
physics.setDrawMode(“hybrid”)
Runtime:addEventListener(“touch”, draw)
return true
end

main()
[/code] [import]uid: 49205 topic_id: 9644 reply_id: 39875[/import]

Hello,

thanks a lot for this. What game is this ?

thank you. [import]uid: 23689 topic_id: 9644 reply_id: 39882[/import]

@Michael

My game isn’t released yet. This drawing thing is a big missing component.

Also, please note that the code I posted doesn’t work as is. [import]uid: 49205 topic_id: 9644 reply_id: 39884[/import]

@rmbsoft, you want to make something like the early Physics games, I guess it was called Crayon Physics, right?

Have a look at samples from Martian Control, from Fruit Samurai

as for limiting the length of the line, you have to calculate how many pixels to an inch and count the pixels that are drawn, if you get the co-ordinates, you can get the length of the line in pixels.

You can either have fine tuned lines by following the finger or having a tap, tap click to draw a line, whereby, you start to draw the line from the first point tapped to the second point tapped and it goes on till the user taps on a button or something. this will give you more rigid lines than fluid lines, but you can then convert these into curves, there are plenty of algorithms to do so.

Carlos even has Books on these, ask him…:wink:

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 9644 reply_id: 39885[/import]

I found this searching the forum for the same thing this is a very simplified version. It should get you started at least. I have a need to do something like this also but I need to work on a interpolation routine to smooth the points.

[lua]display.setStatusBar( display.HiddenStatusBar )

local linePoints = {};

local moved = FALSE;
local bbg = display.newRect(0,0,display.contentWidth,display.contentHeight);
bbg:setFillColor(55,55,55)
local function dragHandles(event)

local phase = event.phase
if “began” == phase then
– Make target the top-most object

local pt = {}
pt.x = event.x;
pt.y = event.y;
table.insert(linePoints,pt);
elseif “moved” == phase then
local pt = {}
pt.x = event.x;
pt.y = event.y;
table.insert(linePoints,pt);
moved = TRUE;
elseif “ended” == phase or “cancelled” == phase then
moved = FALSE;
end

return true

end



local function drawLine()
if ( line ) then line:removeSelf() end

if #linePoints > 2 then
print(#linePoints)
line = display.newLine(linePoints[1].x,linePoints[1].y,linePoints[2].x,linePoints[2].y);
for i = 3, #linePoints, 1 do
line:append(linePoints[i].x,linePoints[i].y);
end
line:setColor(128,128,0);
line.width=4;
end
end



local function draw (event )
if ( moved == TRUE ) then
drawLine()
return true;
end
end



local function main()
Runtime:addEventListener(“touch”,dragHandles);
Runtime:addEventListener(“enterFrame”,draw);
end



main();[/lua] [import]uid: 14451 topic_id: 9644 reply_id: 39908[/import]

Note that the points are stored in a table you will need to turn those points into physics geometry. [import]uid: 14451 topic_id: 9644 reply_id: 39909[/import]

I found this code somewhere on the forum, but when i try to create a physics body from it, it doesn’t match with the line itself.

Say i draw a horizontal line, then the physics body is located at the right x-axis, but the y-axis is way to far to the left?

function drawLine( event )  
  
 if (event.phase == "began") then  
 if line == nil then  
 else  
 line:removeSelf()  
 end  
 end  
 if(event.phase == "ended") then  
  
 line = display.newLine(event.xStart, event.yStart, event.x, event.y)  
 line:setColor(255,0,0)  
 line.width = 15  
 physics.addBody( line, "static", { density=0.3, friction=0.6, bounce=0.8} )  
  
 end  
end  
Runtime:addEventListener("touch", drawLine)  
  

Anyone?
[import]uid: 50459 topic_id: 9644 reply_id: 40287[/import]

@rmbsoft

From what I’ve been able to see, adding a physics body to a line like that will only work if its drawn horizontally or vertically. It basically just creates a rectangular body whose sides just barely contain all of the points. [import]uid: 49205 topic_id: 9644 reply_id: 40322[/import]

here is what I have, it works okay but what is bad about it is that when you swipe your finger fast the physic body (if you go in hybrid) has holes in it. It also sometimes does not show the graphics of the line.
here is the code:
local physics = require (“physics”)
physics.start(true)
physics.setDrawMode “hybrid”

local i = 1
local tempLine
local ractgangle_hit = {}
local prevX , prevY
local function runTouch(event)
if(event.phase==“began”) then
if(tempLine==nil) then
tempLine=display.newLine(event.x, event.y, event.x, event.y)
tempLine:setColor(255,255,255,255)
tempLine.width=4
prevX = event.x
prevY = event.y
end
elseif(event.phase==“moved”) then
tempLine:append(event.x,event.y-2)
tempLine.width=tempLine.width+0.000001
ractgangle_hit[i] = display.newLine(prevX, prevY, event.x, event.y)
ractgangle_hit[i]:append(event.x,event.y)
ractgangle_hit[i].width=2
ractgangle_hit[i].alpha = 0

local Width = ractgangle_hit[i].width * 0.3
local Height = ractgangle_hit[i].height * 0.3
local lineShape = {-Width,-Height,Width,-Height,Width,Height,-Width,Height}

physics.addBody(ractgangle_hit[i], “static”, { density=0.3, friction=0.7, shape = lineShape})
prevX = event.x
prevY = event.y
i = i + 1
elseif(event.phase==“ended”) then
tempLine.parent.remove(tempLine)
tempLine=nil
end
end
Runtime:addEventListener(“touch”, runTouch)
[import]uid: 23689 topic_id: 9644 reply_id: 40413[/import]

a better solution to this is apreciated [import]uid: 23689 topic_id: 9644 reply_id: 40414[/import]

Hey,

How can we make the table in the code for the line to react to physic bodies ? Thank you ! Help is very much appreciated! :slight_smile: [import]uid: 23689 topic_id: 9644 reply_id: 42995[/import]