mouse controls head/camera , compass

I wrote this awhile ago to experiment with controling the cameraa with the mouse. The amount you can turn your head/twist your neck is limited. There is a compass to show which way the player body is facing and head is facing.

Mainly uploading it to save it off computer.

#playing with spin speed


import direct.directbase.DirectStart
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
from direct.task.Task import Task
from direct.showbase.DirectObject import DirectObject
import random, sys, os, math
from pandac.PandaModules import *
from direct.gui.OnscreenImage import OnscreenImage
from pandac.PandaModules import TransparencyAttrib
from direct.gui.DirectGui import *




# Figure out what directory this program is in.
MYDIR=os.path.abspath(sys.path[0])
MYDIR=Filename.fromOsSpecific(MYDIR).getFullpath()

# Function to put instructions on the screen.
def addInstructions(pos, msg):
    return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                    pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)

# Function to put title on the screen.
def addTitle(text):
    return OnscreenText(text=text, style=1, fg=(1,1,1,1),
                    pos=(1.3,-0.95), align=TextNode.ARight, scale = .07)

                    

class World(DirectObject):
                  
                        
    def __init__(self):
        
        self.keyMap = {"run":0, "left":0, "right":0, "backward":0, "turn-left":0, "turn-right":0, "look":1, "forward":0}
        
        self.SPIN_RATE = 80  #how fast you can turn/spin around
        self.PITCH_RATE = 1 #how fast you can raise/lower your head
        self.FORWARD_SPEED = 2
        self.BACKWARD_SPEED = 1
        self.WALK_SPEED = 2
        self.RUN_SPEED = 10
        self.prevtime = 0         #initialize elapse time variable
        self.neckTwist = 0
        
        self.title = addTitle("My Template")
        self.inst1 = addInstructions(0.95, "[ESC]: Quit")
        self.inst2 = addInstructions(0.90, "[A]: Move Left")
        self.inst3 = addInstructions(0.85, "[D]: Move Right")
        self.inst4 = addInstructions(0.80, "[W]: Move Forward")
        self.inst4 = addInstructions(0.75, "[S]: Move Backward")
        self.inst6 = addInstructions(0.70, "[RMB]:  Toggle camera control on/off ")
        self.inst6 = addInstructions(0.65, "[Mouse]:  Look Around")
        self.inst8 = addInstructions(0.55, "")
        self.inst9 = addInstructions(0.50, "")
        


        #place mouse cursor at center of screen at start
        base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2)

        #Load the first environment model
        self.environ = loader.loadModel("models/ground")
        self.environ.reparentTo(render)
        self.environ.setPos(0,0,0)
 
        texHcompass = loader.loadTexture("textures/hCompass.png")
        texBcompass = loader.loadTexture("textures/bCompass.png")
        texcompass = loader.loadTexture("textures/compass.png")
 
        self.Hcompass = loader.loadModel("models/tPlane")
        self.Hcompass.setTexture(texHcompass,1)
        self.Hcompass.reparentTo(base.camera)
        self.Hcompass.setPos(0.6,2,0.4)
        self.Hcompass.setScale(0.050)
        
        self.Bcompass = loader.loadModel("models/tPlane")
        self.Bcompass.setTexture(texBcompass,1)
        self.Bcompass.reparentTo(base.camera)
        self.Bcompass.setPos(0.6,2,0.4)
        self.Bcompass.setScale(0.065)    

        self.compass = loader.loadModel("models/tPlane")
        self.compass.setTexture(texcompass,1)
        self.compass.reparentTo(base.camera)
        self.compass.setPos(0.6,2,0.4)
        self.compass.setScale(0.065)    
 
 
 
 
 
 
 
 
 
       
        #set the camera
        base.disableMouse()
        base.camera.reparentTo(render)
        base.camera.setPos(0,0,1)
        #output camera info
        CameraPosition = "Camera Position: " + str(base.camera.getPos()) +"  H: " + str(base.camera.getH()) +"  P: " + str(base.camera.getP())
        self.inst9.setText(CameraPosition)
        
        #player's body
        self.bodyNP = loader.loadModel("models/cube")
        self.bodyNP.reparentTo(render)
        self.bodyNP.setPos(0,0,1)
        #output player info
        PlayerPosition = "Player Position: " + str(self.bodyNP.getPos()) +"  H: " + str(self.bodyNP.getH()) +"  P: " + str(self.bodyNP.getP())
        self.inst8.setText(PlayerPosition)

        #set up some objects
        self.object2NP = loader.loadModel("models/cube")
        self.object2NP.reparentTo(render)
        
        self.object2NP.setPos(15,0,0)

        self.object3NP = loader.loadModel("models/cube")
        self.object3NP.reparentTo(render)
        self.object3NP.setPos(0,25,0)

        #set lighting
        self.alight = AmbientLight('alight')
        self.alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
        self.alnp = render.attachNewNode(self.alight)

        self.plightN = PointLight('plightN')
        self.plightN.setColor(VBase4(0.8, 0.8, 0.8, 1))
        self.plightNP = self.bodyNP.attachNewNode(self.plightN)
        self.plightNP.setPos(2,2,2)

        self.lightBulbNP = loader.loadModel("models/cube")
        self.lightBulbNP.reparentTo(self.plightNP)
        self.lightBulbNP.setPos(0,0,0)
        self.lightBulbNP.setScale(0.2,0.2,0.2)

        #choose objects affected by lighting
        render.setLight(self.alnp)
        self.bodyNP.setLight(self.plightNP)
        
        #set up keyboard input response
        self.accept("escape", sys.exit)
        self.accept("q", self.setKey, ["left",1])
        self.accept("e", self.setKey, ["right",1])
        self.accept("w", self.setKey,["forward", 1]) 
        self.accept("s", self.setKey, ["backward",1])        
        self.accept("a", self.setKey, ["turn-left",1])
        self.accept("d", self.setKey, ["turn-right",1])
        self.accept("q-up", self.setKey, ["left",0])
        self.accept("e-up", self.setKey, ["right",0])
        self.accept("w-up", self.setKey, ["forward",0])
        self.accept("s-up", self.setKey, ["backward",0])             
        self.accept("a-up", self.setKey, ["turn-left",0])
        self.accept("d-up", self.setKey, ["turn-right",0])
        self.accept("mouse3", self.camToggle)  
        self.accept("space", self.runToggle)
        
        #update every frame       
        #taskMgr.add(self.keepHewRange, "keepHewRangeTask")
        taskMgr.add(self.moving,"movingTask")
    
    def moving (self, task):
        
        if ((self.keyMap["look"]!=0) and base.mouseWatcherNode.hasMouse()) :
            self.MmoveHead()
        self.moveBody()
        self.Hcompass.setR(base.camera.getH()*-1)
        self.Bcompass.setR(self.bodyNP.getH()*-1)        
        return Task.cont
        
    def keepHewRange (self, task):
        #keeps Hew between 0 and 360
        if self.bodyNP.getH()>360:
           self.bodyNP.setH(self.bodyNP.getH()-360) 
        if self.bodyNP.getH()<0:
           self.bodyNP.setH(self.bodyNP.getH()+360)   
        if base.camera.getH()>360:
           base.camera.setH(base.camera.getH()-360) 
        if base.camera.getH()<0:
           base.camera.setH(base.camera.getH()+360) 
          
        return Task.cont

    def runToggle (self):
        if self.keyMap["run"] == 1:
            self.FORWARD_SPEED = self.WALK_SPEED  
            self.keyMap["run"] = 0
        else: 
            self.keyMap["run"] = 1
            self.FORWARD_SPEED = self.RUN_SPEED

                                      
    def camToggle (self):
        if self.keyMap["look"] == 0:
            self.keyMap["look"] = 1
        else:
            self.keyMap["look"] = 0
                
    def setKey(self, key, value):
        self.keyMap[key] = value
        #print key, " = ", value #testing
 
    def moveBody(self):

        
        #used to compensate for differences in the time a task takes                       
        elapsed = 0.02
        #print "Elapsed: ", elapsed
        
        if (self.keyMap["turn-left"]!=0):
            self.bodyNP.setH(self.bodyNP.getH() + elapsed*self.SPIN_RATE )
            base.camera.setH(base.camera.getH() + elapsed*self.SPIN_RATE  )
        if (self.keyMap["turn-right"]!=0):
            self.bodyNP.setH(self.bodyNP.getH() - elapsed*self.SPIN_RATE  )
            base.camera.setH(base.camera.getH() - elapsed*self.SPIN_RATE  )
        if (self.keyMap["forward"]==1):
            forward = self.bodyNP.getNetTransform().getMat().getRow3(1)
            forward.setZ(0)
            forward.normalize()
            oldPos = self.bodyNP.getPos() #testing
            self.bodyNP.setPos(self.bodyNP.getPos() + forward*elapsed*self.FORWARD_SPEED) 
            newPos = self.bodyNP.getPos() #teting
            distanceF = newPos - oldPos #teting
            print "DistanceF: ", distanceF #teting  
        if (self.keyMap["backward"]!=0):
            backward = self.bodyNP.getNetTransform().getMat().getRow3(1)
            backward.setZ(0)
            backward.normalize()
            self.bodyNP.setPos(self.bodyNP.getPos() - backward*elapsed*self.BACKWARD_SPEED)            
        if (self.keyMap["left"]!=0):
            left = self.bodyNP.getNetTransform().getMat().getRow3(0)
            left.setZ(0)
            left.normalize()
            oldPosL = self.bodyNP.getPos() #testing
            self.bodyNP.setPos(self.bodyNP.getPos() - left*elapsed*6 ) 
            newPosL = self.bodyNP.getPos() #teting   
            distanceL = newPosL - oldPosL #teting
            print "DistanceL: ", distanceL #teting            
        if (self.keyMap["right"]!=0):
            right = self.bodyNP.getNetTransform().getMat().getRow3(0)
            right.setZ(0)
            right.normalize()
            self.bodyNP.setPos(self.bodyNP.getPos() + right*elapsed*6 )
 
        base.camera.setPos(self.bodyNP.getPos())

        PlayerPosition = "Player Position: " + str(self.bodyNP.getPos()) +"  H: " + str(self.bodyNP.getH()) +"  P: " + str(self.bodyNP.getP())
        self.inst8.setText(PlayerPosition)
        CameraPosition = "Camera Position: " + str(base.camera.getPos()) +"  H: " + str(base.camera.getH()) +"  P: " + str(base.camera.getP())
        self.inst9.setText(CameraPosition)
        
    def MmoveHead(self):
        mpos = base.mouseWatcherNode.getMouse()
        
        #pitch
        self.camPitch=base.camera.getP()

        fUpOrDown = mpos.getY() #a negative fUD is focus Down
        cPitch = self.PITCH_RATE * fUpOrDown * abs(fUpOrDown)
        if  (self.camPitch + cPitch) < 89 and (self.camPitch + cPitch) > -65 :
            oldP = self.camPitch #testing
            base.camera.setP(self.camPitch + cPitch) 
            newP = base.camera.getP() #testing
            changeP = oldP-newP#testing
            #print
            #print "Change Pitch: ", changeP #testing
            #print "Pitch: ", self.camPitch #testing
            #print
        
        #hew
        self.neckTwist = base.camera.getH() - self.bodyNP.getH()
                
        fLR = mpos.getX() #focus on the left or right
        cHew = 22*fLR*abs(fLR)  #can be + or -
        
        if (abs(self.neckTwist + cHew*-1)) <45.00:
            base.camera.setH(base.camera.getH() + cHew*-1)

        print "cHEW*-1", cHew*-1
        print "camera hew: ",base.camera.getH()
        print "body hew: ",self.bodyNP.getH()
        print "NeckTwist", self.neckTwist
        print 
        

   
 
     

                                
         
              
                   
        PlayerPosition = "Player Position: " + str(self.bodyNP.getPos()) +"  H: " + str(self.bodyNP.getH()) +"  P: " + str(self.bodyNP.getP())
        self.inst8.setText(PlayerPosition)
        CameraPosition = "Camera Position: " + str(base.camera.getPos()) +"  H: " + str(base.camera.getH()) +"  P: " + str(base.camera.getP())
        self.inst9.setText(CameraPosition)




            
w = World()
run()