wrapping a model in a class

Let’s say i’m trying to make a guitar hero type of game. So I have this class which makes the “fretboard”

class fretBoard(NodePath):
    def __init__(self):
        self.width = 8
        self.heigth = 12
        self.length = 50
        ### Draw the board
        self.vdata = GeomVertexData('fretVertices', GeomVertexFormat.getV3c4() , Geom.UHStatic)
        self.vertex = GeomVertexWriter(self.vdata, 'vertex')
        self.color = GeomVertexWriter(self.vdata, 'color')
 
        ### 4 Vertices for 2 triangles
        self.vertex.addData3f(self.width, 0, 0)
        self.color.addData4f(1, 0, 0, 1)
 
        self.vertex.addData3f(self.width, self.length, self.heigth)
        self.color.addData4f(1, 0, 0, 1)
 
        self.vertex.addData3f(0, 0, 0)
        self.color.addData4f(1, 0, 0, 1)
 
        self.vertex.addData3f(0, self.length, self.heigth)
        self.color.addData4f(1, 0, 0, 1)
 
        ### 2 Triangles with above vertices
        self.prim = GeomTriangles(Geom.UHStatic)
        self.prim.addVertex(0)
        self.prim.addVertex(1)
        self.prim.addVertex(2)
        self.prim.closePrimitive()
 
        self.prim.addVertex(2)
        self.prim.addVertex(1)
        self.prim.addVertex(3)
        self.prim.closePrimitive()
 
        ### Geom object with our triangles
        self.geom = Geom(self.vdata)
        self.geom.addPrimitive(self.prim)
 
        ### Node for the board
        self.node = GeomNode('fretBoard')
        self.node.addGeom(self.geom)
        self.nodePath = render.attachNewNode(self.node)
        
        #self.nodePath.reparentTo(render)
        #self.nodePath.setPosHpr(-4, 15, -4, 0, 0, 0)
    def create(self):
        return self.nodePath

At first, I did not have the “create” method, and in my world class I would try to do something like this:

self.board = fretBoard()
self.fretBoard = render.attachNewNode(self.board)

but Panda always kept complaining about self.board not being a NodePath, so I ended up adding the “create” method above (with some help from the IRC), and now I can do this:

self.fretBoard = fretBoard().create()
self.fretBoard.setPos(-4,15,-4)

and it works. Basically my “fretBoard” class just retuns a node with my fret board, and it saves me from typing in all the stuff required to draw the board inside my “world” class. Fine, now my code is a bit cleaner IMO.

Now, on to the “notes”:

class note(NodePath):
    def __init__(self):
        ### Bump.egg from the free panda art
        self.note = loader.loadModel("models/bump")
        self.note.setScale(0.2, 0.2, 0.15)
        self.note.setHpr(0,10,0)
    def create(self, color=1):
        ### Set up the interval for the notes to fall
        if color == 1:
            self.fallInterval = self.note.posInterval(1,Point3(-4,0,-4),startPos=Point3(-4,15,12))
            self.fallSequence = Sequence(self.fallInterval)
        elif color == 2:
            pass
        elif color == 3:
            pass
        elif color == 4:
            pass
        elif color == 5:
            pass
        else:
            pass
        return self.note
    def startFalling(self):
        self.fallSequence.start()

same thing with the “create” method again. It just returns a node, and I can do this in my “world” class:

self.note = note().create(1)
self.note.reparentTo(self.fretBoard)

Now, the problem is because I’m just returning a node, I can’t really do this in the world class

self.note.startFalling()

So my question is how can I actually have a model class which I can instantiate and call its methods, and not have my class just be a glorified helper function??

Basically I just want to be able to do this:

class note(NodePath):
    def __init__(self):
        ### Bump.egg from the free panda art (cat-shapes)
        self.note = loader.loadModel("models/bump")
        self.note.setScale(0.2, 0.2, 0.15)
        self.note.setHpr(0,10,0)
        ### Notes have to fall somehow
        self.fallInterval =  self.note.posInterval(1,Point3(-4,0,-4),startPos=Point3(-4,15,12))
        self.fallSequence = Sequence(self.fallInterval)
    def startFalling(self):
        self.fallSequence.start()


class world(DirectObject):
    def __init__(self):
        ### Draw one note
        self.note = note() #<---- !!!HOW??!!!
        self.note.reparentTo(render)
        self.note.startFalling()


w = world()
run()

my “note” class needs to return something (I think), I just don’t know what.

hmmm i think it works with this code:

class note(NodePath):
    def __init__(self):
        NodePath.__init__(self, loader.loadModel("models/bump"))
        self.setScale(0.2, 0.2, 0.15)
        self.setHpr(0,10,0)
        ### Notes have to fall somehow
        self.fallInterval =  self.posInterval(1,Point3(-4,0,-4),startPos=Point3(-4,15,12))
        self.fallSequence = Sequence(self.fallInterval)
    def startFalling(self):
        self.fallSequence.start()

class world(DirectObject):
    def __init__(self):
        ### Draw one note
        self.note = note() 
        self.note.reparentTo(render)
        self.note.startFalling()


w = world()
run()
        ...

Ah, nice! now I get it.