<offset>: Parse, evaluate, and example test case. (Fixes issue #3)
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Thu, 18 Mar 2010 06:22:48 +0000 (23:22 -0700)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Thu, 18 Mar 2010 06:22:48 +0000 (23:22 -0700)
bulletml/impl.py
bulletml/parser.py
examples/normal/threefire-offset.xml [new file with mode: 0644]
examples/template.xml

index ad39e7bd0d047abcc5917c6829e5fabd7fa26e84..26b95804230b9f76877f5d41bfdf5ed841b1443f 100644 (file)
@@ -125,7 +125,7 @@ class Action(object):
                 break
 
             elif isinstance(action, (parser.FireDef, parser.FireRef)):
-                direction, speed, actions = action(self.params, rank)
+                direction, speed, actions, offset = action(self.params, rank)
                 if direction:
                     direction, type = direction
                     if type == "aim" or type is None:
@@ -153,8 +153,20 @@ class Action(object):
                     speed = 1
                 self.previous_fire_speed = speed
 
-                bullet = Bullet(owner.x, owner.y, direction, speed,
-                                owner.target, actions, self, rank)
+                x, y = owner.x, owner.y
+                if offset:
+                    off_x, off_y = offset(self.params, rank)
+                    if offset.type == "relative":
+                        sin = math.sin(direction)
+                        cos = math.cos(direction)
+                        x += cos * off_x + sin * off_y
+                        y += sin * off_x - cos * off_y
+                    else:
+                        x += off_x
+                        y += off_y
+
+                bullet = Bullet(
+                    x, y, direction, speed, owner.target, actions, self, rank)
                 created.append(bullet)
 
             elif isinstance(action, parser.ChangeSpeed):
index 5e7306908346eb13baf8bbda267d4d9e4cfa2852..a07cc2dab61f7cb74ba3bbeec0f91d83df08f744 100644 (file)
@@ -375,19 +375,51 @@ class ActionRef(object):
         return "%s(params=%r, action=%r)" % (
             type(self).__name__, self.params, self.action)
 
+class Offset(object):
+    """Provide an offset to a bullet's initial position."""
+
+    VALID_TYPES = ["relative", "absolute"]
+
+    def __init__(self, type, x, y):
+        if type not in self.VALID_TYPES:
+            raise ValueError("invalid type %r" % type)
+        self.type = type
+        self.x = x
+        self.y = y
+
+    @classmethod
+    def FromElement(cls, doc, element):
+        """Construct using an ElementTree-style element."""
+        type = element.get("type", "relative")
+        x = None
+        y = None
+        for subelem in element:
+            tag = realtag(subelem)
+            if tag == "x":
+                x = NumberDef(subelem.text)
+            elif tag == "y":
+                y = NumberDef(subelem.text)
+        return cls(type, x, y)
+
+    def __call__(self, params, rank):
+        return (self.x(params, rank) if self.x else 0,
+                self.y(params, rank) if self.y else 0)
+
 class FireDef(object):
     """Fire definition (creates a bullet)."""
 
-    def __init__(self, bullet, direction=None, speed=None):
+    def __init__(self, bullet, direction=None, speed=None, offset=None):
         self.bullet = bullet
         self.direction = direction
         self.speed = speed
+        self.offset = offset
 
     @classmethod
     def FromElement(cls, doc, element):
         """Construct using an ElementTree-style element."""
         direction = None
         speed = None
+        offset = None
 
         for subelem in element.getchildren():
             tag = realtag(subelem)
@@ -399,9 +431,10 @@ class FireDef(object):
                 bullet = BulletDef.FromElement(doc, subelem)
             elif tag == "bulletRef":
                 bullet = BulletRef.FromElement(doc, subelem)
-
+            elif tag == "offset":
+                offset = Offset.FromElement(doc, subelem)
         try:
-            fire = cls(bullet, direction, speed)
+            fire = cls(bullet, direction, speed, offset)
         except UnboundLocalError as exc:
             raise ParseError(str(exc))
         else:
@@ -414,7 +447,7 @@ class FireDef(object):
             direction = self.direction(params, rank)
         if self.speed:
             speed = self.speed(params, rank)
-        return direction, speed, actions
+        return direction, speed, actions, self.offset
 
     def __repr__(self):
         return "%s(direction=%r, speed=%r, bullet=%r)" % (
@@ -435,7 +468,6 @@ class FireRef(object):
         return fired
 
     def __call__(self, params, rank):
-        """Generate a Bullet from the FireDef and params."""
         return self.fire(self.params(params, rank), rank)
 
     def __repr__(self):
diff --git a/examples/normal/threefire-offset.xml b/examples/normal/threefire-offset.xml
new file mode 100644 (file)
index 0000000..5ecb2b1
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" ?>\r
+<!DOCTYPE bulletml SYSTEM "http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/bulletml.dtd">\r
+\r
+<bulletml xmlns="http://www.asahi-net.or.jp/~cs8k-cyu/bulletml"\r
+         xmlns:py="http://code.google.com/p/python-bulletml/">\r
+  <action label="top">\r
+    <actionRef label="threefire">\r
+      <param>10 + 20 * $rank * $rand</param>\r
+    </actionRef>\r
+  </action>\r
+\r
+  <action label="threefire">\r
+    <fire>\r
+      <bulletRef label="dropper">\r
+       <param>$1</param>\r
+       <param>0</param>\r
+      </bulletRef>\r
+      <direction>0</direction>\r
+    </fire>\r
+    <fire>\r
+      <bulletRef label="dropper">\r
+       <param>$1</param>\r
+      </bulletRef>\r
+      <py:offset><py:x>5</py:x><py:y>-5</py:y></py:offset>\r
+    </fire>\r
+    <fire>\r
+      <bulletRef label="dropper">\r
+       <param>$1</param>\r
+      </bulletRef>\r
+      <py:offset><py:x>-5</py:x><py:y>-5</py:y></py:offset>\r
+    </fire>\r
+  </action>\r
+\r
+  <bullet label="dropper">\r
+    <speed>0</speed>\r
+    <action>\r
+      <repeat>\r
+       <times>$1</times>\r
+       <action>\r
+         <fire>\r
+           <bullet>\r
+             <direction type="relative">0</direction>\r
+             <speed type="absolute">1</speed>\r
+           </bullet>\r
+         </fire>\r
+         <wait>4</wait>\r
+       </action>\r
+      </repeat>\r
+      <changeSpeed>\r
+       <term>1</term>\r
+       <speed>1</speed>\r
+      </changeSpeed>\r
+    </action>\r
+  </bullet>\r
+</bulletml>\r
index 9ca98c3258a28acab3ce72e8d0ad58cda2d9ecc7..4b93df8171358308aeffd0705c06a4def97ad9fb 100644 (file)
@@ -1,7 +1,8 @@
 <?xml version="1.0" ?>\r
 <!DOCTYPE bulletml SYSTEM "http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/bulletml.dtd">\r
 \r
-<bulletml xmlns="http://www.asahi-net.or.jp/~cs8k-cyu/bulletml">\r
+<bulletml xmlns="http://www.asahi-net.or.jp/~cs8k-cyu/bulletml"\r
+         xmlns:py="http://code.google.com/p/python-bulletml/">\r
   <action label="top">\r
     \r
   </action>\r