Page 3

ISSUE 5: A New Hope

It's time for some housekeeping before the New Year!  We're going to revamp our code base with a new design, explain the water from Issue 4, add some sound effects and finish with a basic Heads Up Display (HUD).
  • Delicious
  • Digg
  • Reddit
  • StumbleUpon
  • Twitter

newgamefolder/volume1/player.py

from panda3d.core import AmbientLight, DirectionalLight, Vec4, Fog
from panda3d.core import Texture, TextureStage
from pandac.PandaModules import CompassEffect
from pandac.PandaModules import VBase4, TransparencyAttrib
from direct.interval.LerpInterval import LerpTexOffsetInterval, LerpPosInterval
 
class GameWorld():
    def __init__(self,size,loader,scenegraph,camera):
        self.worldsize = size
        self.loader = loader
        self.render = scenegraph
        self.camera = camera
        self.world = self.loader.loadModel("volume1/models/world.bam")
        # the model is 1024 already, so we scale accordingly:
        self.world.setScale(self.worldsize/1024)
        self.world.setPos(0,0,0)
        self.world.reparentTo(self.render)
        self.__createEnvironment()
 
    # private method
    def __createEnvironment(self):
        # Fog
        expfog = Fog("scene-wide-fog")
        expfog.setColor(0.5,0.5,0.5)
        expfog.setExpDensity(0.002)
        self.render.setFog(expfog)
 
        # Our sky
        skysphere = self.loader.loadModel('volume1/models/blue-sky-sphere')
        skysphere.setEffect(CompassEffect.make(self.render))
        skysphere.setScale(0.08)
        # NOT render or you'll fly through the sky!:
        skysphere.reparentTo(self.camera) 
 
        # Our lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.6, .6, .6, 1))
        self.render.setLight(self.render.attachNewNode(ambientLight))
 
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        dlnp = self.render.attachNewNode(directionalLight)
        dlnp.setPos(0,0,260)
        dlnp.setHpr(225,-60,0)#lookAt(self.player)
        self.render.setLight(dlnp)
 
        # water
        self.water = self.loader.loadModel('volume1/models/square.egg')
        self.water.setSx(self.worldsize* 2)
        self.water.setSy(self.worldsize*2)
        self.water.setPos(self.worldsize/2,self.worldsize/2,18) # sea level
        self.water.setTransparency(TransparencyAttrib.MAlpha) 
        nTS = TextureStage('1')
        self.water.setTexture(nTS,self.loader.loadTexture('volume1/models/water.png'))
        self.water.setTexScale(nTS,4)
        self.water.reparentTo(self.render)
        LerpTexOffsetInterval(self.water,200,(1,0),(0,0),textureStage=nTS).loop()
 
    def setGroundMask(self,mask):
        self.world.setCollideMask(mask)
 
    def setWaterMask(self,mask):
        self.water.setCollideMask(mask)
 
    def getSize(self):
        return self.worldsize

Essentially, everything player related (including the model) is in the new class above. There are some changes to watch out for though. First, notice the use of ‘setFluid’ methods in place of ‘set’. These methods are useful when dealing with fast moving objects. You may have noticed the occasional collision blip in Issue 4. This happens when an object is moving so fast and so far frame by frame that it skips over the collision point. The player might be slightly above the terrain while, in the next frame, slightly below. Thus missing the collision point. Instead of simply moving an object (as setPos/X/Y/Z do), setFluidPos/X/Y/Z methods ‘slide’ it from its old position to its new, guaranteeing no collisions are missed. There is another piece of the puzzle to make this work which we will discuss when we reach game.py below.

We have also doubled the maximum speed the player can fly at – for no reason other than for fun! Notice also that we have comments in the code by using triple-quotes (“”) instead of the usual hash (#). Triple quote comments can run over multiple lines whereas hash comments cannot. They also help with automatic code documentation – something for a future Issue but note it is what we used to create the design diagram earlier in this Issue.

Lastly, the ‘lookAtMe’ method sets a camera correctly with regards to the player. It’s a replacement to our old ‘updateCamera’ (essentially) but we have added a bit more magic in the camera trickery. The camera and player will both now roll during play and our new relative positioning gives some nice effects. The video below shows the new camera setup in action.

Quick Nav: Previous page | Next page |

Index: page 1 | page 2 | page 3 | page 4 | page 5 |
All: View full Issue on one Page