I am in the process of writing a new tutorial covering advanced collision using DBC's native collision commands - in particular, covering the navigation of ramps and stairs loaded as .X files.
The basic aim was to use another object
in front of the main character object to test for collision - ie steps or ramps. In order to do this, you need to somehow attach these 'detector' objects to the main character object so they move around with the character.
As it's something I've not done myself before, I expected it to be not all that straight forward, but I wasn't expecting to find the odd behaviour I did find. Let's say that it's no surprise that people say that DBC's native collision commands are not good for doing this kind of thing.
But, not one to give up easily, I decided to persevere...
Anyway, I've discovered the following things about DBC and collision (some of which I knew already and some I have just discovered). Hopefully this list will be a guide for any of you having collision problems.
Here's the list:
1. If you create an object for collision and scale it up or down, the automatically created collision bounding box will not be scaled with it. It will remain the size of the originally created object.
Example:
Rem Example 1 - Scaled Object Collision Test
Rem TDK_Man April 2008
Gosub Setup
Gosub MakeObjects
Do
Gosub KeyInput
Position Camera ObjPosX#,14,ObjPosZ#
Sync
Center Text 400,0,"Object 1 (Red Cube) Colliding With Object "+Str$(ObjHit)
Loop
End
KeyInput:
If LeftKey()=1 Then Dec ObjPosX#,.04
If RightKey()=1 Then Inc ObjPosX#,.04
If UpKey()=1 Then Inc ObjPosZ#,.04
If DownKey()=1 Then Dec ObjPosZ#,.04
Position Object 1,ObjPosX#,ObjPosY#,ObjPosZ#: Rem Player Cube (Scaled Up)
Position Object 2,ObjPosX#,ObjPosY#,ObjPosZ#: Rem Original Player Sized Cube
Rem Check Player Object Collision
ObjHit = Object Collision(1,0)
Return
MakeObjects:
Rem Main Red Cube For Player
CubeSize = 1
ScaleFactor = 300
Make Object Cube 1,CubeSize
Color Object 1,RGB(255,0,0)
Scale Object 1,ScaleFactor,ScaleFactor,ScaleFactor
Rem White Cube same size as main cube for comparison
Make Object Cube 2,CubeSize
If ScaleFactor > 100
Scale Object 2,100,ScaleFactor+10,100
Else
Scale Object 2,100,1,100
Endif
Color Object 2,RGB(255,255,255)
Set Object Collision Off 2
Rem Four Blue Walls For Collision Test
Make Object Box 101,6,5,1
Color Object 101,RGB(0,0,255)
Position Object 101,0,0,5
Make Object Box 102,6,5,1
Color Object 102,RGB(0,0,255)
Position Object 102,0,0,-5
Make Object Box 103,6,5,1
YRotate Object 103,90
Color Object 103,RGB(0,0,255)
Position Object 103,-5,0,0
Make Object Box 104,6,5,1
YRotate Object 104,90
Color Object 104,RGB(0,0,255)
Position Object 104,5,0,0
Return
Setup:
Set Display Mode 800,600,32
Sync On
Sync Rate 0
CLS
Backdrop On: Color Backdrop 0
AutoCam Off
Hide Mouse
Position Camera 0,14,0
Point Camera 0,0,0
ObjPosX#=0.0: ObjPosY#=0.0: ObjPosZ#=0.0
Return
Notice that even though the collision detection is with Object 1 (the red cube), it doesn't register when the red cube bumps into the blue walls - only when the
white cube hits the walls. (The white cube merely shows the size of the red cube before it was scaled up and even has collision turned off).
The same happens when scaling down too. Try setting CubeSize to 2 and ScaleFactor to 30 and running the example again. Remember, the collision test is on the red object - not the white one!
2. Glue Object To Limb Problem
If you use Glue Object To Limb it disables collision on the object being attached. For example, if you want to attach secondary objects around the red main player cube (but not touching it) and have the objects remain in position when the main player cube is moved, you can use the following method (example only uses 1 secondary cube)...
Example:
Rem Offset Limb Object Collision Test
Gosub Setup
Gosub MakeObjects
Do
Gosub KeyInput
Sync
Center Text 400,0,"Object 2 (White Cube) Colliding With: "+Str$(ObjHit)
Loop
End
KeyInput:
If LeftKey()=1 Then Dec ObjPosX#,.05
If RightKey()=1 Then Inc ObjPosX#,.05
If UpKey()=1 Then Inc ObjPosZ#,.05
If DownKey()=1 Then Dec ObjPosZ#,.05
Position Object 1,ObjPosX#,ObjPosY#,ObjPosZ#
Position Object 2,ObjPosX#,ObjPosY#,ObjPosZ#: Rem <<<<< THIS IS LINE A
Rem Check Objects Collision
ObjHit = Object Collision(2,0)
Return
MakeObjects:
Rem Main Red Cube For Player
Make Object Cube 1,1
Set Object Collision On 1
Color Object 1,RGB(255,0,0)
Ghost Object On 1
Rem Player Limb Locator - Small White Cube
Make Object Cube 2,.2
Set Object Collision On 2
rem Glue Object To Limb 2,1,0: Rem <<<<< THIS IS LINE B
Rem Four Blue Walls For Collision Testing
Make Object Box 101,6,5,1
Color Object 101,RGB(0,0,255)
Position Object 101,0,0,5
Make Object Box 102,6,5,1
Color Object 102,RGB(0,0,255)
Position Object 102,0,0,-5
Make Object Box 103,6,5,1
YRotate Object 103,90
Color Object 103,RGB(0,0,255)
Position Object 103,-5,0,0
Make Object Box 104,6,5,1
YRotate Object 104,90
Color Object 104,RGB(0,0,255)
Position Object 104,5,0,0
Return
Setup:
Set Display Mode 800,600,32
Sync On
Sync Rate 0
CLS
Backdrop On
Color Backdrop 0
AutoCam Off
Position Camera 0,14,0
Point Camera 0,0,0
ObjPosX#=0.0: ObjPosY#=0.0: ObjPosZ#=0.0
Return
If however you want to rotate the main cube, you need to use Glue Object. Swap the Rems on the two lines marked Line A and Line B in the above example and run it again.
This time, as the white cube has been glued to object 1, it no longer has any collision.
3. Hide Object Another Object Is Glued To Problem
This was the next step to try and get around problem 2 above...
Create a red cube (1). Next, create a second white cube (2), glue it to the first one, then offset the limb it's attached via.
Note: The intention is to have white cubes on all four sides, so the limbs of the four cubes are offset - not the red cube's limb - as this would only allow positioning on one side. The example below demonstrates this with one white cube for brevity.
As the collision doesn't work with the second cube due to problem 2 above, you turn off it's collision and use this cube's X/Y/Z position (using the Limb Position function) with a third cube - which you
can use for collision testing. This works perfectly as you can see from the following example:
Example:
Rem Example 3
Gosub Setup
Gosub MakeObjects
Do
Gosub KeyInput
Position Camera ObjPosX#,14,ObjPosZ#
Sync
Center Text 400,0,"Wall Object Colliding With: "+Str$(WallHit)
Loop
End
KeyInput:
If LeftKey()=1 Then Dec ObjPosX#,.04
If RightKey()=1 Then Inc ObjPosX#,.04
If UpKey()=1 Then Inc ObjPosZ#,.04
If DownKey()=1 Then Dec ObjPosZ#,.04
Position Object 1,ObjPosX#,ObjPosY#,ObjPosZ#
Rem Position The Cube Used For Collision At The Offset Limb's Position
Position Object 3,Limb Position X(2,0),Limb Position Y(2,0),Limb Position Z(2,0)
Rem Check Objects Collision
WallHit = Object Collision(3,0)
Return
MakeObjects:
Rem Main Red Cube For Player
Make Object Cube 1,1
Color Object 1,RGB(255,0,0)
Rem Player Limb locator (Small White Cube)
Make Object Cube 2,.1
Glue Object To Limb 2,1,0
Offset Limb 2,0,-1,0,0
Set Object Collision Off 2
rem Hide Object 2
Rem Green Collision Detector...
Make Object Cube 3,.5
Color Object 3,RGB(0,128,0)
Ghost Object On 3
Rem Four Blue Walls For Collision Detection
Make Object Box 101,6,5,1
Color Object 101,RGB(0,0,255)
Position Object 101,0,0,5
Make Object Box 102,6,5,1
Color Object 102,RGB(0,0,255)
Position Object 102,0,0,-5
Make Object Box 103,6,5,1
YRotate Object 103,90
Color Object 103,RGB(0,0,255)
Position Object 103,-5,0,0
Make Object Box 104,6,5,1
YRotate Object 104,90
Color Object 104,RGB(0,0,255)
Position Object 104,5,0,0
Return
Setup:
Set Display Mode 800,600,32
Sync On
Sync Rate 0
CLS
Backdrop On
Color Backdrop 0
AutoCam Off
Position Camera 0,14,0
Point Camera 0,0,0
ObjPosX#=0.0: ObjPosY#=0.0: ObjPosZ#=0.0
Return
However, you don't want to be able to see the second white cube (or the third one eventually), so you use Hide Object 2.
The problem is that if you do use
Hide Object 2 then the Limb Position command simply stops working! Try simply removing the Rem from the start of the
Hide Object 2 line in the MakeObjects procedure.
How many of these 'problems' are still present in DBPro, I don't know.
Also, if anyone has any work-arounds that will make the above examples work, please post them here and I'll credit you in the finished tutorial - if it ever gets finished!
I also concede that I may be going about this in completely the wrong way, so if you know of a better way to do the same thing, please feel free to chip in...
TDK_Man