1. schlangen
  2. gallox

Commits

schlangen  committed 566f27c

- added documentation
- updated gamedesign uml
- little code clean up

  • Participants
  • Parent commits 64088f1
  • Branches default

Comments (0)

Files changed (6)

File gallox/editor/widgets.py

View file
  • Ignore whitespace
 
 
 class IconButton(gui.Widget):
+    """
+    Simply an icon with a mouse-down callback that autoloads its icon and
+    can have an overlay to highlight itself when active (by removing it).
+    """
     highlight = True
     used_styles = ["image", "overlay", "overlaybg"]
     def __init__(self, parent, size=(32,32), pos=(0,0), name="dummy",
 #! add to gui.widgets?
 
 class ToggleText(gui.Text):
+    """
+    A text widget that toggles several texts on mouse_down
+    """
     highlight = True
     def __init__(self, parent, size, pos, texts, align="left", **kwargs):
         gui.Text.__init__(self, parent, size, pos, texts[0], align=align, **kwargs)
         self.text = self.texts[self.index]
         
     def toggle(self):
+        # simply simulate a mouse_down
         self.handle_mouse_down(1)
 
 class PanelSwitch(gui.Layer):
+    """
+    Kind of a tab head button, only useful when combined
+    with :class:``PanelList``
+    Is either active or not and has a reference (self.panel)
+    to the Layer with the actual content.
+    ``self.active`` should always be the same as ``self.panel.visible``
+    
+    Uses the suffix "active" when active.
+    """
     style_class_name = "panelswitch"
     highlight = True
     def __init__(self, parent, size, pos, panel, **kwargs):
         
 
 class PanelList(gui.Layer):
+    """
+    Manages a list of Layers like tabs (tab bodies). 
+    Tab heads (PanelSwitches) may be horizontally (0)
+    or vertically (1) oriented. 
+    
+    Add new panels with self.add_panel
+    
+    Use deactivate to hide all panels and reactivate
+    to show the last active panel again.
+    """
     def __init__(self, parent, size=None, pos=(0,0), orient=0, padding=10,tabsize=(90,25), **kwargs):
         gui.Layer.__init__(self, parent, size, pos, **kwargs)
         self.panels = []
         return styles
     
     def add_panel(self, panel, name, index="end"):
+        """
+        :type panel: gui.Layer
+        :param panel: a new panel
+        :type name: str
+        :param name: 
+            name that will be used as tab text and also
+            for internal reference
+        :type index: int or "end"
+        :param index:
+            index for the new panel
+            
+        Add new panel to the PanelList
+        """
         panel.name = name
         if index == "end":
             self.panels.append(panel)
         self.reorder_panels()
         self.activate(name)
         
+    #! add remove_panel(name)
         
     def reorder_panels(self):
         self.widgets = []
         self.active_panel.activate()
         
     def activate(self, name):
+        """
+        activate panel with name ``name``
+        """
         self.handle_ps_clicked(self.switches[name])
         
     def deactivate(self):
+        """
+        deactivate the currently active panel without activating
+        another panel and remember it.
+        """
         if self.active_panel:
             self.last_active_panel = self.active_panel.panel.name
             self.active_panel.deactivate()
         self.active_panel = None
         
     def reactivate(self):
+        """
+        activate the last active panel
+        """
         self.activate(self.last_active_panel or self.panels[0].name)
         self.last_active_panel = None
         
     
 class AttributeList(gui.Layer):
+    """
+    List of general level attributes such as name, 
+    intro message, etc. (see gallox.editor.GENERAL_ATTRIBUTES)
+    
+    """
     def __init__(self, parent, size, pos, attributes, **kwargs):
         gui.Layer.__init__(self, parent, size, pos, **kwargs)
         x, y = 10, 30
         self.inputs = {"authors":[]}
         for name, keyword, minlenght, maxlength, type in attributes:
-            #t = gui.Text(self, "auto", (x,y), "%s:" % name)
             i = gui.TextInput(self, "auto", (x+80, y), 
                             "", template="%s:  %%s" % name, multiline=False, 
                             align="left", anchor="topleft")
                 self.inputs[keyword] = i
             else:
                 self.inputs["authors"].append(i)
-#        y += 20
-#        self.images = {}
-#        for name in ("background", "main", "foreground"):
-#            text = gui.Text(self, "auto", (x,y), "", 
-#                            template=("%s image: %%s" % name))
-#            self.images[name] = text
-#            text.listen("mouse_down", lambda n=name,**kw: self.ask_for_image(n))
-#            y += text.size[1] * 1.5
-            
-#    def ask_for_image(self, name):
-#        FileBrowser(self.get_gui(), (300,400), (200,50), "image", lambda p: self.set_image(p, name))
-        
-#    def set_image(self, path, name):
-#        self.images[name].text = path
-#        img, r = load_image(path, ALPHA_COLOR if name == "main" else None)
-#        self.get_gui().style["map_image_%s" % name] = img
             
     def reset(self, name=""):
+        """
+        clear all input fields, then set name to ``name``
+        """
         for keyword, input in self.inputs.iteritems():
             if keyword == "name":
                 input.set_text(name)
                                 i.set_text(name)
                     else:
                         break
-        
-#        if img_tree:
-#            for img in img_tree.findall("image"):
-#                name = img.get("type")
-#                path = img.get("src")
-##                print "found image %s at %s" % (name, path)
-#                if path and name in self.images and os.path.exists(path):
-#                    self.set_image(path, name)
-#                    print "set image"
-#                else:
-#                    print  path, name in self.images
-#                    print self.images
                     
                     
     def save(self, parent):
+        """
+        :type tree: Element
+        :param tree: parent to add the "about" subtree to
+        """
         general = SubElement(parent, "about")
         for keyword, input in self.inputs.iteritems():
             if keyword != "authors":
                         author = SubElement(general, "author")
                         SubElement(author, "name").text = name
                         
-#        images  = SubElement(parent, "images")
-#        for name, widget in self.images.iteritems():
-#            se = SubElement(images, "image", type=name, src=widget.text)
-            
-    
+
 MAX_FILENAME_LENGTH = 18
     
 #! make more generic and add to gui.widgets
 
 class FileBrowser(gui.Window):
+    """
+    A file browser window.
+    
+    select either an image, a directory or a level
+    """
     style_class_name = "window"
     image_exts = [".png", ".gif", ".jpg", ".jpeg", ".bmp", ".tiff"]
     def __init__(self, parent, size, pos, filter, callback, msg="", **kwargs):
         self.build_dir_info()
         self.init = True
         
-      #  def dummyupdate(styles):
-      #      gui.ScrolledLayer.blit_widget(self.dir_box, styles)
-      #      print "blit widget"
-      #  self.dir_box.blit_widget = dummyupdate
-
         
     def handle_new_path(self, **kw):
         path = self.main_path.get_text()
-#        print "handle new path", path, 
         if os.path.isdir(os.path.abspath(path)):
             self.path = path
             self.build_dir_info()
-#            print "new path:", path
         else:
             self.main_path.set_text(self.path)
-#            print "reset text"
             
     def handle_callback(self, widget, **kw):
         if self.filter == "level":
                     short_name = name
                 t = gui.Text(self.dir_box, "auto", (x,y), short_name,align="left")
                 t.full_text = name
-#                t.auto_resize = False
-#                t.size[0] = min(t.size[0], 70)
                 if special:
                     t.template = "<%s>"
                     t.listen("mouse_down", self.handle_callback)
                     t.listen("mouse_down", self.handle_dir_clicked)
                 y += t.size[1] * 1.5
                 
-                
         self.dir_box.scroll_size = (x+150, 0)
         self.dir_box.init_pos()
         self.dir_box.dirty = True
     def handle_resized(self, **kw):
         if self.init:
             self.build_dir_info()
-    
-BOOL = 1
-INT = 2
-FLOAT = 3
-
-CONVERT_FUNCTIONS = [None, bool, int, float]
+            
+            
     
 DEFAULT_ATTRS = {"fix_no":False, "turnable":False, "resizable":False}
 SPRITES = {
         "gun":{"turnable":True},
         "ship":{"fix_no":True, "turnable":True},
            }
+           
+           
+def mybool(s):
+    """
+    convert a string to a boolean and also consider "False" as False
+    
+    this is neccessary to save booleans with str(boolean) explicitly
+    as "True" and "False". Otherwise False would have to be saved as
+    "" what is too implicit.    
+    """
+    return s not in ("", "False")
+
+# parameter types
+BOOL = 1
+INT = 2
+FLOAT = 3
+# list of functions to convert a value from a string back to its original type
+CONVERT_FUNCTIONS = [None, mybool, int, float]
+           
+"""
+General information about the parameters a sprite of a certain type
+can have, structured as {type : [list of params]} dict where one 
+parameter consists of 
+
+  - a name, that is used for any internal usage
+  - a repr_name, that is used whenever the name is displayed for the user
+  - a type, that must be one of BOOL, INT, FLOAT
+  - a default value
+  - an args dict, that will be passed to the widget used for this type.
+    
+Two useful values for the arg dict of an int param are, for example, "min_val"
+and "max_val" (used by gui.NumberInput) to control the range of the param value.
+    
+"""
 SPRITE_PARAMS = {
         "plattform":[
                { "name": "refuel",
                 {"name":"shotFreq",
                 "repr_name":"shot frequency [px/s]",
                 "type":FLOAT,
-                "default": -5,
+                "default": 5,
                 "args":{"max_val":100,
                         "min_val":1}
                 },
                ],
         "ship":[],
            }
+
+#! do not define such values here
 HIGHLIGHT_COLOR = (255,0, 200)
                                              
 class Sprite(gui.Widget):
+    """
+    Represents game sprites of any type.
+    
+    sprite.attributes 
+    ''''''''''''''''''
+    depend on the sprite type and influence the way the
+    sprite can be edited, ie. if it can be resized or turned.
+    
+    
+    sprite.parameters
+    ''''''''''''''''''
+    depend on the individual object and have only influence in
+    the actual game and can be edited via the param tab of the
+    sprite editor.
+
+    
+    names
+    '''''''''''
+    Every sprite object has a representative, unique name, 
+    sprite.repr build from the type and a serial number that
+    makes it easy to reference sprites. Widgets that belong
+    to a certain sprite need to save only the repr of a sprite.
+    To get the sprite to a given repr use the :meth:``Sprite.get``
+    class method.
+    """
     counters = {}
     _id2obj_dict = weakref.WeakValueDictionary()
     def __init__(self, parent, name, size=None, pos=(0,0),degrees=0, **kwargs):
         self.parameters = dict([(d["name"], d["default"]) 
                                 for d in SPRITE_PARAMS[self.name]])
         
-            
-        
         if self._is("fix_no"):
             if self.name in self.counters:
                 raise ValueError, "number of %s sprites limited to 1" % self.name
     
     @classmethod
     def get(cls, name):
+        """
+        :type name: str
+        :param name:
+            repr of a sprite object
+        :rtype: :class:`Sprite`
+        :returns:
+            the sprite object represented by repr
+            
+        Get the sprite object from a given repr
+        """
         try:
             return cls._id2obj_dict[str(name)]
         except KeyError:
         return styles
     
 class Map(gui.ScrolledLayer):
+    """
+    The actual map.
+    Scrollable Layer that is parent of all Sprites.
+    """
     used_styles = ["image_background", "image_main", "image_foreground"]
     style_class_name = "map"
     def __init__(self, parent, size=None, pos=(0,0), **kw):
         
     def blit_widget_top(self, styles):
         if self.dragging[1] and self.dragging_anchor and self.last_drag_pos:
+            # draw scrolling controller
             x1, y1 = self.dragging_anchor
             x2, y2 = self.last_drag_pos
             my_x, my_y = self.rect.topleft
             for point, color in zip(points, colors):
                 pygame.draw.line(self.image, color, point, (x2,y2), 3)
             
-#            r = pygame.draw.line(self.image, (255,255,0), (x1,y1), (x2,y2), 5)
-#            self.line_rect = r.move(-my_x, -my_y)
             
     def handle_new_scroll_size(self, **kw):
         sx, sy = self.scroll_size
                 - self.offset_y + self.size[1]/2.)
 
     def clear(self):
-        # remove all but scrollbars
+        # remove all widgets but scrollbars
         self.widgets = self.fixed_widgets[:]
         
     def handle_mouse_dragged(self, rel, abs, buttons, **kw):
         if self.auto_dragging:
             self.auto_dragging = False
             self.dragging[1] = False
-            
-    
-        
-        
+
+
         
 class List(gui.Layer):
     """
+    List of items (names/strings) with additional :class:``IconButton``\ s
+    
     #! todo
     self.meta_objects -> don't remove
+    like "--- main layer ---"
     """
     def __init__(self, parent, size=None, pos=(0,0), items=[], icons=[], 
                  events=[], item_kwargs={}, **kwargs):
                     i.listen(event_name, item_cb(name, callback))
                 x += i.size[0] + 10
                 self.lines[name][icon] = i
-#            t.listen("post_mouse_down", 
-#                     lambda t=t,**kw: self._send_event("item_selected", 
-#                                                       item=t.text))
-#            if cmd is not None:
-#                tc = gui.Text(self, "auto", (x+t.size[0], y), cmd, 
-#                              highlight=True)
-#                tc.listen("post_mouse_down", 
-#                     lambda t=t,**kw: self._send_event("item_cmd", 
-#                                                              item=t.text))
             y += h * 1.5
         self.item_width = x
         self.dirty = True
 
 
 class SpriteParamEditor(gui.Layer):
+    """
+    Editor for sprite parameters.
+    Set self.sprite to any sprite to make its parameters editable.
+    Gets all information from SPRITE_PARAMETERS.
+    """
     def __init__(self, parent, size, pos, **kwargs):
         gui.Layer.__init__(self, parent, size, pos, **kwargs)
         self._sprite = None
         
     
 class SpriteEditor(gui.Layer):
+    """
+    Main editor component that contains the :class:``Map``\ , 
+    the :class:``SpriteParamEditor`` and some :class:``Lists``
+    to edit and manage all sprites.
+    """
     def __init__(self, parent, size, pos, **kwargs):
         gui.Layer.__init__(self, parent, size, pos, **kwargs)
         style = self.style
         self.update_lists()
         
 class NewLevelDialogue(gui.Layer):
+    """
+    Dialogue to get all data from the user that is required
+    to create a new level
+    """
     def __init__(self, parent, size, pos, **kwargs):
         gui.Layer.__init__(self, parent, size, pos, **kwargs)
         y = 130

File gallox/main.py

View file
  • Ignore whitespace
                 
         # "menu" or "game" or "editor"
         self.state = "menu"
-        self.fade_to(self.menu)
+#        self.fade_to(self.menu)
 #        self.start_game("testlevel")
-#        self.start_editor()
+        self.start_editor()
         self.photo_sound = load_sound("photo.wav")
         self.c = 0
         

File gallox/map.py

View file
  • Ignore whitespace
             if pygame.sprite.spritecollideany(bullet, self.plattforms):
                 point = bullet.rect.center
         if point:
-            if isinstance(bullet, PlayerBullet):
+            if isinstance(bullet, ShipBullet):
                 pygame.draw.circle(self.image, ALPHA_COLOR, point,
                                    BULLET_HOLE_RADIUS)
                 # update mask

File gallox/sprites/player.py

View file
  • Ignore whitespace
         self.plattform = None
         
     def fire(self):
-        PlayerBullet(self.rect.center, self.rot, self.map, self.groups())
+        ShipBullet(self.rect.center, self.rot, self.map, self.groups())
         
     def update(self, events, ticks):
         if self.plattform:
 #            print "b00m!!!  [reset]"
         
             
-class PlayerBullet(Bullet):
+class ShipBullet(Bullet):
     def explode(self):
         Explosion(self.rect.center, self.map.allsprites)

File gamedesign.dia

  • Ignore whitespace
Binary file modified.

File testlevel/level.xml

View file
  • Ignore whitespace
       <size h="34" w="39" />
       <rotSpeed>4.0</rotSpeed>
       <actionScope>20</actionScope>
-      <autoAim>True</autoAim>
+      <autoAim>False</autoAim>
       <shotFreq>1.0</shotFreq>
     </sprite>
     <sprite degrees="-130" type="ship">
     <sprite degrees="10" type="gun">
       <position x="789" y="490" />
       <size h="34" w="39" />
-      <rotSpeed>4</rotSpeed>
+      <rotSpeed>4.0</rotSpeed>
       <actionScope>60</actionScope>
-      <autoAim>False</autoAim>
-      <shotFreq>-5</shotFreq>
+      <autoAim>True</autoAim>
+      <shotFreq>-5.0</shotFreq>
     </sprite>
     <sprite type="plattform">
       <position x="818" y="611" />
     <sprite degrees="-160" type="gun">
       <position x="342" y="552" />
       <size h="34" w="39" />
-      <rotSpeed>4</rotSpeed>
+      <rotSpeed>4.0</rotSpeed>
       <actionScope>60</actionScope>
-      <autoAim>False</autoAim>
-      <shotFreq>-5</shotFreq>
+      <autoAim>True</autoAim>
+      <shotFreq>-5.0</shotFreq>
     </sprite>
   </sprites>
 </level>