Reputation: 870
I have a function update()
in a Character
class such that every time an instance of the class character is made, the update
method needs to be called in the main loop for example:
troll = Character()
monster = Character()
while True:
troll.update()
monster.update()
This is fine, but is unclean if I were to have a lot of instances of the Character
class.
I know this can be done using the @classmethod annotation
. But I don't want to do this, are there other ways?
Any suggestions?
Upvotes: 0
Views: 148
Reputation: 1480
I think what you are looking for is the composite pattern. You create a CompositeCharacter class that contains all Character instances. You can then call an update method in the CompositeCharacter object that will iteratively call the update method on all of it's children (your Character object collection).
You could define your composite class like this, or some variant of this. The point is that your instantiated CompositeCharacter object will have an internal list and provide methods to manipulate that list.
class CompositeCharacter():
children = []
def update(self):
for c in self.children:
c.update()
def add(self, char):
self.children.append(char)
At the beginning of your code, you instantiate the composite characters object into some variable reference... say compCharacters.
compCharacters = CompositeCharacter()
Or you could instantiate many CompositeCharacters based on some grouped character class
trollCharacters = CompositeCharacter()
monsterCharacters = CompositeCharacter()
humanCharacters = CompositeCharacter()
Then when you instantiate your individual Character()s you add them to the appropriate CompositeCharacter object.
troll = Character()
compCharacters.add(troll) OR trollCharacters.add(troll)
monster = Character()
compCharacters.add(monster) OR monsterCharacters.add(monster)
If you have added them to a general composite object (compCharacters) then you just call the update on that object
compCharacters.update()
Or, if you've used specialized groupings you could just call the update on whichever group you want to update.
trollCharacters.update()
OR
monsterCharacters.update()
OR
humanCharacters.update()
You could also keep all of your specialized composite objects in a parent composite object. Then you could call a global update if you wish or call a specialized one.
compCharacters = CompositeCharacter()
trollCharacters = CompositeCharacter()
compCharacters.add(trollCharacters)
monsterCharacters = CompositeCharacter()
compCharacters.add(monsterCharacters)
humanCharacters = CompositeCharacter()
compCharacters.add(humanCharacters)
Then to call the global update just call comp
compCharacters.update()
Upvotes: 1
Reputation: 11180
You cannot use a class method here, because a class method does not apply to an instance, but to some part of class that all sprites share.
Let's say your Character has an update method that moves the sprite. So it would look something like this:
def update(self):
self.pos = (self.pos[0] + self.v[0], self.pos[1] + self.v[1])
If you where to make it a class method, the first argument would be a class, not an instance, so there is no way to change an instance from a class method, unless the class itself has a list of instances.
The approach you should take should depend on the size of the game.
For starters, just put them in a list, and iterate to call each instance update method.
Another way would be to have a list of characters in the class, as RyPeck suggested. I think storing the list in the main program is better, because there is no need for the class to know about the existence of any instance.
Upvotes: 1
Reputation: 8147
Taking advantage of storing data in classes.
class Character():
instances = []
def __init__(self):
Character.instances.append(self)
self.x = 0
def class_update(self):
for x in self.instances:
x.instance_update()
def instance_update(self):
self.x += 1
A = Character()
B = Character()
A.class_update()
B.class_update()
C = Character()
C.class_update()
print Character.instances
print A, B, C
print A.x, B.x, C.x
Output -
[<__main__.Character instance at 0x10a8523f8>, <__main__.Character instance at 0x10a852440>, <__main__.Character instance at 0x10a852488>]
<__main__.Character instance at 0x10a8523f8> <__main__.Character instance at 0x10a852440> <__main__.Character instance at 0x10a852488>
3 3 1
I am unaware of the pitfalls of such an approach without knowing more about what it is you need to accomplish.
Upvotes: 2
Reputation: 122052
You could keep all of your Character
objects in a dict
:
characters = {}
characters["troll"] = Character()
characters["monster"] = Character()
Then updating all of your characters is easy:
for character in characters.values():
character.update()
Upvotes: 1