Computer Science Canada

OVal detection

Author:  upthescale [ Tue Jun 27, 2006 12:48 pm ]
Post subject:  OVal detection

I am makign a fish game, where i have to eat bigger fish, and if bigger fish eat u you lose. But the other fish are on a random size, they will always be an oval, there y size is the random part. Whats the best way to do a hit detection with ovals?

Author:  MysticVegeta [ Tue Jun 27, 2006 12:59 pm ]
Post subject: 

how about Math.Distance??

Author:  upthescale [ Tue Jun 27, 2006 1:12 pm ]
Post subject: 

I am trying, but that is usually for circles, not ovals

Author:  the_short1 [ Tue Jun 27, 2006 2:05 pm ]
Post subject: 

..yes you can.. math.distance can be used... but not directly..
http://en.wikipedia.org/wiki/Ellipse
you the properties of the ellipse... and some advanced math concepts.. if you havnt learned about ellipses in math.. i would recomend making them circles instead.. i can do it .,., but tahts calculus and discreet under my belt Wink . . and i dont have time to write it for you.. srry

Author:  Mazer [ Wed Jun 28, 2006 2:05 pm ]
Post subject: 

You could try to work your way through this.

If that's too complicated and/or the ovals in question are long enough you might want to try treating them as rectangles for a rough approximation of collision detection (or better yet, a series of smaller rectangles that make up a rough oval shape).

Author:  MysticVegeta [ Wed Jun 28, 2006 3:08 pm ]
Post subject: 

Here is a demo I made to detect for oval collision:

Advantages are: Well that you have oval detection now.
Disadvantages are: Its too slow, Its only valid for integral x,y values of collision. ie: If the ovals only collide when x not= n and y not= n, where n is an integer, then it wont work.

code:
var x1 := Rand.Int (1, maxx)
var x2 := Rand.Int (1, maxx)

var y1 := Rand.Int (1, maxy)
var y2 := Rand.Int (1, maxy)

var c := Rand.Int (20, 200)
var c1 := Rand.Int (20, 200)
var c2 := Rand.Int (20, 200)
var c3 := Rand.Int (20, 200)

drawfilloval (x1, y1, c, c1, brightred)
drawfilloval (x2, y2, c2, c3, brightblue)

fcn collide (x1 : int, y1 : int, x2 : int, y2 : int, c : int, c1 : int, c2 : int, c3 : int, p : int, q : int) : boolean
    /* GENERAL EQUATION OF AN ELLIPSE IS:
     (X - H) ^ 2   +   (Y - K) ^ 2
     -----------      -------------  = 1
     A^2               B^2

     A is Radius # 1.
     B is Radius # 2.
     (H, K) is the centre. Here, it cant be negative, but it could if graphed on Cartesian plane.
     (X, Y) are non-constant variables.

     Strategy: Loop through all (x, y) plug in to see whether any of the coordinates satisfy equation for both ellipses
     */
    for x : 1 .. p
        for y : 1 .. q
            var eq1 := (((x - x1) ** 2) / (c ** 2)) + (((y - y1) ** 2) / (c1 ** 2))
            var eq2 := (((x - x2) ** 2) / (c2 ** 2)) + (((y - y2) ** 2) / (c3 ** 2))
            if (round (eq1) = 1 and round (eq1) = round (eq2)) then
                result true
            end if
        end for
    end for
    result false
end collide

if (collide (x1, y1, x2, y2, c, c1, c2, c3, maxx, maxy)) then
    put "These ovals collide"
else
    put "These ovals do not collide"
end if

Author:  BenLi [ Wed Jun 28, 2006 3:59 pm ]
Post subject: 

surprised that nobody said it yet... but you could always dumb it down to whatdotcolor...

Author:  MysticVegeta [ Wed Jun 28, 2006 4:15 pm ]
Post subject: 

And how do you suppose you would do that with whatdotcolor? There is no way you can do that with whatdotcolor unless ofcourse you are Andy. but it will be complicated since you cant really loop thourgh all the pixels of any of the ovals.

Author:  MysticVegeta [ Wed Jun 28, 2006 4:42 pm ]
Post subject: 

Hmm I am sort of wondering if we can use some geometry to do this, for eg: using major and minor radii. I have got this so far but it doesnt give correct answer all the time, there are 2 methods I used:

code:
var x1 := Rand.Int (1, maxx)
var x2 := Rand.Int (1, maxx)

var y1 := Rand.Int (1, maxy)
var y2 := Rand.Int (1, maxy)

var c := Rand.Int (20, 200)
var c1 := Rand.Int (20, 200)
var c2 := Rand.Int (20, 200)
var c3 := Rand.Int (20, 200)

drawfilloval (x1, y1, c, c1, brightred)
drawfilloval (x2, y2, c2, c3, brightblue)

fcn collide2 (x1 : int, y1 : int, x2 : int, y2 : int, c : int, c1 : int, c2 : int, c3 : int) : boolean
    %  if (Math.Distance (x1, y1, x2, y2) <= (min (c, c1) + min (c2, c3))) and
    % (Math.Distance (x1, y1, x2, y2) <= (max (c, c1) + max (c2, c3))) then
    if (Math.Distance (x1, y2, x2, y2) <= (max (c, c1) + max (c2, c3)) div 2) then
        result true
    end if
    result false
end collide2

if (collide2 (x1, y1, x2, y2, c, c1, c2, c3)) then
    put "These ovals collide ", x1, " ", y1, " ", x2, " ", y2
else
    put "These ovals do not collide ", x1, " ", y1, " ", x2, " ", y2
end if

Author:  MysticVegeta [ Thu Jun 29, 2006 11:32 am ]
Post subject: 

wait ignore the post above, I have been thinking and came up with 3 scenarios.

If the Distance between the centres is less than the sum of the minor radii of both the oval, then 100% they are colliding.

If the Distance between the centres is greater than the sum of the major radii of both the oval, then 100% they are NOT colliding.

If the Distance between the centres is > sum of minor radii but < sum of major radii, then more scenarios in this on arise, I dont know how to find a solution to this scenario...

Does someone has a lead in this scenario?

Author:  TheOneTrueGod [ Thu Jun 29, 2006 1:11 pm ]
Post subject: 

Well, since like 8 other people gave you code, I might as well also.
code:

function Dist (x1, y1, x2, y2 : real) : real
    result sqrt ((x2 - x1) ** 2 + (y2 - y1) ** 2)
end Dist

var mx, my, but : int
var ovx, ovy, ovXSize, ovYSize := 100
ovYSize := 20
loop
    drawfilloval (ovx, ovy, ovXSize, ovYSize, black)
    mousewhere (mx, my, but)
    locate (1, 1)
    if sqrt (((ovx - mx)) ** 2 + ((ovy - my) * (ovXSize / ovYSize)) ** 2) < 100 then
        put "It Hit"
    else
        put ""
    end if
end loop

Author:  Clayton [ Thu Jun 29, 2006 2:31 pm ]
Post subject: 

Good job as always TOTG, however i have one question to ask: why did you include fcn Dist if you didnt use it??? anyways, in case anyone hasnt noticed, upthescale has been banned, so why are we posting in this topic?

Author:  Slaivis [ Thu Jun 29, 2006 2:57 pm ]
Post subject: 

SuperFreak82 wrote:
Good job as always TOTG, however i have one question to ask: why did you include fcn Dist if you didnt use it??? anyways, in case anyone hasnt noticed, upthescale has been banned, so why are we posting in this topic?



Just because the op can no longer use the information, that doesn't mean that the rest of us can't. Smile

I sure plan to use TOTG's code if I find a use for it!

Author:  MysticVegeta [ Thu Jun 29, 2006 3:10 pm ]
Post subject: 

TheOneTrueGod wrote:
Well, since like 8 other people gave you code, I might as well also.
code:

function Dist (x1, y1, x2, y2 : real) : real
    result sqrt ((x2 - x1) ** 2 + (y2 - y1) ** 2)
end Dist

var mx, my, but : int
var ovx, ovy, ovXSize, ovYSize := 100
ovYSize := 20
loop
    drawfilloval (ovx, ovy, ovXSize, ovYSize, black)
    mousewhere (mx, my, but)
    locate (1, 1)
    if sqrt (((ovx - mx)) ** 2 + ((ovy - my) * (ovXSize / ovYSize)) ** 2) < 100 then
        put "It Hit"
    else
        put ""
    end if
end loop


I sort of knew that too. But What I was asking was to detect collision betwen 2 ovals.. btw: What formula did you use?

Author:  TheOneTrueGod [ Thu Jun 29, 2006 3:59 pm ]
Post subject: 

Er, ya, I was going to use the Dist formula orginally, but then I used a modified one, and forgot to take it out Razz.

And I just experimented with the properties of a circle and an oval. Used some random formulas that made sense to me, etc.

As for collision between two ovals, I'd have to work on it a bit more, but something along the lines of

-Find the closest point from oval 1 to oval 2. (Use trig / oval properties for this.)
-Use the oval formula from before.

I may or may not make up some'n, if I feel like it, and post it later.

As for why this topic is still alive, i'd say its something to have if someone who has the same question later on feels like searching...
I know that only happens like... once a week... but still. Thats one less question a week that doesn't need to be answered Razz.

Author:  BenLi [ Thu Jun 29, 2006 4:51 pm ]
Post subject: 

well perhaps with whatdotcolor you could designate points on the player's fish's mouth that could detect when it touches another color

Author:  Clayton [ Thu Jun 29, 2006 5:05 pm ]
Post subject: 

well the only problem with that theory, is that, what happens if the point that you are checking with View.WhatDotColor misses the color you are looking for and you end up going to the wrong place? the best idea in this case would be to use some math and come up with some kind of algorithm to figure out collision detection with ovals

Author:  Mazer [ Thu Jun 29, 2006 8:39 pm ]
Post subject: 

The whatdotcolour approach screams of Andy tutelage, but the whole "mouth" thing was a good idea. If two fishes' tail fins touch they aren't eating each other, so why check for such a collision? You'd (that is, anyone attempting a similar problem would) probably want to specify a point for the mouth and do circular colision detection (with a relatively small radius) with the other ovals.

If you're at all serious about game development, let go of whatdotcolour. And if you're not, you needn't worry about collision detection! Wink

Author:  BenLi [ Fri Jun 30, 2006 6:47 pm ]
Post subject: 

true. Well, to simplify the problem, you can try designating a ratio of x radius to y radius. The fish will be similar...

Author:  MysticVegeta [ Sun Jul 02, 2006 11:30 am ]
Post subject: 

Is it me or did my post before just disappeared?

Anyways, Like that I said before (in my deleted post) you lose accuracy with whatdotcolor, thats why I was making a second method after making the loop method which uses major and minor radii but apparently its deleted for some reason.

Author:  zylum [ Sun Jul 02, 2006 5:30 pm ]
Post subject: 

if your just detecting of a fish's mouth is touching any other part of a fish that is really easy. detecting whether a point is in an oval is much easier than detecting whether two ovals are touching.

since you can describe an oval parametrically like so:

x = xRadius*cos(theta)
y = yRadies*sin(theta)

all you really need to know is theta. theta is just the angle between the fish's mouth and the centre of the fish you are collision detecting. using this theta, you find the x and y coordinate where the edge of the oval is. if this coordinate is closer to the centre than the fish's mouth, then there is no collision, otherwise there is a collision.

Author:  TokenHerbz [ Sun Jul 09, 2006 11:39 pm ]
Post subject: 

i see math i once used to know, its a shame i forgot it all :S

Anyone know a good site to refresh my skills in it?


: