Help with Gravity/Bounce Code...

Blitz3D Forums/Blitz3D Programming/Help with Gravity/Bounce Code...

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

This demo - not by me, BTW - may be of some use?

;
; Bouncing ball physics - by Vincent DeCampo 2/1/04
;

Const GRAVITY#=-.05
Const BALLS=1

Graphics3D 640,480

;*** Type for Ball ***
Type Ball_Object
	Field Entity
	Field Pivot
	Field x#
	Field y#
	Field z#
	Field dx#
	Field dy#
	Field dz#
	Field xMin#
	Field xMax#
	Field yMin#
	Field yMax#
	Field zMin#
	Field zMax#
	Field elasticity#
	Field friction#
End Type

;*** Lets create the floor ***
Room=CreateTerrain(64)
PositionEntity room,-32,0,-32
EntityColor Room, 0, 150, 0

;******* Create Initial Ball ******
Blitz.Ball_Object = New Ball_Object
InitBallVars(Blitz)
Collisions BALLS, BALLS, 1, 2

;***** Create Camera *****
camera=CreateCamera()
PositionEntity camera,0,5,-40
PointEntity camera, Blitz\Entity

;**********************************
;			 Main Loop
;**********************************
;
While Not KeyHit(1)

	If KeyHit(57) Then

		;***** Seed RND Generator *****
		SeedRnd (MilliSecs())
		
		;*** Create New Ball ***
		Blitz.Ball_Object = New Ball_Object	
		InitBallVars Blitz

	End If

	;**** Perform Room Physics ****
	For Ball.Ball_Object = Each Ball_Object
		BallPhysics (Ball)		
	Next

	UpdateWorld	

	;**** Perform Ball-on-Ball Physics ****
	CheckCollisions (Blitz)
		
	RenderWorld 
RenderWorld
	Text 0,5,"Press SPACE to throw another ball"
	Text 0,15,"Press ESC to Exit" + TrisRendered()

	Flip 1
Wend

End
Function Flipper() 
While ScanLine()<>0: Wend 
Flip False 
End Function 
;**********************************

Function CheckCollisions (Ball.Ball_Object)

	For C.Ball_Object = Each Ball_Object
				
		If EntityCollided(c\Entity, BALLS)
					
			For i = 1 To CountCollisions(c\Entity)

				Ent=CollisionEntity (c\Entity, i)

				;Get the normal of the surface which the entity collided with. 
				Nx# = CollisionNX(c\Entity, i) 
				Ny# = CollisionNY(c\Entity, i) 
				Nz# = CollisionNZ(c\Entity, i) 
			
				;Compute the dot product of the entity's motion vector And the normal of the surface collided with. 				
				VdotN# = (c\dx# * Nx# + c\dy# * Ny# + c\dz# * Nz#)
									
				;Calculate the normal force. 
				NFx# = -2.0 * Nx# * VdotN# 
				NFy# = -2.0 * Ny# * VdotN# 
				NFz# = -2.0 * Nz# * VdotN# 
										
				;Add the normal force to the direction vector. 
				c\dx# = c\dx# + NFx#/2
				c\dy# = c\dy# + NFy#/2	;Force /2 assumes balls equal in mass
				c\dz# = c\dz# + NFz#/2
								
				For Hit.Ball_Object = Each Ball_Object

					If Hit\Entity = Ent Then
						
						;Add negative force to collision entity vector		
						Hit\dx# = Hit\dx# - NFx#/2
						Hit\dy# = Hit\dy# - NFy#/2	;Force /2 assumes balls equal in mass
						Hit\dz# = Hit\dz# - NFz#/2		
											
					End If
																									
				Next

			Next
												
		EndIf
		
	Next
							
End Function

;**********************************

Function InitBallVars(Ball.Ball_Object)

	;Create Ball
	Ball\Entity=CreateSphere()
	ScaleEntity Ball\Entity, 1,1,1
	EntityType Ball\Entity, BALLS

	;txt=LoadTexture("blitzlogo.bmp")
	;EntityTexture Ball\Entity, txt
	
	;Create Pivot
	Ball\Pivot=CreatePivot()
	
	;*** Variables for Ball ***	
	Ball\x#=0
	Ball\y#=20	;set ball 20 units above floor
	Ball\z#=0
	Ball\dx#=Rand(5)
	Ball\dy#=0	;at rest
	Ball\dz#=Rand(5)
	Ball\yMin#=1
	Ball\yMax#=9999
	Ball\xMin#=-32
	Ball\xMax#=32
	Ball\zMin#=-32
	Ball\zMax#=32
	Ball\elasticity#=.75	;value from >0 to <1 (1=pure elastic collision)
	Ball\friction#=.01
	;**************************

End Function

;**********************************

Function BallPhysics (Ball.Ball_Object)

	If ball\y   =< Ball\yMin# Then
		Ball\y  =  Ball\yMin#
		Ball\dy = -Ball\dy
		Ball\dy =  Ball\dy * Ball\elasticity
	End If

	If Ball\x   =< Ball\xMin# Then
		Ball\x  =  Ball\xMin#
		Ball\dx = -Ball\dx
		Ball\dx =  Ball\dx * Ball\elasticity
		UpdatePivot (Ball)
	End If

	If  Ball\x >=  Ball\xMax# Then
		Ball\x  =  Ball\xMax#
		Ball\dx = -Ball\dx
		Ball\dx =  Ball\dx * Ball\elasticity
		UpdatePivot (Ball)
	End If
	
	If Ball\z   =< Ball\zMin# Then
		Ball\z  =  Ball\zMin#
		Ball\dz = -Ball\dz
		Ball\dz =  Ball\dz * Ball\elasticity
		UpdatePivot (Ball)
	End If

	If Ball\z  >=  Ball\zMax# Then
		Ball\z  =  Ball\zMax#
		Ball\dz = -Ball\dz
		Ball\dz =  Ball\dz * Ball\elasticity
		UpdatePivot (Ball)
	End If
	
	If Ball\y  >= Ball\yMin# Then
		Ball\dy = Ball\dy + GRAVITY
	End If	

	Ball\x = Ball\x + Ball\dx
	Ball\z = Ball\z + Ball\dz
	Ball\y  = Ball\y + Ball\dy

	Ball\dx = Ball\dx - (Ball\dx*Ball\friction)
	Ball\dz = Ball\dz - (Ball\dz*Ball\friction)

	;Move ball to new coords
	PositionEntity  Ball\Entity, Ball\x, Ball\y, Ball\z, 0

	;Rotate mesh to give appearance of rolling	
	TurnEntity Ball\Entity, Ball\dz*50,0,-Ball\Dx*50, 1
			
End Function

Function UpdatePivot (Ball.Ball_Object)

	;Move pivot to coords + deltas
	PositionEntity Ball\Pivot, Ball\x+Ball\dx, Ball\y+Ball\dy, Ball\z+Ball\dz
	
	PointEntity Ball\Entity, Ball\Pivot, 0		

End Function


[edit] Actually, I've just seen some 'sticky' collisions happening when 2 balls hit, so there must be a bugette somewhere. Like I said, not my code so I ain't fixing it. :)