changeset 619:4ffa9d159588

Some coordinate operators, to reduce foo_x, foo_y everywhere.
author Jeremy Thurgood <firxen@gmail.com>
date Fri, 06 May 2011 16:37:43 +0200
parents 72865593bdc7
children 6cc0d54df531
files skaapsteker/physics.py skaapsteker/utils.py
diffstat 2 files changed, 61 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/skaapsteker/physics.py	Fri May 06 15:20:25 2011 +0200
+++ b/skaapsteker/physics.py	Fri May 06 16:37:43 2011 +0200
@@ -12,6 +12,7 @@
 
 from . import options
 from .constants import EPSILON
+from .utils import cadd, csub, cmul, cdiv, cclamp, cint, cneg, cabs
 
 class Sprite(pygame.sprite.Sprite):
 
@@ -59,29 +60,17 @@
     def draw_debug(self, surface):
         pygame.draw.rect(surface, self.get_debug_color(), self.collide_rect, 1)
 
-    def deltaf(self, df):
-        dv = df[0] / self.mass, df[1] / self.mass
-        self.deltav(dv)
 
     def deltav(self, dv):
-        v_x, v_y = self.velocity
-        v_x, v_y = v_x + dv[0], v_y + dv[1]
+        velocity = cadd(self.velocity, dv)
+        self.velocity = cclamp(velocity, self.terminal_velocity)
 
-        t_v = self.terminal_velocity
-        v_x = max(min(v_x, t_v[0]), -t_v[0])
-        v_y = max(min(v_y, t_v[1]), -t_v[1])
-
-        self.velocity = (v_x, v_y)
 
     def deltap(self, dt):
         old_pos = self.rect.topleft
-        v_x, v_y = self.velocity
-        f_x, f_y = self._float_pos
-        d_x, d_y = v_x * dt, v_y * dt
-        f_x, f_y = f_x + d_x, f_y + d_y
-        self._float_pos = f_x, f_y
-        self.rect.topleft = int(f_x), int(f_y)
-        delta_pos = self.rect.left - old_pos[0], self.rect.top - old_pos[1]
+        self._float_pos = cadd(self._float_pos, cmul(self.velocity, dt))
+        self.rect.topleft = cint(self._float_pos)
+        delta_pos = csub(self.rect.topleft, old_pos)
         self.collide_rect.move_ip(delta_pos)
         self.floor_rect.move_ip(delta_pos)
 
@@ -105,8 +94,7 @@
         pass
 
     def apply_friction(self):
-        v_x, v_y = self.velocity
-        self.velocity = self.friction_coeff[0] * v_x, self.friction_coeff[1] * v_y
+        self.velocity = cmul(self.velocity, self.friction_coeff)
 
     def bounce(self, other, normal):
         """Alter velocity after a collision.
@@ -115,26 +103,23 @@
            normal: unit vector (tuple) normal to the collision
                    surface.
            """
-        v_x, v_y = self.velocity
-        b_x = 1.0 + self.bounce_factor[0] * other.bounce_factor[0]
-        b_y = 1.0 + self.bounce_factor[1] * other.bounce_factor[1]
-        dv_x = - normal[0] * b_x * v_x
-        dv_y = - normal[1] * b_y * v_y
+        bounce_factor = cadd(cmul(self.bounce_factor, other.bounce_factor), 1)
+        deltav = cmul(cneg(normal), cmul(self.velocity, bounce_factor))
 
-        if normal == (0, 1) and (other.floor or other.block) and v_y > 0 and self.collide_rect.top < other.collide_rect.top:
+        if normal == (0, 1) and (other.floor or other.block) and self.velocity[1] > 0 and self.collide_rect.top < other.collide_rect.top:
             # Colliding with the ground from above is special
             self.on_solid = True
-            dv_y = -v_y
+            deltav = (deltav[0], -self.velocity[1])
 
         if other.mobile:
             total_mass = self.mass + other.mass
             f_self = self.mass / total_mass
             f_other = other.mass / total_mass
 
-            self.deltav((dv_x * f_self, dv_y * f_self))
-            other.deltav((- dv_x * f_other, - dv_y * f_other))
+            self.deltav(cmul(deltav, f_self))
+            self.deltav(cmul(cneg(deltav), f_other))
         else:
-            self.deltav((dv_x, dv_y)) # oof
+            self.deltav(deltav) # oof
 
     def update(self):
         pass # only called in wants_update = True
@@ -174,7 +159,7 @@
 
 class World(object):
 
-    GRAVITY = 0.0, 9.8 * 80.0 # pixels / s^2
+    GRAVITY = cmul((0.0, 9.8), 80.0) # pixels / s^2
 
     def __init__(self, bounds):
         self._all = pygame.sprite.LayeredUpdates()
@@ -221,8 +206,7 @@
 
     def _backout_collisions(self, sprite, others, dt):
         frac, normal, idx = 0.0, None, None
-        v_x, v_y = sprite.velocity
-        abs_v_x, abs_v_y = abs(v_x), abs(v_y)
+        abs_v_x, abs_v_y = cabs(sprite.velocity)
 
         # We only backout of "solide" collisions
         if sprite.block:
@@ -247,6 +231,16 @@
         for other in others:
             sprite.collided(other)
 
+
+    def do_gravity(self, dt):
+        dv = cmul(self.GRAVITY, dt)
+        for sprite in self._gravitators:
+            if sprite.on_solid:
+                sprite.deltav((dv[0], 0.0))
+            else:
+                sprite.deltav(dv)
+
+
     def update(self):
         if self._last_time is None:
             self._last_time = time.time()
@@ -256,13 +250,7 @@
         now = time.time()
         self._last_time, dt = now, now - self._last_time
 
-        # gravity
-        dv = self.GRAVITY[0] * dt, self.GRAVITY[1] * dt
-        for sprite in self._gravitators:
-            if sprite.on_solid:
-                sprite.deltav((dv[0], 0.0))
-            else:
-                sprite.deltav(dv)
+        self.do_gravity(dt)
 
         # friction
         for sprite in self._mobiles:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skaapsteker/utils.py	Fri May 06 16:37:43 2011 +0200
@@ -0,0 +1,34 @@
+import operator
+import functools
+
+
+def mktuple(thing):
+    if isinstance(thing, (list, tuple)):
+        return tuple(thing)
+    return (thing, thing)
+
+
+def coord_op(fun, coord, operand):
+    operand = mktuple(operand)
+    return (fun(coord[0], operand[0]),
+            fun(coord[1], operand[1]))
+
+
+def mk_cop(op):
+    return functools.partial(coord_op, op)
+
+
+def mk_cuop(op):
+    return lambda coord: (op(coord[0]), op(coord[1]))
+
+
+cadd = mk_cop(operator.add)
+csub = mk_cop(operator.sub)
+cmul = mk_cop(operator.mul)
+cdiv = mk_cop(operator.div)
+cclamp = mk_cop(lambda a, b: max(min(a, b), -b))
+
+cint = mk_cuop(int)
+cneg = mk_cuop(lambda a: -a)
+cabs = mk_cuop(abs)
+