From 76079fba9b913a620bb4fee71504d427e0f9df10 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Fri, 9 Apr 2010 23:31:16 -0700 Subject: [PATCH 1/1] Re-reverse coordinate system to match OpenGL. Add element. --- bulletml-runner | 16 ++++++++--- bulletml/impl.py | 42 ++++++++++++++++----------- bulletml/parser.py | 43 ++++++++++++++++++++++++---- examples/normal/threefire-offset.xml | 3 ++ 4 files changed, 77 insertions(+), 27 deletions(-) diff --git a/bulletml-runner b/bulletml-runner index 7c262b0..3dfdfa3 100755 --- a/bulletml-runner +++ b/bulletml-runner @@ -16,7 +16,7 @@ except ImportError: yaml = None try: - import psycox + import psyco except ImportError: pass else: @@ -28,11 +28,17 @@ def main(argv): pygame.display.init() screen = pygame.display.set_mode([600, 600], pygame.DOUBLEBUF) - bullet = pygame.Surface([3, 3]) - bullet.fill([255, 0, 0]) + red = pygame.Surface([3, 3]) + red.fill([255, 0, 0]) + green = pygame.Surface([3, 3]) + green.fill([0, 255, 0]) + blue = pygame.Surface([3, 3]) + blue.fill([0, 0, 255]) clock = pygame.time.Clock() target = bulletml.Bullet() + bullets = dict(red=red, green=green, blue=blue) + file_idx = 0 while True: @@ -81,6 +87,7 @@ def main(argv): target.x, target.y = pygame.mouse.get_pos() target.x /= 2 target.y /= 2 + target.y = 300 - target.y if not paused or go: lactive = list(active) @@ -120,7 +127,8 @@ def main(argv): y *= 2 x -= 1 y -= 1 - screen.blit(bullet, [x, y]) + bullet = bullets.get(obj.appearance, red) + screen.blit(bullet, [x, 600 - y]) clock.tick(60) pygame.display.flip() diff --git a/bulletml/impl.py b/bulletml/impl.py index 6e8138a..5d7cb54 100644 --- a/bulletml/impl.py +++ b/bulletml/impl.py @@ -2,11 +2,11 @@ from __future__ import division -import math +from math import atan2, sin, cos, pi as PI from bulletml import parser -PI_2 = math.pi * 2 +PI_2 = PI * 2 __all__ = ["Action", "Bullet"] @@ -68,7 +68,7 @@ class Action(object): self.previous_fire_direction = other.previous_fire_direction self.previous_fire_speed = other.previous_fire_speed - def step(self, owner, created, sin=math.sin, cos=math.cos): + def step(self, owner, created): """Advance by one frame.""" s_params = self.params rank = owner.rank @@ -123,18 +123,19 @@ class Action(object): child = self.__class__( owner, self, actions, params, rank, repeat) owner.replace(self, child) - child.step(owner, created, sin, cos) + child.step(owner, created) break elif isinstance(action, (parser.ActionDef, parser.ActionRef)): actions, params = action(s_params, rank) child = self.__class__(owner, self, actions, params, rank) owner.replace(self, child) - child.step(owner, created, sin, cos) + child.step(owner, created) break elif isinstance(action, (parser.FireDef, parser.FireRef)): - direction, speed, offset, tags, actions = action(s_params, rank) + direction, speed, offset, tags, appearance, actions = action( + s_params, rank) if direction: direction, type = direction if type == "aim" or type is None: @@ -174,10 +175,12 @@ class Action(object): x += off_x y += off_y + if appearance is None: + appearance = owner.appearance bullet = owner.__class__( x=x, y=y, direction=direction, speed=speed, target=owner.target, actions=actions, rank=rank, - tags=tags, Action=self.__class__) + appearance=appearance, tags=tags, Action=self.__class__) created.append(bullet) elif isinstance(action, parser.ChangeSpeed): @@ -209,7 +212,7 @@ class Action(object): direction += owner.aim - owner.direction # Normalize to [-pi, pi). - direction = (direction + math.pi) % PI_2 - math.pi + direction = (direction + PI) % PI_2 - PI if frames <= 0: owner.direction += direction else: @@ -262,10 +265,13 @@ class Action(object): owner.vanish() break + elif isinstance(action, parser.Appearance): + owner.appearance = action.appearance + else: - self.handle(action, owner, created, sin, cos) + self.handle(action, owner, created) - def handle(self, action, owner, created, sin, cos): + def handle(self, action, owner, created): """Override in subclasses for new action types.""" raise NotImplementedError(action.__class__.__name__) @@ -292,7 +298,8 @@ class Bullet(object): """ def __init__(self, x=0, y=0, direction=0, speed=0, target=None, - actions=(), rank=0.5, tags=(), Action=Action): + actions=(), rank=0.5, tags=(), appearance=None, + Action=Action): self.x = self.px = x self.y = self.py = y self.mx = 0 @@ -303,6 +310,7 @@ class Bullet(object): self.target = target self.rank = rank self.tags = set(tags) + self.appearance = appearance # New bullets reset the parent hierarchy. self._actions = [Action(self, None, action, params, rank) for action, params in actions] @@ -317,10 +325,10 @@ class Bullet(object): def __repr__(self): return ("%s(%r, %r, accel=%r, direction=%r, speed=%r, " - "actions=%r, target=%r, vanished=%r)") % ( + "actions=%r, target=%r, appearance=vanished=%r)") % ( type(self).__name__, self.x, self.y, (self.mx, self.my), self.direction, self.speed, self._actions, self.target, - self.vanished) + self.appearance, self.vanished) @property def aim(self): @@ -334,7 +342,7 @@ class Bullet(object): except AttributeError: return 0 else: - return math.atan2(target_x - self.x, self.y - target_y) + return atan2(target_x - self.x, target_y - self.y) @property def finished(self): @@ -373,7 +381,7 @@ class Bullet(object): else: self._actions[idx] = new - def step(self, sin=math.sin, cos=math.cos): + def step(self): """Advance by one frame. This updates the position and velocity, and may also set the @@ -384,11 +392,11 @@ class Bullet(object): created = [] for action in self._actions: - action.step(self, created, sin, cos) + action.step(self, created) self.px = self.x self.py = self.y self.x += self.mx + sin(self.direction) * self.speed - self.y += self.my - cos(self.direction) * self.speed + self.y += -self.my + cos(self.direction) * self.speed return created diff --git a/bulletml/parser.py b/bulletml/parser.py index 5435925..c4b3e04 100644 --- a/bulletml/parser.py +++ b/bulletml/parser.py @@ -254,6 +254,23 @@ class Untag(object): """Construct using an ElementTree-style element.""" return cls(element.text) +class Appearance(object): + """Set a bullet appearance.""" + + def __init__(self, appearance): + self.appearance = appearance + + def __getstate__(self): + return dict(appearance=self.appearance) + + def __setstate__(self, state): + self.__init__(state["appearance"]) + + @classmethod + def FromXML(cls, doc, element): + """Construct using an ElementTree-style element.""" + return cls(element.text) + class Vanish(object): """Make the owner disappear.""" @@ -361,11 +378,13 @@ class Accel(object): class BulletDef(object): """Bullet definition.""" - def __init__(self, actions=(), direction=None, speed=None, tags=()): + def __init__(self, actions=(), direction=None, speed=None, tags=(), + appearance=None): self.direction = direction self.speed = speed self.actions = list(actions) self.tags = set(tags) + self.appearance = appearance def __getstate__(self): state = [] @@ -377,6 +396,8 @@ class BulletDef(object): state.append(("actions", self.actions)) if self.tags: state.append(("tags", list(self.tags))) + if self.appearance: + state.append(("appearance", self.appearance)) return state def __setstate__(self, state): @@ -412,6 +433,7 @@ class BulletDef(object): self.direction and self.direction(params, rank), self.speed and self.speed(params, rank), self.tags, + self.appearance, actions) def __repr__(self): @@ -579,13 +601,14 @@ class Offset(object): class FireDef(object): """Fire definition (creates a bullet).""" - def __init__( - self, bullet, direction=None, speed=None, offset=None, tags=()): + def __init__(self, bullet, direction=None, speed=None, offset=None, + tags=(), appearance=None): self.bullet = bullet self.direction = direction self.speed = speed self.offset = offset self.tags = set(tags) + self.appearance = appearance def __getstate__(self): state = [] @@ -597,6 +620,8 @@ class FireDef(object): state.append(("offset", self.offset)) if self.tags: state.append(("tags", list(self.tags))) + if self.appearance: + state.append(("appearance", self.appearance)) try: params = self.bullet.params except AttributeError: @@ -620,6 +645,7 @@ class FireDef(object): speed = None offset = None tags = set() + appearance = None for subelem in element.getchildren(): tag = realtag(subelem) @@ -635,8 +661,10 @@ class FireDef(object): offset = Offset.FromXML(doc, subelem) elif tag == "tag": tags.add(subelem.text) + elif tag == "appearance": + appearance = subelem.text try: - fire = cls(bullet, direction, speed, offset, tags) + fire = cls(bullet, direction, speed, offset, tags, appearance) except UnboundLocalError as exc: raise ParseError(str(exc)) else: @@ -644,13 +672,15 @@ class FireDef(object): return fire def __call__(self, params, rank): - direction, speed, tags, actions = self.bullet(params, rank) + direction, speed, tags, appearance, actions = self.bullet(params, rank) if self.direction: direction = self.direction(params, rank) if self.speed: speed = self.speed(params, rank) tags = tags.union(self.tags) - return direction, speed, self.offset, tags, actions + if self.appearance: + appearance = self.appearance + return direction, speed, self.offset, tags, appearance, actions def __repr__(self): return "%s(direction=%r, speed=%r, bullet=%r)" % ( @@ -813,6 +843,7 @@ ActionDef.CONSTRUCTORS = dict( wait=Wait, vanish=Vanish, tag=Tag, + appearance=Appearance, untag=Untag, action=ActionDef, actionRef=ActionRef) diff --git a/examples/normal/threefire-offset.xml b/examples/normal/threefire-offset.xml index 5ecb2b1..1b6d240 100644 --- a/examples/normal/threefire-offset.xml +++ b/examples/normal/threefire-offset.xml @@ -16,18 +16,21 @@ 0 0 + red $1 5-5 + green $1 -5-5 + blue -- 2.20.1