Accurate 3D Pong Physics

Blitz3D Forums/Blitz3D Programming/Accurate 3D Pong Physics

Need a little help 3D Math Gurus. I'm nearly complete with my 3D pong game but, unfortunately, I'm stumped on getting the orbs to deflect with proper direction (angle) when colliding with a Walls, Paddles, and other Orbs.

I was referencing this excellent 2D Billiards Style Collision Physics for the basis of 3D conversion. However, I'm using Blitz3D Entity Collision and the orbs travel all directions (XYZ planes).

Needless to say my 3D conversion of the 2D code is not working and my hair is falling out. I have a strong feeling that Im supposed to use Blit3's fancy Collision Normal and Vector functions somewhere in there.

This was supposed to be easy...:(

I was able to restore the code back to its working 2D-in-3D conversion.
; ID: 415
; Author: Phish
; Modified by F.L.Taylor
; Date: 2002-09-03 11:43:20
; Title: Billiards Style Collision Physics
; Description: 2D circle collision response which can be used for almost anything where 2 objects collide in 2 dimensions

;------------------------------------------
;2D COLLISION DEMO CODE
;------------------------------------------
; By Joseph 'Phish' Humfrey
; This type of collision response isn't
; just useful for pool and billiard style
; games, and in fact, I didn't write it for
; that reason at all. I wrote it because I
; needed to have collision for the space
; ships in my game 'Unity'. When their
; shields are up, they use this relatively
; simple method. It can be used for almost
; anything - player character bouncing off
; enemies in a platform game, to space
; ship collision, to a game which does
; actually involve balls. The basic
; algorithm which I used would work for
; both 2d and 3d, so if you would like to
; see it, email me at phish@...
;------------------------------------------
; The actual code which works out what
; happens after a collision is in the
; UpdateCirclePhysics() function.
;------------------------------------------
; Enjoy!
;------------------------------------------
;------------------------------------------

Graphics3D 800, 600, 16, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()




;------------------------------------------
; MAIN DATA TYPE
;------------------------------------------
; This exact type isn't supposed to be used
; Instead, you should use some of the fields
; in your own type, or just use this one
; for reference, to see what each field does
Type HP_orb
	Field netid%
	Field x#
	Field y#
	Field z#
	Field entity%
	Field dx#
	Field dy#		;x and y speeds
	Field dz#
	Field radius#	;radius of circle
	Field mass#	 ;mass of circle
	Field state%
End Type

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






;------------------------------------------
; SET UP BALLS INTO A POOL STYLE ARRANGEMENT
; FOR DEMO
;------------------------------------------
.Setup


;HP_OrbQ ball (smaller so you know which it is :)
HP_OrbQ.HP_Orb = New HP_Orb
HP_OrbQ\entity = CreateSphere(64)
EntityShininess(HP_OrbQ\entity,.8)
HP_OrbQ\x = -20
HP_OrbQ\y = -100
HP_OrbQ\dx = -3
HP_OrbQ\dy = Rnd(4)-2
HP_OrbQ\radius = 1
HP_OrbQ\mass = 50

For xloop = 1 To 3
	For yloop = 1 To 3
		HP_Orb.HP_Orb = New HP_Orb
		HP_Orb\entity = CopyEntity(HP_OrbQ\entity)		
		EntityShininess(HP_Orb\entity,.8)
		EntityColor(HP_Orb\entity,255,0,0)
		HP_Orb\x = xloop*3
		HP_Orb\y = yloop*3
		HP_Orb\dx=0
		HP_Orb\dy=0
		HP_Orb\radius = 1
		HP_Orb\mass = 50
	Next
Next


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

Global camera = CreateCamera()
PositionEntity(camera,15,15,-45)
light=CreateLight()
RotateEntity(light,90,0,0,0)



;------------------------------------------
;MAIN LOOP
;------------------------------------------
; This is the main While..Wend game loop
While Not KeyDown(1)

	Cls
	
	
	If KeyDown(200) TranslateEntity(camera,0,0,1);up forward
	If KeyDown(201) TranslateEntity(camera,0,-1,0);pgup up
	If KeyDown(203) TranslateEntity(camera,-1,0,0);left
	If KeyDown(208) TranslateEntity(camera,0,0,-1);down backward
	If KeyDown(209) TranslateEntity(camera,0,1,0);pgdown down
	If KeyDown(205) TranslateEntity(camera,1,0,0);right
	
	
	UpdateCirclePhysics()
	UpdateWorld()
	RenderCircles()
	RenderWorld()
	
	;------------
	; Reset button
	Text 10, 10, "Press a mouse button to reset."
	Text 10, 25, "Press Esc to exit."
	If GetMouse() Then
		ClearWorld()
		For HP_Orb.HP_Orb = Each HP_Orb
			Delete HP_Orb
		Next
		Goto setup
	End If
	;------------
	
	VWait()
	Flip
	
Wend
;------------------------------------------
;------------------------------------------
End

;------------------------------------------
Function UpdateCirclePhysics()
;------------------------------------------
; This is the main physics function for the
; circles. It contains the very basic
; movement physics as well as the collision
; response code.
;------------------------------------------

	For HP_Orb.HP_Orb = Each HP_Orb
	
		;update positions
		HP_Orb\x=HP_Orb\x+HP_Orb\dx
		HP_Orb\y=HP_Orb\y+HP_Orb\dy
		;HP_Orb\z=HP_Orb\y+HP_Orb\dz
				
		;gradually slow down
		HP_Orb\dx=HP_Orb\dx*0.99
		HP_Orb\dy=HP_Orb\dy*0.99
		;HP_Orb\dz=HP_Orb\dz*0.99		
		
		
		;------------------------------------------
		;COLLISION CHECKING
		;------------------------------------------
		; Check Each HP_Orb in the loop against
		; every other (HP_Orb against HP_Orb2)
		For HP_Orb2.HP_Orb = Each HP_Orb
		
				
			collisionDistance# = HP_Orb\radius+HP_Orb2\radius
			actualDistance# = Sqr((HP_Orb2\x-HP_Orb\x)^2 +(HP_Orb2\y-HP_Orb\y)^2 );+(HP_Orb2\z-HP_Orb\z)^2  )
			
			;Collided or not?
			If actualDistance<collisionDistance Then
				
				collNormalAngle#=ATan2(HP_Orb2\y-HP_Orb\y, HP_Orb2\x-HP_Orb\x)
				;collNormalAngleZ#=ATan2(HP_Orb2\y-HP_Orb\y, HP_Orb2\z-HP_Orb\z)

				;Position exactly touching, no intersection
				moveDist1#=(collisionDistance-actualDistance)*(HP_Orb2\mass/Float((HP_Orb\mass+HP_Orb2\mass)))
				moveDist2#=(collisionDistance-actualDistance)*(HP_Orb\mass/Float((HP_Orb\mass+HP_Orb2\mass)))
				HP_Orb\x=HP_Orb\x + moveDist1*Cos(collNormalAngle+180)
				HP_Orb\y=HP_Orb\y + moveDist1*Sin(collNormalAngle+180)
				;HP_Orb\z=HP_Orb\x + moveDist1*Cos(collNormalAngleZ+180)
				
				HP_Orb2\x=HP_Orb2\x + moveDist2*Cos(collNormalAngle)
				HP_Orb2\y=HP_Orb2\y + moveDist2*Sin(collNormalAngle)
				;HP_Orb2\z=HP_Orb2\z + moveDist2*Cos(collNormalAngleZ)
				
				;------------------------------------------
				;COLLISION RESPONSE
				;------------------------------------------
				;n = vector connecting the centers of the circles.
				;we are finding the components of the normalised vector n
				HP_OrbnX#=Cos(collNormalAngle)
				HP_OrbnY#=Sin(collNormalAngle)
				;HP_OrbnZ#=Cos(collNormalAngleZ)
				
				;now find the length of the components of each movement vectors
				;along n, by using dot product.
				HP_Orba1# = HP_Orb\dx*HP_OrbnX  +  HP_Orb\dy*HP_OrbnY ;+  HP_Orb\dz*HP_OrbnZ
				HP_Orba2# = HP_Orb2\dx*HP_OrbnX +  HP_Orb2\dy*HP_OrbnY ;+  HP_Orb\dz*HP_OrbnZ
				 
				;optimisedP = 2(a1 - a2)
				;             ----------
				;              m1 + m2
				optimisedP# = (2.0 * (HP_Orba1-HP_Orba2)) / (HP_Orb\mass + HP_Orb2\mass)
				
				;now find out the resultant vectors
				;r1 = c1\v - optimisedP * mass2 * n
				HP_Orb\dx = HP_Orb\dx - (optimisedP*HP_Orb2\mass*HP_OrbnX)
				HP_Orb\dy = HP_Orb\dy - (optimisedP*HP_Orb2\mass*HP_OrbnY)
				;HP_Orb\dz = HP_Orb\dz - (optimisedP*HP_Orb2\mass*HP_OrbnZ)
				
				;r2 = HP_Orb2\v - optimisedP * mass1 * n
				HP_Orb2\dx = HP_Orb2\dx + (optimisedP*HP_Orb\mass*HP_OrbnX)
				HP_Orb2\dy = HP_Orb2\dy + (optimisedP*HP_Orb\mass*HP_OrbnY)
				;HP_Orb2\dz = HP_Orb2\dz + (optimisedP*HP_Orb\mass*HP_OrbnZ)

			End If

		Next
		;------------------------------------------
		;------------------------------------------
		
				;Simple Bouncing off walls.
			If HP_Orb\x<HP_Orb\radius Then
				HP_Orb\x=HP_Orb\radius
				HP_Orb\dx=HP_Orb\dx*-0.9
			End If
			If HP_Orb\x>40-HP_Orb\radius Then
				HP_Orb\x=40-HP_Orb\radius
				HP_Orb\dx=HP_Orb\dx*-0.9
			End If
			If HP_Orb\y<HP_Orb\radius Then
				HP_Orb\y=HP_Orb\radius
				HP_Orb\dy=HP_Orb\dy*-0.9
			End If
			If HP_Orb\y>40-HP_Orb\radius Then
				HP_Orb\y=40-HP_Orb\radius
				HP_Orb\dy=HP_Orb\dy*-0.9
			End If
		
	Next

End Function





;------------------------------------------
Function RenderCircles()
;------------------------------------------
; Simple function draws all the circles
; on the screen.
;------------------------------------------

	For HP_Orb.HP_Orb = Each HP_Orb
		PositionEntity(HP_Orb\entity,HP_Orb\x,HP_Orb\y,HP_Orb\z)
	Next
	
End Function
;------------------------------------------
;------------------------------------------


I desire my game to play exactly like this one.

Any help from the great Blitz3D Masters will be appreciated.

This should do what you require ...

http://www.blitzbasic.com/codearcs/codearcs.php?code=670

Stevie G you are very Great!!!

Almost there!

I'm using the code provided here. The Orbs wants to continue in the same direction after collision.

; ID: 415
; Author: Phish
; Modified by F.L.Taylor
; Date: 2002-09-03 11:43:20
; Title: Billiards Style Collision Physics
; Description: 2D circle collision response which can be used for almost anything where 2 objects collide in 2 dimensions

;------------------------------------------
;2D COLLISION DEMO CODE
;------------------------------------------
; By Joseph 'Phish' Humfrey
; This type of collision response isn't
; just useful for pool and billiard style
; games, and in fact, I didn't write it for
; that reason at all. I wrote it because I
; needed to have collision for the space
; ships in my game 'Unity'. When their
; shields are up, they use this relatively
; simple method. It can be used for almost
; anything - player character bouncing off
; enemies in a platform game, to space
; ship collision, to a game which does
; actually involve balls. The basic
; algorithm which I used would work for
; both 2d and 3d, so if you would like to
; see it, email me at phish@...
;------------------------------------------
; The actual code which works out what
; happens after a collision is in the
; HP_OrbPhysicsUpdate() function.
;------------------------------------------
; Enjoy!
;------------------------------------------
;------------------------------------------

Graphics3D 800, 600, 16, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()

;Collision
Const	HP_COLLISIONTYPE_NONE	=	0
Const	HP_COLLISIONTYPE_ARENA	=	1
Const	HP_COLLISIONTYPE_PLAYER	=	2
Const	HP_COLLISIONTYPE_ORB	=	3
Const	HP_COLLISIONTYPE_POWERUP	=	4
Const	HP_COLLISIONMETHOD_ELLIPSOID	=	1
Const	HP_COLLISIONMETHOD_POLYGON	=	2
Const	HP_COLLISIONMETHOD_BOX	=	3
Const	HP_COLLISIONRESPONSE_STOP	=	1
Const	HP_COLLISIONRESPONSE_SLIDE	=	2
Const	HP_COLLISIONRESPONSE_SLIDENOSLOPE	=	3

Collisions(HP_COLLISIONTYPE_ORB,HP_COLLISIONTYPE_PLAYER,HP_COLLISIONMETHOD_BOX,HP_COLLISIONRESPONSE_SLIDE)
Collisions(HP_COLLISIONTYPE_ORB,HP_COLLISIONTYPE_POWERUP,HP_COLLISIONMETHOD_ELLIPSOID,HP_COLLISIONRESPONSE_STOP)
Collisions(HP_COLLISIONTYPE_ORB,HP_COLLISIONTYPE_ARENA,HP_COLLISIONMETHOD_POLYGON,HP_COLLISIONRESPONSE_SLIDE)
Collisions(HP_COLLISIONTYPE_PLAYER,HP_COLLISIONTYPE_ARENA,HP_COLLISIONMETHOD_POLYGON,HP_COLLISIONRESPONSE_SLIDE)

;------------------------------------------
; MAIN DATA TYPE
;------------------------------------------
; This exact type isn't supposed to be used
; Instead, you should use some of the fields
; in your own type, or just use this one
; for reference, to see what each field does


Type HP_orb
	Field netid%
	Field x#
	Field y#
	Field z#
	Field entity%
	Field velx#
	Field vely#		;x and y speeds
	Field velz#
	Field radius#	;radius of circle
	Field mass#	 ;mass of circle
	Field state%
End Type

Type HP_PlayerCamera
	Field entity%
End Type

Type HP_GameArena
	Field entity%
End Type

;------------------------------------------
; SET UP BALLS INTO A POOL STYLE ARRANGEMENT
; FOR DEMO
;------------------------------------------
.Setup


;HP_OrbQ
HP_OrbQ.HP_Orb = New HP_Orb
HP_OrbQ\entity = CreateSphere(64)
EntityShininess(HP_OrbQ\entity,.8)
;HP_OrbQ\x = -20
;HP_OrbQ\y = -100
;HP_OrbQ\velx = -Rnd(4)*.1
;HP_OrbQ\vely = Rnd(4)-2*.1
HP_OrbQ\radius = 1
HP_OrbQ\mass = 50
EntityType(HP_OrbQ\entity%,HP_COLLISIONTYPE_ORB)
EntityRadius(HP_OrbQ\entity%,HP_OrbQ\radius)

;HP_Orbs
For xloop = 1 To 3
	For yloop = 1 To 3
		HP_Orb.HP_Orb = New HP_Orb
		HP_Orb\entity = CopyEntity(HP_OrbQ\entity)		
		EntityShininess(HP_Orb\entity,.8)
		EntityColor(HP_Orb\entity,255,0,0)
		HP_Orb\x = xloop*3
		HP_Orb\y = yloop*3
		HP_Orb\velx=0
		HP_Orb\vely=0
		HP_Orb\radius = 1
		HP_Orb\mass = 50
		EntityType(HP_Orb\entity%,HP_COLLISIONTYPE_ORB)
		EntityRadius(HP_Orb\entity%,HP_Orb\radius)
	Next
Next

;Arena
HP_GameArena.HP_GameArena = New HP_GameArena
HP_GameArena\entity=CreateCube()
FlipMesh(HP_GameArena\entity)
PositionEntity(HP_GameArena\entity,15,15,0)
EntityAlpha(HP_GameArena\entity,.5)
ScaleEntity(HP_GameArena\entity,20,20,20)
EntityType(HP_GameArena\entity,HP_COLLISIONTYPE_ARENA)

;Camera
Global HP_PlayerCamera.HP_PlayerCamera = New HP_PlayerCamera
HP_PlayerCamera\entity=CreateCamera()
PositionEntity(HP_PlayerCamera\entity,15,15,-45)
HP_PlayerCameraLight=CreateLight()
RotateEntity(HP_PlayerCameraLight,90,0,0,0)
EntityParent(HP_PlayerCameraLight,HP_PlayerCamera\entity) 

;------------------------------------------
;MAIN LOOP
;------------------------------------------
; This is the main While..Wend game loop
While Not KeyDown(1)

	If KeyDown(200) TranslateEntity(HP_PlayerCamera\entity,0,0,1);up forward
	If KeyDown(201) TranslateEntity(HP_PlayerCamera\entity,0,-1,0);pgup up
	If KeyDown(203) TranslateEntity(HP_PlayerCamera\entity,-1,0,0);left
	If KeyDown(208) TranslateEntity(HP_PlayerCamera\entity,0,0,-1);down backward
	If KeyDown(209) TranslateEntity(HP_PlayerCamera\entity,0,1,0);pgdown down
	If KeyDown(205) TranslateEntity(HP_PlayerCamera\entity,1,0,0);right
	
	HP_OrbPhysicsUpdate2()
	UpdateWorld()
	
	HP_OrbRender()
	RenderWorld()
	
	;------------
	; Reset button
	Text 10, 10, "Press a LMB Launch Orb, RMB reset."
	Text 10, 25, "Press Esc to exit."
	
	If MouseHit(2) Then
		ClearWorld()
		For HP_Orb.HP_Orb = Each HP_Orb
			Delete HP_Orb
		Next
		Goto setup
	End If

	If MouseHit(1) Then
		HP_OrbQ.HP_Orb = First HP_Orb
		HP_OrbQ\velx = -Rnd(4)*.1
		HP_OrbQ\vely = Rnd(4)-2*.1
	End If	
	
	
	;------------
	
	VWait()
	Flip
	
Wend
;------------------------------------------
;------------------------------------------
End

Function HP_OrbPhysicsUpdate2()
	For HP_Orb.HP_Orb = Each HP_Orb
	
		If HP_Orb = First HP_Orb DebugLog(EntityX(HP_Orb\entity)+""+EntityY(HP_Orb\entity)+""+EntityZ(HP_Orb\entity))
		
		
		;update positions
		HP_Orb\x=HP_Orb\x+HP_Orb\velx
		HP_Orb\y=HP_Orb\y+HP_Orb\vely
		;HP_Orb\z=HP_Orb\y+HP_Orb\velz
				
		;gradually slow down
		HP_Orb\velx=HP_Orb\velx*0.99
		HP_Orb\vely=HP_Orb\vely*0.99
		;HP_Orb\velz=HP_Orb\velz*0.99		
		
		HP_OrbPhysicsOn=True
		If HP_OrbPhysicsOn	
	
		For HP_OrbCountCollisions = 1 To CountCollisions(HP_Orb\entity)
			; Calculate bounce: 
			
			DebugLog("HIT") 
		
			; Get the normal of the surface collided with. 
			HP_OrbPhysicsNx# = CollisionNX#(HP_Orb\entity, HP_OrbCountCollisions) 
			HP_OrbPhysicsNy# = CollisionNY#(HP_Orb\entity, HP_OrbCountCollisions) 
			HP_OrbPhysicsNz# = CollisionNZ#(HP_Orb\entity, HP_OrbCountCollisions) 
			
			; Compute the dot product of the ball's motion vector and the normal of the surface collided with. 
			HP_OrbPhysicsVdotN# = HP_Orb\velx#*HP_OrbPhysicsNx# + HP_Orb\vely#*HP_OrbPhysicsNy# + HP_Orb\velz#*HP_OrbPhysicsNz# 
	
			; Calculate the normal force. 
			HP_OrbPhysicsNFx# = -2.0 * HP_OrbPhysicsNx# * HP_OrbPhysicsVdotN# 
			HP_OrbPhysicsNFy# = -2.0 * HP_OrbPhysicsNy# * HP_OrbPhysicsVdotN# 
			HP_OrbPhysicsNFz# = -2.0 * HP_OrbPhysicsNz# * HP_OrbPhysicsVdotN# 
			
			; Add the normal force to the motion vector. 
			HP_OrbPhysicsBounce# = .987654321
			
			HP_Orb\velx#=(HP_Orb\velx# + HP_OrbPhysicsNFx#)*HP_OrbPhysicsBounce#
			HP_Orb\vely#=(HP_Orb\vely# + HP_OrbPhysicsNFy#)*HP_OrbPhysicsBounce#
			HP_Orb\velz#=(HP_Orb\velz# + HP_OrbPhysicsNFz#)*HP_OrbPhysicsBounce#

		Next
		
		EndIf
		
	Next
End Function


;------------------------------------------
Function HP_OrbRender()
;------------------------------------------
; Simple function draws all the circles
; on the screen.
;------------------------------------------

	For HP_Orb.HP_Orb = Each HP_Orb
		PositionEntity(HP_Orb\entity,HP_Orb\x,HP_Orb\y,HP_Orb\z)
		;ResetEntity(HP_Orb\entity)
	Next
	
End Function


Not quite sure on whats needed to adjust the motion vector for proper deflection.

Hmm i used something a while back for a breakout game, you subtract the ball z/x location(however your game is setup) by the paddles z/x position, then you devide it untill its a working math, then you use this to get the balls z/x volocity...

dif# = entityx(ball) - entityx(paddle) / 8

If entityscollide(ball,type_padle)
ballx_dir = dif
ballz_dir = 0.5
End if

Moveentity ball,ballx_dir,0,ballz_dir


@Yahfree: Thanks. I'll give it a shot and see what it does.

The above code from Yahfree is nonsense, at least to me ;) ... use a coefficient of restitution like so ...

Function HP_OrbPhysicsUpdate2()
	For HP_Orb.HP_Orb = Each HP_Orb
	
		If HP_Orb = First HP_Orb DebugLog(EntityX(HP_Orb\entity)+""+EntityY(HP_Orb\entity)+""+EntityZ(HP_Orb\entity))
		
		
		;update positions
		HP_Orb\x=HP_Orb\x+HP_Orb\velx
		HP_Orb\y=HP_Orb\y+HP_Orb\vely
		;HP_Orb\z=HP_Orb\y+HP_Orb\velz
				
		;gradually slow down
		HP_Orb\velx=HP_Orb\velx*0.99
		HP_Orb\vely=HP_Orb\vely*0.99
		;HP_Orb\velz=HP_Orb\velz*0.99		
		
		HP_OrbPhysicsOn=True
		If HP_OrbPhysicsOn	
	
		For HP_OrbCountCollisions = 1 To CountCollisions(HP_Orb\entity)
			; Calculate bounce: 
			
			DebugLog("HIT") 
		
			; Get the normal of the surface collided with. 
			HP_OrbPhysicsNx# = CollisionNX#(HP_Orb\entity, HP_OrbCountCollisions) 
			HP_OrbPhysicsNy# = CollisionNY#(HP_Orb\entity, HP_OrbCountCollisions) 
			HP_OrbPhysicsNz# = CollisionNZ#(HP_Orb\entity, HP_OrbCountCollisions) 
			
			; Compute the dot product of the ball's motion vector and the normal of the surface collided with. 
			HP_OrbPhysicsVdotN# = HP_Orb\velx#*HP_OrbPhysicsNx# + HP_Orb\vely#*HP_OrbPhysicsNy# + HP_Orb\velz#*HP_OrbPhysicsNz# 
	
			;set coeficient of restitution
			COR# = .987654321 	
			;COR# = 0.0	;inelastic collision
			;COR# = 1.0 ;elastic collision
			
			; Calculate the normal force. 
			HP_OrbPhysicsNFx# = -( 1.0 + COR ) * HP_OrbPhysicsNx# * HP_OrbPhysicsVdotN# 
			HP_OrbPhysicsNFy# = -( 1.0 + COR ) * HP_OrbPhysicsNy# * HP_OrbPhysicsVdotN# 
			HP_OrbPhysicsNFz# = -( 1.0 + COR ) * HP_OrbPhysicsNz# * HP_OrbPhysicsVdotN# 
			
			HP_Orb\velx# = HP_Orb\velx# + HP_OrbPhysicsNFx#
			HP_Orb\vely# = HP_Orb\vely# + HP_OrbPhysicsNFy#
			HP_Orb\velz# = HP_Orb\velz# + HP_OrbPhysicsNFz#

		Next
		
		EndIf
		
	Next
End Function


EDIT : Actually - that does the same as your code - e.g. no reflection and jittery as hell. Seems to be a collision issue which is resolved by moving the orb slightly away from contact.

I made some other changes. Note that there is no need to store the x,y,z position as this is what entityx,y,& z are for. You can then use translateentity based on your velocity vector.

; ID: 415
; Author: Phish
; Modified by F.L.Taylor
; Date: 2002-09-03 11:43:20
; Title: Billiards Style Collision Physics
; Description: 2D circle collision response which can be used for almost anything where 2 objects collide in 2 dimensions

;------------------------------------------
;2D COLLISION DEMO CODE
;------------------------------------------
; By Joseph 'Phish' Humfrey
; This type of collision response isn't
; just useful for pool and billiard style
; games, and in fact, I didn't write it for
; that reason at all. I wrote it because I
; needed to have collision for the space
; ships in my game 'Unity'. When their
; shields are up, they use this relatively
; simple method. It can be used for almost
; anything - player character bouncing off
; enemies in a platform game, to space
; ship collision, to a game which does
; actually involve balls. The basic
; algorithm which I used would work for
; both 2d and 3d, so if you would like to
; see it, email me at <a href="mailto:phish@aelius.com">phish@...;
;------------------------------------------
; The actual code which works out what
; happens after a collision is in the
; HP_OrbPhysicsUpdate() function.
;------------------------------------------
; Enjoy!
;------------------------------------------
;------------------------------------------

Graphics3D 800, 600, 16, 2
SetBuffer BackBuffer()
SeedRnd MilliSecs()

;Collision
Const	HP_COLLISIONTYPE_NONE	=	0
Const	HP_COLLISIONTYPE_ARENA	=	1
Const	HP_COLLISIONTYPE_PLAYER	=	2
Const	HP_COLLISIONTYPE_ORB	=	3
Const	HP_COLLISIONTYPE_POWERUP	=	4
Const	HP_COLLISIONMETHOD_ELLIPSOID	=	1
Const	HP_COLLISIONMETHOD_POLYGON	=	2
Const	HP_COLLISIONMETHOD_BOX	=	3
Const	HP_COLLISIONRESPONSE_STOP	=	1
Const	HP_COLLISIONRESPONSE_SLIDE	=	2
Const	HP_COLLISIONRESPONSE_SLIDENOSLOPE	=	3

Collisions(HP_COLLISIONTYPE_ORB,HP_COLLISIONTYPE_PLAYER,HP_COLLISIONMETHOD_BOX,HP_COLLISIONRESPONSE_SLIDE)
Collisions(HP_COLLISIONTYPE_ORB,HP_COLLISIONTYPE_POWERUP,HP_COLLISIONMETHOD_ELLIPSOID,HP_COLLISIONRESPONSE_STOP)
Collisions(HP_COLLISIONTYPE_ORB,HP_COLLISIONTYPE_ARENA,HP_COLLISIONMETHOD_POLYGON,HP_COLLISIONRESPONSE_SLIDE)
Collisions(HP_COLLISIONTYPE_PLAYER,HP_COLLISIONTYPE_ARENA,HP_COLLISIONMETHOD_POLYGON,HP_COLLISIONRESPONSE_SLIDE)

;------------------------------------------
; MAIN DATA TYPE
;------------------------------------------
; This exact type isn't supposed to be used
; Instead, you should use some of the fields
; in your own type, or just use this one
; for reference, to see what each field does


Type HP_orb
	Field netid%
;	Field x#
;	Field y#
;	Field z#
	Field entity%
	Field velx#
	Field vely#		;x and y speeds
	Field velz#
	Field radius#	;radius of circle
	Field mass#	 ;mass of circle
	Field state%
End Type

Type HP_PlayerCamera
	Field entity%
End Type

Type HP_GameArena
	Field entity%
End Type

;------------------------------------------
; SET UP BALLS INTO A POOL STYLE ARRANGEMENT
; FOR DEMO
;------------------------------------------
.Setup


;HP_OrbQ
HP_OrbQ.HP_Orb = New HP_Orb
HP_OrbQ\entity = CreateSphere(64)
EntityShininess(HP_OrbQ\entity,.8)
;HP_OrbQ\x = 20
;HP_OrbQ\y = 20
;HP_OrbQ\velx = -Rnd(4)*.1
;HP_OrbQ\vely = Rnd(4)-2*.1
HP_OrbQ\radius = 1
HP_OrbQ\mass = 50
EntityType(HP_OrbQ\entity%,HP_COLLISIONTYPE_ORB)
EntityRadius(HP_OrbQ\entity%,HP_OrbQ\radius)

;HP_Orbs
For xloop = 1 To 3
	For yloop = 1 To 3
		HP_Orb.HP_Orb = New HP_Orb
		HP_Orb\entity = CopyEntity(HP_OrbQ\entity)		
		EntityShininess(HP_Orb\entity,.8)
		EntityColor(HP_Orb\entity,255,0,0)
		PositionEntity HP_Orb\entity, xloop*3, yloop*3, 0
		HP_Orb\velx=0
		HP_Orb\vely=0
		HP_Orb\radius = 1
		HP_Orb\mass = 50
	;	EntityType(HP_Orb\entity%,HP_COLLISIONTYPE_ORB)
		EntityRadius(HP_Orb\entity%,HP_Orb\radius)
	Next
Next

;Arena
HP_GameArena.HP_GameArena = New HP_GameArena
HP_GameArena\entity=CreateCube()
FlipMesh(HP_GameArena\entity)
PositionEntity(HP_GameArena\entity,15,15,0)
EntityAlpha(HP_GameArena\entity,.5)
ScaleEntity(HP_GameArena\entity,20,20,20)
EntityType(HP_GameArena\entity,HP_COLLISIONTYPE_ARENA)

;Camera
Global HP_PlayerCamera.HP_PlayerCamera = New HP_PlayerCamera
HP_PlayerCamera\entity=CreateCamera()
PositionEntity(HP_PlayerCamera\entity,15,15,-45)
HP_PlayerCameraLight=CreateLight()
RotateEntity(HP_PlayerCameraLight,90,0,0,0)
EntityParent(HP_PlayerCameraLight,HP_PlayerCamera\entity) 

;------------------------------------------
;MAIN LOOP
;------------------------------------------
; This is the main While..Wend game loop
While Not KeyDown(1)

	If KeyDown(200) TranslateEntity(HP_PlayerCamera\entity,0,0,1);up forward
	If KeyDown(201) TranslateEntity(HP_PlayerCamera\entity,0,-1,0);pgup up
	If KeyDown(203) TranslateEntity(HP_PlayerCamera\entity,-1,0,0);left
	If KeyDown(208) TranslateEntity(HP_PlayerCamera\entity,0,0,-1);down backward
	If KeyDown(209) TranslateEntity(HP_PlayerCamera\entity,0,1,0);pgdown down
	If KeyDown(205) TranslateEntity(HP_PlayerCamera\entity,1,0,0);right
	
	HP_OrbPhysicsUpdate2()
	HP_OrbRender()

	UpdateWorld()
	RenderWorld()
	
	;------------
	; Reset button
	Text 10, 10, "Press a LMB Launch Orb, RMB reset."
	Text 10, 25, "Press Esc to exit."
	
	If MouseHit(2) Then
		ClearWorld()
		For HP_Orb.HP_Orb = Each HP_Orb
			Delete HP_Orb
		Next
		Goto setup
	End If

	If MouseHit(1) Then
		HP_OrbQ.HP_Orb = First HP_Orb
		HP_OrbQ\velx = -Rnd(4)*.1
		HP_OrbQ\vely = Rnd(4)-2*.1
	End If	
	
	
	;------------
	
	VWait()
	Flip
	
Wend
;------------------------------------------
;------------------------------------------
End

Function HP_OrbPhysicsUpdate2()

	For HP_Orb.HP_Orb = Each HP_Orb
	
		If HP_Orb = First HP_Orb DebugLog(EntityX(HP_Orb\entity)+""+EntityY(HP_Orb\entity)+""+EntityZ(HP_Orb\entity))
		
			;gradually slow down
			HP_Orb\velx=HP_Orb\velx*0.99
			HP_Orb\vely=HP_Orb\vely*0.99
			HP_Orb\velz=HP_Orb\velz*0.99		
			
			HP_OrbPhysicsOn=True
			If HP_OrbPhysicsOn	
		
			For HP_OrbCountCollisions = 1 To CountCollisions(HP_Orb\entity)
				; Calculate bounce: 
				
				DebugLog("HIT") 
			
				; Get the normal of the surface collided with. 
				HP_OrbPhysicsNx# = CollisionNX#(HP_Orb\entity, HP_OrbCountCollisions) 
				HP_OrbPhysicsNy# = CollisionNY#(HP_Orb\entity, HP_OrbCountCollisions) 
				HP_OrbPhysicsNz# = CollisionNZ#(HP_Orb\entity, HP_OrbCountCollisions) 
				;move it slightly away from collision
				TranslateEntity HP_Orb\entity, .01 * HP_OrbPhysicsNx , .01 * HP_OrbPhysicsNy , .01 * HP_OrbPhysicsNz
								
				; Compute the dot product of the ball's motion vector and the normal of the surface collided with. 
				HP_OrbPhysicsVdotN# = HP_Orb\velx#*HP_OrbPhysicsNx# + HP_Orb\vely#*HP_OrbPhysicsNy# + HP_Orb\velz#*HP_OrbPhysicsNz# 
		
				;set coeficient of restitution
				COR# = .987654321 	
				;COR# = 0.0	;inelastic collision
				;COR# = 1.0 ;elastic collision
				
				; Calculate the normal force. 
				HP_OrbPhysicsNFx# = -( 1.0 + COR ) * HP_OrbPhysicsNx# * HP_OrbPhysicsVdotN# 
				HP_OrbPhysicsNFy# = -( 1.0 + COR ) * HP_OrbPhysicsNy# * HP_OrbPhysicsVdotN# 
				HP_OrbPhysicsNFz# = -( 1.0 + COR ) * HP_OrbPhysicsNz# * HP_OrbPhysicsVdotN# 
				
				HP_Orb\velx# = HP_Orb\velx# + HP_OrbPhysicsNFx#
				HP_Orb\vely# = HP_Orb\vely# + HP_OrbPhysicsNFy#
				HP_Orb\velz# = HP_Orb\velz# + HP_OrbPhysicsNFz#
	
			Next
		
		EndIf
		
	Next
End Function

;------------------------------------------
Function HP_OrbRender()
;------------------------------------------
; Simple function draws all the circles
; on the screen.
;------------------------------------------

	For HP_Orb.HP_Orb = Each HP_Orb
	
		TranslateEntity HP_Orb\entity, HP_Orb\velx, HP_Orb\vely, HP_Orb\velz
	
	Next
	
End Function


@Stevie G: Awesome! I truly appreciate your assistance. Now all I have to do is replace my directplay code.