Hi there,
i was wondering, what is the most efficient way to create and handle multiple scenes?
For example, in a Lobby scene i might have a camera, an actor, and some UI, that would be different in another scene, say for example during a match. How can you implement this?
Thanks for your time in advance,
Tom.
I don’t know about the most efficient approach, but what I usually do is create classes to encapsulate such things, and then create, destroy, show, or hide them as called for.
So something like this:
class Scene():
def __init__(self):
self.rootNode = NodePath(PandaNode("scene root"))
# Other initialisation here as appropriate
def show(self):
self.rootNode.reparentTo(render)
def hide(self):
self.rootNode.detachNode()
def destroy(self):
if self.rootNode is not None:
self.rootNode.removeNode()
self.rootNode = None
# Other cleanup here as called for
# Create and show a scene
scene1 = Scene()
scene1.show()
# Now, replace it with another scene
# If it might be used again:
scene1.hide()
# If it's no longer relevant:
scene1.destroy()
scene2 = Scene()
scene2.show()
The above is, to be clear, a simplistic example–in a full game I’d likely have a class managing the scenes, perhaps keeping a list of them, and so would actually discard “scene1” rather than leaving it hanging around as an unused variable.)
1 Like
How do you think that i can handle the “update” function in the scene, the one that runs every frame to do stuff? I set up a basic test, and for example the keyboard events were still occuring even if the scene was hidden using your function. If you want to look at its code:
def update(self, task) -> None:
if self.first_frame:
try:
self.previous_x = base.mouseWatcherNode.getMouseX()
self.previous_y = base.mouseWatcherNode.getMouseY()
except:
self.previous_x = 0
self.previous_y = 0
self.FpsController = FPSController(self.previous_x, self.previous_y, config_data)
self.first_frame = False
dt = globalClock.getDt()
if self.keyMap[MOVE_FWD]:
if self.keyMap[RUN]:
deg = math.radians(base.camera.getH())
base.camera.setPos(base.camera.getPos() + Vec3(math.sin(deg)*-10*dt, math.cos(deg)*10*dt, 0))
self.tempActor.setPos(self.tempActor.getPos() + Vec3(math.sin(deg)*-10*dt, math.cos(deg)*10*dt, 0))
self.tempActor.getChild(0).setH(180)
deg = math.radians(base.camera.getH())
base.camera.setPos(base.camera.getPos() + Vec3(math.sin(deg)*-5*dt, math.cos(deg)*5*dt, 0))
self.tempActor.setPos(self.tempActor.getPos() + Vec3(math.sin(deg)*-5*dt, math.cos(deg)*5*dt, 0))
self.tempActor.getChild(0).setH(180)
if self.keyMap[MOVE_BACK]:
deg = math.radians(base.camera.getH())
base.camera.setPos(base.camera.getPos() + Vec3(math.sin(deg)*5*dt, math.cos(deg)*-5*dt, 0))
self.tempActor.setPos(self.tempActor.getPos() + Vec3(math.sin(deg)*5*dt, math.cos(deg)*-5*dt, 0))
self.tempActor.getChild(0).setH(180)
if self.keyMap[MOVE_LEFT]:
deg = math.radians(base.camera.getH() + 90)
base.camera.setPos(base.camera.getPos() + Vec3(math.sin(deg)*-5*dt, math.cos(deg)*5*dt, 0))
self.tempActor.setPos(self.tempActor.getPos() + Vec3(math.sin(deg)*-5*dt, math.cos(deg)*5*dt, 0))
self.tempActor.getChild(0).setH(180)
if self.keyMap[MOVE_RIGHT]:
deg = math.radians(base.camera.getH() - 90)
base.camera.setPos(base.camera.getPos() + Vec3(math.sin(deg)*-5*dt, math.cos(deg)*5*dt, 0))
self.tempActor.setPos(self.tempActor.getPos() + Vec3(math.sin(deg)*-5*dt, math.cos(deg)*5*dt, 0))
self.tempActor.getChild(0).setH(180)
if self.keyMap[WEAPON_SHOOT]:
print("shot")
self.UpdateVisualController()
self.world.doPhysics(dt)
return task.cont
Please note that
self.UpdateVisualController()
is not a Panda3D method but a function that i created to make you camera move as in a FPS game.
What I usually do is to have a central “framework” or “game” class that manages the “scene” or “world” classes. That central class then operates the update-task, and in turn calls the update methods of any relevant “scene”/“world” class-instances.
This should result in only the currently-active “scenes”/“worlds” being updated.
As an alternative, you could simply have the “scene” class remove its update-task when it’s hidden or destroyed, and create that task when it’s shown.
1 Like