Simple "bouncing ball" physics?

Blitz3D Forums/Blitz3D Beginners Area/Simple "bouncing ball" physics?

Ash(Posted 2004) [#1]
I'm a bit of a physics newbie, so I'll need help with this...

What variables would need to be defined in order to allow simple "bouncing ball" physics to be obtained? Currently, I have worked out that my ball needs to have a mass, and that a value for gravity needs to be defined. I would like my ball to bounce realistically off the walls of a cuboid 3D room. However, my game is not like Pong, so I don't want the ball to have a constant velocity - rather, I'd like it to be influenced by gravity. (Basically, what I mean by this is that even if the ball hits a wall or even the ceiling, it will ultimately hit the floor again anyway due to gravity.)

If anyone could offer some more help as to how to go about implementing basic "bouncing ball" physics in 3D, then I'd love to hear it, as I currently have absolutely no idea what I'm doing when it comes to physics - but I realise that if I want to program games, then I'd need some sort of physics knowledge to be able to simulate different things.

What I'd like to eventually have with this game is a gravity value for each level (taking 10 as Earth's gravity), so that I can change the way the ball bounces (how high it bounces, or how slowly it falls) with different levels. I'd also like the ball's left/right movement controllable using the keyboard, so that you can move the bouncing ball over an obstacle course, which will be the point of my game.

Sorry for the long post, thanks for your time, and many thanks in advance for your help. I get easily confused when it comes to matters of physics, so please try and explain this to me in as newbie-friendly a way as possible.

Thanks.


Apocalypse(Posted 2004) [#2]
This is how i've done it in the past. Not with Blitz but in other languages. Hope I remembered it right...

;You need variables for speed for each vector
SpeedX=0
SpeedY=0
SpeedZ=0
;Then you need vector speeds
Dx=0
Dy=0
Dz=0
;Then you need flags for adding or subtracting vector speeds
DirX=1
DirY=1
DirZ=1
;Then you need to calculate speed for each vector
SpeedX=SpeedX+(Dx*DirX)
SpeedY=SpeedY+(Dy*DirY)
SpeedZ=SpeedZ+(Dz*DirZ)
;Then you need to take into account gravity
if Dy>0 then Dy=Dy-Gravity
;Then you need to take into account boundaries
;and perform an elastic transfer of inertia
If EntityX<min or EntityX>max then DirX=DirX * (-1)
If EntityY<min or EntityY>max then DirY=DirY * (-1)
if EntityZ<min or EntityZ>max then DirZ=DirZ * (-1)
;Then finally, if you want the ball to eventually slow
;down then subtract a resistance force from vector speeds.
if Dx>0 then Dx=Dx-.1 else Dx=0
if Dy>0 then Dy=Dy-.1 else Dy=0
if Dz>0 then Dz=Dz-.1 else Dz=0


Ash(Posted 2004) [#3]
Hmm... so how would I take into account the mass of the ball, considering I want the bouncing effect to change depending on how heavy the ball is? We have gravity, but eventually, I want to have different ball materials which will affect the ball's mass, and therefore its bounce: like rubber (normal bounce), steel (littler bounce) and glass (paperweight style - no bounce, just roll)...

I will fiddle with the example you've given though. Thanks for that. It is much appreciated, for now, at least I have something to start with. :)

However, even though I'm fiddling, nothing is yet final. I'm still open to suggestions.


RepeatUntil(Posted 2004) [#4]
Hi,

there is a code for simple ball boucing (with gravity, friction) which was used millions of times. This code appears often on this forum. But I am not sure who writes it (swift ?) and where is this code. Maybe in the code archive? Anyway, try to do a search on this forum.
The code is very simple, and yet perfect for what you want to do!


Apocalypse(Posted 2004) [#5]
All objects fall at the same rate regardless of their mass (Isaac Newton). The only thing the mass of the ball would change would be collisions with other balls of lesser or greater mass (not equal transfer of vector inertia). As for different materials, that would also only change the transfer of inertia when hitting other objects or the wall. (ie: a rubber ball may rebound with 99% of the energy it hits the wall whereas a bowling ball may only transfer 20% of its energy in a collision).


Apocalypse(Posted 2004) [#6]
Here's some code to cut-n-paste
-------------------------------

; Bouncing ball physics
;
Const GRAVITY#=-.05

Graphics3D 640,480

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

;Create Ball
RedBall=CreateSphere(8)
EntityColor RedBall,255,0,0

;Create Camera
camera=CreateCamera()
PositionEntity camera,0,5,-16

;Variables for Ball
x#=0
y#=20 ;set ball 20 units above floor
z#=0
dx#=0 ;at rest
dy#=0 ;at rest
dz#=0 ;at rest
elasticity#=.75 ;value from >0 to <1 (1=pure elastic collision)

While Not KeyHit(1)

If y=<1 Then
y=1
dy=-dy
dy=dy * elasticity
End If

If y>=1 Then
dy=dy + GRAVITY
x=x+dx
y=y+dy
z=z+dz
End If

PositionEntity RedBall, x, y, z

UpdateWorld
RenderWorld

Flip

Wend

End


joncom2000(Posted 2004) [#7]
Apocalypse (Posted 2004-01-31 11:01:46)

All objects fall at the same rate regardless of their mass (Isaac Newton).

Really, so if I throw you and a feather out of an airplane at 1000 feet you both will hit the ground at the same time? What school did you go to?
I am sure Isaac Newton is turning in his grave.

Here's some theory for you:-

The magnitude of terminal velocity depends on the weight of the falling body. For a heavy object, the terminal velocity is generally greater than a light object. This is because air resistance is proportional to the falling body's velocity squared. For an object to experience terminal velocity, air resistance must balance weight. An example that shows this phenomenon was the classic illustration of a rock and a feather being dropped simultaneously. In a vacuum with zero air resistance, these two objects will experience the same acceleration. But on the earth this is not true. Air resistance will equal weight more quickly for the feather than it would for the rock. Thus the rock would accelerate longer and experience a terminal velocity greater than the feather.

Another factor that affects terminal velocity is the orientation at which a body falls. If an object falls with a larger surface area perpendicular to the direction of motion it will experience a greater force and a smaller terminal velocity. On the other hand, if the object fell with a smaller surface area perpendicular to the direction of motion, it will experience a smaller force and a greater terminal velocity.


Apocalypse(Posted 2004) [#8]
This version bounces in all three axis and uses the Blitz logo as a texture for the ball to give the appearance of actually rolling. Simple and basic. You will need to make sure you have the image file blitzlogo.bmp to run the demo now.
-----------------------------------------------------------

; Bouncing ball physics
;
Const GRAVITY#=-.05

Graphics3D 640,480

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

;Create Ball
RedBall=CreateSphere(8)
;EntityColor RedBall,255,0,0
FlipMesh RedBall
txt=LoadTexture("blitzlogo.bmp")
EntityTexture RedBall, txt


;Create Camera
camera=CreateCamera()
PositionEntity camera,0,15,-45

SeedRnd (MilliSecs())

;Variables for Ball
x#=0
y#=20 ;set ball 20 units above floor
z#=0
dx#=Rand(5)
dy#=0;at rest
dz#=Rand(5)

elasticity#=.8 ;value from >0 to <1 (1=pure elastic collision)
friction#=.01

PointEntity camera, RedBall

While Not KeyHit(1)

If KeyHit(57) Then
;Variables for Ball
x#=0
y#=20 ;set ball 20 units above floor
z#=0
dx#=Rand(5)
dy#=0;at rest
dz#=Rand(5)
End If

If y=<1 Then
y=1
dy=-dy
dy=dy * elasticity
End If

If x=<-32 Then
x=-32
dx=-dx
dx=dx * elasticity
End If

If x>=32 Then
x=32
dx=-dx
dx=dx * elasticity
End If

If z=<-32 Then
z=-32
dz=-dz
dz=dz * elasticity
End If

If z>=32 Then
z=32
dz=-dz
dz=dz * elasticity
End If

If y>=1 Then
dy=dy + GRAVITY
y=y+dy
End If

x=x+dx
z=z+dz

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

;Move ball to new coords
PositionEntity RedBall, x, y, z

;Rotate mesh to give appearance of rolling
RotateMesh RedBall, -dz*100,0,-dx*100

UpdateWorld
RenderWorld

Text 0,5,"Press ESC to Exit"
Text 0,15,"Press SPACE to throw ball"

Flip


Wend

End


Apocalypse(Posted 2004) [#9]
[joncom2000]
>>Really, so if I throw you and a feather out of an airplane at 1000 feet you both will hit the ground at the same time? What school did you go to?
I am sure Isaac Newton is turning in his grave<<

You are speaking about a completely different set of physics when you talk about wind resistance. The original post was speaking to a general algorithm for bouncing a ball, not a feather. Your pedantic rant, while wonderfully written, is woefully out of place for this discussion.

PS: Throw your feather and a bowling ball on the moon and they both indeed fall at the same rate. Isaac Netwon rolling in his grave INDEED!


FlameDuck(Posted 2004) [#10]
The magnitude of terminal velocity depends on the weight of the falling body.
No. There is no 'weight' aspect to physics. There is mass and force.
For a heavy object, the terminal velocity is generally greater than a light object.
No. Weight has nothing to do with it.
This is because air resistance is proportional to the falling body's velocity squared.
No. The two most significant factors are speed and cross-sectional area of the object.
For an object to experience terminal velocity, air resistance must balance weight.
No. Terminal velocity is reached when air resistance becomes as great a force as the acceleration of gravity, thus preventing any further acceleration.

Here's some good info on Newtons Second Law.


joncom2000(Posted 2004) [#11]
Flameduck, this is taken from the site you point to

Terminal velocity occurs when the air resistance (sometimes called "drag") force equals the weight iof the falling object. This means that:
the object is falling with a constant velocity - its acceleration is zero.
heavy objects will have a higher terminal velocity than light objects. Therefore, heavy objects will fall faster in air than light objects.

So your saying my previous post is wrong yet the site you point to says basicly the same thing? Ok no problem.

Apocalypse, sorry, I do not imply that your coded example is incorrect, it does exactly as the original poster requested :) I just disagree with your statement on Newton's theory.

But enough of that, you have given a good example of simulating a bouncing ball, lets let Ash see how he get's on and put the topic back on track :)


Ash(Posted 2004) [#12]
Hmmmmmmm...

I've been playing around with your example, Apocalypse, and I've found that it's good if you specify the position values absolutely. However, I'm currently toying with the idea of using the Blitz collision system to handle collisions with the ground and walls - because my level is not just a box... It's a CShop level with ramps and obstacles, and I want an easy way to handle all the collisions.

The gravity works until the ball collides with the level; after that, it gets stuck on the ground and does not bounce back up.

Here's the code I have:
If Not EntityCollided(Player(i)\Model, COLTYPE_Level) Then
	Player(i)\dY = Player(i)\dY + MAP_CurrentMap\Gravity
	Player(i)\Y = Player(i)\Y + Player(i)\dY
ElseIf EntityCollided(Player(i)\Model, COLTYPE_Level) Then
	Player(i)\Y = CollisionY(Player(i)\Model, 1) + 0.1
	ResetEntity Player(i)\Model
	DebugLog Player(i)\Y
	Player(i)\dY = -Player(i)\dY
	DebugLog Player(i)\dY
	Player(i)\dY = Player(i)\dY * Player(i)\Elasticity
	Player(i)\Y = Player(i)\Y + Player(i)\dY			
EndIf
PositionEntity Player(i)\Model, Player(i)\X, Player(i)\Y, Player(i)\Z


When the ball hits the ground, the values of Player(i)\Y and Player(i)\dY get stuck in this loop:

0.1
-10.0
0.1
10.0


Why does this happen, and how can I get the ball to bounce back up, rather than stay on the ground like a vegetable? (I'm only working with the Y axis for now - once I get the Y axis working, I can just use the same principle for the X and Z axes, to enable collisions on the walls.)

Your help is much appreciated.


Apocalypse(Posted 2004) [#13]
Here is the new and improved version.

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

Const GRAVITY#=-.05
Const BALLS=1
Const GROUND=2

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

Collisions BALLS, BALLS, 1, 2
Collisions BALLS, GROUND,2, 3

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

Plane1=CreateTerrain(64)
EntityColor Plane1, 160,0,0
PositionEntity Plane1,-48,32,-32
RotateEntity  Plane1,0,0,-45
EntityType Plane1, GROUND

Plane2=CreateTerrain(64)
EntityColor Plane2, 0,0,170
PositionEntity Plane2,0,-16,-32
RotateEntity  Plane2,0,0,45

EntityType Plane2, GROUND

;******* Create Initial Ball ******
Blitz.Ball_Object = New Ball_Object
InitBallVars(Blitz)

;***** Create Camera *****
camera=CreateCamera()
PositionEntity camera,0,35,-50
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 
		
	Text 0,5,"Press SPACE to throw another ball"
	Text 0,15,"Press ESC to Exit"

	Flip

Wend

End

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

Function CheckCollisions (Ball.Ball_Object)

	For C.Ball_Object = Each Ball_Object
				
		If EntityCollided(c\Entity, BALLS) > 0 
					
			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
													
		Else
		
			If EntityCollided(c\Entity, GROUND) >0
		
				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, 1) 
					Ny# = CollisionNY(c\Entity, 1) 
					Nz# = CollisionNZ(c\Entity, 1) 
				
					;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#
					c\dy# = c\dy# + NFy#
					c\dz# = c\dz# + NFz#
	
				Next
			
			End If
		
		End If
		
	Next
							
End Function

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

Function InitBallVars(Ball.Ball_Object)

	;Create Ball
	Ball\Entity=CreateSphere(16)
	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(10-5)
	Ball\dy#=0	;at rest
	Ball\dz#=Rand(10-5)
	Ball\yMin#=1
	Ball\yMax#=9999
	Ball\xMin#=-32
	Ball\xMax#=32
	Ball\zMin#=-32
	Ball\zMax#=32
	Ball\elasticity#=.85	;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

PS: You need the file Blitzlogo.bmp as the ball texture.


Apocalypse(Posted 2004) [#14]
What you need to do is add a collision test for the floor or scenery, then during the collision check, if the collision in not with another ball, skip over the section that applies negative force back to the colliding entity (since it will be the wall), and make sure you give 100% of the positive force back to the ball instead of Force/2.

I will try to modify the code to deal with your situation.


Rob Farley(Posted 2004) [#15]
heavy objects will have a higher terminal velocity than light objects. Therefore, heavy objects will fall faster in air than light objects.

I think you're slightly misguided, it's nothing to do with the objects weight it's to do with the amount of drag it causes. If you could have a feather that is the size of a football pitch that weighed over a tonne and a bowling ball... the bowling ball would fall faster.