Moving Ball to static ball dynamic collision

Monkey Forums/Monkey Code/Moving Ball to static ball dynamic collision

Jesse(Posted 2013) [#1]

Import mojo
Const INVALID_DISTANCE:Float = 10000000.0
Class Ball
	Field x:Float
	Field y:Float
	
	Field dx:Float 'direction
	Field dy:Float 'direction
	
	Field vx:Float 'velocity
	Field vy:Float 'velocity
	Field speed:Float
	Field radius

	Method New(x:Float,y:Float,radius:Float,angle:Float,speed:Float)
		Self.x = x
		Self.y = y
		
		Self.dx = Cos(angle)
		Self.dy = Sin(angle)
		
		Self.vx = Self.dx * speed
		Self.vy = Self.dy * speed
		Self.radius = radius
		Self.speed = speed
		
	End Method
	
	Method Render:Void()
		DrawCircle x,y,radius
		SetColor 0,255,0
		DrawLine x,y,x+vx,y+vy
		
	End Method
	
End Class

Class RoundWall

	Field x:Float
	Field y:Float
	
	Field radius:Float
	
	Method New(x:Float,y:Float,radius:Float)
		Self.x = x
		Self.y = y
		Self.radius = radius
	
	End Method
	
	Method Render:Void()

		DrawCircle x,y,radius
		
	End Method
	
End Class


'resolve position of ball at time of collision using pythagoreans theorem
Function Collided:Float(ball:Ball,wall:RoundWall)

	'vector from the ball center to wall center.
	Local x:Float = wall.x - ball.x
	Local y:Float = wall.y - ball.y

	'dot product: closest distance from center of wall to path of ball
	Local dotP:Float = x * ball.dx + y * ball.dy	
	If dotP < 0 Return INVALID_DISTANCE' ball is moving away from wall

	'closest distance between wall center and ball center at time of collision
	'(C = hypotenuse)
	Local C:Float = ball.radius + wall.radius
	'A = opposite side = perpendicular dot product
	Local A:Float = ball.dx * y - ball.dy * x
	If C < Abs(A) Return INVALID_DISTANCE 'ball's path is too far to either side of wall
	'B = adjacent side
	Local B:Float = Sqrt((C*C) - (A*A)) ' pithagoreans theorem
	
	'exact distance of ball to point of collision
	Local poc:Float = dotP-B
	If poc > ball.speed Return INVALID_DISTANCE 'wall is too far
	Return poc
End Function




Class Game Extends App
	Field ball:Ball
	Field wall:RoundWall

	Method OnCreate:Int()
		ball = New Ball(100,100,10,45,200)
		wall = New RoundWall(205,250,30)
	
		SetUpdateRate 30
		Return True
	End Method
	
	
	Method OnUpdate:Int()
		Return True
	End Method
	
	Method OnRender:Int()
		Cls
		ball.x = MouseX()
		ball.y = MouseY()
		SetColor 200,0,0
		wall.Render()
		ball.Render()
		SetColor 255,255,255
		Local collision:Float = Collided(ball,wall)
		If collision <> INVALID_DISTANCE
			DrawText "ball collided with wall ",100,10
			DrawCircle(ball.x+ball.dx*collision,ball.y+ball.dy*collision,ball.radius)
		Else
			DrawCircle(ball.x+ball.vx,ball.y+ball.vy,ball.radius)
		Endif
		Return True
	
	End Method
	
End Class


Function Main:Int()
	
	New Game
	Return True

End Function



Sammy(Posted 2013) [#2]
Thanks Jesse. BTW is there any specific reason why your getting your input within the OnRender () method?


Jesse(Posted 2013) [#3]
You are welcome.

I did everything on the OnRender to hopefully make it easier to understand and prevented me from having to create some redundant code.