Trigonometry Help - Missle Tracking
Author |
Message |
RedRogueXIII
|
Posted: Mon Apr 03, 2006 8:32 pm Post subject: Trigonometry Help - Missle Tracking |
|
|
Hello, I am having problems getting the projectile to track properly.
It is based on angles, finding the angle going to the target then shifting its direction as appropriate to hit it.
But :
-the projectile seems to not work properly when going straight up, down, left or right.
- the projectile turns the longer way to get to the angle, say if it was at 356 and the target angle was 4 then it goes back down clockwise instead of counter-clockwise
- When it goes left it just plain messes up, i have no explanation or do not understand why it does this ?
Help would be very much appreciated. (there are no images)
::: NOTE : Press Space to launch one missle, the target is always the mouse.
code: | View.Set ("graphics, offscreenonly")
var misslex, missley, missleAngle, missleSpeed, mx, my, mb, clsize, timerchk, savedTime : int
clsize := 10
var shootFlag : boolean := false
var chars : array char of boolean
timerchk := 0
savedTime := 0
missleAngle := 90
missleSpeed := 10
proc crosshair
drawoval (mx, my, clsize div 2, clsize div 2, green)
drawline (mx, my + clsize div 4, mx, my + clsize, green)
drawline (mx, my - clsize div 4, mx, my - clsize, green)
drawline (mx - clsize div 4, my, mx - clsize, my, green)
drawline (mx + clsize div 4, my, mx + clsize, my, green)
drawbox (mx - clsize div 4, my - clsize div 4, mx + clsize div 4, my + clsize div 4, green)
end crosshair
proc missleGuidanceSystem (targetx, targety, misslex, missley, timerchk, timesave, angle : int)
%********The problems lie in this process of code.
if timerchk >= savedTime + 10 then % change amount for faster reacting missle.
savedTime := timerchk
drawline (misslex, missley, targetx, targety, green)
var ang, difx, dify : real
% Find the difference between the missle and the target
difx := (misslex - targetx)
dify := (missley - targety)
if difx = 0 then
difx := 0.00000001
end if
ang := angle
% Find the Angle wanted
if dify < 0 and difx > 0 then
ang := arctand (dify / difx)
if ang < 0 then
ang := 180 + ang
end if
elsif dify > 0 and difx < 0 then
ang := arctand (dify / difx)
if ang < 0 then
ang := 360 + ang
end if
elsif dify < 0 and difx < 0 then
ang := arctand (dify / difx) - 180
if ang < 0 then
ang := 180 + ang
end if
elsif dify > 0 and difx > 0 then
ang := arctand (dify / difx) + 180
if ang < 0 then
ang := 360 + ang
end if
end if
% move the missle's angle closer to the 'wanted' angle
if ang = 0 or ang = 360 then
ang := 0
if missleAngle > 135 and missleAngle < 180 then
missleAngle -= 5
elsif missleAngle > 185 and missleAngle < 235 then
missleAngle += 5
end if
elsif missleAngle > 235 and ang < 45 or missleAngle > 270 and ang < 90 then
missleAngle += 5
elsif missleAngle < 90 and ang > 270 or missleAngle < 45 and ang > 235 then
missleAngle -= 5
elsif missleAngle < ang then
missleAngle += 5
if missleAngle > 360 then
missleAngle -= 360
end if
elsif missleAngle > ang then
missleAngle -= 5
if missleAngle < 0 then
missleAngle += 360
end if
end if
locate (2, 1)
put misslex - targetx, " x ", missley - targety, " y ", ang : 0 : 0, " angle " ..
end if
end missleGuidanceSystem
proc move (x, y, distance, angle : int)
% Moves the ship depending on the angle.
var ang : real := intreal (angle)
var h, w, m, b : real
h := distance * sind (ang)
w := distance * cosd (ang)
misslex := x + round (w)
missley := y + round (h)
end move
proc collision
% Handles Collision
if Math.Distance (misslex, missley, mx, my) <= 10 then
for decreasing i : 4 .. 1
drawfilloval (mx, my, i * 5, i * 5, 40 + i)
end for
shootFlag := false
end if
end collision
proc launch
% Press space to creat a missle
Input.KeyDown (chars)
if chars (' ') and shootFlag = false then
shootFlag := true
misslex := maxx div 2
missley := 30
savedTime := Time.Elapsed
end if
end launch
proc drawMissle
drawfilloval (misslex, missley, 3, 3, red)
end drawMissle
loop
timerchk := Time.Elapsed
mousewhere (mx, my, mb)
crosshair
launch
if shootFlag = true then
drawMissle
missleGuidanceSystem (mx, my, misslex, missley, timerchk, savedTime, missleAngle)
move (misslex, missley, missleSpeed, missleAngle)
collision
end if
locate (1, 1)
put shootFlag, " ", timerchk, " ", savedTime, " ", missleAngle, "degrees angle " ..
drawfilloval (maxx div 2, 0, 20, 20, blue)
View.Update
cls
delay (10)
end loop
% PROBLEMS MISSLE WILL NOT GO OVER 360 TO GET A VALUE LESS THAN 90
% COMPASS DIRECTIONS ALSO MESSED UP.
|
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
MysticVegeta
|
Posted: Mon Apr 03, 2006 10:10 pm Post subject: (No subject) |
|
|
why not use an if structure to say if difference is > 180 then use counter clockwise else use clockwise i.e. if angle > 180, angle is 360 - angle?
PS: I am a complete newbie to trig, i only know grade 10 trig, so I might have a stupid answer |
|
|
|
|
|
TokenHerbz
|
Posted: Tue Apr 04, 2006 2:45 pm Post subject: (No subject) |
|
|
i took grade 11 hardcore trig, but that was 2 years ago :S
Anyways, i forgot it all, and i can't run your program cause my turing dosn't have math.distance thing...
anyways, i recomend going into the compsci.ca irc channel, and ask a person named """"Ultrahex""""
He helped me with some trig, but, don't bug him, if its a no its a no, or you'll get banned. |
|
|
|
|
|
HellblazerX
|
Posted: Tue Apr 04, 2006 5:01 pm Post subject: (No subject) |
|
|
for the portion of code that looks for the angle between the missle and the target, I would suggest you use this piece of code:
code: | %****************************CALCULATE GUN ANGLE*********************
hyp := Math.Distance (mx, my, maxx div 2, maxy div 2 - 7)
width := mx - maxx div 2
if hyp = 0 then
hyp := 0.001
end if
player.gunangle := round (arccosd (width / hyp))
if my < maxy div 2 - 7 then
player.gunangle := round ((180 - player.gunangle) + 180)
end if |
Me and my partner made this about a year ago for our final project, so I don't remember much about it. But i do remember that arctand gave us a lot of troubles, so we just used arccosd instead.
As for finding the quickest way to turn, try this:
code: | var difang : int := ang - missleAngle
if difang > 0 and difang < 180 then
missleAngle += 5
elsif difang > 0 and difang >= 180 then
missleAngle -= 5
elsif difang < 0 and difang < -180 then
missleAngle -= 5
elsif difang < 0 and difang >= -180 then
missleAngle += 5
end if
if missleAngle < 0 then
missleAngle += 360
elsif missleAngle > 360 then
missleAngle -= 360
end if
|
basically, with this code, it calculates the difference between the desired angle and the missle's angle. If the difference is positive, and less than 180, then you should go counterclockwise, which is adding angles, but if it is less than 180, then you should go clockwise, which is subtracting angles. if the difference is negative and less then -180, then you should go clockwise, and counterclockwise if it is greater than -180. The last portion is to wrap around the angle so you don't go greater than 360 or less than 0.
As for the projectile not working properly when turned at 90, 180, 270 and 360 degrees, add 0.0001 to the angle you're working with. Because tan of 180 and 360 gives 0, which is a problem when dividing by that, and tan of 90 and 270 degrees is undefined, which is even more of a problem. |
|
|
|
|
|
RedRogueXIII
|
Posted: Wed Apr 19, 2006 8:25 pm Post subject: (No subject) |
|
|
BUMP- Im justing bumping this to show my solution in case anyone has the same problem. (BTW: Added a graphical smoke trail to the missle, to increase performance just comment it out in the main loop)
code: |
View.Set ("graphics, offscreenonly")
var misslex, missley, missleAngle, missleSpeed, missleTurnSpeed, mx, my, mb, clsize, timerchk, savedTime : int
clsize := 10
var smokecount, smokeMin, smokeMax : int
var smokex, smokey, savTime : flexible array 0 .. 0 of int
smokecount := 0
smokeMin := 1
smokeMax := 1
var shootFlag : boolean := false
var chars : array char of boolean
timerchk := 0
savedTime := 0
missleAngle := 90
missleSpeed := 7
missleTurnSpeed := 5
function speedAdjustments (startAngle, endAngle : int) : int
% Changes how fast the missle will turn
var value1, value2, low : int := 0
if endAngle > startAngle then
value1 := abs (startAngle + (360 - endAngle))
elsif endAngle < startAngle then
value1 := abs (startAngle - endAngle)
end if
if endAngle > startAngle then
value2 := abs (startAngle - endAngle)
elsif endAngle < startAngle then
value2 := abs ((360 - startAngle) + endAngle)
end if
if startAngle >= endAngle - 7 and startAngle <= endAngle + 7 then
result missleSpeed
end if
if min (value1, value2) = value1 then
low := value1
elsif min (value1, value2) = value2 then
low := value2
end if
/* Find the lowest difference then change
the speed according to how big the difference is for more precise targeting*/
if low > 0 and low < 45 then
result 1
elsif low > 45 and low < 90 then
result 5
elsif low > 90 and low < 135 then
result 10
%elsif low > 135 and low < 180 then
%result 15 %
elsif low > 170 then
result 15
end if
result 5 % This is the base missleTurning Speed
end speedAdjustments
function upOrDown (startAngle, endAngle : int) : int
% Finds if the missle's angle will be added, subtracted or stay the same.
var value1, value2 : int := 0
var move : int := 0 % 1 adds 2 minuses 3 says stay on course
if endAngle > startAngle then
value1 := abs (startAngle + (360 - endAngle))
elsif endAngle < startAngle then
value1 := abs (startAngle - endAngle)
end if
if endAngle > startAngle then
value2 := abs (startAngle - endAngle)
elsif endAngle < startAngle then
value2 := abs ((360 - startAngle) + endAngle)
end if
% 1 adds 2 minuses 3 says stay on course
if min (value1, value2) = value1 then
move := 1
elsif min (value1, value2) = value2 then
move := 2
end if
if startAngle >= endAngle - 5 and startAngle <= endAngle + 5 then
move := 3
end if
result move
end upOrDown
proc crosshair
% Draws a crosshair
drawoval (mx, my, clsize div 2, clsize div 2, green)
drawline (mx, my + clsize div 4, mx, my + clsize, green)
drawline (mx, my - clsize div 4, mx, my - clsize, green)
drawline (mx - clsize div 4, my, mx - clsize, my, green)
drawline (mx + clsize div 4, my, mx + clsize, my, green)
drawbox (mx - clsize div 4, my - clsize div 4, mx + clsize div 4, my + clsize div 4, green)
end crosshair
proc missleGuidanceSystem (targetx, targety, misslex, missley, timerchk, timesave, angle : int)
%********The problems lie in this process of code.
if timerchk >= savedTime + 10 then % change amount for faster reacting missle.
savedTime := timerchk
drawline (misslex, missley, targetx, targety, green)
var ang, difx, dify, ratio : real
% Find the difference between the missle and the target
difx := (misslex - targetx)
dify := (missley - targety)
if difx not= 0 then
ratio := dify / difx
else
ratio := dify / 0.001
end if
ang := arctand (abs (ratio))
if difx < 0 then
ang := 180 - ang
end if
if dify < 0 then
ang := 360 - ang
end if
missleTurnSpeed := speedAdjustments (angle, round (ang))
% STEER TEH EXPLOSIVE WARHEAD :P
if upOrDown (angle, round (ang)) = 3 then
elsif upOrDown (angle, round (ang)) = 2 then
missleAngle -= missleTurnSpeed
elsif upOrDown (angle, round (ang)) = 1 then
missleAngle += missleTurnSpeed
end if
if missleAngle > 360 then
missleAngle := 0
elsif missleAngle < 0 then
missleAngle := 360
end if
end if
end missleGuidanceSystem
proc move (x, y, distance, angle : int)
% Moves the ship depending on the angle.
var ang : real := intreal (angle)
var h, w, m, b : real
h := distance * sind (ang)
w := distance * cosd (ang)
misslex := x + round (w)
missley := y + round (h)
end move
proc collision
% Handles Collision
if Math.Distance (misslex, missley, mx, my) <= 10 then
for decreasing i : 4 .. 1 % draws a pretty explosion that lasts less than a second :(
drawfilloval (mx, my, i * 5, i * 5, 40 + i)
end for
shootFlag := false
end if
end collision
proc launch
% Press space to create a missle
Input.KeyDown (chars)
if chars (' ') and shootFlag = false then
shootFlag := true
misslex := maxx div 2
missley := 30
savedTime := Time.Elapsed
end if
end launch
proc smoke
% Create some nice graphical smoke to follow your missle around
var r : int := Rand.Int (5, 7) %(smokeMin*10, smokeMax * 10) Save for faster computers :(
if timerchk mod 1000 >= 0 then
smokecount += r
new smokex, smokecount
new smokey, smokecount
new savTime, smokecount
for i : smokecount - r + 1 .. smokecount
smokex (i) := misslex
smokey (i) := missley
savTime (i) := timerchk
end for
end if
if smokecount > 0 then
for i : 1 .. smokecount - 1
if savTime (i) + 3000 <= timerchk or smokex (i) < 0 or smokey (i) < 0 or smokex (i) > maxx or smokey (i) > maxy then
for k : i .. smokecount - 1
smokex (k) := smokex (k + 1)
smokey (k) := smokey (k + 1)
savTime (k) := savTime (k + 1)
end for
smokecount -= 1
end if
end for
for i : 1 .. smokecount
r := Rand.Int (-1, 1)
smokex (i) := smokex (i) + r
r := Rand.Int (-1, 1)
smokey (i) := smokey (i) + r
drawdot (smokex (i), smokey (i), grey)
end for
end if
end smoke
proc drawMissle
drawfilloval (misslex, missley, 3, 3, red)
%drawarc (misslex, missley, 20, 20, 0, missleAngle, green)
end drawMissle
loop
timerchk := Time.Elapsed
mousewhere (mx, my, mb)
crosshair
launch
if shootFlag = true then
drawMissle
missleGuidanceSystem (mx, my, misslex, missley, timerchk, savedTime, missleAngle)
collision
move (misslex, missley, missleSpeed, missleAngle)
smoke
end if
locate (1, 1)
put shootFlag, " ", timerchk, " ", savedTime, " ", missleAngle, "degrees angle " ..
drawfilloval (maxx div 2, 0, 20, 20, blue)
View.Update
cls
delay (10)
end loop
|
|
|
|
|
|
|
NikG
|
Posted: Wed Apr 19, 2006 10:41 pm Post subject: (No subject) |
|
|
Wow!
That smoke trail is awesome, but a little buggy.
What are your plans for this (i.e. what kind of game is this, or are you just experimenting?) |
|
|
|
|
|
RedRogueXIII
|
Posted: Fri Apr 21, 2006 4:34 pm Post subject: (No subject) |
|
|
Well i made it for a game I am/was working on, but now further into it, I doubt if Turing will be able to handle parts of it. Anyways the game is supposed to be similar to the popular Evasive manuvers game, eg topdown ship dog-fighting, but I don't know if I'll finish it in Turing. |
|
|
|
|
|
codemage
|
Posted: Mon Apr 24, 2006 8:55 am Post subject: (No subject) |
|
|
Still goes a bit buggy for some angles. If you get it just right, the missile keeps heading in the opposite direction indefinitely.
Out of curiosity, what things are you planning to do that allegedly can't be done in Turing? |
|
|
|
|
|
Sponsor Sponsor
|
|
|
RedRogueXIII
|
Posted: Thu Apr 27, 2006 9:55 pm Post subject: (No subject) |
|
|
The parts I believe that Turing can't handle at the same time are the scrolling background which i intended to make a map editor for, a pre-set point walls systems, multiple graphics(like being able to handle 10 or more ships on screen + accomodating missles/ lasers/bombs , proper ai navigation around the walls and then i planned to try online multiplayer over the sending and receiving of commands to a server program...
and yea its the missles are still buggy, got to fix that... |
|
|
|
|
|
|
|