Bouncing off the walls

BlitzMax Forums/MiniB3D Module/Bouncing off the walls

siread(Posted 2007) [#1]
Hi chaps. I'm trying to bounce my balls off walls. The code below (adapted from the archives) works perfectly for walls that are at right angles (0,90,180,270) but anything else and the ball just sticks to the wall. Can you see anything wrong with this code?

Local SpeedVectorLength# = Sqr(xvel*xvel + zvel*zvel)
		
		For Local i:Int = 1 To CountCollisions(mesh)
			Local myentity:TEntity = CollisionEntity(mesh, i)
				
			Select GetEntityType(myentity)
				Case CTYPE_WALL
					' Get the normal of the surface which the entity collided with. 
					Local Nx# = CollisionNX(mesh, i) 
					Local Ny# = CollisionNY(mesh, i) 
					Local Nz# = CollisionNZ(mesh, i) 
					
					' Compute the dot product of the entity's motion vector and the normal of the surface collided with. 
					Local VdotN# = xvel*Nx# + yvel*Ny# + zvel*Nz#
					
					' Calculate the normal force. 
					Local NFx# = -2.0 * Nx# * VdotN# 
					Local NFy# = -2.0 * Ny# * VdotN# 
					Local NFz# = -2.0 * Nz# * VdotN# 
					
					' Add the normal force To the direction vector. 
					xvel = (xvel + NFx#) * 0.6	' 0.6 = Bounciness
					yvel = (yvel + NFy#) * 0.6
					zvel = (zvel + NFz#) * 0.6
					
					direction = ATan2(zvel, xvel)
			End Select
		Next



simonh(Posted 2007) [#2]
Have you made direction a float?


siread(Posted 2007) [#3]
Yes.


siread(Posted 2007) [#4]
Ok, check out the following code. If you test it in Blitz3D it works perfectly. The ball bounces off the angles, no problem. In miniB3D however, the ball gets stuck to the surface of the goal mesh. If you remove the rotation of the goal then it bounces fine.

Import sidesign.miniB3D	' Comment out this line in Blitz3D

Graphics3D(800,600,16,2)

Const CTYPE_BALL = 1, CTYPE_WORLD = 2
Const gravity#=-0.04

Collisions(CTYPE_BALL, CTYPE_WORLD, 2, 2)

Global pitch = CreateCube()			;' The Ground
EntityColor(pitch, 0, 200, 0)
ScaleMesh(pitch, 2042,0,2800)
PositionEntity pitch, 0, -50, 0
EntityType(pitch, CTYPE_WORLD)

Global goal = CreateCube()			;' The goal (walls)
EntityColor(goal, 100, 100, 100)
ScaleMesh(goal, 100,50,100)
RotateEntity(goal, 0, 135, 0)		;' Comment out this line in miniB3D to see that collisions work ok when mesh isn't rotated
PositionEntity goal, 0, -50, 250
EntityType(goal, CTYPE_WORLD)

Global x#=0, y#=50, z#=0			;' The ball
Global xvel#=0, yvel#=0, zvel#=0
Global ball = CreateSphere(64)
ScaleMesh(ball, 10,10,10)
EntityRadius(ball,10)
EntityColor(ball, 255, 0, 0)
PositionEntity ball, x,y,z
EntityType(ball, CTYPE_BALL)

Global light = CreateLight()		;' Lights
RotateEntity light, 90,0,0

camera=CreateCamera()				;' Camera
CameraClsColor camera,100,100,255
CameraRange(camera, 1, 5000)
RotateEntity camera,45,0,0

;' Uncomment the following line in Blitz3D
'Const KEY_ESCAPE=1, KEY_LEFT=203, KEY_RIGHT=205, KEY_UP=200, KEY_DOWN=208, KEY_SPACE=57

While Not KeyHit(KEY_ESCAPE)		;' Action!

UpdateBall()

PositionEntity camera,x,200,z-100

UpdateWorld()
RenderWorld()
Flip

Wend

End


Function UpdateBall()
	If KeyDown(KEY_SPACE)
		x=0
		y=0
		z=0
		PositionEntity(ball,x,y,z)
		xvel#=0
		yvel#=0
		zvel#=0
	EndIf
	
	yvel = yvel +gravity#
	
	;' Ball Fwd/Back/Left/Right
	If KeyDown(KEY_UP) 		zvel = zvel + 0.25
	If KeyDown(KEY_DOWN)		zvel = zvel - 0.25
	If KeyDown(KEY_LEFT) 		xvel = xvel - 0.25
	If KeyDown(KEY_RIGHT) 	xvel = xvel + 0.25

	Local SpeedVectorLength# = Sqr(xvel*xvel + zvel*zvel)
		
	For i = 1 To CountCollisions(ball)
		Local myentity = CollisionEntity(ball, i)
				
		Select GetEntityType(myentity)
			Case CTYPE_WORLD
				;'Get the normal of the surface which the entity collided with. 
				Local Nx# = CollisionNX(ball, i) 
				Local Ny# = CollisionNY(ball, i) 
				Local Nz# = CollisionNZ(ball, i) 
				
				;'Compute the dot product of the entity's motion vector And the normal of the surface collided with. 
				Local VdotN# = xvel*Nx# + yvel*Ny# + zvel*Nz#
				
				;'Calculate the normal force. 
				Local NFx# = -2.0 * Nx# * VdotN# 
				Local NFy# = -2.0 * Ny# * VdotN# 
				Local NFz# = -2.0 * Nz# * VdotN# 
		
				;'Add the normal force To the direction vector. 
				xvel = (xvel + NFx#) * 0.8
				yvel = (yvel + NFy#) * 0.8
				zvel = (zvel + NFz#) * 0.8
		End Select
		Next
		
	TranslateEntity(ball, xvel, yvel, zvel)
	x = EntityX(ball)
	y = EntityY(ball)
	z = EntityZ(ball)
End Function




simonh(Posted 2007) [#5]
Yep, bug. With collision method 4 it works, with method 2 the normals aren't being transformed.