[SOLVED] Bezier Curves, how to trace a line?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: Bezier Curves, how to trace a line?

Post by unixfreak »

MasterLee wrote: Fri Apr 21, 2017 6:21 am Read the following post it covers the problem
https://love2d.org/forums/viewtopic.php ... me#p210511
I'm fully aware of how that can cause problems in some use cases, but it isn't important here. The i value is only being used to remove that index from the list, it's not referenced anywhere else.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Bezier Curves, how to trace a line?

Post by zorg »

unixfreak wrote: Fri Apr 21, 2017 6:48 am
MasterLee wrote: Fri Apr 21, 2017 6:21 am Read the following post it covers the problem
https://love2d.org/forums/viewtopic.php ... me#p210511
I'm fully aware of how that can cause problems in some use cases, but it isn't important here. The i value is only being used to remove that index from the list, it's not referenced anywhere else.
But it is referenced, by the ipairs iterator. You are basically pulling elements out under the iterator, which also moves all indices back by one, making it skip entries.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: Bezier Curves, how to trace a line?

Post by unixfreak »

zorg wrote: Fri Apr 21, 2017 7:37 am But it is referenced, by the ipairs iterator. You are basically pulling elements out under the iterator, which also moves all indices back by one, making it skip entries.
Then i suppose it must be good practice to iterate over all tables backwards where items are added/removed in a loop every time? There isn't a visible problem as it is, but looking closer now i can see what problem that could cause.
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: Bezier Curves, how to trace a line?

Post by unixfreak »

On the topix of bezier curves,
I tried to look through Ref's example, where the car moves around the track, although i can't work out what is actually going on in the code to rotate the sprite in the correct direction of movement.

I do see this on the wiki:
https://love2d.org/wiki/BezierCurve:getDerivative
This function can be used to rotate sprites moving along a curve in the direction of the movement and compute the direction perpendicular to the curve at some parameter t.
However i'm not sure how to utilise that to rotate a sprite. Does anyone have an example of this function?
How would you use it? It returns userdata as "BezierCurve", but plotting/drawing it doesn't explain much of what it is doing.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Bezier Curves, how to trace a line?

Post by raidho36 »

From basic math knowledge, derivative of a function is another function, which value equals to tangent of original function curve at any given point. It can be interpreted as its direction in that point. Mathematically defined as f'(x) = Δx / Δf, i.e. ratio of step length to step value change - its tangent.

So you compute a derivative of the curve, and you get another curve that has original curve's direction in it. When you draw a sprite, you sample its position from original curve, and rotation from derivative curve. I've never used it, so you may need to pass it through arc tangent function to get meaningful angle.
Attachments
315px-Derivative_of_a_function.svg.png
315px-Derivative_of_a_function.svg.png (23.4 KiB) Viewed 5835 times
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: Bezier Curves, how to trace a line?

Post by unixfreak »

My maths knowledge isn't too great, but that makes things more understandable. I have just been fiddling around with math.atan2 in an attempt to rotate a sprite along the derivative curve, but can't seem to get it to work right.

I put together a small love file with relevant code of what i am trying to do here.
The sprite is rotating, but i must be setting something wrong, as it is inaccurate.

The derivatives are drawn here, but end up far off the screen in most cases.
Basically, right click somewhere, then left click somewhere else. Hopefully this should make sense of what i'm trying to do.
bezier_test.love
(2.58 KiB) Downloaded 106 times
Also the code, to save having to unzip it all.

Code: Select all

missiles = {}
missiles.launched = {}
missiles.icbm = love.graphics.newImage("icbm.png")


target = {
	x = love.graphics.getWidth()/2,
	y = love.graphics.getHeight()/2
}

function ripairs(t)
	--same as ipairs, but itterate from last to first
	local function ripairs_it(t,i)
		i=i-1
		local v=t[i]
		if v==nil then return v end
		return i,v
	end
	return ripairs_it, t, #t+1
end



function love.mousepressed(x,y,button) 
	--left click to launch a missile
	if button == 1 then
		missiles.add(x,y,target.x,target.y)
	end
	
	--right click to set a target
	if button == 2 then
		target.x = x
		target.y = y
	end
	
end


function missiles.add(x,y)	
	
	local ax = x
	local ay = y
	local tx = target.x
	local ty = target.y
	
	
	--values for the bezier curve
	local bx,by
	if ax < tx then 
		bx = ax + (tx - ax)
	else
		bx = tx+ (ax -tx)
	end
	
	if ay < ty then
		by = 0
	else
		by = 0
	end
	
	local trajectory = love.math.newBezierCurve(
		tx,ty,bx,by,ax,ay
	)
	
	
	table.insert(missiles.launched, {
		x = ax, -- missile source
		y = ay,
		
		mx = ax, -- missile projectile
		my = ay,
		
		tx = tx, -- missile destination
		ty = ty,
		
		dx = 0, -- missile derivative
		dy = 0,
		
		t = 0, -- missile time / distance
				
		trajectory = trajectory, -- the bezier curves
		derivative = trajectory:getDerivative(),
		
		angle = 0, -- angle of missile sprite
		o = 200, --opacity
		speed = 0.25, -- speed used for "t"
		info = false, -- hud overlay
		weapon = "ICBM" -- weapon type
	})
	
	--sound.playfx("launch")
	

end

function love.update(dt)
	for i, missile in ripairs(missiles.launched) do

		missile.t = missile.t+missile.speed*dt
		
		
		if missile.t > 1 then
			--missile reaches destination
			table.remove(missiles.launched,i)
		else
		
			--evaluate missile trajectory
			missile.mx,missile.my = missile.trajectory:evaluate(missile.t)
			
			--evaluate missile derivative trajectory
			missile.dx,missile.dy = missile.derivative:evaluate(missile.t)
			
			--find the difference in angle (draw missile sprite using this)
			missile.angle = math.atan2(missile.mx-missile.dx, missile.my-missile.dy)

		end
	end
end

function love.draw()
	for i, missile in ipairs(missiles.launched) do
		
		
		love.graphics.setColor(0,255,0,200)
		love.graphics.circle("fill",missile.mx,missile.my,10)
				
		--draw incremental beacons across trajectory
		for i=0,10 do
			local x,y = missile.trajectory:evaluate(i/10)
			local size = 5
			love.graphics.rectangle("fill",x-size/2,y-size/2,size,size)
			
			local x,y = missile.derivative:evaluate(i/10)
			local size = 5
			love.graphics.rectangle("fill",x-size/2,y-size/2,size,size)
		end
		
		--the bezier curve (trajectory)
		love.graphics.setColor(
			255,0,0,missile.o
		)
		love.graphics.line(missile.trajectory:render())
		
		--derivative curve
		love.graphics.line(missile.derivative:render())
	
		
		--position of point/time on the bezier curves
		love.graphics.circle("fill",missile.mx,missile.my,5)
		love.graphics.circle("fill",missile.dx,missile.dy,5)
		
		
		love.graphics.line(missile.mx,missile.my,missile.dx,missile.dy)
		
		
		love.graphics.setColor(
			255,155,0,255
		)
		love.graphics.draw(missiles.icbm, missile.mx,missile.my, missile.angle, 1,1,missiles.icbm:getWidth()/2,missiles.icbm:getHeight()/2)
	
	
	end
	
	love.graphics.setColor(255,255,255,255)
	love.graphics.print("right click to select launch site\nleft click to launch missile",10,10)
end

User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Bezier Curves, how to trace a line?

Post by raidho36 »

Yes, you should just feed it derivative coordinates. I had to offset resulting angle because your sprite is rotated.
Attachments
bezier_test.love
(2.52 KiB) Downloaded 146 times
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: Bezier Curves, how to trace a line?

Post by unixfreak »

raidho36 wrote: Sat Apr 22, 2017 8:55 pm Yes, you should just feed it derivative coordinates. I had to offset resulting angle because your sprite is rotated.
I had a feeling i was plotting the derivative wrongly, but seems that was not the case. :awesome: Many thanks! That works perfectly.
Thank you everyone for the suggestions / examples. I think i understand this alot better now.
User avatar
alberto_lara
Party member
Posts: 372
Joined: Wed Oct 30, 2013 8:59 pm

Re: [SOLVED] Bezier Curves, how to trace a line?

Post by alberto_lara »

I know it's already solved but maybe you could try a tweening library the next time, flux is a nice option :)
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: [SOLVED] Bezier Curves, how to trace a line?

Post by unixfreak »

alberto_lara wrote: Sat Apr 22, 2017 10:35 pm I know it's already solved but maybe you could try a tweening library the next time, flux is a nice option :)
Yes, that's always the easiest/fastest approach, but i've never been keen on using libraries for making small demos/games. Mostly because i'd like to use Love2D as a learning experience, which can be carried across other programming languages with the logic. A complicated library mostly does everything without teaching you much of how it actually works. Just my opinion though.
Post Reply

Who is online

Users browsing this forum: No registered users and 46 guests