# HG changeset patch # User Jeremy Thurgood # Date 1304692663 -7200 # Node ID 4ffa9d15958836dfc8c79fd6a05b007f33cd0cb9 # Parent 72865593bdc7cd7523548c2883f93f82f03be6b6 Some coordinate operators, to reduce foo_x, foo_y everywhere. diff -r 72865593bdc7 -r 4ffa9d159588 skaapsteker/physics.py --- 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: diff -r 72865593bdc7 -r 4ffa9d159588 skaapsteker/utils.py --- /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) +