Commits

Xathos  committed d580b52

cleaning up...

  • Participants
  • Parent commits c8605ac

Comments (0)

Files changed (4)

File design/GoodCodingPractices.txt

-Good Object Oriented Programming Practices:
-(By Seiji Emery)
-
-Don't use globals, except for root-level objects (tanks, for example). Globals
-are ugly things better implemented as attributes for a common object, and they
-might not behave like you would expect them to (ie assigning to a global in a
-function without first declaring global <name>)
-
-One object should be created for every distinct concept (eg a tank), and
-encapsulate the implementation: internal variables and methods should be hidden
-from the outside world (prefix these names with '_'), while public interfaces
-should be created to simplify access to the important input/output aspects of
-the object.
-
-Objects should never rely on multiple data attributes to store the value of
-something. If two data attributes are directly interrelated, make one of them
-an attribute, and the other a property (a set of methods disguised as an
-attribute that uses code to calculate and return/set/delete a value). Don't
-make a Rect class that has data attributes for the four corners of the
-rectangle *and* height/width; instead, either store both x, y pairs and make
-width/height properties, or store the dimensions as x, y, width, height, and
-create x2, y2 properties to access these (or better yet, create a property for
-every corner and set x, y to the object's center (see Rect and Entity
-classes)).
-
-Use class inheritance to extend the functionality of an object. If your concept
-can exist independently however, create a new object for it -- use attributes
-to get the functionality you need. Eg: a projectile is distinct from a tank, so
-it should have its own class.
-
-If you have to write something more than three times in your program,
-encapsulate the repeated code into a function or object (whichever is
-appropriate). Why? Well, if you want to make a change, you only have to edit it
-once, instead of tracking it down and changing it in all places where it occurs
-- this makes maintenance and updates *much* simpler.
-
-Good OOP is not necessarily all about classes: functions are objects too (in
-Python), and a simple function that just returns an initialized object is
-always better than a full class definition if that's all you need to do.
-Functions that act as object initializers should follow the same naming
-conventions as classes -- because I say so, and since it makes sense. (see
-PlayerController)
-
-Use function callbacks, closures, and lambdas wherever practical. Don't use
-lambdas for anything more complex than a single expression - if it needs to be
-more complex, use a plain function and pass the function reference instead of a
-lambda (the two are completely compatible)
-
-Use docstrings to document what functions, classes, and methods do. Detail is
-good; at the very least explain anything that may be unclear to others.
-
-Use good naming practices: names should be descriptive and unique (per
-namespace). Avoid abbreviations unless absolutely necessary.
-
-Follow the naming conventions of pep 8; *try* to keep lines within 79
-characters, though if they overflow a little bit don't worry about it (but
-absolutely no 200 character lines). Note: lists of items within parentheses may
-be legitimately continued on the next line as long as successive lines are of
-the same indentation and are at least indented two levels above the previous
-line; other code may be continued by by typing '\' at the end of the line.
-
-Prototype code that does not follow OOP guidelines is okay as long as the
-author promises to encapsulate it into a logical object/objects as soon as the
-prototype is finished and before said code is added to the main codebase.

File design/ModularActorDesign.txt

-Actor / Modular Code Design:
-
-Actor:
-    parameters change actor behavior.
-    methods send the actor requests.
-    state and constant parameters are kept internal.
-    properties give access to parts of actor state.
-    internal update methods are routinely called by parent objects.
-
-Example:
-
-TankActor:
-    parameters:
-        controller
-        speed
-        turn_speed
-        target
-        projectile
-        fire_rate
-        limit_tracking
-        turret_tracking_speed
-    methods:
-        drive()
-        turn()
-        fire()
-    properties:
-        position
-        rotation
-        turret_rotation
-    internals:
-        _body
-        _turret
-        _fire_timer
-        _projectiles
-    update method:
-        update()
-    

File design/ObjectList.txt

-Modular objects:
-    Tank
-    TankProjectile
-    TankProjectileCollection
-    PredictiveAI
-    Point2d
-    Entity
-
-Tank:
-    parameters:
-        initialization:
-            tank_img_path (string)
-            turret_img_path (string)
-        controller (function)
-        speed (float)
-        turn_speed (float)
-        target (Point2d)
-        projectile (TankProjectile)
-        fire_rate (float)
-        limit_tracking (bool)
-        turret_tracking_speed (float)
-    methods:
-        drive (direction (float))
-        turn (direction (float))
-        fire ()
-    properties:
-        position (Point2d)
-        rotation (float)
-        turret_rotation (float)
-    update:
-        update()
-        draw()
-
-TankProjectile:
-    parameters:
-        initialization:
-            img_path (string)
-        speed (float)
-        auto_destruct_time (float)
-        damage (float)
-    methods:
-        spawn (position (Point2d), direction (Point2d)) (TankProjectileInstance)
-
-TankProjectileCollection:
-    methods:
-        add (projectile (TankProjectileInstance))
-    update:
-        update()
-        draw()
-
-PredictiveAI:
-    parameters:
-        target (Point2d)
-    update:
-        ai_update()
-        draw_crosshair()
-
-Entity:
-    parameters:
-        initialization:
-            img (pyglet image data)
-            blend_src (int)
-            blend_dest (int)
-            batch (pyglet graphics batch)
-            group (pyglet group ?)
-            usage (string)
-        x (float)
-        y (float)
-        children (list)
-        tags (list)
-    methods:
-        move (direction (Point2d))
-        move_to (position (Point2d))
-        rotate (degrees (float))
-        to_world_space (local_space (Point2d)) (Point2d)
-        add_tag (tag (string))
-        add_child (child (Entity))
-        remove_child (child (Entity))
-        find_with_tag (tag (string))
-        find_all_with_tag (tag (string))
-    properties:
-        w (float)
-        h (float)
-        rect (Rect)
-        bottom_left (Point2d)
-        bottom_center (Point2d)
-        bottom_right (Point2d)
-        center_left (Point2d)
-        center (Point2d)
-        center_right (Point2d)
-        top_left (Point2d)
-        top_center (Point2d)
-        top_right (Point2d)
-    update:
-        update()
-        draw()
-
-Point2d:
-    parameters:
-        x (float)
-        y (float)
-    methods:
-        __repr__ () (string)
-        __add__ (other (Point2d, Rect, Entity, or 2 element tuple)) (Point2d)
-        __sub__ (other (Point2d, Rect, Entity, or 2 element tuple)) (Point2d)
-        __mul__ (scalar (float)) (Point2d)
-        __div__ (scalar (float)) (Point2d)
-        scale (x_scale (float), y_scale (float))
-    properties:
-        rect
-        tuple_

File design/Python_OOP_tidbits.txt

-A few tidbits about Python OOP:
-
-When defining methods that accept other objects as parameters (like Point2d's
-__add__ method), use try...except blocks over type checking with if...else blocks.
-Using type checking will mean that only *one* type of parameter work, and this
-is why a statically typed language like Java has _tons_ of overloaded functions that
-each try to do the same thing (one for each case).
-
-So with Java my add method might look like this
-(not sure what the addition overload method is called, so I'll just call it add):
-
-class Point2d {
-    public void add (Point2d point) {
-        x += point.x;
-        y += point.y;
-    }
-    public void add (Rect rect) {
-        x += rect.x;
-        y += y.x;
-    }
-}
-As you can see, I'll need to add a new add method for every type that I want to support
-addition with.
-
-On the other hand, Python is a dynamically typed lanugage, so I can simply code this:
-
-class Point2d:
-    def __add__ (self, other):
-         try:
-             return Point2d(self.x + other.x, self.y + other.y)
-         except AttributeError:
-             pass
-
-This will accept ANY object that has x, y attributes - Point2d, Rect, Entity, etc., without the
- need for coding extra cases - all that is needed to make two classes have compatible
- methods is to give them shared attributes (attributes that are named the same)
-
-Things to watch out for:
-     Don't give your 'shared' attributes vague or common names. They should be clear and unambiguous.
-     Try not to ever use plain except statements - always attach the case of error that you are expecting
-     (this can unintentionally silence errors from other areas in your code). If you're not sure what the error is
-     named, open up a python shell, and intentionally reproduce the error (the traceback should give the error
-        type).
-     Also don't ever modify self variables in an overloaded __add__ or similar method - always return a new
-     object. If you just modify self, or modify and return self, your addition operators (or whatever) will NOT
-     work as you would expect them to (personal experience)