Blitz3d Collisions not working correctly

Blitz3D Forums/Blitz3D Beginners Area/Blitz3d Collisions not working correctly

Uhfgood(Posted 2005) [#1]
The collisions aren't working right. Essentially I have an array of cubes layed out like a table. I have a sphere I created. I scaled down the cubes and the sphere to 1,1,1 (.5 meaning half). The gameToken is the sphere the cubes are the playfield. I also have a gravity field in the TGameObject type, so it will start moving down if another field is set to allow gravity. If I place the sphere (gameToken) 6 units above the cubes (playfield) the sphere will move down towards the board resting on top of it like it should. However, if I place the sphere one unit closer then the collision goes haywire.

Also a thing to note is I use y for z, that is, the playfield is 2d x and y, I'll put in the playfield y coordinate into the z position, because up corresponds to into the screen, and down corresponds to out of the screen.
For instance PositionEntity( gameToken, x, 0, y ) - even though y is in the z coordinate it represents y on the game board.

Consider this source code -

; m = member, b = boolean

Const b_DebugMode = False

; This won't have positional information
; as blitz will do that for me.  It will
; have velocity, speed, and gravity parameters
; probably some blitz collision information as well
Type TGameObject

	Field m_entity
	Field m_xVelocity#
	Field m_yVelocity#
	Field m_zVelocity#
	Field m_xSpeed#
	Field m_ySpeed#
	Field m_zSpeed#	
	Field mb_useGravity
	Field m_gravity#
	
End Type

Global debugtxt$ = ""

; most of the game entities
; to copy all the playfield 'cells'
; from; Gametoken is the piece that 
; moves around the board.

Global camera, light, gameToken.TGameObject
Dim Playfield( 12, 12 )

Global logfile

;;; General Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Function fn_AddDebugTxt( txt$ )

	debugTxt = debugTxt + txt$ + "|"
 
End Function

Function fn_ShowDebugTxt( txt$ )

	If( Right( txt, 1 ) <> "|" ) Then txt = txt + "|"

	ty = 0
	Repeat
		tx = Instr( txt, "|" )
		If( tx > 0 )
			Text( 0, ty, Left( txt, tx - 1 ) )
			txt = Right( txt, Len( txt ) - tx )
			ty = ty + 10
		End If
	Until tx = 0
	
	debugTxt$ = ""
	
End Function

Function fn_OpenLogFile()

	If( b_DebugMode = True )
	
		Cdate$ = CurrentDate$()
		Ctime$ = CurrentTime$()
		Cdir$ = CurrentDir$()
		logdir$ = Cdir$ + "log"
		
		If( FileType( logdir$ ) = 0 )
			CreateDir( logdir$ )
		End If
		
		LogFileName$ = logdir$ + "\" + Cdate$ + "log.txt"
		
		If( FileType( logdir$ ) = 2 )
			
			If( FileType( LogFileName$ ) = 1 )
				logfile = OpenFile( LogFileName$ )
				Repeat
					SeekFile( logfile, i )
					i = i + 1
				Until Eof( logfile )	
			Else
				logfile = WriteFile( LogFileName$ )
		
			End If
			
			If( logfile <> 0 )
			
				WriteLine( logfile, "" )
				WriteLine( logfile, LogFileName$ + " opened successfully." )
				WriteLine( logfile, "" )
				WriteLine( logfile, "log file opened on " + Cdate$ + " at " + Ctime$ + "." )
		
			Else
				DebugLog( "Could not create or open log file." )	
			End If
			
		End If
	
	End If
	
End Function ; fn_OpenLogFile()

;--------------------------------------;

Function fn_CloseLogFile()

	If( b_DebugMode = True )
	
		If( logfile <> 0 )
		
			WriteLine( logfile, "Logging successful, closing log file." )
			WriteLine( logfile, "" )
			WriteLine( logfile, "---" )
			CloseFile( logfile )
		
		End If
	
	End If

End Function ; fn_CloseLogFile()

;--------------------------------------;

; This function generally creates everything in 
; the game.  First the camera, then the light, then
; playfield and finally the game token.
Function fn_CreateWorld()

	; camera 
	camera=CreateCamera() 
	PositionEntity( camera, 6, 2, -16 )
	temppivot = CreatePivot()
	PositionEntity( temppivot, 6, 0, -6 )
	;RotateEntity( camera, 60, -20, 0 )
	PointEntity( camera, temppivot )
	FreeEntity( temppivot )
	
	; light
	AmbientLight 32, 32, 32
	light=CreateLight() 
	RotateEntity light, 60, 0, 0

	fn_CreatePlayfield()
	fn_CreateGameToken()
			
End Function ; fn_CreateWorld()

;--------------------------------------;

; free everything
Function fn_DestroyWorld()

	fn_DestroyGameToken()
	fn_DestroyPlayfield()

	FreeEntity( light )	
	FreeEntity( camera )
	
End Function ; fn_DestroyWorld

Function fn_ManageCollisions()

	; cell y is as you're looking from the top down, essentially the 2d
	; version used the y coordinates, but as y literally goes up and down
	; i have to worry about the z position (in and out of the screen)
	
	readjusted_z# = -EntityZ( gameToken\m_entity )
	
	fn_AddDebugTxt( "x = " + EntityX( gameToken\m_entity ) + " y = " + EntityZ( gameToken\m_entity ) )
	ul_x = ( EntityX( gameToken\m_entity ) - 0.45 )
	ul_y = ( readjusted_z# - 0.45 )
	fn_AddDebugTxt( "upperleft x = " + ul_x + " upperleft y = " + ul_y )
	ur_x = ( EntityX( gameToken\m_entity ) + 0.45 )
	ur_y = ( readjusted_z# - 0.45 )
	fn_AddDebugTxt( "upperright x = " + ur_x + " upperright y = " + ur_y )
	ll_x = ( EntityX( gameToken\m_entity ) - 0.45 )
	ll_y = ( readjusted_z# + 0.45 )
	fn_AddDebugTxt( "lowerleft x = " + ll_x + " lowerleft y = " + ll_y )
	lr_x = ( EntityX( gameToken\m_entity ) + 0.45 )
	lr_y = ( readjusted_z# + 0.45 )
	fn_AddDebugTxt( "lowerright x = " + lr_x + " lowerright y = " + lr_y )
	
	Collisions( 1, 2, 3, 1 )
	
End Function

;;; Playfield related functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Create the playfield, which at the moment
; is nothing more than an array of cubes.
Function fn_CreatePlayfield()

	; initial cube as a starting point
	Local cube = CreateCube() 
	ScaleEntity( cube, 0.5, 0.5, 0.5 )
	; 12 x 12 game board ( 0 - 11 = 12 positions )
	; note using y for z, swapping axes as the 2d
	; gameboard is being layed out flat like a table
	For y = 0 To 11
		For x = 0 To 11
			If( y > 0 ) Then adj_y = -y
			; create each "cell"
			Playfield( x, y ) = CopyEntity( cube )
			; position it relative to the other cells
			PositionEntity( Playfield( x, y ), x, 0, adj_y )
			EntityType( Playfield( x, y ), 2 )
			EntityBox( Playfield( x, y ), x, 0, adj_y, 0.5, 0.5, 0.5 )
			; give it a random color for indentity
			EntityColor( Playfield( x, y ), Rand( 63, 192 ), Rand( 63, 192 ), Rand( 63, 192 ) )
		Next
	Next
	
	; no more need for the cube
	FreeEntity( cube )
	
End Function ; fn_CreatePlayfield

;--------------------------------------;

; free up all the cells essentially
Function fn_DestroyPlayfield()

	For y = 0 To 11
		For x = 0 To 11
			FreeEntity( Playfield( x, y ) )
		Next
	Next

End Function ; fn_DestroyPlayfield

;;; Game Token Related Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; The piece the player directs
Function fn_CreateGameToken()

	gameToken = fn_CreateGameObject()
	
	; Make sure it created correctly
	If( gameToken <> Null )

		; now create the mesh/model etc
		gameToken\m_entity = CreateSphere()
		ScaleEntity( gameToken\m_entity, 0.45, 0.45, 0.45 )
		EntityType( gameToken\m_entity, 1 )
		EntityRadius( gameToken\m_entity, 0.90 )
		PositionEntity( gameToken\m_entity, 5.5, 6.00, -5.5 )
		gameToken\m_xSpeed# = 0.0
		gameToken\m_ySpeed# = 0.0
		gameToken\m_zSpeed# = 0.0
		gameToken\m_xVelocity# = 0.0
		gameToken\m_yVelocity# = 0.0
		gameToken\m_zVelocity# = 0.0
		gameToken\mb_useGravity = True
		gameToken\m_gravity# = -0.002
	Else
		RuntimeError( "Could not create game token." )
	End If
		
End Function ; fn_CreateGameToken()

;--------------------------------------;

; get rid of the game piece
Function fn_DestroyGameToken()

	fn_DestroyGameObject( gameToken )
	
End Function ; fn_DestroyGameToken()

;--------------------------------------;

Function fn_MoveGameToken()

	If( gameToken\mb_useGravity = True )
		gameToken\m_yVelocity# = gameToken\m_yVelocity# + gameToken\m_gravity#
	End If
	
	dx# = gameToken\m_xVelocity#
	dy# = gameToken\m_yVelocity#
	dz# = gameToken\m_zVelocity#
	
	TranslateEntity( gameToken\m_entity, dx#, dy#, dz# )
	
End Function

;;; TGameObject Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; A quick note about game object functions.  It's not always
; good to create super long function names, so most of the
; game object functions shortend TGameObject as TGOb For instance
; fn_TGObXXX() - where XXX is the rest of the function name.

;--------------------------------------;

; create and return a game object (game entity,
; but since this is blitz i called it an object)
Function fn_CreateGameObject.TGameObject()

	; 'o' is temporary
	Local o.TGameObject
	
	; create it make sure everything went well
	o.TGameObject = New TGameObject
	If( o <> Null )
		Return( o )
	Else
		RuntimeError( "Could not create game object." )
	End If
	
End Function ; fn_CreateGameObject.TGameObject()

;--------------------------------------;

; Get rid of it
Function fn_DestroyGameObject( o.TGameObject )

	; if there's an entity created free it first
	If( o\m_entity <> 0 )
		FreeEntity( o\m_entity )
	End If
	
	Delete( o )
	
End Function ; fn_DestroyGameObject( o.TGameObject )

;--------------------------------------;

Function fn_TGObSetXVelocity( o.TGameObject, value# )

	o\m_xVelocity# = value#
	
End Function

;--------------------------------------;

Function fn_TGObGetXVelocity#( o.TGameObject )

	Return( o\m_xVelocity# )
	
End Function

;--------------------------------------;

Function fn_TGObSetYVelocity( o.TGameObject, value# )

	o\m_yVelocity# = value#
	
End Function

;--------------------------------------;

Function fn_TGObGetYVelocity#( o.TGameObject )

	Return( o\m_yVelocity# )
	
End Function

;--------------------------------------;

Function fn_TGObSetZVelocity( o.TGameObject, value# )

	o\m_zVelocity# = value#
	
End Function

;--------------------------------------;

Function fn_TGObGetZVelocity#( o.TGameObject )

	Return( o\m_zVelocity# )
	
End Function

;--------------------------------------;

Function fn_TGObSetXSpeed( o.TGameObject, value# )

	o\m_xSpeed# = value#
	
End Function

;--------------------------------------;

Function fn_TGObGetXSpeed#( o.TGameObject )

	Return( o\m_xSpeed# )
	
End Function

;--------------------------------------;

Function fn_TGObSetYSpeed( o.TGameObject, value# )

	o\m_ySpeed# = value#
	
End Function

;--------------------------------------;

Function fn_TGObGetYSpeed#( o.TGameObject )

	Return( o\m_ySpeed# )
	
End Function

;--------------------------------------;

Function fn_TGObSetZSpeed( o.TGameObject, value# )

	o\m_zSpeed# = value#
	
End Function

;--------------------------------------;

Function fn_TGObGetZSpeed#( o.TGameObject )

	Return( o\m_zSpeed# )
	
End Function

;--------------------------------------;

Function fn_TGObSetGravityFlag( o.TGameObject, b_flag )

	o\mb_useGravity = b_flag

End Function

;--------------------------------------;

Function fn_TGObGetGravityFlag( o.TGameObject )

	Return( o\mb_useGravity )
	
End Function

;--------------------------------------;

Function fn_TGObSetGravity( o.TGameObject, value# )

	o\m_gravity = value

End Function

;--------------------------------------;

Function fn_TGObGetGravity#( o.TGameObject )

	Return( o\m_gravity# )
	
End Function

;--------------------------------------;

.main

Graphics3D 640,480 
SetBuffer BackBuffer() 

fn_OpenLogFile()

fn_CreateWorld()

While Not KeyDown( 1 ) 
	fn_MoveGameToken()
	fn_ManageCollisions()
	UpdateWorld
	RenderWorld 
	fn_ShowDebugTxt( debugTxt )
	Flip 
Wend 

fn_DestroyWorld()

fn_CloseLogFile()

End


If anyone can tell me what i'm doing wrong, i'd appreaciate it.


Stevie G(Posted 2005) [#2]
Replace these lines in the create game token function ..

EntityRadius( gameToken\m_entity, 0.50 )
PositionEntity( gameToken\m_entity, 5.5, 6.00, -5.5 )
ResetEntity ( gameToken\m_entity )



Note that positionentity still has collision checking so you have to use reset entity or entitytype entity, 0 to position the entity intially.


Uhfgood(Posted 2005) [#3]
Oh thanks, it works now.

Although looking back over my code it looks like something else of my calculation is wrong. I scaled my entity (the sphere) to about 45 percent (I believe) 0.45, and yet I set my entity radius to .90 - my reasoning is that half of 90 is 45, but that seems backwards now...

Does it looks like i'm making the entity radius twice as big as the actual sphere?

btw, if I change entity radius to .45 instead of .90 - then the collision doesn't seem to work.


Rook Zimbabwe(Posted 2005) [#4]
If you want it to look like the marble thing is resting on the table thing set the marble thing entityradius to .65 then...

When you scaled the sphere you did not scale the radius of collision... turn it to entityradius to 1 and see... .45 is too small for collisions I think there is a minimum I heard about but I am unsure... The center point may not be striking ANY of the cubes but may be slipping between the centers! You have to BOXMAP the collisions of the cubes maybe???


Uhfgood(Posted 2005) [#5]
how comes .65 looks correct? When I asked about a minimum limit for entityradius most everyone said that it's not true... so i don't know what is going on. and what do you mean by boxmap?

Keith


Uhfgood(Posted 2005) [#6]
I made an interesting discovery... I set my entity box to .5, .5, .5 - when those are for height, width, depth... that' means that only half of the box size was a collision box.

Which means that I should put them at 1 because they've all been scaled to just 1 unit. Okay so I had to go back and mess with my token creation, now I can set the entity radius to .5 and that works, instead of 6.5 -- I still don't know how all this works out correctly though, as it's still being positioned from the center.


Rook Zimbabwe(Posted 2005) [#7]
I am still slightly confused by the entitybox as well... Sorry... perhaps someone else knows???


Stevie G(Posted 2005) [#8]
If you want a box scale of 1 unit across just use entitybox -.5,-.5,.-5,1,1,1. I'm pretty sure it works in a similar way to fitmesh.

Stevie


Uhfgood(Posted 2005) [#9]
Anyone else that replies in here, please look at my other message, a slightly different problem but along the same lines

http://www.blitzbasic.com/Community/posts.php?topic=45833


Uhfgood(Posted 2005) [#10]
Thanks for the help this works now.