Feeds:
Posts
Comments

Archive for October, 2009

Stevie G asks on the blitzbasic forums:

My mind’s gone a blank so I’m looking for some help here. What I need is the angle of elevation a weapon needs to be at to launch a projectile and hit a target. The target can be higher or lower than the weapon. I’m working in 2d so have the following information available:

X0 = X coord of weapon
Y0 = Y coord of weapon
X1 = X coord of target
Y1 = Y coord of target
Speed = Launch Speed of projectile
Gravity = -9.8

I’m not interested in including wind resistence etc..

A Level maths to the rescue! Use one of the equations of motion:

s = ut + \frac{1}{2}at^2

Where s is the distance travelled, u is the initial velocity, a is the acceleration, and t is time elapsed. We want to find an angle \phi to shoot the projectile at which will satisfy this equation.

Deal with the x- and y-components of motion separately. There’s no acceleration in the x-axis, so that equation will be easy to rearrange to get an expression for t:

\begin{array}{rcl}s_x &=& x_1-x_0 \\ u_x &=& V \cos(\phi) \\ a_x &=& 0 \\ \\ s_x &=& (V \cos(\phi))t \\ t &=& \frac{s_x}{V \cos(\phi)} \end{array}

Now we can put that into the equation for the y-axis:

\begin{array}{rcl}s_y &=& y_1-y_0 \\ u_y &=& V \sin(\phi) \\ a_y &=& g \\ \\ s_y &=& V \sin(\phi) (\frac{s_x}{V \cos(\phi)}) + \frac{1}{2}g(\frac{s_x^2}{V^2\cos^2(\phi)}) \end{array}

Now some clever cancelling and use of trig identities:

\begin{array}{rcl} s_x \tan(\phi) + \frac{gs_x^2}{2V^2}\sec^2(\phi) - s_y &=& 0 \\ \frac{gs_x^2}{2V^2}\tan^2(\phi) + s_x\tan(\phi) + (\frac{gs_x^2}{2V^2} - s_y) &=& 0 \end{array}

which, if you’re willing to believe it, is a quadratic equation in \tan(\phi). Use the quadratic formula to find \tan(\phi) and hence \phi. Simples!

… that’s a lie, so here’s some bmax code:

Graphics 600,600,0Graphics 600,600,0
Global bullets:TList=New TList
Type bullet
	Field x#,y#
	Field vx#,vy#
	Field path#[]

	Function Create:bullet(x#,y#,vx#,vy#)
		b:bullet=New bullet
		bullets.addlast b
		b.x=x
		b.y=y
		b.vx=vx
		b.vy=vy
		Return b
	End Function

	Method update()
		path:+[x,y]

		x:+vx
		y:+vy
		vy:+g
		DrawRect x-5,y-5,10,10

		For i=0 To Len(path)-1 Step 2
			DrawRect path[i],path[i+1],1,1
		Next

		If x>600 Or y>600
			bullets.remove Self
		EndIf
	End Method
End Type

'the setup is that you've got a cannon at (0,300), trying to fire at the mouse cursor.
'gravity is directed down the screen and the velocity of the projectiles is fixed at 20 px per frame.
'there will be some inaccuracy in the projectiles drawn on the screen because I'm using a discrete timestep model, due to I'm lazy.

Const g#=1,v#=20

While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())
	sx#=MouseX()
	sy#=MouseY()-300

	a#=g*sx*sx/(2*v*v)	'coefficients of the quadratic equation
	b#=sx
	c#=a-sy

	If b*b>4*a*c	'if solution exists

		t#=(-b+Sqr(b*b-4*a*c))/(2*a)		'this is tan(phi)

		an#=ATan(t)
		DrawLine 0,300,sx,sy+300

		If MouseHit(1)
			bullet.Create 0,300,v*Cos(an),v*Sin(an)
		EndIf

	Else
		DrawText "no solution!",0,0
	EndIf

	For bu:bullet=EachIn bullets
		bu.update
	Next

	Flip
	Cls
Wend

Hope that’s useful!

Read Full Post »