Source code for pi3d.sprite.Ball
from pi3d.Display import Display
from numpy import dot
from pi3d.shape.Sprite import ImageSprite
[docs]class Ball(ImageSprite):
""" This class is used to take some of the functionality of the CollisionBalls
demo out of the main file. It inherits from the ImageSprite class that is
passed (in addition to standard Shape constructor arguments) the Shader and
the [Texture] to use.
In order to fit the Display dimensions the z value has to be set to 1000
This allows the Ball dimensions to be set in approximately pixel sizes
"""
def __init__(self, camera=None, light=None, shader=None, texture=None,
radius=0.0, x=0.0, y=0.0, z=1000, vx=0.0, vy=0.0, decay=0.001):
super(Ball, self).__init__(texture=texture, shader=shader,
camera=camera, light=light, w=2.0*radius,
h=2.0*radius, name="",x=x, y=y, z=z)
self.radius = radius
#self.unif[0] = x
#self.unif[1] = y
#self.unif[2] = z
self.vx = vx
self.vy = vy
self.mass = radius * radius
self.decay = decay
[docs] def move(self):
self.translateX(self.vx)
self.translateY(self.vy)
[docs] def hit(self, otherball):
"""Used for pre-checking ball positions."""
dx = (self.unif[0] + self.vx) - (otherball.unif[0] + otherball.vx)
dy = (self.unif[1] + self.vy) - (otherball.unif[1] + otherball.vy)
rd = self.radius + otherball.radius
return dot(dx, dy) < (rd * rd)
[docs] def bounce_collision(self, otherball):
"""work out resultant velocities using 17th.C phsyics"""
# relative positions
rd = self.radius + otherball.radius
dx = self.unif[0] - otherball.unif[0]
if abs(dx) > rd:
return
dy = self.unif[1] - otherball.unif[1]
if dx * dx + dy * dy > rd * rd:
return
# check sign of a.b to see if converging
dotP = dx * (self.vx - otherball.vx) + dy * (self.vy - otherball.vy)
if dotP >= 0:
return
R = otherball.mass / self.mass #ratio of masses
"""Glancing angle for equating angular momentum before and after collision.
Three more simultaneous equations for x and y components of momentum and
kinetic energy give:
"""
if dy:
D = dx / dy
delta2y = 2 * (D * self.vx + self.vy -
D * otherball.vx - otherball.vy) / (
(1 + D * D) * (R + 1))
delta2x = D * delta2y
delta1y = -1 * R * delta2y
delta1x = -1 * R * D * delta2y
elif dx:
# Same code as above with x and y reversed.
D = dy / dx
delta2x = 2 * (D * self.vy + self.vx -
D * otherball.vy - otherball.vx) / (
(1 + D * D) * (R + 1))
delta2y = D * delta2x
delta1x = -1 * R * delta2x
delta1y = -1 * R * D * delta2x
else:
delta1x = delta1y = delta2x = delta2y = 0
self.vx += delta1x
self.vy += delta1y
otherball.vx += delta2x
otherball.vy += delta2y
[docs] def bounce_wall(self, width, height):
left, right, top, bottom = -width/2.0, width/2.0, height/2.0, -height/2.0
if self.unif[0] > (right - self.radius):
self.vx = -abs(self.vx)
elif self.unif[0] < (left + self.radius):
self.vx = abs(self.vx)
if self.unif[1] > (top - self.radius):
self.vy = -abs(self.vy)
elif self.unif[1] < (bottom + self.radius):
self.vy = abs(self.vy)
[docs] def repaint(self, t):
self.move()
self.bounce_wall(Display.INSTANCE.width, Display.INSTANCE.height)
self.draw()