
-----------------------------------
Canned
Thu Sep 11, 2008 6:52 pm

[HELP] Circle to Line Collision
-----------------------------------
I know how to do rectangle collision, but how do I detect whether a circle has collided with a line?

-----------------------------------
[Gandalf]
Thu Sep 11, 2008 8:11 pm

RE:[HELP] Circle to Line Collision
-----------------------------------
I believe everything you need is included in the [url=http://compsci.ca/v3/viewtopic.php?p=139959]collision detection tutorial by richcash.  Take a look on the second page for circle-line collisions.

-----------------------------------
evildaddy911
Sun Oct 16, 2011 11:52 am

RE:[HELP] Circle to Line Collision
-----------------------------------
same problem man, i looked at the tutorial a week ago, and still havent figured out how to do it
 :idea: im thinking that a good way would be to use the area/circumference formula, and whatdotcolor, but i havent figured out out to do the for loops for that

-----------------------------------
Aange10
Sun Oct 16, 2011 12:47 pm

Re: [HELP] Circle to Line Collision
-----------------------------------

 idea im thinking that a good way would be to use the area/circumference formula, and whatdotcolor, but i haven't figured out out to do the for loops for that


Yes, there are many ways to do it (: ... For loops can be confusing at first, but once you lean them you'll find out how useful they are(:. But, anyways, I've taken a look at what you all want to do, and I've decided I'll help you all learn how to do it.

First and foremost, everything (other than the fors) I used came from http://compsci.ca/v3/viewtopic.php?t=13661&postdays=0&postorder=asc&start=0 (Collision detection tutorial). Sometimes it's easier, though, to learn when you already have a basic gist of things. Anyways, on to yall's problem:


I know how to do rectangle collision, but how do I detect whether a circle has collided with a line?


        The same basic ideas. Lets look step-by-step at what to do. Now, the first thing to do (as always) is to define our variables. Here's my example I'll be using:


View.Set ("graphics:maxx;maxy,position:center;center") % Set Screen
% Define Variables
var circle_radius, circle_x, circle_y : int
var line_x1,line_x2,line_y1,line_y2 : int
var circle_x_velocity : real := 3.0
circle_radius := 20
circle_x := 20
circle_y := maxy div 2
line_x1 := maxx - (maxx div 2) + 70
line_x2 := maxx - (maxx div 2) - 30
line_y1 := maxy div 2
line_y2 := maxy div 2
% An array so we can check the distance from each point in the line
var distance : array 0 .. (line_x1 - line_x2) of real
%%


    Everything is pretty straight forward. We have variables to keep track of the points in the line, and the x,y & radius of the circle. Now, if you don't know what arrays are yet, I suggest you read http://compsci.ca/v3/viewtopic.php?t=14333, before you continue. ... The purpose of this array is so that we can find the distance from our circle to every point in the line (as apposed to just one point of the line).

    Our next step is to put this array to use, using the equation given to us in the Collision Detection tutorial (the distance formula).


      % Moves the circle
    circle_x += round (circle_x_velocity)
    % Update the distance from the circle to each point of the line
    for i : 0 .. upper (distance)
        distance (i) := sqrt (((line_x1 - i) - circle_x) ** 2 + ((line_y1) - circle_y) ** 2)
    end for


    Now, the trick here is with the for statement. A for is just an infinite loop that repeats a number of times (x .. y) in this case, (0 .. upper(distance)), now if you read the arrays tutorial, you'll know that upper(distance) is just a pointer to the upper range of the array distance. Which in this case is (line_x1 - line_x2). So, to clarify, we have a for loop i that is repeating its self  o .. upper(distance)  times. In this situation, upper(distance) is = line_x1 - line_x2  which is = 100. So it's repeating itself 101 times (0 counts as a time!).
    Each time a for executes its self, it assigns the number of executions to the variable i. So if it's on it's 20th execution, i = 19 (remember, 0 counts as an execution!). ... Now that we have a basic understanding of for loops (if you're still confused I suggest you read http://compsci.ca/v3/viewtopic.php?t=3678 as they can explain it better than I can), we can continue with the code:
    As I said before, each time the for executes, it assigns i a value. Now by adding i into our distance equation, we effectively check every point on the line.


    % Draw our objects
    drawline (line_x1, line_y1, line_x2, line_y2, red)
    drawfilloval (circle_x, circle_y, circle_radius, circle_radius, blue)
    % Check for collision at each point
    for i : 0 .. upper (distance)
        if distance (i)  execute the function -> output the result than it does for it to just do the equation.)

-----------------------------------
evildaddy911
Sun Oct 16, 2011 2:39 pm

RE:[HELP] Circle to Line Collision
-----------------------------------
for now im going to stick to the Math.Distance, 
thanks for the help!

-----------------------------------
Aange10
Sun Oct 16, 2011 2:46 pm

RE:[HELP] Circle to Line Collision
-----------------------------------
No problem!(: So I take it your program works now?

-----------------------------------
evildaddy911
Sun Oct 16, 2011 3:01 pm

RE:[HELP] Circle to Line Collision
-----------------------------------
not completely, i have to change half the code...

-----------------------------------
Aange10
Sun Oct 16, 2011 3:08 pm

Re: RE:[HELP] Circle to Line Collision
-----------------------------------
not completely, i have to change half the code...

Happens =/ ... If you need help feel free to ask


EDIT: Just realized


A for is just an infinite loop that repeats a number of times


... Oops. Sorry, i meant to say "A for is just a loop that repeats itself a number of times"

Sorry  8-)

-----------------------------------
evildaddy911
Sun Oct 16, 2011 3:24 pm

Re: [HELP] Circle to Line Collision
-----------------------------------
yah, im stuck :cry: 
heres my code, im trying to replace the whatdotcolor for the brightgreen i shoot and the purple that the enemy shoots:
[code]View.Set ("graphics:max;max,nobuttonbar")
var myx, myy, mousex, mousey, button, cpuhp, myhp, kills, damage, typ, rad, enemyx, enemyy, move, score, dlay : int
var mode : string
var chars : array char of boolean
enemyx := Rand.Int (100, maxx - 100)
enemyy := Rand.Int (100, maxy - 100)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                               DRAWENEMY
proc drawenemy
    drawfilloval (enemyx, enemyy, 10, 10, white)
    move := Rand.Int (1, 8)
    if enemyx > 0 then
        if move = 1 then
            enemyx := enemyx + Rand.Int (1, 6)
        end if
    end if
    if enemyy > 0 then
        if move = 2 then
            enemyy := enemyy + Rand.Int (1, 6)
        end if
    end if
    if enemyx < maxx then
        if move = 3 then
            enemyx := enemyx - Rand.Int (1, 6)
        end if
    end if
    if enemyy < maxy then
        if move = 4 then
            enemyy := enemyy - Rand.Int (1, 6)
        end if
    end if
    if enemyy < maxy then
        if enemyx < maxx then
            if move = 5 then
                enemyy := enemyy - Rand.Int (1, 6)
                enemyx := enemyx - Rand.Int (1, 6)
            end if
        end if
    end if
    if enemyy < maxy then
        if enemyx > 0 then
            if move = 6 then
                enemyx := enemyx + Rand.Int (1, 6)
                enemyy := enemyy - Rand.Int (1, 6)
            end if
        end if
    end if
    if enemyy > 0 then
        if enemyx > 0 then
            if move = 7 then
                enemyx := enemyx + Rand.Int (1, 6)
                enemyy := enemyy + Rand.Int (1, 6)
            end if
        end if
    end if
    if enemyy > 0 then
        if enemyx < maxx then
            if move = 8 then
                enemyx := enemyx - Rand.Int (1, 4)
                enemyy := enemyy + Rand.Int (1, 4)
            end if
        end if
    end if
    drawfilloval (enemyx, enemyy, 10, 10, black)
    drawfilloval (enemyx - 2, enemyy, 1, 2, green)
    drawfilloval (enemyx + 2, enemyy, 1, 2, green)
    drawline (enemyx - 3, enemyy - 4, enemyx + 3, enemyy - 4, red)
end drawenemy
%                                                               HEALTH
proc health
    if whatdotcolor (enemyx, enemyy) = brightred then
        cpuhp := cpuhp - 7500
    end if
    if whatdotcolor (enemyx, enemyy) = brightblue then
        cpuhp := cpuhp - 125
    end if
    if whatdotcolor (enemyx, enemyy) = brightgreen then
        cpuhp := cpuhp - 3
    end if
    if whatdotcolor (myx, myy) = purple then
        myhp := myhp - 5
    end if
    if whatdotcolor (myx, myy) = gray then
        myhp := myhp - 100
    end if
    if whatdotcolor (myx, myy) = brightblue then
        myhp := myhp - 200
    end if
    put cpuhp
    put myhp
end health
%                                                               DAMAGE
proc dmge
    for counter : 0 .. 100
        if whatdotcolor (counter, 100) = brightred then
            damage := damage + 125
            score := score + 125
        end if
        if whatdotcolor (100, counter) = brightred then
            damage := damage + 125
            score := score + 125
        end if
        if whatdotcolor (counter, 100) = brightblue then
            damage := damage + 2
            score := score + 2
        end if
        if whatdotcolor (100, counter) = brightblue then
            damage := damage + 2
            score := score + 2
        end if
        if whatdotcolor (counter, 100) = brightgreen then
            damage := damage + 1
            score := score + 1
        end if
        if whatdotcolor (100, counter) = brightgreen then
            damage := damage + 1
            score := score + 1
        end if
    end for
    if whatdotcolor (myx, myy) = purple then
        damage := damage * (1 div 100)
    end if
    if whatdotcolor (myx, myy) = gray then
        damage := damage - 300
    end if
    if whatdotcolor (myx, myy) = brightblue then
        damage := damage - 750
    end if
    put damage
end dmge
%                                                               GRENADE
proc grenade (l, m : int)
    if mode = "KILLS" then
        drawfilloval (Rand.Int (l - 50, l + 50), Rand.Int (m - 10, m + 10), 15, 15, brightblue)
        health
    elsif mode = "DAMAGE" then
        drawfilloval (Rand.Int (l - 125, l + 125), Rand.Int (m - 10, m + 10), 15, 15, brightblue)
        dmge
    end if
    delay (250)
    cls
end grenade
%                                                               SHOT
proc shot (q, w, e, r, clr : int)
    drawline (q + 1, w, 1000 * (e - q) + e + 1, 1000 * (r - w) + r, clr)
    drawline (q, w, 1000 * (e - q) + e, 1000 * (r - w) + r, clr)
    drawline (q - 1, w, 1000 * (e - q) + e - 1, 1000 * (r - w) + r, clr)
    drawline (q, w + 1, 1000 * (e - q) + e, 1000 * (r - w) + r + 1, clr)
    drawline (q, w - 1, 1000 * (e - q) + e, 1000 * (r - w) + r - 1, clr)
    if mode = "KILLS" then
        health
    elsif mode = "DAMAGE" then
        dmge
    end if
    delay (10)
    cls
end shot

%                                                               ATTK
proc attk (a, b : int)
    typ := Rand.Int (0, 5)
    if typ < 3 then
        if mode = "KILLS" then
            for counter : 1 .. 100
                drawline (a, b, Rand.Int (0, maxx), Rand.Int (0, maxy), purple)
            end for
        elsif mode = "DAMAGE" then
            for counter : 1 .. Rand.Int (500, 2000)
                drawline (a, b, 2 * Rand.Int (-5, maxx), 2 * Rand.Int (-5, maxy), purple)
            end for
        end if
        health
        delay (20)
        cls
    elsif typ = 3 then
        myhp := myhp - 1
        damage := damage - 100
    elsif typ = 4 then
        if mode = "DAMAGE" then
            drawfilloval (a, b, maxy div 2, maxy div 2, gray)
            dmge
        end if
        delay (20)
        cls
    elsif typ = 5 then
        if mode = "DAMAGE" then
            for qwe : 1 .. Rand.Int (15, 50)
                drawfilloval (Rand.Int (100, maxx), Rand.Int (100, maxy), 25, 25, brightblue)
            end for
        elsif mode = "KILLS" then
            drawfilloval (Rand.Int (0, maxx), Rand.Int (0, maxy), 40, 40, brightblue)
            health
        end if
        delay (10)
        cls
    end if
end attk
%                                                               BUTTONS
proc buttons
    %                                                           MOVEMENT
    if myy < maxy then
        if chars ('w') then
            drawfilloval (myx, myy, 10, 10, white)
            myy := myy + 5
        end if
    end if

    if myx < maxx - 1 then
        if chars ('d') then
            drawfilloval (myx, myy, 10, 10, white)
            myx := myx + 5
        end if
    end if

    if myx > 0 then
        if chars ('a') then
            drawfilloval (myx, myy, 10, 10, white)
            myx := myx - 5
        end if
    end if

    if myy > 0 then
        if chars ('s') then
            drawfilloval (myx, myy, 10, 10, white)
            myy := myy - 5
        end if
    end if
    %                                                           ATTACKS
    if chars (chr (ORD_SPACE)) then
        grenade (mousex, mousey)
    end if

    if chars ('f') then
        for i : 1 .. 25
            drawoval (myx, myy, i, i, brightred)
            delay (30)
        end for
        if mode = "KILLS" then
            health
        elsif mode = "DAMAGE" then
            dmge
        end if
        cls
    end if

    if button = 1 then
        shot (myx, myy, mousex, mousey, brightgreen)
    end if

end buttons

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
loop
    loop
        put "Welcome to my game."
        put "The objective is to destroy the enemy using lasers, grenades and melee attacks." : 10
        put ""
        put "Use the arrow keys to move your character, a small red ball."
        put "Click the mouse to shoot a laser, press Space to use a grenade, or press F to perform a melee attack."
        put "Pressing M will end the game and P will pause."
        put "WARNING: grenades will hurt you too"
        put "The enemy will be a black square in the bottom corner. It will randomly shoot purple lasers across the screen, and will sometimes use a melee attack, in the form of a gray circle."
        put "Type KILLS or DAMAGE to begin, or QUIT to quit"
        get mode
        exit when mode = "KILLS"
        exit when mode = "DAMAGE"
        if mode = "QUIT" then
            Window.Close (defWinID)
        end if
        delay (250)
        cls
    end loop

    myx := Rand.Int (maxy div 2, maxx)
    myy := Rand.Int (maxy div 2, maxy)
    cpuhp := 200
    myhp := 500
    kills := 0
    damage := 100
    score := 0

    %%%%%%%%%%%%%%%%%%%%%%%%%%
    if mode = "KILLS" then
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        loop
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            drawenemy         %%%%%draws enemy
            Mouse.Where (mousex, mousey, button)
            Input.KeyDown (chars)
            exit when chars ('m')
            for dly : 1 .. 20
                if dly = 1 then
                    attk (enemyx, enemyy)
                end if
            end for
            %                                                       MOVEMENT
            buttons
            %                                                       PAUSE
            if chars ('p') then
                loop
                    Mouse.Where (mousex, mousey, button)
                    drawfilloval (enemyx, enemyy, 10, 10, black)
                    drawfilloval (enemyx - 2, enemyy, 1, 2, green)
                    drawfilloval (enemyx + 2, enemyy, 1, 2, green)
                    drawline (enemyx - 3, enemyy - 4, enemyx + 3, enemyy - 4, red)
                    drawfilloval (myx, myy, 10, 10, red)
                    put "GAME PAUSED"
                    put "ENEMY:", cpuhp, "  YOU:", myhp, "  KILLS:", kills
                    put "press L to resume"
                    Input.KeyDown (chars)
                    if chars ('l') then
                        exit
                    end if
                    delay (250)
                    cls
                end loop
            end if
            %                                                       KILLS
            if cpuhp < 0 then
                put "KILL"
                kills := kills + 1
                cpuhp := 200 + 10 * kills
                myhp := myhp + 2 * kills
                enemyx := Rand.Int (100, maxx - 100)
                enemyy := Rand.Int (100, maxy - 100)
                delay (1000)
            end if

            exit when myhp < 0

            drawfilloval (myx, myy, 10, 10, red)
            delay (20)
        end loop
    end if


    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if mode = "DAMAGE" then
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        loop
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            drawfillbox (0, 0, 100, 100, black)             %%%%%draws enemy
            Mouse.Where (mousex, mousey, button)
            Input.KeyDown (chars)
            exit when chars ('m')
            dlay := Rand.Int (1, 10)
            if dlay = 1 then
                attk (50, 50)
            end if
            %                                                   MOVEMENT
            buttons
            %                                                   PAUSE
            if chars ('p') then
                loop
                    drawfillbox (0, 0, 100, 100, black)
                    put "GAME PAUSED"
                    put "DAMAGE:", damage
                    put "press L to resume"
                    Input.KeyDown (chars)
                    if chars ('l') then
                        exit
                    end if
                    delay (250)
                    cls
                end loop
            end if

            exit when damage < 0

            drawfilloval (myx, myy, 10, 10, red)
            delay (20)
        end loop
    end if

    put "GAME OVER. Restart game"
    if mode = "KILLS" then
        put "KILLS:", kills
    elsif mode = "DAMAGE" then
        put "SCORE:", score
    end if
    delay (100)
    put ""
    put ""
end loop
[/code]
can you help?

-----------------------------------
Aange10
Sun Oct 16, 2011 3:46 pm

RE:[HELP] Circle to Line Collision
-----------------------------------
I'm sure I can. But first you need to clean up a bit. 1. You need to do more commenting on your code. For example, what is the purpose of each line. When you finish commenting that, not only can other people fully understand it, but you might figure out what's wrong as well.
2. typ,rad,dly ... What do these variables mean? 

and 3. I suggest you make some variables like


var player_laser, player_gernade, player_mele, cpu_laser : int
player_laser := brightred
.
.


That away it'll be easier to see what the whatdot colors are looking for. Instead of seeing "brightpurple" everywhere, we could see "enemy laser"

-----------------------------------
evildaddy911
Mon Oct 17, 2011 7:00 am

RE:[HELP] Circle to Line Collision
-----------------------------------
ok... ill work on it
