Ask two coders about good OO style and you get three answers. At least. Here is one way to do this:
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
class World:
def __init__( self, path ):
self.np = loader.loadModelCopy( path )
self.np.reparentTo( render )
def add( self, object ):
object.np.reparentTo( self.np )
class Player( DirectObject ):
def __init__( self, path ):
self.np = loader.loadModelCopy( path )
self.accept( 'escape', self.exit )
def exit( self ):
taskMgr.stop( )
class Enemy:
def __init__( self, path ):
self.np = loader.loadModelCopy( path )
world1 = World( '<path to worldFile>' )
player1 = Player( '<path to playerFile>' )
world1.add( player1 )
enemy1 = Enemy( '<path to enemyFile>' )
world1.add( enemy1 )
run( )
I don’t like this very much, since World.add( ) uses implicit knowledge about the objects that is added ( object.np is the NodePath instance ). The python manual says “explicit is better than implicit”, and so perhaps this one is better:
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
class World:
def __init__( self, path ):
self.np = loader.loadModelCopy( path )
self.np.reparentTo( render )
def addObject( self, klass, path ):
object = klass( path )
object.addTo( self.np )
class Object:
def __init__( self, path ):
self.np = loader.loadModelCopy( path )
def addTo( self, np ):
self.np.reparentTo( np )
class Player( Object, DirectObject ):
def __init__( self, path ):
Object.__init__( self, path )
self.accept( 'escape', self.exit )
def exit( self ):
taskMgr.stop( )
class Enemy( Object ):
def __init__( self, path ):
Object.__init__( self, path )
world1 = World( '<path to worldFile>' )
world1.addObject( Player, '<path to playerFile>' )
world1.addObject( Enemy, '<path to enemyFile>' )
run( )
I think it may be possible to derive from the classes provided by Panda (World from NodePath, Player and Enemy from Actor and so on), but since you probably want to have a collision node, exposed joints and several invisible triggers floating around with the player/enemies I think it is a good idea to have a container classes that holds everything together.
In the above examples only Player is derived from DirectObject. DirectObject provides event handling methods like “accept”, “ignore” and so on. Again there are thousands of ways to do it, and perhaps you want to derive Player from FSM (Finite State Machine), and give player a controler attribute the handles input and can be exchanged with other controler instances specialised for walking, swimming, … . In this case Controler would have to be derived from DirectObject.
Hope this help
enn0x