Detecting collision on lines which are on an angle

09-04-2001, 04:38 AM
I've got a program that generates random landscapes for my moon lander game
ive made a flat point etc to land on but my problem is detecting if the ship crashes into the lines that arnt the landing pad.

iam using an array of points that are joined up as lines

ive tried using gradients but i havent got that to work,

has anyone got some code or suggestions?


09-04-2001, 09:53 AM
I am assuming your landing ship is a picture box or an image made of a rectangle, correct?

Try this:

1. Each time you move the ship, calculate the location of the center point of the ship: (Left + Width)/2 , (Top + Height) / 2

2. Determine a "radius" length from the center of your ship at which distance the ship would collide with an object. You can do a cheap estimate of this radius by taking the width or height of your ship (which ever is greater) and dividing by 2.

3. Loop through each point in your array of points to see if that point is within the radius distance from the center point of your ship. To calculate the distance between your ship's center point and a point on the landscape, use the Pythagorean Theorem (yes, there IS a use for school math!!). The Pythagorean Theorem is used to calculate the length between two different points. The formula is A-squared plus B-squared equals C-squared. Here's an example:

The ship's center point is at 50,50.
A point of land is at 60,60.
The ship's 'radius' is 10.

so, to compute (^2 means squared):
Distance^2 = (50-60)^2 + (50-60)^2
Distance^2 = 100+100
Distance^2 = 200
Distance is about 14

Thus, since the distance between the center of the ship and the point of land is about 14 (and 14 is greater than the ship's 'radius' of 10), there is no collision.

To do this in code, you could put something like this:

Dim Radius as Integer
Dim Distance as Single
Dim ShipX as Integer 'The X coordinate of the center of the ship
Dim ShipY as Integer 'The Y coordinate of the center of the ship
Dim LandX as Integer
Dim LandY as integer

ShipX = (Ship.Left + Ship.Width)/2
ShipY = (Ship.Top + Ship.Height)/2
LandX = TerrainPoint.X 'Or whatever you called your terrain point variable
LandY = TerrainPoint.Y
Radius = Ship.Height/2
Distance = Sqr((ShipX - LandX)^2 + (ShipY-LandY)^2)
if Distance <= Radius then
End if

I hope this helps.

09-05-2001, 10:00 AM
i dont quite understand how using the distant of the landscape between the ship will detect the collision
because i'll be using multiple lines and i want to be able to detect if the ship hits in between the lines


09-05-2001, 10:24 AM
This might be a complicated way to do it, but you could use the CreateRectRgn and CombineRgn API calls to create a region the shape of your terrain. Even if it is a bunch of angled lines, you could do it by approximating it into a large number of narrow rectangles and combining them together. Then you could use another function, whose name escapes me at the moment, to test whether or not a rectangle is within or touching the region. Something like "rectinrgn"....

Edit: RectInRegion....

"I have a plan so cunning you could put a tail on it and call it a weasel!" - Edmund Blackadder<P ID="edit"><FONT class="small"><EM>Edited by BillSoo on 09/05/01 12:18 PM.</EM></FONT></P>

09-05-2001, 10:29 AM
When you detect the distance between the landscape and the ship, all you're doing is calculating how close the ship is to the land. If the ship gets too close (i.e. the land comes in contact with the outer edge of the ship), then they collide.

If you're setting it up so that the ship flies between two lines, you could check to see if the ship is too close to one side, then check to see if it's too close to the other side. If it's too close to either side, there will be a collision.

09-06-2001, 08:26 AM
Billso i think your way is quite complicated

teric the problem using the distance betweent he two points is that if it is in the middle it wont detect it colliding as it thinks it will still detect it that much higher

hm i had a great idea yesterday but i forgot :)


09-06-2001, 09:00 AM
as it should only be the 2 bottom corners of your ship that would first hit the landscape you could use the GetPixel API to detect the colour of the pixel just offset of each corner, and if they are the colour of the landscape then you've got a hit
<pre><font color=blue>Private <font color=blue>Declare</font color=blue> Function</font color=blue> GetPixel <font color=blue>Lib</font color=blue> "gdi32" (<font color=blue>ByVal</font color=blue> hdc <font color=blue>As Long</font color=blue>, <font color=blue>ByVal</font color=blue> X <font color=blue>As Long</font color=blue>, <font color=blue>ByVal</font color=blue> Y <font color=blue>As Long</font color=blue>) <font color=blue>As Long</font color=blue></pre>

09-06-2001, 09:09 AM
Ah, I see what you're saying, andrewo. Yes, you're right--detecting the distance to just the end points of each line will not correctly detect collisions in some cases.

It looks like BillSoo's idea may be the best way to go. I would look into it.

09-06-2001, 11:37 AM
Yes it is complicated...but it's not that bad. And once it's done, it's easier to use.

Check out for an example of a "skinned form". This is a form that conforms to any shape. It's done using this technique of combining strips of regions....

"I have a plan so cunning you could put a tail on it and call it a weasel!" - Edmund Blackadder

09-09-2001, 01:10 AM
it doesnt 100% work fast..but i just gotta rearrange my code abit to fix it and it sometimes detects the ship hitting the land a little bit over it but that must be some error i did typing

what i have got is
finding the equation of the line..represented as y=mx+b
and the ships x,y position

ok so to find the gradient of the line you got to have the two points
x1,y1 and x2,y2

you need the gradient(m) of the line first so to get the gradient you use (y2-y1)/(x2-x1)

then you need the y-intercept(b)
you would use the equation
which is using the other working out:
b= y1-((y2-y1)/(x2-x1)*x)
so now you have the equation of the line
and to work out if the ship(a point) is above or below the terrain
you would put the ships x and y into the equation you worked out
y=mx+b or all together would be y= ((y2-y1)/(x2-x1))x +(y1-((y2-y1)/(x2-x1)*x))

Remember the 0,0 is at the top left hand of the screen
and x1,x2 are the two points of the line
so you write:
if y>= mx+b and x>x1 and x<2 then showcollision

sorta complicated but not really

and if you have lots of lines for your landscape you would use an array..heres an example of my code using an aray...

For i = 1 To 28
Pol.X = Ship.Left
Pol.Y = Ship.Top + Ship.Height
Pol.X1 = Points(i).X
Pol.X2 = Points(i + 1).X
Pol.Y1 = Points(i).Y
Pol.M = (Points(i + 1).Y - Points(i).Y) / (Points(i + 1).X - Points(i).X)
Pol.B = Pol.Y1 - (Pol.M * Pol.X)
If (Pol.Y >= Pol.M * Pol.X + Pol.B) And (Pol.X >= Pol.X1) And (Pol.X <= Pol.X2) Then showcollision


09-09-2001, 01:16 AM
hey thats a good idea Ad1
,checking if the colour of the bottom of the ship changes to the landscape ..could you give me some example code, that would be more accurate then my current code


09-10-2001, 01:11 AM
i ended up working out how to use the getpixel method and it works great heres my code

For i = 0 To 15
If CraftBottom(i) = 8421504 Or CraftBottom(i) = 0 Then Freeze = False Else Freeze = True
If CraftBottom(i) = 255 Then Freeze = True And Land = True
CraftBottom(i) = GetPixel(Me.hdc, Lander.Left + i, Lander.Top + Lander.Height)
Next i


09-10-2001, 02:40 AM
I'm glad it works for you....

In general though, the getpixel method has limitations. Particularly if the background is of multiple colours....

"I have a plan so cunning you could put a tail on it and call it a weasel!" - Edmund Blackadder

09-10-2001, 08:15 PM
yea thats true
it also runs a bit slow
like i had to bring the game milliseconds down from 30 to 5 to make it actually work at a resonable speed


EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum