Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Trigonometry Help - Missle Tracking
Index -> Programming, Turing -> Turing Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
RedRogueXIII




PostPosted: 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
Sponsor
sponsor
MysticVegeta




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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
Sponsor
sponsor
RedRogueXIII




PostPosted: 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...
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 9 Posts ]
Jump to:   


Style:  
Search: