This module gives a simple implementation of the physics behind bouncing balls.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | '''Module for physics simulation.
This module provides two classes that allow the
approximation of physics behind bouncing balls.'''
################################################################################
__version__ = '$Revision: 0 $'
__date__ = 'February 20, 2007'
__author__ = 'Stephen "Zero" Chappell <my.bios@gmail.com>'
__credits__ = '''\
S. Schaub, for introducing me to programming.
B. Brown, for teaching me some math courses.
C. Parker, for freely providing boids pseudocode.'''
################################################################################
import math as _math
import sys as _sys
################################################################################
class Vector:
'Vector(x, y) -> Vector'
def __init__(self, x, y):
'Initialize the Vector object.'
self.x = float(x)
self.y = float(y)
def __repr__(self):
'Return the vector\'s representation.'
return 'Vector(%r, %r)' % (self.x, self.y)
def __iter__(self):
'Return an iterator.'
yield self.x
yield self.y
def __add__(self, vector):
'Return the sum of vector addition.'
return Vector(self.x + vector.x, self.y + vector.y)
def __sub__(self, vector):
'Return the difference of vector subtraction.'
return Vector(self.x - vector.x, self.y - vector.y)
def __mul__(self, number):
'Return the product of vector multiplication.'
return Vector(self.x * number, self.y * number)
def __div__(self, number):
'Return the quotient of vector division.'
return Vector(self.x / number, self.y / number)
def __iadd__(self, vector):
'Execute addition in-place.'
self.x += vector.x
self.y += vector.y
return self
def __isub__(self, vector):
'Execute subtraction in-place.'
self.x -= vector.x
self.y -= vector.y
return self
def __imul__(self, number):
'Execute multiplication in-place.'
self.x *= number
self.y *= number
return self
def __idiv__(self, number):
'Execute division in-place.'
self.x /= number
self.y /= number
return self
def __abs__(self):
'Return the vector\'s magnitude.'
return _math.hypot(self.x, self.y)
def unit(self):
'Return the unit vector.'
return self / abs(self)
################################################################################
class Ball:
'Ball(x, y, radius) -> Ball'
def __init__(self, x, y, radius):
'Initialize the Ball object.'
self.pos = Vector(x, y)
self.vel = Vector(0, 0)
self.err = Vector(0, 0)
self.rad = radius
def crash(self, ball):
'Try to crash two balls together.'
p = ball.pos - self.pos
a = abs(p)
if a <= self.rad + ball.rad:
v = self.vel - ball.vel
s = _sub(_ang(p), _ang(v))
if s < _PI_D_2:
e = p * (_math.cos(s) * abs(v) / a)
ball.err += e
self.err -= e
def correct(self):
'Update the ball\'s velocity.'
self.vel += self.err
self.err = Vector(0, 0)
def move(self, frames_per_second):
'Update the ball\'s position.'
self.pos += self.vel / frames_per_second
################################################################################
_PI_M_2 = _math.pi * 2
_PI_D_2 = _math.pi / 2
################################################################################
def _ang(vector):
'Private module function.'
return _math.atan2(vector.x, vector.y) % _PI_M_2
def _sub(angle_a, angle_b):
'Private module function.'
diff = abs(angle_a - angle_b)
return _PI_M_2 - diff if diff > _math.pi else diff
################################################################################
if __name__ == '__main__':
_sys.stdout.write('Content-Type: text/plain\n\n')
_sys.stdout.write(file(_sys.argv[0]).read())
|
Please see Kaos Rain (MKv3) for sample usage.
Tags: algorithms