Welcome back! In this issue you will learn how to add a sky to your game, add some lighting and some fog. You will create controls for your player and be able to fly around your 3D world, barrel roll, loop-the-loop and more! We’ll also dip into how the camera works and how to control it while also explaining how positioning and transformations work. With a further snippet on performance tuning there’s a lot to cover, so away we go…!
1. Position and Transformation
We left Issue 2 with our player positioned on the terrain but did not explain those last few lines of code. So here they are again:
self.player = self.loader.loadModel("alliedflanker.egg") self.player.setPos(20,20,65) self.player.setH(225) self.player.reparentTo(self.render) |
The first line should look familiar. The same way we loaded our world, we load the model for our player. Likewise, the fourth line, re-parents the player to render. Again, exactly as we did with our world in Issue 1.
Those other two lines do warrant some explanation. We first make a call to ‘setPos’ which, you may have guessed, sets the position of our player. Four values are given. The first one is our world. This is an important concept you will see time and time again with Panda3D. We are performing relative positioning. Position our player relative to the world. It’s a powerful approach – your game objects can be positioned, moved and oriented relative to each other.
Having said that, in this instance, you could completely omit the world parameter and just call setPos with the 3 numbers given! We do not specify the worlds position in our code and thus it defaults to 0,0,0 …making our relative positioning effectively normal positioning. That does not detract from the fact that it’s a very powerful concept, hence our inclusion in the code snippet.
The remaining three values are X, Y and Z. The diagram shown should hopefully be self explanatory, note that where the 3 lines intersect, all values are zero. As such, XYZ values can be positive or negative:
You can also set these co-ordinates individually instead of all at once as we have done here. There’s a summary table below of what Panda3D API provides.
Next, that other line of code where we called ‘setH’. H is short for Heading (sometimes called Yaw). As well as having a position a model also has a ‘transformation’, again given by three numbers. Heading (H), Pitch (P) and Roll (R). As with position, we can set them individually or all at once. Refer back to the XYZ diagram above where we also marked out HPR and what the values do. We can even set position and transformation at the same time with one call. Below is a summary of the ‘set’ methods available for a models position, transformation and size (scale):
| Scale | Position | Transformation |
| setScale(sx,sy,sz) setSx(sx) setSy(sy) setSz(sz) |
setPos(x,y,z) setX(x) setY(y) setZ(z) |
setHpr(h,p,r) setH(h) setP(p) setR(r) |
| setPosHprScale(x,y,z,h,p,r,sx,sy,sz) …set all of them in one go! |
||
Try changing some of the values and re-run your game. Notice what happens. A large part of game development is trial and error! You should be able to re-position your player and also alter the orientation of your player. Remember, your world is 1024×1024 (refer back to our export settings in Issue 1 from L3DT) with a maximum terrain height (highest mountain peak) set to 60 – so it’s quite easy to position your player off the map, under the ground or hidden in a mountain by accident! Notice we set our initial player position above to 65 – making sure it was never hidden underground irrespective of XY values.
There are some tricks and techniques to positioning that we’ll cover in a future issue along with some other debugging techniques. For now, however, you will have to re-run your game every time you change the values to see what happens. What you are looking to find is your preferred ‘start position’ for the player. Ultimately, we’ll store this value in a ‘constant’ variable, but right now – the values are only used once in the whole code so it is not necessary (wise developers make the correct decision between over and under engineering a solution, they also recognise when it is time to re-engineer).
Quick Nav: Next page |
Index: page 1 | page 2 | page 3 | page 4 | page 5 |
All: View full Issue on one Page









Another nice article, and longer than the others!
I must admit, that I didn’t read everything – mostly because I’m not that new to Panda.
There are only a few things I spotted which I didn’t like 100%.
First, how you fixed the model’s orientation shouldn’t become common practice. It’s better to rotate the model in a 3D app or using some panda tools (there are a few command line tools. i bet you’d find something useful there). For me consistency sounds better than workarounds and individual fixes.
Another thing is something done pretty common and by nearly everyone: you code functional (means: using functions for each task), whereas real object orienting coding is more appropriate here, IMHO.
E.g. instead of createEnvironment(self) I’d create a class Environment with methods load() and destroy() (or uload or something). Optionally that class could inherit from NodePath, which you use as holder for the models and lights and so on. In this case you’d even have a handle to a whole branch in the scene graph by only instancing your class.
But well, it’s more of individual taste, I guess.
As last, a word of positive critique: I love your graphics! Really, reading a dry text about coding is way more fun having some pictures to look at while working towards having the same. The visual aspect is something many authors forget and I’m glad you did not.
All in all, I wish there were more of such articles when I started. Or in other words: keep up the good work!
It’s all coming in good time! We’re starting out nice and simple to help new programmers get to grips with both Python and Panda3D. You are right, more classes makes sense, and we’ll be doing exactly that as we progress.
You are correct regarding the model. Again though, new developers are not generally fluent with 3D modeling. At this juncture, our focus is purely coding for the most part. Dealing with 3D models is another topic for the future. As such, it’s worth illustrating the type of issues you may run into grabbing models ‘off the shelf’.
Thanks for the positive feedback!
Thanks for the Issues. Havent looked through in detail but i like the terrain issue. I want finer control over the texturing of the terrain though, if that software you used dont already have it. I keep looking for a better terrain maker. Going to make one myself if none of them provide what i need.
Very cool tutorial, thanks! I’m working my way through. One correction: Your first code sample includes a call to setPos, and you then discuss passing 4 parameters to it, but that particular code sample given only includes three. Just need to prepend self.world to ‘em and you’re all good.
Thanks again. Feel free to delete this comment after you’ve made the correction.
I’m not sure if i’ll get a reply or not but i am loving these articles! I wish to fulfill a career in programming one day. But when i add the code for lighting, fog and sky i get the same “MyApp instance has no attribute ‘maxdistance’
I’ve checked the code and i’m sure i did everything right.
Help would be greatly appreciated.
@vinny iam getting the same error . now what’s the solution for it ???
@Vinny – the text tells you to add self.creatEnvironment() into your constructor – but it doesn’t say that it must be at the end of the constructor, otherwise self.maxdistance isn’t defined. Look for it in the code and you’ll see where it is defined.