User:Nnz/Object composition

From RogueBasin
< User:Nnz
Revision as of 07:22, 26 November 2010 by Nnz (talk | contribs) (Created page with ':''This page is a draft.'' This is a somewhat deeper explanation of the "object composition" method employed in part 6 of the python+libtcod roguelike tutorial. Although it conta…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
This page is a draft.

This is a somewhat deeper explanation of the "object composition" method employed in part 6 of the python+libtcod roguelike tutorial. Although it contains some technical details, it might be useful for those wanting to extrapolate the contents of the tutorial to make a full-blown game.

Introduction to Composition

Object composition is basic: You have an object, and another object (a component) is placed inside a property of the main object. It looks like this:

class SomeComponentClass:
    def __init__(self, foo, bar)
        self.foo = foo
        self.bar = bar

class MainClass:
    def getFoo(self):
        if hasattr(self.component, "foo"):
            return self.component.foo

    def __init__(self, spam, eggs, component):
        self.spam = spam
        self.eggs = eggs
        self.component = component

# Example
blah = MainClass(spam="qwerty", eggs="qwertyuiop", component=SomeComponentClass(foo=1, bar=2))
print blah.getFoo()
# Returns 1

There's not much special code here, except that an instance of SomeComponentClass has been passed to the component argument in MainClass.

As we can see from MainClass.getFoo(), the functions in MainClass have access to the functions and properties in MainClass.component -- in other words, the "outer" object has access to the "inner" one. But does the "inner" object have access to the "outer" one? Can a method in blah.component access blah.spam and blah.eggs?

Normally, the answer would be no. But with a bit of not-so-special code, it's quite possible.

    def __init__(self, spam, eggs, component):
        self.spam = spam
        self.eggs = eggs
        self.component = component
        if self.component:
            self.component.owner = self

This is where things get funky. What's basically happening is that the MainClass instace is storing the component, and then putting itself as a property of the component. Now the component has access to its owner and can get and set its properties:

class SomeComponentClass:

    def getSpam(self):
        if self.owner:
            return self.owner.spam

    def __init__(self, foo, bar)
        self.foo = foo
        self.bar = bar

Multiple Components

Swapping Components

Nested Components

Application to Roguelikes

All it took was a little bit of slightly unnatural code, and we have the foundation for a flexible system of components. Now let's see how this applies to roguelike games (or any computer RPG, for that matter.)