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
|