Feeds:
Posts
Comments

Posts Tagged ‘aiming’

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 »

In this post, SpaceTW asked:

Hi, I need help aiming at moving targets for a program. I have the variables for the speed and direction of the enemies, but the targeting is still not accurate enough.

There’s a very simple solution if you don’t mind the bullets travelling at different speeds, but that can lead to bullets travelling very fast or very slow, so let’s say that we want every bullet to go the same speed. Here’s the solution:

Suppose you have a tower at a fixed position (x_0,y_0), and an enemy at initial position (x_1,y_1) moving in the direction (v_x,v_y).

You want to shoot a bullet travelling at a certain velocity V so that it collides with the enemy.

Let the direction of the bullet be (d_x,d_y).

If d_x=v_x and d_y=v_y, then the bullet will move in parallel with the enemy, always staying the same distance from it.

You can now consider that the enemy is not moving at all, relative to the bullet, and the difference in position between them is (x_1-x_0, y_1-y_0). The bullet can move along this line to collide with the bullet.

If the bullet takes t frames to reach the bullet, we now get:

\begin{array}{rcl}d_x = (x_1-x_0)/t + v_x \\ d_y = (y_1-y_0)/t + v_y \end{array}

As we said that the bullet’s velocity is V, we get

d_x^2 + d_y^2 = V^2

Which expands out to:

\begin{array}{rcl} \left(\frac{1}{t}\right)^2 \left[ (x_1 - x_0)^2 + (y_1 - y_0)^2 \right] && \\ + \frac{1}{t} \left[ v_x (x_1 - x_0) + v_y ( y_1 - y_0) \right] &&\\ + v_x^2 + v_y^2 - V^2 &=& 0 \end{array}

(I had to split that over a few lines so it would fit in the post column, sorry!)

Which is a quadratic equation! So set:

\begin{array}{rcl} a &=& (x_1-x_0)^2 + (y_1-y_0)^2 \\ b &=&  2[ v_x(x_1-x_0) + v_y(y_1-y_0) ] \\ c &=&  v_x^2 + v_y^2 - V^2 \end{array}

Then, using the quadratic formula:

\frac{1}{t} = \frac{-b + \sqrt{ b^2 - 4ac}}{2a}

You can now put that back into the equations for d_x and d_y, and you’re done!

Here’s the result, written in BlitzMax:

diffx:double=x2-x1
diffy:double=y2-y1
v:Double=3                'desired speed of bullet

a:Double=diffx*diffx+diffy*diffy
b:Double=2*(vx*diffx+vy*diffy)
c:Double=vx*vx+vy*vy-v*v

tInv#=(-b+Sqr(b*b-4*a*c))/(2*a)   ' solve 1/t
dx=diffx*tInv+vx
dy=diffy*tInv+vy

That’s it!

Read Full Post »