therevills asks on the blitzbasic.com forums:
Does any one know how to do this?I know the following:
* Start x,y
* End x,y
* Gravity
* Height of the wallDiagrams:
………………..wall
____s______|__________e__________s_|
……|
……|
……|_e_etc
Any ideas?
What I’ll do is find the smallest possible solution to this problem – the angle and speed to fire the projectile such that it just skims the top of the wall before it hits the end point. I’ll also only consider the case where the end point is at the same height as the start point. You can use the ideas in my previous post to sort out the other cases.
The relevant equation of motion is:
where is distance travelled, is initial velocity, is acceleration, and is time elapsed.
Suppose that the projectile reaches the wall at and the end point at .
We’ll say that the distance from the start to the wall is , the distance to the end point is , and the height of the wall is .
We’ll also say that the speed of the projectile is and the angle it is fired at is .
So we want:
We can rearrange the first two equations (involving three unknowns, so we definitely need the other two!) to find in terms of :
Use the fact that to get
which will come in handy in a bit.
Doing the same kind of thing with the other two equations, we get
Substitute the thing we had for to get
Rearrange and use that trig fact again to get
Cancel down the left side and use :
Hooray, we’ve got a formula for ! Once we’ve found that, we can put it back into the handy equation for , and we’ve got both the angle and speed of the projectile. Remember this give the minimum solution – you can increase and rearrange the handy equation to get a suitable value for .
As always, here’s some BlitzMax code demonstrating this:
Graphics 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 Const g#=1,x1#=300 While Not (KeyHit(KEY_ESCAPE) Or AppTerminate()) x2#=MouseX() y#=MouseY()-300 DrawLine 300,300,300,300+y DrawLine 0,300,x2,300 If MouseHit(1) If x2>x1 And y<0 theta# = ATan(-y*x2/(x2*x1-x1*x1)) v=Sqr(g*x2/(Sin(2*theta))) Print theta Print v bullet.Create(0,300,v*Cos(-theta),v*Sin(-theta)) EndIf EndIf For bu:bullet=EachIn bullets bu.update Next Flip Cls Wend