Here's the DBP code for a rotated box collision routine;
Sync On : Sync Rate 0
AutoCam Off
`Makes the "rectangle". Just a simple Plain that is in Wireframe
Make Object Plain 1,20,40
Position Object 1,100,0,100
XRotate Object 1,270
Fix Object Pivot 1
Set Object 1,0,0,0
Global objwidth = 20
Global objheight = 40
`Positions the camera above the rectangle to easily see it.
Position Camera Object Position X(1),200,Object Position Z(1)
Point Camera Object Position X(1),0,Object Position Z(1)
Randomize Timer()
`Makes 200 spheres and randomly positions them around the Rectangle
For x = 2 To 361
Make Object Plain x,1,1
XRotate Object x,270 : Fix Object Pivot x
_random(x)
Color Object x,RGB(255,0,0)
Next x
st As Float
et As Float
time As Float = 0.0
Do
time = 0.0
fps = Screen FPS()
For x = 2 To 361
`Loops through each sphere, passing it's current X and Z coords as the
`points to check for collision
st = (Timer() * 1.0)
coll = _rot_box(Object Position X(1),Object Position Z(1),objwidth,objheight,Object Angle Y(1),Object Position X(x),Object Position Z(x),Object Size(x))
et = ((Timer() - st) * 1.0)
time = ((time + et) * 1.0)
`If no collision, then keep on moving the object
If coll = 0
Point Object x,Object Position X(1),0,Object Position Z(1)
Move Object x,1
EndIf
`If there was an error, then report it.
If coll = 2
Text 0,100,"Error"
EndIf
Next x
`Simple camera and object controls.
If RightKey() = 1 Then YRotate Object 1,_wrap(Object Angle Y(1) + 1,360)
If LeftKey() = 1 Then YRotate Object 1,_wrap(Object Angle Y(1) - 1,360)
If UpKey() = 1 Then Move Camera 2
If DownKey() = 1 Then Move Camera -2
`Just re-randomizes the positions of the spheres.
If InKey$() = "r"
For x = 2 To 361
_random(x)
Next x
EndIf
Text 0,0,"Screen FPS() = " + Str$(fps)
Text 0,20,"Press 'r' To reset positions of balls"
Text 0,60,"Current Rotation = " + Str$(Object Angle Y(1)) + " degrees"
Text 0,Screen Height() - 20,"Time for 360 iterations = " + Str$(time) + " ms"
Sync
Loop
Function _random(x)
`The Repeat... Until loops just makes sure no sphere's get placed
`inside the rectangle.
Repeat
objx = NewXValue(Object Position X(1),(x - 1),Rnd(100) + 50)
objy = 0
objz = NewZValue(Object Position Z(1),(x - 1),Rnd(100) + 50)
Until _rot_box(Object Position X(1),Object Position Z(1),objwidth,objheight,Object Angle Y(1),objx,objz,0.0) = 0
Position Object x,objx,objy,objz
Point Object x,Object Position X(1),0,Object Position Z(1)
EndFunction
Function _rot_box(boxx As Float,boxz As Float,xlength As Float,zlength As Float,boxrot As Float,px As Float,pz As Float,buffer As Float)
remstart
The method I'm using simply takes all the points into account,
converts them into a non-rotated box, then distance checks them all
boxx:
The position of the centre of the box on the X axis
boxz:
The position of the centre of the box on the Z axis
xlength
_____/\_____
| |
_ ____________
| | |
| | |
zlength < | |
| | |
|_ |____________|
boxrot:
The angle that box is rotated to currently ( 1 to 360, where 0 = 360 )
px:
The position of the External/Internal point on the X axis
pz:
The position of the External/Internal point on the Z axis
buffer:
This is the distance from the edge of the box that you want to check from.
ie, if you wanted to check the collision for 2 units outside the box's
actuall dimensions, then set the buffer to 2.
The Function returns;
0 for no collision;
1 for collision;
2 for function error ( usually due to incorrect input values ).
remend
`Declare's the local variables to be used in the function
Local collision As Boolean = 0
Local centrea As Float = 0
Local theta As Float = 0
Local dist As Float = 0
`Just extends/retracts the collision distance to comply with the buffer value
xlength = xlength + (buffer * 2.0)
zlength = zlength + (buffer * 2.0)
`Set's the position values so that we are working with the origin as 0,0
px = px - boxx
pz = pz - boxz
`Gets the angle between the centre of the xlength, and the diagonal from the centre to the
`corner of the rectangle
centrea = (ATan((xlength / 2) / (zlength / 2)))
`This takes the angle between the external/internal point, and the centre of the box
`and the xaxis and converts it to a point between the same lines, but on a
`non-rotated box.
theta = (ATan(px / pz)) - boxrot
`Simply makes the following calculation a little easier by restricting the
`angle to one side of the rectangle
theta = _wrap(theta,180)
`This part is a little difficult to explain without Diagrams.
`Basically, the first IF function gets the collision distance for objects who's
`angle is between the lines going from the centre to the corners of the rectangle.
`The second if function gets the collision distance for object's that are in
`the remaining angles ( on the one side of the rectangle )
If ( theta >= centrea ) And ( theta <= (180 - centrea) )
If theta < 90 Then theta = 90 - theta Else theta = theta - 90
dist = (xlength / 2) / Cos(theta)
Else
If theta > 90 Then theta = 180 - theta
dist = (zlength / 2) / Cos(theta)
EndIf
`This is a simple distance check using Pythagorus Theorum.
`If the points tested are closer to the centre of the rectangle than
`the collision distance, then those points are colliding with the rectangle
If Sqrt( px^2 + pz^2) < dist Then collision = 1
EndFunction collision
Function _wrap(var As Integer,max As Integer)
If ( var < max ) And ( var >= 0 )
ExitFunction var
EndIf
If ( var > ( max * -1 ) ) And ( var < 0 )
ExitFunction ( max + var )
EndIf
If var >= max
var = var MOD max
EndIf
If var <= ( max * -1 )
var = max + ( var MOD max )
EndIf
EndFunction var
That includes an example of how to use the function
I'm having some trouble converting that to DBC atm though ( all the types and stuff are giving me greif ).
Also, if you want really simple collision, remember to try distance checks, that gives you circle collision.
Also, if you want to mix circle collision, and box, then simply check every ten degree's around the circle of collision with the box, that way it reduces the amount of checks needed ( only 36 ) for the circle. THere's probably a better way, but at the moment, I'm a bit rushed.
Enjoy.
Jess.
PS Here's what I have for DBC so far:
Sync On : Sync Rate 0
AutoCam Off
`Makes the "rectangle". Just a simple Plain that is in Wireframe
Make Object Plain 1,20,40
Position Object 1,100,0,100
XRotate Object 1,270
Fix Object Pivot 1
Set Object 1,0,0,0
`Width / Height
Dim obj#(1)
obj#(0) = 20.0
obj#(1) = 40.0
`Positions the camera above the rectangle to easily see it.
Position Camera Object Position X(1),200,Object Position Z(1)
Point Camera Object Position X(1),0,Object Position Z(1)
Randomize Timer()
`Makes 200 spheres and randomly positions them around the Rectangle
For x = 2 To 361
Make Object Plain x,1,1
XRotate Object x,270 : Fix Object Pivot x
_random(x)
Color Object x,RGB(255,0,0)
Next x
st# = 0.0
et# = 0.0
time# = 0.0
Do
time# = 0.0
fps = Screen FPS()
For x = 2 To 361
`Loops through each sphere, passing it's current X and Z coords as the
`points to check for collision
st# = (Timer() * 1.0)
coll = _rot_box(Object Position X(1),Object Position Z(1),obj#(0),obj#(1),Object Angle Y(1),Object Position X(x),Object Position Z(x),Object Size(x))
et# = ((Timer() - st) * 1.0)
time# = ((time + et) * 1.0)
`If no collision, then keep on moving the object
If coll = 0
Point Object x,Object Position X(1),0,Object Position Z(1)
Move Object x,1
EndIf
`If there was an error, then report it.
If coll = 2
Text 0,100,"Error"
EndIf
Next x
`Simple camera and object controls.
If RightKey() = 1 Then YRotate Object 1,WrapValue(Object Angle Y(1) + 1)
If LeftKey() = 1 Then YRotate Object 1,WrapValue(Object Angle Y(1) - 1)
If UpKey() = 1 Then Move Camera 2
If DownKey() = 1 Then Move Camera -2
`Just re-randomizes the positions of the spheres.
If InKey$() = "r"
For x = 2 To 361
_random(x)
Next x
EndIf
Text 0,0,"Screen FPS() = " + Str$(fps)
Text 0,20,"Press 'r' To reset positions of balls"
Text 0,60,"Current Rotation = " + Str$(Object Angle Y(1)) + " degrees"
Text 0,Screen Height() - 20,"Time for 360 iterations = " + Str$(time) + " ms"
Sync
Loop
Function _random(x)
`The Repeat... Until loops just makes sure no sphere's get placed
`inside the rectangle.
Repeat
objx# = NewXValue(Object Position X(1),(x - 1),Rnd(100) + 50.0)
objy# = 0
objz# = NewZValue(Object Position Z(1),(x - 1),Rnd(100) + 50.0)
Until _rot_box(Object Position X(1),Object Position Z(1),obj#(0),obj#(1),Object Angle Y(1),objx#,objz#,0.0) = 0
Position Object x,objx,objy,objz
Point Object x,Object Position X(1),0,Object Position Z(1)
EndFunction
Function _rot_box(boxx#,boxz#,xlength#,zlength#,boxrot#,px#,pz#,buffer#)
remstart
The method I'm using simply takes all the points into account,
converts them into a non-rotated box, then distance checks them all
boxx:
The position of the centre of the box on the X axis
boxz:
The position of the centre of the box on the Z axis
xlength
_____/\_____
| |
_ ____________
| | |
| | |
zlength < | |
| | |
|_ |____________|
boxrot:
The angle that box is rotated to currently ( 1 to 360, where 0 = 360 )
px:
The position of the External/Internal point on the X axis
pz:
The position of the External/Internal point on the Z axis
buffer:
This is the distance from the edge of the box that you want to check from.
ie, if you wanted to check the collision for 2 units outside the box's
actuall dimensions, then set the buffer to 2.
The Function returns;
0 for no collision;
1 for collision;
2 for function error ( usually due to incorrect input values ).
remend
`Declare's the local variables to be used in the function
collision = 0
centrea# = 0.0
theta#t = 0.0
dist# = 0.0
`Just extends/retracts the collision distance to comply with the buffer value
xlength# = xlength# + (buffer# * 2.0)
zlength# = zlength# + (buffer# * 2.0)
`Set's the position values so that we are working with the origin as 0,0
px# = px# - boxx#
pz# = pz# - boxz#
`Gets the angle between the centre of the xlength, and the diagonal from the centre to the
`corner of the rectangle
centrea# = (ATan((xlength# / 2.0) / (zlength# / 2.0)))
`This takes the angle between the external/internal point, and the centre of the box
`and the xaxis and converts it to a point between the same lines, but on a
`non-rotated box.
theta# = (ATan(px# / pz#)) - boxrot#
`Simply makes the following calculation a little easier by restricting the
`angle to one side of the rectangle
theta# = _wrap(theta#,180)
`This part is a little difficult to explain without Diagrams.
`Basically, the first IF function gets the collision distance for objects who's
`angle is between the lines going from the centre to the corners of the rectangle.
`The second if function gets the collision distance for object's that are in
`the remaining angles ( on the one side of the rectangle )
If ( theta# >= centrea# ) And ( theta# <= (180 - centrea#) )
If theta# < 90 Then theta# = 90 - theta# Else theta# = theta# - 90
dist# = (xlength# / 2.0) / Cos(theta#)
Else
If theta# > 90 Then theta# = 180 - theta#
dist = (zlength# / 2.0) / Cos(theta#)
EndIf
`This is a simple distance check using Pythagorus Theorum.
`If the points tested are closer to the centre of the rectangle than
`the collision distance, then those points are colliding with the rectangle
If Sqrt( px#^2 + pz#^2) < dist# Then collision = 1
EndFunction collision
Function _wrap(var,max)
If ( var < max ) And ( var >= 0 )
ExitFunction var
EndIf
If ( var > ( max * -1 ) ) And ( var < 0 )
ExitFunction ( max + var )
EndIf
If var >= max
var = var MOD max
EndIf
If var <= ( max * -1 )
var = max + ( var MOD max )
EndIf
EndFunction var#
Function _mod(val1,val2)
result = val1 - (Int(val1 / val2) * val2)
EndFunction result

Team EOD :: Programmer/All-Round Nice Guy
Aust. Convention!