4. An out of body experience!
You may have noticed by now that if you fly high or to edges of your terrain, you see the sky end! It’s a problem we’ll be fixing soon. To understand what is going on in your game it often helps to use something Panda3D provides called the ‘out of body experience’ (or ‘OOBE’). Basically, in OOBE mode you get the same effect as at the end of Issue 1 – move around your terrain using the standard mouse controls. The difference is the main game camera is still present and can be seen!
Below is a screen shot of OOBE mode – notice the camera! While in OOBE mode you can still fly the player using the keyboard but can also observe the in-game camera following the player around!
To enable OOBE add this line in your constructor:
When you wish to turn this off, comment out the line with a ‘#’. You could also add this into your debug mode if you wish by adding the call to an IF statement (if self.debug == True: base.oobe()).
If you run into problems with visibility in OOBE try commenting out the call to setFar in your constructor (you’ll recall we limited the camera view for performance purposes in-game, but in-debug you may wish to turn this off).
5. Voodoo Magic!
That was strange wasn’t it? We simply called ‘base.oobe()’. Not ‘self.base.oobe()’. Look back at your createEnvironment method too. Notice we just referred to ‘render’ and not ‘self.render’. Why is that?
We did it on purpose to illustrate something in Panda3D that isn’t really good practise. The use of Global Variables. A global variance is one that exists in the global name space. That is, it is available to all classes/code/modules within a project. You can reference a global variable anywhere in your code and it will work.
After our discussions on name spaces and scoping previously we’re going to say, quite clearly, global variables are bad and should be avoided. Sadly, we cannot avoid the ‘base’ global variable. We do however recommend replacing your other global references (render) with their ‘self’ counterparts.
So why is it there? The answer from one of the Panda3D developers “this was done back when Panda was just an internal tool for a small group of people” and “Panda3D 2.0 won’t do this kind of thing”. Consider it confirmed; Globals are bad!
If you still wish to know what other global variables there are head over to our Cheat Sheet section, there’s an image dedicated to ‘Voodoo Globals’.
6. The camera values from Issue 3
Refer back to your updateCamera method. We defined this in Issue 3 but did not explain to you how we came up with the values. The values are what keeps the camera positioned during the game relative to the player.
Create a new Python (.py) file as follows:
from direct.showbase.ShowBase import ShowBase from direct.task import Task class ShooterGame(ShowBase): def __init__(self): ShowBase.__init__(self) self.world = self.loader.loadModel("models/world.bam") self.world.reparentTo(self.render) self.player = self.loader.loadModel("models/alliedflanker") self.player.setPos(20,20,65) self.player.setH(225) self.player.reparentTo(self.render) self.camera.setPos(self.player, 25.6225, 3.8807, 10.2779) self.camera.lookAt(self.player) self.taskMgr.add(self.updateTask, "update") def updateTask(self,task): # 'str' simple converts the Vec3 to string we can print print "POS: "+str(self.camera.getPos(self.player)) print "HPR: "+str(self.camera.getHpr(self.player)) return Task.cont my_shooter_game = ShooterGame() my_shooter_game.run()
…and save it in your game directory as ‘campositioner.py’. Now execute this new Python program. It will behave identically to what you had at the end of Issue 2. You will have a world, a player on the world and the default camera position and mouse controls. While the game is running look at the command prompt/terminal from which you launched the game and notice it is constantly printing out values – the position of the camera relative to the player. All you now need to do is position the camera how you would like it to be during the game. Once you have done this, the values being printed out in your terminal values are the values you need to put in to your updateCamera method. Simples! 🙂