andrewo 09042001, 03: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?
~
Teric 09042001, 08: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 Asquared plus Bsquared equals Csquared. 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 = (5060)^2 + (5060)^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 + (ShipYLandY)^2)
if Distance <= Radius then
'Collision!
End if
I hope this helps.
andrewo 09052001, 09: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
~
BillSoo 09052001, 09: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>
Teric 09052001, 09: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.
andrewo 09062001, 07: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 :)
~
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>
Teric 09062001, 08:09 AM Ah, I see what you're saying, andrewo. Yes, you're rightdetecting 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.
BillSoo 09062001, 10:37 AM Yes it is complicated...but it's not that bad. And once it's done, it's easier to use.
Check out www.thescarms.com 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
andrewo 09092001, 12: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 (y2y1)/(x2x1)
then you need the yintercept(b)
you would use the equation
b=ymx
which is using the other working out:
b= y1((y2y1)/(x2x1)*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= ((y2y1)/(x2x1))x +(y1((y2y1)/(x2x1)*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
~
andrewo 09092001, 12: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
~
andrewo 09102001, 12: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
~
BillSoo 09102001, 01: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
andrewo 09102001, 07: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
~
