News
Forums
Code
Logs
Gallery
Specs
Search
Ball Collisions
Monkey Forums
/
Monkey Code
/
Ball Collisions
impixi
(Posted 2011)
[#1]
Some simple but effective ball collision demo code.
List-based version:
#rem Ball Collisions - List version Port And modification of this BlitzMax code:
http://www.blitzbasic.com/codearcs/codearcs.php?code=2383
#end Strict Import mojo Import monkey.math Import monkey.random Const GRAVITY:Float = 0.098 Global DW:Int, DH:Int Global NumBalls:Int = 5 Function Main:Int() New MyApp Return 0 End Class MyApp Extends App Field ballList:List<Ball> Method OnCreate:Int() DW = DeviceWidth() DH = DeviceHeight() ballList = New List<Ball> Seed = Millisecs() For Local n:Int = 1 To NumBalls ballList.AddLast New Ball(0, Floor(Rnd(0.0, DW)), Floor(Rnd(0.0, DH)), Rnd(-5.0, 5.0), Rnd(-5.0, 5.0), 1.0, 0.001, 10.0) Next SetUpdateRate 60 Return 0 End Method OnUpdate:Int() If TouchHit(0) NumBalls = NumBalls + 1 ballList.AddLast New Ball(0, TouchX(0), TouchY(0), Rnd(-5.0, 5.0), Rnd(-5.0, 5.0), 1.0, 0.001, 10.0) End For Local b:Ball = Eachin ballList b.Update For Local b2:Ball = Eachin ballList BallVsBall(b, b2) End End Return 0 End Method OnRender:Int() Cls 0, 0, 0 DrawText "L-Click/Touch = Additional Ball", 5, 5 For Local b:Ball = Eachin ballList b.Render() End Return 0 End End Class Ball Field kind:Int Field x:Float Field y:Float Field vx:Float Field vy:Float Field friction:Float Field mass:Float Field radius:Float Method New(k:Int, sx:Float, sy:Float, svx:Float, svy:Float, fric:Float, m:Float, r:Float) kind = k x = sx y = sy vx = svx vy = svy friction = fric mass = m radius = r End Method Update:Void() vx = (vx * friction) vy = ((vy + GRAVITY) * friction) If kind <> 0 vx = 0 vy = 0 Endif x = (x + vx) y = (y + vy) If ((x + radius) < 0.0) Then vx = -(vx) If (x > (DW - radius)) vx = -(vx) x = DW - radius Endif If ((y + radius) < 0) Then vy = -(vy) If (y > (DH - radius)) vy = -(vy) y = DH - radius Endif End Method Render:Void() DrawOval(x - (radius / 2.0), y - (radius / 2.0), radius * 2.0, radius * 2.0) End End Function BallVsBall:Void(b:Ball, b2:Ball) Local collisiondistance:Float = (b.radius + b2.radius) Local actualdistance:Float = GetDistance(b.x, b.y, b2.x, b2.y) If (actualdistance < collisiondistance) Local normal:Float = ATan2((b2.y - b.y), (b2.x - b.x)) Local movedist1:Float = ((collisiondistance - actualdistance) * (b2.mass / Float((b.mass + b2.mass)))) Local movedist2:Float = ((collisiondistance - actualdistance) * (b.mass / Float((b.mass + b2.mass)))) b.x = (b.x + (movedist1 * Cos(normal + 180.0))) b.y = (b.y + (movedist1 * Sin(normal + 180.0))) b2.x = (b2.x + (movedist2 * Cos(normal))) b2.y = (b2.y + (movedist2 * Sin(normal))) Local nx:Float = Cos(normal) Local ny:Float = Sin(normal) Local a1:Float = ((b.vx * nx) + (b.vy * ny)) Local a2:Float = ((b2.vx * nx) + (b2.vy * ny)) Local opt:Float = ((2.0 * (a1 - a2)) / (b.mass + b2.mass)) b.vx = (b.vx - (opt * b2.mass * nx)) b.vy = (b.vy - (opt * b2.mass * ny)) b2.vx = (b2.vx + (opt * b.mass * nx)) b2.vy = (b2.vy + (opt * b.mass * ny)) Endif End Function GetDistance:Float(x1:Float, y1:Float, x2:Float, y2:Float) Return Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) End
Array-based version:
#rem Ball Collisions - Array version Port And modification of this BlitzMax code:
http://www.blitzbasic.com/codearcs/codearcs.php?code=2383
#end Strict Import mojo Import monkey.math Import monkey.random Const GRAVITY:Float = 0.098 Global DW:Int, DH:Int Global NumBalls:Int = 5 Function Main:Int() New MyApp Return 0 End Class MyApp Extends App Field ballArray:Ball[] Method OnCreate:Int() DW = DeviceWidth() DH = DeviceHeight() ballArray = New Ball[NumBalls] Seed = Millisecs() For Local i:Int = 0 Until ballArray.Length ballArray[i] = New Ball(0, Floor(Rnd(0.0, DW)), Floor(Rnd(0.0, DH)), Rnd(-5.0, 5.0), Rnd(-5.0, 5.0), 1.0, 0.001, 10.0) Next SetUpdateRate 60 Return 0 End Method OnUpdate:Int() If TouchHit(0) NumBalls += 1 ballArray = ballArray.Resize(NumBalls) ballArray[ballArray.Length - 1] = New Ball(0, TouchX(0), TouchY(0), Rnd(-5.0, 5.0), Rnd(-5.0, 5.0), 1.0, 0.001, 10.0) End For Local i:Int = 0 Until ballArray.Length ballArray[i].Update For Local j:Int = 0 Until ballArray.Length If (i <> j) Then BallVsBall(ballArray[i], ballArray[j]) End End Return 0 End Method OnRender:Int() Cls 0, 0, 0 DrawText "L-Click/Touch = Additional Ball", 5, 5 For Local i:Int = 0 Until ballArray.Length ballArray[i].Render End Return 0 End End Class Ball Field kind:Int Field x:Float Field y:Float Field vx:Float Field vy:Float Field friction:Float Field mass:Float Field radius:Float Method New(k:Int, sx:Float, sy:Float, svx:Float, svy:Float, fric:Float, m:Float, r:Float) kind = k x = sx y = sy vx = svx vy = svy friction = fric mass = m radius = r End Method Update:Void() vx = (vx * friction) vy = ((vy + GRAVITY) * friction) If kind <> 0 vx = 0 vy = 0 Endif x = (x + vx) y = (y + vy) If ((x + radius) < 0.0) Then vx = -(vx) If (x > (DW - radius)) vx = -(vx) x = DW - radius Endif If ((y + radius) < 0) Then vy = -(vy) If (y > (DH - radius)) vy = -(vy) y = DH - radius Endif End Method Render:Void() DrawOval(x - (radius / 2.0), y - (radius / 2.0), radius * 2.0, radius * 2.0) End End Function BallVsBall:Void(b:Ball, b2:Ball) Local collisiondistance:Float = (b.radius + b2.radius) Local actualdistance:Float = GetDistance(b.x, b.y, b2.x, b2.y) If (actualdistance < collisiondistance) Local normal:Float = ATan2((b2.y - b.y), (b2.x - b.x)) Local movedist1:Float = ((collisiondistance - actualdistance) * (b2.mass / Float((b.mass + b2.mass)))) Local movedist2:Float = ((collisiondistance - actualdistance) * (b.mass / Float((b.mass + b2.mass)))) b.x = (b.x + (movedist1 * Cos(normal + 180.0))) b.y = (b.y + (movedist1 * Sin(normal + 180.0))) b2.x = (b2.x + (movedist2 * Cos(normal))) b2.y = (b2.y + (movedist2 * Sin(normal))) Local nx:Float = Cos(normal) Local ny:Float = Sin(normal) Local a1:Float = ((b.vx * nx) + (b.vy * ny)) Local a2:Float = ((b2.vx * nx) + (b2.vy * ny)) Local opt:Float = ((2.0 * (a1 - a2)) / (b.mass + b2.mass)) b.vx = (b.vx - (opt * b2.mass * nx)) b.vy = (b.vy - (opt * b2.mass * ny)) b2.vx = (b2.vx + (opt * b.mass * nx)) b2.vy = (b2.vy + (opt * b.mass * ny)) Endif End Function GetDistance:Float(x1:Float, y1:Float, x2:Float, y2:Float) Return Sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) End