Exemple #1
0
class Speedometer(DirectObject):

    def __init__(self):
        self.initSpeedometer()

    def initSpeedometer(self):
        """Initialize display of the Speedometer."""

        #Load image of the speedometer on the screen.
        ppp = ( -1, 0, -0.7 )
        self.spdm = OnscreenImage(image = 'Resources/Images/speedometer.png', scale=0.25, pos = ppp )
        self.spdm.setTransparency(TransparencyAttrib.MAlpha) #Enable Transparency

        #Load image of the speedometer's pointer on the screen.
        self.pointer = OnscreenImage(image = 'Resources/Images/needle.png', scale=0.25, pos = ppp )
        self.pointer.setTransparency(TransparencyAttrib.MAlpha) #Enable Transparency
        self.updateSpeedometer(0)

    def updateSpeedometer(self, speed):
        """Update indicator of speed on the speedometer, i.e, angle of the pointer.
            - mainPlayerSpeed: Current speed of the player.
            - maxSpeed: maxSpeed of the player."""

        #Set range of the movement of the pointer, according to the image of the speedometer.
        minAngle, maxAngle = 0 , 270
        maxSpeed = 280
                
        #Calculate the new current angle of the pointer.
        currentAngle = (speed - 46) * maxAngle / maxSpeed

        #Set new rotation to the pointer.
        self.pointer.setR(currentAngle)
Exemple #2
0
class Speedometer(DirectObject):
    def __init__(self):
        self.initSpeedometer()

    def initSpeedometer(self):
        """Initialize display of the Speedometer."""

        #Load image of the speedometer on the screen.
        ppp = (-1, 0, -0.7)
        self.spdm = OnscreenImage(image='Resources/Images/speedometer.png',
                                  scale=0.25,
                                  pos=ppp)
        self.spdm.setTransparency(
            TransparencyAttrib.MAlpha)  #Enable Transparency

        #Load image of the speedometer's pointer on the screen.
        self.pointer = OnscreenImage(image='Resources/Images/needle.png',
                                     scale=0.25,
                                     pos=ppp)
        self.pointer.setTransparency(
            TransparencyAttrib.MAlpha)  #Enable Transparency
        self.updateSpeedometer(0)

    def updateSpeedometer(self, speed):
        """Update indicator of speed on the speedometer, i.e, angle of the pointer.
            - mainPlayerSpeed: Current speed of the player.
            - maxSpeed: maxSpeed of the player."""

        #Set range of the movement of the pointer, according to the image of the speedometer.
        minAngle, maxAngle = 0, 270
        maxSpeed = 280

        #Calculate the new current angle of the pointer.
        currentAngle = (speed - 46) * maxAngle / maxSpeed

        #Set new rotation to the pointer.
        self.pointer.setR(currentAngle)
Exemple #3
0
class Car():
    def __init__(self,world,space,pos):
        #variables
        self.world=world
        self.world.setContactSurfaceLayer(0.01)
        self.space=space
        self.turn=False
        self.turnspeed=0.0
        self.turnangle=0.0
        self.carOrientation=1
        self.acceleration=False
        self.maxSpeed=0
        self.accForce=0
        #Body of the our car - similar the boxes
        self.box = loader.loadModel("car")
        self.box.setPos(pos)
        self.box.setColor(1,0.5,0.5)
        self.box.reparentTo(render)     
        self.body=OdeBody(self.world)
        M = OdeMass()
        M.setBox(4, 1.8, 4, 0.5)
        self.body.setMass(M)
        self.body.setPosition(self.box.getPos(render))
        self.bodyGeom = OdeBoxGeom(self.space, 1,3,1)
        self.bodyGeom.setBody(self.body)
        
        self.joints=[] #suspensions
        self.wheelsbody=[] #wheels body
        self.wheelsgeom=[] #wheels geometry
        self.wheels=[]     #wheels visualisation
        for i in range(4):
            #set physic of the wheel
            self.wheelsbody.append(OdeBody(self.world))
            M = OdeMass()
            M.setCylinder(2,2,1, 0.4)
            self.wheelsbody[i].setMass(M)
            self.wheelsbody[i].setQuaternion(Quat(0.7,0,0.7,0))
            self.wheelsbody[i].setFiniteRotationMode(1)
            #self.wheelsgeom.append(OdeCylinderGeom(self.space, 1,0.4))
            self.wheelsgeom.append(OdeSphereGeom(self.space, 1))
            self.wheelsgeom[i].setBody(self.wheelsbody[i])  
            self.wheelsgeom[i].setCategoryBits(BitMask32(0x00000002))
            #add hinge2 joint, wich simulate suspension
            self.joints.append(OdeHinge2Joint(self.world))
            self.joints[i].attachBodies(self.body,self.wheelsbody[i])
            #min/max angle for the wheel. Set min=max for stable turn
            self.joints[i].setParamHiStop(0, 0.0)
            self.joints[i].setParamLoStop(0, 0.0)
            #Error reduction parameter of suspension
            self.joints[i].setParamSuspensionERP(0, 0.9)
            #Blending of forces - in this case influences rigidity of a suspension
            self.joints[i].setParamSuspensionCFM(0, 0.001)            
            #self.joints[i].setParamFudgeFactor(0,0.1)
            #axis of joint: set one - vertical, and one - horisontal
            self.joints[i].setAxis1(0,0,1)
            self.joints[i].setAxis2(1,0,0)            
            #visual mesh of wheel
            self.wheels.append(loader.loadModelCopy("wheel"))
            self.wheels[i].setColor(1,0.5,0.5)
            self.wheels[i].setScale(1,1,2)
            self.wheels[i].reparentTo(render)
        
        wheelDistance = 3.1 #1.8
        bodyDistance = 5.2 # 1.1
        #bodyHeight = 2.5
        bodyHeight= -1.5#car add
        #set wheels to start position
        self.wheelsbody[0].setPosition(pos.getX()-wheelDistance,pos.getY()+bodyDistance,pos.getZ()+bodyHeight)
        self.wheelsbody[1].setPosition(pos.getX()-wheelDistance,pos.getY()-bodyDistance,pos.getZ()+bodyHeight)
        self.wheelsbody[2].setPosition(pos.getX()+wheelDistance,pos.getY()+bodyDistance,pos.getZ()+bodyHeight)
        self.wheelsbody[3].setPosition(pos.getX()+wheelDistance,pos.getY()-bodyDistance,pos.getZ()+bodyHeight)
        #set joints to start position
        self.joints[0].setAnchor(Vec3(pos.getX()-(wheelDistance-0.2),pos.getY()+bodyDistance,pos.getZ()+bodyHeight))    
        self.joints[1].setAnchor(Vec3(pos.getX()-(wheelDistance-0.2),pos.getY()-bodyDistance,pos.getZ()+bodyHeight))
        self.joints[2].setAnchor(Vec3(pos.getX()+(wheelDistance-0.2),pos.getY()+bodyDistance,pos.getZ()+bodyHeight))
        self.joints[3].setAnchor(Vec3(pos.getX()+(wheelDistance-0.2),pos.getY()-bodyDistance,pos.getZ()+bodyHeight))
        #Set surface types for the wheels
        self.space.setSurfaceType(self.wheelsgeom[0],1)
        self.space.setSurfaceType(self.wheelsgeom[2],1)
        self.space.setSurfaceType(self.wheelsgeom[1],2)
        self.space.setSurfaceType(self.wheelsgeom[3],2)
        
        self.maxVelocity = 65
        self.maxSpeed=50
        self.accForce=500
        
        # register actions and tasks
        axis=[1,3]
        axis2=[1,3,0,2]
        base.accept('w', self.Accel,[self.maxVelocity, 40,axis])
        base.accept('w-up', self.Accel,[0, 15,axis2])
        base.accept('s', self.Accel,[-25, 40,axis])
        base.accept('s-up', self.Accel,[0, 15,axis2])
        base.accept('space', self.Accel, [0, 200,axis2])
        base.accept('space-up', self.Accel, [0, 15,axis2])
        base.accept('shift', self.Accel, [0, 50,axis2])
        base.accept('shift-up', self.Accel, [0, 15,axis2])
        base.accept('d', self.Turn,[True,0.01])       
        base.accept('a', self.Turn,[True,-0.01])       
        base.accept('d-up', self.Turn,[False,0.01])       
        base.accept('a-up', self.Turn,[False,-0.01])
        taskMgr.add(self.TurnTask,"Rule Car")
        taskMgr.add(self.JetTask,"Jet Task")
        taskMgr.doMethodLater(0.5,self.checkRotation, "checkRotation")
        #Setup the camera basis
        self.camPosNode = self.box.attachNewNode('camPosNode')
        self.camPosNode.setPos(0,6,-2)
        self.camLookatNode = self.box.attachNewNode('camLookatNode')
        self.camLookatNode.setPos(0,0,2)
        base.camLens.setFar(10000)
        
        #spedometer
        spdm = OnscreenImage(image = 'spdm.png', scale=0.25, pos = (1, 0, -0.6))
        spdm.setTransparency(TransparencyAttrib.MAlpha)
        self.pointer = OnscreenImage(image = 'spdm_pointer.png', scale=0.25, pos = (1, 0, -0.6))
        self.pointer.setTransparency(TransparencyAttrib.MAlpha)
        self.lastPos = Vec3(0,0,0)
    
    def addCamdist(self, v):
      self.camDistance += v
      print "new camdistance:", self.camDistance
    
    #acceleration function
    def Accel(self, aspect, force, axis):
        for i in [1,3,0,2]:
            self.joints[i].setParamFMax(1, 0)
        #We use two different methods for move forward and backward
        #Forward - "jet engine" - add force to the body of the car
        #Backward - angular engine - add angular speed to the wheels
        if aspect>0:
            self.acceleration=True
        else:
            self.acceleration=False
            for i in axis:
                #set angular engine speed
                self.joints[i].setParamVel(1,aspect*self.carOrientation)
                #and force to it
                self.joints[i].setParamFMax(1, force)
    #check car orientation, and change control according to it
    def checkRotation(self,task):
        oldO=self.carOrientation
        if abs(int(self.box.getR()))<90:
            self.carOrientation=1
        else:
            self.carOrientation=-1
        if oldO<>self.carOrientation:
            self.camPosNode.setZ(-self.camPosNode.getZ())
            for i in [1,3,0,2]:
                self.joints[i].setParamVel(1,-self.joints[i].getParamVel(1))
        return task.again
    #turn wheels - set variables
    def Turn(self,enabled,aspect):
        self.turn=enabled
        self.turnspeed=aspect
    #immediately, turn wheels here
    def TurnTask(self,task):
        #calculate angle
        if not self.turn:
            if self.turnangle>0:
                self.turnspeed=-0.01*self.carOrientation
            if self.turnangle<0:
                self.turnspeed=0.01*self.carOrientation
            if -0.01<self.turnangle<0.01:
                self.turnangle=0;
        self.turnangle=self.turnangle+self.turnspeed*self.carOrientation
        if self.turnangle>0.3:
            self.turnangle=0.3
        if self.turnangle<-0.3:
            self.turnangle=-0.3
        # and set angle to the front wheels
        self.joints[0].setParamHiStop(0, self.turnangle)
        self.joints[0].setParamLoStop(0, self.turnangle)
        self.joints[2].setParamHiStop(0, self.turnangle)
        self.joints[2].setParamLoStop(0, self.turnangle)
        # will fix wheel position a bit better
        for i in xrange(4):
          self.wheelsbody[i].setFiniteRotationAxis(self.joints[i].getAxis2())        
        return task.cont
    #task for jet engeene    
    def JetTask(self,task):
        if self.acceleration<>0:
            if self.maxSpeed>self.body.getLinearVel().length():
                self.body.addRelForce(0,self.accForce,0)
        return task.cont
    #sync our visible geometry with them physic bodyes
    def Sync(self):
        self.box.setPos(render, self.body.getPosition())
        self.box.setQuat(render,Quat(self.body.getQuaternion()))
        for i in range(4):
            self.wheels[i].setPos(render, self.wheelsbody[i].getPosition())
            self.wheels[i].setQuat(render,Quat(self.wheelsbody[i].getQuaternion()))
        # update the camera
        camVec = self.camPosNode.getPos(render) - self.body.getPosition()
        
        camDistance = Vec2(-5, 3)
        targetCamPos = self.body.getPosition() + camVec * camDistance.getX() + Vec3(0,0,camDistance.getY())
        camLookat = self.camLookatNode.getPos(render)
        dPos = targetCamPos - base.camera.getPos(render)
        dt = globalClock.getDt()
        base.camera.setPos(base.camera.getPos(render) + dPos * dt / .5)
        base.camera.lookAt(camLookat)
        # the speedometer pointer
        curPos = self.box.getPos(render)
        vel = (self.lastPos - curPos).length() * 6000 / self.maxVelocity
        self.lastPos = curPos
        dr=vel-self.pointer.getR()
        if dr>30:
            dr=30
        dr=dr*0.1
        self.pointer.setR(self.pointer.getR()+dr)
Exemple #4
0
class Drive(ShowBase):
	def __init__(self):
		ShowBase.__init__(self)
		
		#Setup
		scene = BulletWorld()
		scene.setGravity(Vec3(0, 0, -9.81))
		base.setBackgroundColor(0.6,0.9,0.9)
		fog = Fog("The Fog")
		fog.setColor(0.9,0.9,1.0)
		fog.setExpDensity(0.003)
		render.setFog(fog)
		#Lighting
		
		#Sun light
		sun = DirectionalLight("The Sun")
		sun_np = render.attachNewNode(sun)
		sun_np.setHpr(0,-60,0)
		render.setLight(sun_np)
		
		#Ambient light
		amb = AmbientLight("The Ambient Light")
		amb.setColor(VBase4(0.39,0.39,0.39, 1))
		amb_np = render.attachNewNode(amb)
		render.setLight(amb_np)
		
		#Variables
		self.gear = 0
		
		self.start = 0
		
		self.Pbrake = 0
		
		self.terrain_var = 1
		
		self.time = 0
		
		self.headlight_var = 0
		
		self.RPM = 0
		
		self.clutch = 0
		
		self.carmaxspeed = 100 #KPH
		
		self.carmaxreversespeed = -40 #KPH
		
		self.steering = 0
		
		
		#Functions
		def V1():
			camera.setPos(0.25,-1.2,0.5)
			camera.setHpr(0,-13,0)
			
		def V2():
			camera.setPos(0,-15,3)
			camera.setHpr(0,-10,0)
			
		def V3():
			camera.setPos(0,0,9)
			camera.setHpr(0,-90,0)
			
		def up():
			self.gear = self.gear -1
			if self.gear < -1:
				self.gear = -1
				
		def down():
			self.gear = self.gear +1
			if self.gear > 1:
				self.gear = 1
				
		def start_function():
			self.start = 1
			self.start_sound.play()
			self.engine_idle_sound.play()
			self.RPM = 1000
			
		def stop_function():
			self.start = 0
			self.engine_idle_sound.stop()
				
		def parkingbrake():
			self.Pbrake = (self.Pbrake + 1) % 2
			
		def rotate():
			Car_np.setHpr(0, 0, 0)
			
		def horn():
			self.horn_sound.play()
			
		def set_time():
			if self.time == -1:
				sun.setColor(VBase4(0.4, 0.3, 0.3, 1))
				base.setBackgroundColor(0.8,0.7,0.7)
			if self.time == 0:
				sun.setColor(VBase4(0.7, 0.7, 0.7, 1))
				base.setBackgroundColor(0.6,0.9,0.9)
			if self.time == 1:
				sun.setColor(VBase4(0.2, 0.2, 0.2, 1))
				base.setBackgroundColor(0.55,0.5,0.5)
			if self.time == 2:
				sun.setColor(VBase4(0.02, 0.02, 0.05, 1))
				base.setBackgroundColor(0.3,0.3,0.3)
				
			if self.time == -2:
				self.time = -1
			if self.time == 3:
				self.time = 2
			
		def time_forward():
			self.time = self.time + 1
			
		def time_backward():
			self.time = self.time -1
			
		def set_terrain():
			if self.terrain_var == 1:
				self.ground_model.setTexture(self.ground_tex, 1)
				self.ground_model.setScale(3)
			if self.terrain_var == 2:
				self.ground_model.setTexture(self.ground_tex2, 1)
				self.ground_model.setScale(3)
			if self.terrain_var == 3:
				self.ground_model.setTexture(self.ground_tex3, 1)
				self.ground_model.setScale(4)
				
			if self.terrain_var == 4:
				self.terrain_var = 1
			if self.terrain_var == 0:
				self.terrain_var = 3
			
		def next_terrain():
			self.terrain_var = self.terrain_var + 1
			
		def previous_terrain():
			self.terrain_var = self.terrain_var - 1
			
		def show_menu():
			self.menu_win.show()
			self.a1.show()
			self.a2.show()
			self.a3.show()
			self.a4.show()
			self.t1.show()
			self.t2.show()
			self.ok.show()
			self.exit_button.show()
			
		def hide_menu():
			self.menu_win.hide()
			self.a1.hide()
			self.a2.hide()
			self.a3.hide()
			self.a4.hide()
			self.ok.hide()
			self.t1.hide()
			self.t2.hide()
			self.exit_button.hide()
		
		def Menu():
			self.menu_win = OnscreenImage(image = "Textures/menu.png", pos = (0.9,0,0), scale = (0.5))
			self.menu_win.setTransparency(TransparencyAttrib.MAlpha)
			
			#The Arrow Buttons
			self.a1 = DirectButton(text = "<", scale = 0.2, pos = (0.55,0,0.25), command = previous_terrain)
			self.a2 = DirectButton(text = ">", scale = 0.2, pos = (1.15,0,0.25), command = next_terrain)
			self.a3 = DirectButton(text = "<", scale = 0.2, pos = (0.55,0,0.0), command = time_backward)
			self.a4 = DirectButton(text = ">", scale = 0.2, pos = (1.15,0,0.0), command = time_forward)
			
			#The Text
			self.t1 = OnscreenText(text = "Terrain", pos = (0.85,0.25,0), scale = 0.1, fg = (0.4,0.4,0.5,1))
			self.t2 = OnscreenText(text = "Time", pos = (0.85,0,0), scale = 0.1, fg = (0.4,0.4,0.5,1))
			
			#The Buttons
			self.ok = DirectButton(text = "Okay", scale = 0.11, pos = (0.87,0,-0.25), command = hide_menu)
			self.exit_button = DirectButton(text = "Quit", scale = 0.11, pos = (0.87,0,-0.42), command = sys.exit)
			
		Menu()
		
		
		def take_screenshot():
			base.screenshot("Screenshot")
			
		def set_headlights():
			if self.headlight_var == 1:
				Headlight1.setColor(VBase4(9.0,8.9,8.9,1))
				Headlight2.setColor(VBase4(9.0,8.9,8.9,1))
			if self.headlight_var == 0:
				Headlight1.setColor(VBase4(0,0,0,1))
				Headlight2.setColor(VBase4(0,0,0,1))
			
		def headlights():
			self.headlight_var = (self.headlight_var + 1) % 2
			
		def update_rpm():
			
			#Simulate RPM
			if self.start == 1:
				if self.gear == 0:
					self.RPM = self.RPM - self.RPM / 400
				else:
					self.RPM = self.RPM + self.carspeed / 9
					self.RPM = self.RPM - self.RPM / 200
			
			#Reset RPM to 0 when engine is off
			if self.start == 0:
				if self.RPM > 0.0:
					self.RPM = self.RPM - 40
				if self.RPM < 10:
					self.RPM = 0.0
								
			#Idle RPM power
			if self.start == 1:
				if self.RPM < 650:
					self.RPM = self.RPM + 4
				if self.RPM < 600:
					self.clutch = 1
				else:
					self.clutch = 0
					
			#RPM limit		
			if self.RPM > 6000:
				self.RPM = 6000
				

		#Controls 
		inputState.watchWithModifiers("F", "arrow_up")
		inputState.watchWithModifiers("B", "arrow_down")
		inputState.watchWithModifiers("L", "arrow_left")
		inputState.watchWithModifiers("R", "arrow_right")
		
		do = DirectObject()
		
		do.accept("escape", show_menu)
		do.accept("1", V1)
		do.accept("2", V2)
		do.accept("3", V3)
		do.accept("page_up", up)
		do.accept("page_down", down)
		do.accept("x-repeat", start_function)
		do.accept("x", stop_function)
		do.accept("p", parkingbrake)
		do.accept("backspace", rotate)
		do.accept("enter", horn)
		do.accept("f12", take_screenshot)
		do.accept("h", headlights)
		
		#The ground
		self.ground = BulletPlaneShape(Vec3(0, 0, 1,), 1)
		self.ground_node = BulletRigidBodyNode("The ground")
		self.ground_node.addShape(self.ground)
		self.ground_np = render.attachNewNode(self.ground_node)
		self.ground_np.setPos(0, 0, -2)
		scene.attachRigidBody(self.ground_node)
		
		self.ground_model = loader.loadModel("Models/plane.egg")
		self.ground_model.reparentTo(render)
		self.ground_model.setPos(0,0,-1)
		self.ground_model.setScale(3)
		self.ground_tex = loader.loadTexture("Textures/ground.png")
		self.ground_tex2 = loader.loadTexture("Textures/ground2.png")
		self.ground_tex3 = loader.loadTexture("Textures/ground3.png")
		self.ground_model.setTexture(self.ground_tex, 1)
		
		#The car
		Car_shape = BulletBoxShape(Vec3(1, 2.0, 1.0))
		Car_node = BulletRigidBodyNode("The Car")
		Car_node.setMass(1200.0)
		Car_node.addShape(Car_shape)
		Car_np = render.attachNewNode(Car_node)
		Car_np.setPos(0,0,3)
		Car_np.setHpr(0,0,0)
		Car_np.node().setDeactivationEnabled(False)
		scene.attachRigidBody(Car_node)
		
		Car_model = loader.loadModel("Models/Car.egg")
		Car_model.reparentTo(Car_np)
		Car_tex = loader.loadTexture("Textures/Car1.png")
		Car_model.setTexture(Car_tex, 1)
		
		self.Car_sim = BulletVehicle(scene, Car_np.node())
		self.Car_sim.setCoordinateSystem(ZUp)
		scene.attachVehicle(self.Car_sim)
		
		#The inside of the car
		Car_int = loader.loadModel("Models/inside.egg")
		Car_int.reparentTo(Car_np)
		Car_int_tex = loader.loadTexture("Textures/inside.png")
		Car_int.setTexture(Car_int_tex, 1)
		Car_int.setTransparency(TransparencyAttrib.MAlpha)
		
		#The steering wheel
		Sw = loader.loadModel("Models/Steering wheel.egg")
		Sw.reparentTo(Car_np)
		Sw.setPos(0.25,0,-0.025)
		
		#The first headlight
		Headlight1 = Spotlight("Headlight1")
		lens = PerspectiveLens()
		lens.setFov(180)
		Headlight1.setLens(lens)
		Headlight1np = render.attachNewNode(Headlight1)
		Headlight1np.reparentTo(Car_np)
		Headlight1np.setPos(-0.8,2.5,-0.5)
		Headlight1np.setP(-15)
		render.setLight(Headlight1np)
		
		#The second headlight
		Headlight2 = Spotlight("Headlight2")
		Headlight2.setLens(lens)
		Headlight2np = render.attachNewNode(Headlight2)
		Headlight2np.reparentTo(Car_np)
		Headlight2np.setPos(0.8,2.5,-0.5)
		Headlight2np.setP(-15)
		render.setLight(Headlight2np)
		
		#Sounds
		self.horn_sound = loader.loadSfx("Sounds/horn.ogg")
		self.start_sound = loader.loadSfx("Sounds/enginestart.ogg")
		self.engine_idle_sound = loader.loadSfx("Sounds/engineidle.ogg")
		self.engine_idle_sound.setLoop(True)
		self.accelerate_sound = loader.loadSfx("Sounds/enginethrottle.ogg")
				
		#Camera
		base.disableMouse()
		camera.reparentTo(Car_np)
		camera.setPos(0,-15,3)
		camera.setHpr(0,-10,0)
		
		#Wheel function
		def Wheel(pos, np, r, f):
			w = self.Car_sim.createWheel()
			w.setNode(np.node())
			w.setChassisConnectionPointCs(pos)
			w.setFrontWheel(f)
			w.setWheelDirectionCs(Vec3(0, 0, -1))
			w.setWheelAxleCs(Vec3(1, 0, 0))
			w.setWheelRadius(r)
			w.setMaxSuspensionTravelCm(40)
			w.setSuspensionStiffness(120)
			w.setWheelsDampingRelaxation(2.3)
			w.setWheelsDampingCompression(4.4)
			w.setFrictionSlip(50)
			w.setRollInfluence(0.1)
		
		#Wheels	
		w1_np = loader.loadModel("Models/Lwheel")
		w1_np.reparentTo(render)
		w1_np.setColorScale(0,6)
		Wheel(Point3(-1,1,-0.6), w1_np, 0.4, False)
		
		w2_np = loader.loadModel("Models/Rwheel")
		w2_np.reparentTo(render)
		w2_np.setColorScale(0,6)
		Wheel(Point3(-1.1,-1.2,-0.6), w2_np, 0.4, True)
		
		w3_np = loader.loadModel("Models/Lwheel")
		w3_np.reparentTo(render)
		w3_np.setColorScale(0,6)
		Wheel(Point3(1.1,-1,-0.6), w3_np, 0.4, True)
		
		w4_np = loader.loadModel("Models/Rwheel")
		w4_np.reparentTo(render)
		w4_np.setColorScale(0,6)
		Wheel(Point3(1,1,-0.6), w4_np, 0.4, False)
		

		
		#The engine and steering
		def processInput(dt):
			
			#Vehicle properties
			self.steeringClamp = 35.0
			self.steeringIncrement = 70
			engineForce = 0.0
			brakeForce = 0.0
			
			
			#Get the vehicle's current speed
			self.carspeed = self.Car_sim.getCurrentSpeedKmHour()
			
			
			#Engage clutch when in gear 0
			if self.gear == 0:
				self.clutch = 1
			
			
			#Slow the steering when at higher speeds
			self.steeringIncrement = self.steeringIncrement - self.carspeed / 1.5
			
			
			#Reset the steering
			if not inputState.isSet("L") and not inputState.isSet("R"):
				
				if self.steering < 0.00:
					self.steering = self.steering + 0.6
				if self.steering > 0.00:
					self.steering = self.steering - 0.6
					
				if self.steering < 1.0 and self.steering > -1.0:
					self.steering = 0
			
			
			#Slow the car down while it's moving
			if self.clutch == 0:
				brakeForce = brakeForce + self.carspeed / 5
			else:
				brakeForce = brakeForce + self.carspeed / 15
		
			
			#Forward
			if self.start == 1:
				if inputState.isSet("F"):
					self.RPM = self.RPM + 35
					self.accelerate_sound.play()
				if self.clutch == 0:
					
					if self.gear == -1:
						if self.carspeed > self.carmaxreversespeed:	
							engineForce = -self.RPM / 3
							
					if self.gear == 1:
						if self.carspeed < self.carmaxspeed:
							engineForce = self.RPM / 1

			
			#Brake	
			if inputState.isSet("B"):
				engineForce = 0.0
				brakeForce = 12.0
				if self.gear != 0 and self.clutch == 0:
					self.RPM = self.RPM - 20
				
			#Left	
			if inputState.isSet("L"):
				if self.steering < 0.0:
					#This makes the steering reset at the correct speed when turning from right to left
					self.steering += dt * self.steeringIncrement + 0.6
					self.steering = min(self.steering, self.steeringClamp)
				else:
					#Normal steering
					self.steering += dt * self.steeringIncrement
					self.steering = min(self.steering, self.steeringClamp)
			
			#Right	
			if inputState.isSet("R"):
				if self.steering > 0.0:
					#This makes the steering reset at the correct speed when turning from left to right
					self.steering -= dt * self.steeringIncrement + 0.6
					self.steering = max(self.steering, -self.steeringClamp)
				else:
					#Normal steering
					self.steering -= dt * self.steeringIncrement
					self.steering = max(self.steering, -self.steeringClamp)
			
			#Park
			if self.Pbrake == 1:
				brakeForce = 10.0
				if self.gear != 0 and self. clutch == 0:
					self.RPM = self.RPM - 20
				
				
			#Apply forces to wheels	
			self.Car_sim.applyEngineForce(engineForce, 0);
			self.Car_sim.applyEngineForce(engineForce, 3);
			self.Car_sim.setBrake(brakeForce, 1);
			self.Car_sim.setBrake(brakeForce, 2);
			self.Car_sim.setSteeringValue(self.steering, 0);
			self.Car_sim.setSteeringValue(self.steering, 3);
			
			#Steering wheel
			Sw.setHpr(0,0,-self.steering*10)
		
		
		#The HUD
		self.gear_hud = OnscreenImage(image = "Textures/gear_hud.png", pos = (-1,0,-0.85), scale = (0.2))
		self.gear_hud.setTransparency(TransparencyAttrib.MAlpha)
		
		self.gear2_hud = OnscreenImage(image = "Textures/gear2_hud.png", pos = (-1,0,-0.85), scale = (0.2))
		self.gear2_hud.setTransparency(TransparencyAttrib.MAlpha)
		
		self.starter = OnscreenImage(image = "Textures/starter.png", pos = (-1.2,0,-0.85), scale = (0.15))
		self.starter.setTransparency(TransparencyAttrib.MAlpha)
		
		self.park = OnscreenImage(image = "Textures/pbrake.png", pos = (-0.8,0,-0.85), scale = (0.1))
		self.park.setTransparency(TransparencyAttrib.MAlpha)
		
		self.rev_counter = OnscreenImage(image = "Textures/dial.png", pos = (-1.6, 0.0, -0.70), scale = (0.6,0.6,0.4))
		self.rev_counter.setTransparency(TransparencyAttrib.MAlpha)
		
		self.rev_needle = OnscreenImage(image = "Textures/needle.png", pos = (-1.6, 0.0, -0.70), scale = (0.5))
		self.rev_needle.setTransparency(TransparencyAttrib.MAlpha)
		
		self.rev_text = OnscreenText(text = " ", pos = (-1.6, -0.90, 0), scale = 0.05)
		
		self.speedometer = OnscreenImage(image = "Textures/dial.png", pos = (-1.68, 0.0, -0.10), scale = (0.7,0.7,0.5))
		self.speedometer.setTransparency(TransparencyAttrib.MAlpha)
		
		self.speedometer_needle = OnscreenImage(image = "Textures/needle.png", pos = (-1.68, 0.0, -0.10), scale = (0.5))
		self.speedometer_needle.setTransparency(TransparencyAttrib.MAlpha)
		
		self.speedometer_text = OnscreenText(text = " ", pos = (-1.68, -0.35, 0), scale = 0.05)
		
		
		#Update the HUD
		def Update_HUD():
			
			#Move gear selector
			if self.gear == -1:
				self.gear2_hud.setPos(-1,0,-0.785)
			if self.gear == 0:
				self.gear2_hud.setPos(-1,0,-0.85)
			if self.gear == 1:
				self.gear2_hud.setPos(-1,0,-0.91)
				
			#Rotate starter
			if self.start == 0:
				self.starter.setHpr(0,0,0)
			else:
				self.starter.setHpr(0,0,45)	
				
			#Update the parking brake light
			if self.Pbrake == 1:
				self.park.setImage("Textures/pbrake2.png")
				self.park.setTransparency(TransparencyAttrib.MAlpha)
			else:
				self.park.setImage("Textures/pbrake.png")
				self.park.setTransparency(TransparencyAttrib.MAlpha)	
				
			#Update the rev counter
			self.rev_needle.setR(self.RPM/22)	
			rev_string = str(self.RPM)[:4]
			self.rev_text.setText(rev_string+" RPM")
			
			#Update the speedometer
			if self.carspeed > 0.0:
				self.speedometer_needle.setR(self.carspeed*2.5)
			if self.carspeed < 0.0:
				self.speedometer_needle.setR(-self.carspeed*2.5)
			speed_string = str(self.carspeed)[:3]
			self.speedometer_text.setText(speed_string+" KPH")
					
					
						
		#Update the program
		def update(task):
			dt = globalClock.getDt() 
			processInput(dt)
			Update_HUD()
			set_time()
			set_terrain()
			set_headlights()
			update_rpm()
			scene.doPhysics(dt, 5, 1.0/180.0)
			return task.cont
			
		taskMgr.add(update, "Update")
Exemple #5
0
class Jack(HUDElement):
    def __init__(self):
        HUDElement.__init__(self)
        self.dir = ani.model_dir / 'hud' / 'jack'
        self.text_scale = 0.4
        self.text_color = (1, 1, 1, 1)

        self.arc = OnscreenImage(image=panda_path(self.dir / 'arc.png'),
                                 pos=(1.4, 0, -0.45),
                                 parent=aspect2d,
                                 scale=0.075)
        self.arc.setTransparency(TransparencyAttrib.MAlpha)

        self.cue_cartoon = OnscreenImage(
            image=panda_path(self.dir / 'cue.png'),
            parent=aspect2d,
            pos=(0, 0, 0),
            scale=(0.15, 1, 0.01),
        )
        self.cue_cartoon.setTransparency(TransparencyAttrib.MAlpha)
        autils.alignTo(self.cue_cartoon, self.dummy_right, autils.CL, autils.C)
        self.cue_cartoon.setZ(-0.40)

        autils.alignTo(self.arc, self.cue_cartoon, autils.LR, autils.CR)

        self.rotational_point = OnscreenImage(image=panda_path(
            ani.model_dir / 'hud' / 'english' / 'circle.png'),
                                              parent=self.arc,
                                              scale=0.15)
        self.rotational_point.setTransparency(TransparencyAttrib.MAlpha)
        autils.alignTo(self.rotational_point, self.arc, autils.C, autils.LR)

        self.cue_cartoon.wrtReparentTo(self.rotational_point)

        self.text = OnscreenText(
            text="0 deg",
            pos=(-1, -1.4),
            scale=self.text_scale,
            fg=self.text_color,
            align=TextNode.ACenter,
            mayChange=True,
            parent=self.arc,
        )

    def set(self, theta):
        self.text.setText(f"{theta:.1f} deg")
        self.rotational_point.setR(theta)

    def init(self):
        self.show()

    def show(self):
        self.arc.show()
        self.cue_cartoon.show()

    def hide(self):
        self.arc.hide()
        self.cue_cartoon.hide()

    def destroy(self):
        self.hide()
        del self.arc
class MyApp(ShowBase):
    def __init__(self, fStartDirect=True):
        #ConfigVariableBool("fullscreen",0).setValue(1)
        ShowBase.__init__(self) 
        self.loadInitialCamPos()#initialize camera positioning 
        self.assocs=dict()
        self.loadBooleans()
        self.loadLists()
        self.shuffleCards()
        self.loadValues()
        #creates a random sequence of cards we will memorize 
        self.setInputs()
        #set up keyboard and mouse inputs
        self.setUpCollision()
        #sets up collision detection
        self.setUpScene()
        #sets up geometry in the 3D Enviroments
        self.loadSFX()
        self.light=self.setUpPointLight()
        taskMgr.add(self.setUpChest, 'setUpChest')
        #sets up rotating graphic of chest
        
    def loadValues(self):
        self.counter,self.lightCounter,self.fade,self.numFireflies=0,0,0,15
        self.numCards=13
        self.numCardsCopy=copy.copy(self.numCards)
        self.shuffledCardFacesCopy=copy.copy(self.shuffledCardFaces)
        
    def loadLists(self):
        self.cardsPos,self.imageList,self.visitedItems=[],[],[]
        self.buttonList,self.lastCoord,self.fireFlyList=[],[],[]
        self.previousCard,self.nextCard=[],[]
        
    def loadBooleans(self):
        self.toggleChest=False
        self.fadeToggle=False
        self.togglePreviousCard=False
        self.toggleNextCard=False
        self.toggleBar=True
        self.titleText=None
        self.userLocation=None
        
    def loadInitialCamPos(self):
        #we disable our mouse because we be using a different method
        #that will set up our mouse controls 
        base.disableMouse()
        self.camPosx,self.camPosz=15,28
        self.camera.setH(90)
        self.camera.setP(-25)
        self.heading=0
        base.camera.setPos(self.camPosx,0,self.camPosz)
        
    def loadSFX(self):
        self.soundSteps = loader.loadMusic("footsteps.wav")
        #circus in the Sky is a piece written by Uzman Riaz (credit)
        #self.circusInTheSky=loader.loadMusic("circusInTheSky.wav")
        
    def setUpCollision(self):
        #pusher and queue are handlers from when a collision occurs
        self.cTrav = CollisionTraverser()
        self.queue = CollisionHandlerQueue()
        self.pusher = CollisionHandlerPusher()
        #set up scene geometrys
        self.setUpCollisionRay()
        self.setUpCollisionNode()
        
    def setUpPointLight(self):
        taskMgr.doMethodLater(.1, self.createTitleText, 'textFadeInOut')
        #we create multiple point lights to make it appear as if there are
        #'firefly' entities within the chest 
        for n in xrange(self.numFireflies):
            self.generateLights("%fFirefly"%n)
        #sets up a soft ambient light so that our 3D enviroment appears
        #more realistic 
        self.alight = AmbientLight('ambientLight')
        self.alight.setColor(VBase4(.6, .6, .6, 1))
        alnp = render.attachNewNode(self.alight)
        render.setLight(alnp)
        self.treasureChest.setLight(alnp)

    def createTitleText(self,task):
        #task allows up to fade text in and out 
        self.updateFade()
        if self.titleText!=None:
            self.titleText.remove()
        self.titleText=OnscreenText(text="[Click on the chest to begin]",
                                    style=Plain,pos=(0,0),fg=(1,1,1,self.fade))
        if self.toggleChest==True:
            self.titleText.remove()
            return task.done
        return task.again
    
    def generateLights(self,name):
        #generate pointlights and reparenting them to the chest 
        name=PointLight("Light")
        name=render.attachNewNode(name)
        name.setPos(0,0,22)
        name.hide()
        self.modelLight = loader.loadModel("misc/Pointlight.egg.pz")
        self.modelLight.reparentTo(name)
        self.treasureChest.setLight(name)
        self.fireFlyList.append(name)
        
    def setUpChest(self,task):
        if self.toggleChest==True:
            #chest rotates backwards if clicked on
            self.speed=-1.5
        else: self.speed=.5
        #chest rotates forward slowly 
        self.lightCounter+=1
        angle,radius= radians(self.heading),1.2
        x,y,z =(cos(angle)*radius,sin(angle)*radius,sin(angle)*radius)
        self.heading+=self.speed
        self.heading%=360
        self.treasureChest.setH(self.heading)
        if self.lightCounter%7==0:
            for n in xrange(self.numFireflies):
                self.generateFireFlies(x,y,n)
        if abs(self.treasureChest.getH()-360)<2 and self.toggleChest==True:
            #if chest is activated and the chest if facing the camera 
            taskMgr.add(self.moveChest, 'moveChest')
            return task.done 
        else: return Task.cont
        
    def moveChest(self,task):
        #units are calculated so that camera and chest move simultaneously
        #to create smooth transition between frames 
        self.alight.setColor(VBase4(.8, .8, .8, 1))
        self.shiftChestUnits,self.intervals=.1,52.0
        x,y,z=self.treasureChest.getPos()
        newx=x+self.shiftChestUnits
        self.treasureChest.setPos(newx,y,z)
        self.moveCamera()
        if int(x)==self.camPosx-10:
            #if we get within a range of acceptable values
            # we set up our homepage 
            self.homePage()
            return task.done
        else:
            return task.cont
    
    def moveCamera(self):
        self.originalZ,self.targetZ=28.0,22.0
        self.shiftCameraZ=(self.originalZ-self.targetZ)/self.intervals
        self.pitchChange=25.0/self.intervals
        newPitch=self.camera.getP()+self.pitchChange
        newHeight=self.camera.getPos()[2]-self.shiftCameraZ
        camerax,cameray=self.camera.getPos()[0],self.camera.getPos()[1]
        self.camera.setPos(camerax,cameray,newHeight)
        self.camera.setP(newPitch)
        
    def generateFireFlies(self,x,y,n):
        zLowerLimit=21.0
        zHigherLimit=22.0
        light=self.fireFlyList[n]
        self.xFirefly=random.uniform(-x,x)
        self.yFirefly=random.uniform(-y,y)
        self.zFirefly=random.uniform(zLowerLimit,zHigherLimit)
        light.setPos(self.xFirefly,self.yFirefly,self.zFirefly)
        
    def setUpFog(self):
        self.fogDensity=.03
        myFog = Fog("fog")
        myFog.setColor(1,1,1)
        myFog.setExpDensity(self.fogDensity)
        render.setFog(myFog)
        
    def displayHelpPanel(self):
        self.dummyNode1=self.createDummyNode("self.dummyNode1")
        self.dummyNode2=self.createDummyNode("self.dummyNode2")
        self.dummyNode3=self.createDummyNode("self.dummyNode3")
        self.floorPlan=OnscreenImage(
            image="floorplan.png",
            scale=(.4,.25,.55),
            pos=(.7,0,.3))
        self.floorPlan.setTransparency(TransparencyAttrib.MAlpha)
        self.floorPlan.reparentTo(self.dummyNode1)
        self.displayToggleBar()
        self.displayAdjacencies()
        taskMgr.doMethodLater(.1, self.createSubTitle, 'textFadeInOut')
       
    def createSubTitle(self,task):
        self.previousTitlePos=(-1.205,.89)
        self.nextTitlePos=(-1.195,-.43)
        try:
            self.titlePrevious.destroy()
            self.titlePrevious=OnscreenText(
                text="[Previous]",pos=self.previousTitlePos,
                scale=.045,fg=(1,1,1,self.fade))
        except:
            self.titlePrevious=OnscreenText(
                text="[Previous]",pos=self.previousTitlePos,
                scale=.045,fg=(1,1,1,self.fade))
        try :
            self.titleNext.destroy()
            self.titleNext=OnscreenText(
                text="[Next]",pos=self.nextTitlePos,scale=.045,fg=(1,1,1,self.fade))
        except: 
            self.titleNext=OnscreenText(
                text="[Next]",pos=self.nextTitlePos,
                scale=.045,fg=(1,1,1,self.fade))
        return task.again
        
    def createDummyNode(self,name):
        name=render.attachNewNode("2d")
        name.reparentTo(aspect2d)
        return name 

    def displayToggleBar(self):
        self.toggleBarImage=DirectButton(
            image = "hidebar.png",scale=(.07,0.1,.55),pos=(1.17,0,.3),
            relief=None,command=lambda: self.switchDisplays(
                self.toggleBar,self.dummyNode1,self.toggleBarImage,
                "hidebar.png","showbar.png",
                (.07,0.1,.55),(1.17,0,.3)))
        self.togglePreviousBar()
        self.toggleNextBar()
    
    def togglePreviousBar(self):
        self.previousBarPos=(-1.2,0,.57)
        self.togglePreviousBarImage=(DirectButton(
        image = "hidebarshort.png",
        scale=(.07,0.1,.195),pos=self.previousBarPos,relief=None,
        command= lambda: self.switchDisplays(
            self.togglePreviousCard,
            self.dummyNode2,self.togglePreviousBarImage,
            "hidebarshort.png","showbarshort.png",
            (.07,0.1,.195),self.previousBarPos)))
            
    def toggleNextBar(self):
        self.nextBarPos=(-1.2,0,-.7)
        self.toggleNextBarImage=(DirectButton(
        image = "hidebarshort.png",
        scale=(.07,0.1,.195),pos=self.nextBarPos,relief=None,
        command= lambda: self.switchDisplays(
            self.toggleNextCard,self.dummyNode3,self.toggleNextBarImage,
            "hidebarshort.png","showbarshort.png",
            (.07,0.1,.195),self.nextBarPos)))
            
    def switchPreviousCardDisplay(self):
        self.toggleBarPrevious=not(self.toggleBarPrevious)
        
    def displayAdjacencies(self):
        if self.previousCard:
            self.displayPreviousCard()
        if self.nextCard:
            self.displayNextCard()
            
    def displayPreviousCard(self):
        self.previousCardPos=(-1,0,.58)
        self.previousCardTextPos=(-.9,.57)
        prevCard=self.previousCard.split(".")[0]
        self.previousCard=OnscreenImage(
            image=self.previousCard,pos=self.previousCardPos,
            scale=(0.07,0.82,0.12))
        self.previousCard.reparentTo(self.dummyNode2)
        try:
            self.assocPrevText.destroy() 
            self.assocPrevText=OnscreenText(
                text="(%s)"%self.inputs[prevCard],
                pos=self.previousCardTextPos,
                scale=.06,fg=(1,1,1,1),align=TextNode.ALeft)
            self.assocPrevText.reparentTo(self.dummyNode2)
        except:
            self.assocPrevText=OnscreenText(
                text="(%s)"%self.inputs[prevCard],
                pos=self.previousCardTextPos,
                scale=.06,fg=(1,1,1,1),align=TextNode.ALeft)
            self.assocPrevText.reparentTo(self.dummyNode2)
    
    def displayNextCard(self):
        self.nextCardPos=(-1,0,-.685)
        self.nextCardTextPos=(-.9,-.69)
        nextCard=self.nextCard.split(".")[0]
        self.nextCard=OnscreenImage(
            image=self.nextCard,pos=self.nextCardPos,scale=(0.07,0.82,0.12))
        self.nextCard.reparentTo(self.dummyNode3)
        try:
            self.assocNextText.destroy()
            self.assocNextText=OnscreenText(
                text="(%s)"%self.inputs[nextCard],
                pos=self.nextCardTextPos,
                scale=.06,fg=(1,1,1,1),align=TextNode.ALeft)
            self.assocNextText.reparentTo(self.dummyNode3)
        except:
            self.assocNextText=OnscreenText(
                text="(%s)"%self.inputs[nextCard],
                pos=self.nextCardTextPos,scale=.06,
                fg=(1,1,1,1),align=TextNode.ALeft)
            self.assocNextText.reparentTo(self.dummyNode3)
            
            
    def switchDisplays(self,toggleBar,dummyNode,imageNode,hideImage,
                       showImage,scale,pos):
        toggleBar=not(toggleBar)
        if toggleBar==True:
            dummyNode.show()
            imageNode.destroy()
            imageNode=(DirectButton(image = hideImage,scale=scale,pos=pos,
                                    relief=None, command=lambda:
                                        self.switchDisplays(
                                            toggleBar,dummyNode,
                                            imageNode,hideImage,
                                            showImage,scale,pos)))
        else:
            dummyNode.hide()
            imageNode.destroy()
            imageNode=(DirectButton(image = showImage,scale=scale,pos=pos,
                                    relief=None, command= lambda:
                                        self.switchDisplays(
                                            toggleBar,dummyNode,
                                            imageNode,hideImage,
                                            showImage,scale,pos)))

    def shuffleCards(self):
        self.shuffledCardNames=[]
        self.shuffledCardFaces=copy.copy(cardFaces)
        random.shuffle(self.shuffledCardFaces)
        for face in self.shuffledCardFaces:
            self.shuffledCardNames.append(face.split(".")[0])
        
    def setUpCollisionRay(self):
        #Make a collision node for ours selection ray
        #Repurposed from Panda3D Documentation
        self.selectionNode = CollisionNode('mouseRay')
        self.selectionNP = camera.attachNewNode(self.selectionNode)
        self.selectionNode.setFromCollideMask(
            GeomNode.getDefaultCollideMask())
        self.selectionNode.setFromCollideMask(1)
        self.selectionNode.setIntoCollideMask(0)
        self.selectionRay = CollisionRay()
        #Make our ray
        self.selectionNode.addSolid(self.selectionRay)
        #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.cTrav.addCollider(self.selectionNP,self.queue)
    
    def setUpCollisionNode(self):
        #add a collision node to our camera
        self.fromObject = base.camera.attachNewNode(
            CollisionNode('colNode'))
        self.fromObject.setPos(0,0,3)
        self.fromObject.node().addSolid(CollisionSphere(0, 0, 0, .5))
        self.fromObject.node().setIntoCollideMask(0)
        self.cTrav.addCollider(self.fromObject,self.pusher)
        self.pusher.addCollider(
            self.fromObject, base.camera, base.drive.node())
        
    def setInputs(self):
        self.accept("mouse1",self.mouse1Tasks)
        self.accept('escape', sys.exit)

        
    def playFootSteps(self):
        self.soundSteps.play()
        
    def mouse1Tasks(self):
        self.mouseTask()
        
    def setUpScene(self):
        #self.setUpControls()
        self.setUpBackground()
        #set up the items where we can store information
        self.setUpItems()
    
    def mouseTask(self):
        self.scale=53
        self.loadItemList()
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.selectionRay.setFromLens(
                base.camNode, mpos.getX(), mpos.getY())
            #self.cTrav.showCollisions(render)
            if self.queue.getNumEntries() > 0:
                self.mouseEntry()
    
    def mouseEntry(self):
        #if we've clicked on something
        self.queue.sortEntries()
        #we get closest item
        pickedObj = self.queue.getEntry(0).getIntoNodePath().getTag("items")
        #check if what we clicked is what we want (has proper tag)
        if len(pickedObj)>0 and (pickedObj not in self.visitedItems):
            self.mouseTaskSupport(pickedObj)
        if self.queue.getEntry(0).getIntoNodePath().getTag("openChest"):
            self.toggleChest=True
            
    def mouseTaskSupport(self,pickedObj):
        self.assocs[
            self.shuffledCardNames[self.counter]]=self.items[int(pickedObj)]
        self.counter+=1
        self.visitedItems.append(pickedObj)
        #self.queue.getEntry(0).getIntoNodePath().clearTag("items")
        #if len(self.visitedItems)==len(self.items):
        if len(self.visitedItems)==5:
            self.testMemory()
        self.drawMiniCards(-self.camera.getPos()[1]/self.scale+.40,
                           self.camera.getPos()[0]/self.scale-.2)
        self.updateDisplayCards()
        self.displayAdjacencies()
    
    def loadItemList(self):
        self.items=["painting","post","tv","bed","carpet","table","tree",
                    "shelf","loveSeat1","loveSeat2","longSofa",
                    "dinnerTable","dinnerChair1","dinnerChair2"]
    def testMemory(self):
        self.nextButton=DirectButton(image = 'arrow.png',
                                     scale=.15,pos=(0.8,0,-0.6),
                                     relief=None, command=self.recallMemory)
        self.nextButton.setTransparency(TransparencyAttrib.MAlpha)
    
    def displayPriorityArrow(self):
        self.arrow=OnscreenImage(image="arrow2.png",
                                 scale=(.05,.1,.05),pos=(-.51,0,-.6),
                                 color=(1,0,0,0))
        self.arrow.setTransparency(TransparencyAttrib.MAlpha)
        taskMgr.doMethodLater(.1, self.fadeArrow, 'arrowFadeInOut')
    
    def displayUserLocation(self,task,scale=(.05,1,.05)):
        self.updateFade()
        if self.userLocation!=None:
            self.userLocation.destroy(),self.userAngle.destroy()
        x=-self.camera.getPos()[1]/self.scale+.40
        y=self.camera.getPos()[0]/self.scale-.2
        self.userLocation=OnscreenImage(
            image="dot.png",pos=(x,0,y),scale=scale,
            color=(1,1,1,self.fade))
        self.userAngle=OnscreenImage(
            image="rotating.png",pos=(x,0,y),scale=scale,
            color=(1,1,1,self.fade))
        self.userAngle.setR(-self.camera.getHpr()[0])
        self.userLocation.setTransparency(TransparencyAttrib.MAlpha)
        self.userAngle.setTransparency(TransparencyAttrib.MAlpha)
        self.userLocation.reparentTo(self.dummyNode1)
        self.userAngle.reparentTo(self.dummyNode1)
        return Task.again
    
    def updateFade(self):
        if self.fadeToggle==True:
            self.fade+=.05
            if self.fade>1:
                self.fadeToggle=False
        elif self.fadeToggle==False:
            self.fade-=.05
            if self.fade<0:
                self.fadeToggle=True
        
    def drawMiniCards(self,x,y):
        self.lastCoord+=([[x,0,y]])
        self._draw_line_segs(self.dummyNode1,self.lastCoord)
        for i in xrange(len(self.lastCoord)):   
            self.miniCards=OnscreenImage(
                image=self.shuffledCardFaces[i],
                pos=(self.lastCoord[i][0],0,self.lastCoord[i][2]),
                scale=(0.03,0.82,0.050))
            self.miniCards.reparentTo(self.dummyNode1)
        
    def _draw_line_segs(self, parent, points, thickness=1.5):
        segs = LineSegs()
        segs.setThickness(thickness)
        segs.setColor( Vec4(1,0,0,.35) )
        if points:
            segs.moveTo(points[0][0], points[0][1], points[0][2])
            for p in points[1:]:
                segs.drawTo(p[0], p[1], p[2])
        lines = NodePath(segs.create())
        lines.reparentTo(parent)

    def recallMemory(self):
        self.checkList=[]
        self.checkListFaces=[]
        self.startCard=0
        self.endCard=13
        self.cardSet=0
        self.bk=OnscreenImage(image="bk.png",scale=(2,1,1))
        self.recallCards(self.startCard,self.endCard, self.cardSet,0)
        self.scaleCards=(0.1,0.1,0.13)
        scaleCards2=(0.07,0.05,0.10)
        self.recallMemoryPrompt=OnscreenText(
                    text="List the cards in the sequence as you recall",
                    pos=(0,.45),scale=.045,fg=(0,0,0,.75))

    def recallCards(self,startCard,endCard,cardSet,createEntries=1):
        for i in xrange(startCard,endCard):
            x=2*(i+1)/(self.numCards+1.0)-1-cardSet*1.75
            self.cardsPos.append(x)
            self.createButtons(i,x)
            if createEntries==1:
                self.createEntries(x, cardSet)
        for image in self.buttonList:
            image.setTransparency(TransparencyAttrib.MAlpha)
    
    def createButtons(self,i,x):
        self.buttonList.append(DirectButton(
            image = cardFaces[i],scale=(0.06,0.1,0.095),pos=(x,0,.3),
            relief=None, command=lambda: self.createCheckButtons(i)))
        
    def createCheckButtons(self,i):
        self.correctCount=0
        self.checkList.append(i)
        self.checkListFaces.append(cardFaces[i])
        for i in xrange(len(self.checkList)):
            x=2*(i+1)/(self.numCards+1.0)-1
            self.cards=OnscreenImage(image=self.checkListFaces[i],
                                     pos=(x,0,-.2),scale=(0.06,0.1,0.095))
        if len(self.checkList)==13:
            correct=self.testResults()
            self.results=OnscreenText(
                text="You recalled %d out of %d correctly"%(
                    correct,self.numCards),pos=(0,-0.85),scale=.1)
    
    def testResults(self):
        for i in xrange(len(self.shuffledCardFaces)):
            if self.shuffledCardFaces[i]==self.checkListFaces[i]:
                self.correctCount+=1
        return self.correctCount 
            
    def updateDisplayCards(self):
        self.numCardsCopy-=1
        self.previousCard=self.shuffledCardFacesCopy.pop(0)
        if len(self.shuffledCardFacesCopy)!=0:
            self.nextCard=self.shuffledCardFacesCopy[0]
        else: self.nextCard=False 
        for image in self.imageList:
            image.destroy()
        self.displayCards()
        
    def displayCards(self):
        for i in xrange(self.numCardsCopy):
            x=2*(i+1)/(self.numCards+1.0)-.65
            self.cardsPos.append(x)
            self.imageList.append(OnscreenImage(
                image="%s"%(self.shuffledCardFacesCopy[i]),
                pos=(x,0,-.8),scale=(0.05,0.05,0.08)))
            #we use middle numbers as coordinates
    def fadeArrow(self,task): 
        self.arrow.setColor(1,0,0,self.fade) 
        return task.cont
        
    def setUpBackground(self):
        self.scale=10
        #load grass and set position, scale, and texture
        self.walls=loader.loadModel("Walls")
        self.walls.setPos(0,0,0)
        self.walls.setScale(self.scale,self.scale,self.scale)
        walltex1 = loader.loadTexture('walltex1.png')
        self.walls.setTexture(walltex1)
        #render our object
        self.walls.reparentTo(render)
        self.loadColGeomsSet1()
        self.loadColGeomsSet2()
        self.setUpBackgroundSupport()
    
    def setUpBackgroundSupport(self):
        for geom in self.colGeoms:
            self.createCollisionGeom(*geom)
        cFloorNode=CollisionNode('floorCollision')
        floorQuad=CollisionPolygon(Point3(5, 0, 0), Point3(-1.5,0,0),
                                   Point3(-1.5, -4, 0),Point3(5, -4, 0))
        cFloorNode.addSolid(floorQuad)
    
    def loadColGeomsSet1(self):
        self.colGeoms=[
            (11,(2.4,-1.80,1),(2.4,-1.80,0),(.55,-1.80,0),
            (.55,-1.80,1)),#Interior 2b (firsthalf),
            (1,(5,-.05,0),(5,-.05,1),(-1.5,-.05,1), (-1.5,-.05,0)),#West Wall
            (2,(-1.5,0,0),(-1.5,0,1),(-1.5,-4,1), (-1.5,-4,0)),#South Edge
            (5,(0.52,0,0),(0.52,0,1),(0.52,-1.2,1), (0.52,-1.2,0)),
            #South Wall_1_Interior
            (3,(0.38,0,1),(0.38,0,0),(0.38,-1.2,0), (0.38,-1.2,1)),
            #South Wall_1_Exterior
            (4,(0.38,-1.7,1),(0.38,-1.7,0),(0.38,-4,0),(0.38,-4,1)),
            #South Wall_2_Exterior
            (6,(0.52,-1.7,0),(0.52,-1.7,1),(0.52,-4,1),(0.52,-4,0)),
            #South Wall_2 Interior
            (7,(1.8,0,1),(1.8,0,0),(1.8,-1.45,0),(1.8,-1.45,1)),
            #Interior 1 (TV)
            (8,(1.9,0,0),(1.9,0,1),(1.9,-1.45,1),(1.9,-1.45,0)),
            #Interior 1b (TV)
            (9,(2.4,-1.95,0),(2.4,-1.95,1),(.55,-1.95,1), (.55,-1.95,0)),
            #Interior 2 (firsthalf)
            (10,(3.95,-1.95,0),(3.95,-1.95,1), (2.7,-1.95,1),(2.7,-1.95,0))]
            #Interior 2 (secondhalf)
        
    def loadColGeomsSet2(self):
        self.colGeoms+=[
            (12,(3.95,-1.80,1),(3.95,-1.80,0), (2.7,-1.80,0),
              (2.7,-1.80,1)), #Interior 2b (secondhalf)
            (13,(2.95,-1.9,0),(2.95,-1.9,1),(2.95,-2.1,1),
                (2.95,-2.1,0)),#North Wall 1 Exterior (firsthalf)E
            (14,(2.95,-2.48,0),(2.95,-2.48,1),(2.95,-4,1),
                (2.95,-4,0)),#North Wall 1 Exterior (secondhalf)E
            (15,(2.7,-1.9,1),(2.7,-1.9,0),(2.7,-2.1,0),
                (2.7,-2.1,1)), #North Wall 1b Interior (firsthalf) E
            (16,(2.7,-2.48,1),(2.7,-2.48,0),(2.7,-4,0),
                (2.7,-4,1)), #North Wall 1b Interior (secondhalf) E
            (17,(3.82,0,1),(3.82,0,0),(3.82,-.35,0),
                Point3(3.82,-.35,1)),#North Wall 2 Interior (firsthalf) W
            (18,(3.82,-1.1,1),(3.82,-1.1,0),(3.82,-1.9,0),
                Point3(3.82,-1.9,1)),#North Wall 2 Interior (secondhalf) W
            (19,(4,0,0),(4,0,1),(4,-.35,1),
                Point3(4,-.35,0)),#North Wall 2 Exterior (firsthalf) W
            (20,(4,-1.1,0),(4,-1.1,1),(4,-1.9,1),
                Point3(4,-1.9,0))#North Wall 2 Exterior (secondhalf) W
            ]
        
    def createCollisionGeom(self,n,firstPts,secondPts,thirdPts,fourthPts):
        collisionNode="wallCollision%d"%n
        collisionNodeName="cWallNode%d"%n
        collisionNodeName=CollisionNode(collisionNode)
        quadName="wallQuad%d"%n
        quadName=CollisionPolygon(Point3(firstPts),Point3(secondPts),
                                  Point3(thirdPts),Point3(fourthPts))
        collisionNodeName.addSolid(quadName)
        self.wallC=self.walls.attachNewNode(collisionNodeName)
        
        self.roof=self.loadItems("Roof","rooftex.png",scaleX=6,scaleY=6)
        self.walls2=self.loadItems("Walls2","walltex2.png")
        self.grass=self.loadItems("grass",'8CYNDAC0.png')
        self.floor=self.loadItems("floor","floor.png")
        self.exterior=self.loadItems("exterior",'brick.png')
        
    def setUpItems(self):
        self.itemList=[]
        self.scale=10
        self.tv=self.loadItems("tv",'tv.png')
        self.carpet=self.loadItems("carpet","carpet.png")
        self.white=self.loadItems("white","walltex2.png",8,4)
        self.painting=self.loadItems("painting","kosbie.png")
        self.wood=self.loadItems("wood","wood.png",8,4)
        self.tree=self.loadItems("GroomedTree",None,1,1,.9,(52,-5,0))
        self.shelf=self.loadItems("shelf","darkwood.png")
        self.couches=self.loadItems("couch","leather.png",5,5)
        self.dining=self.loadItems("chairs","wood.png")
        self.treasureChest=self.loadItems(
            "treasurechest","woodpanel.png",1,1,None,(0,0,20))
        self.sky=self.loadItems("sky","sky.png",1,1)
        self.selectionItems = render.attachNewNode("selectionRoot")
        self.setUpCollisionGeom()
        
    def setUpCollisionGeom(self):
        self.paintingNode=self.loadCollisionPolygon(
            "painting",self.painting,(3.35,-.07,.45),(3.35,-.07,.8),
            (2.9,-.07,.8),(2.9,-.07,.45))
        self.postNode=self.loadCollisionTube(
            "post",self.wood,.25,-2,0,.25,-2,.55,.03)
        self.tvNode=self.loadCollisionPolygon(
            "tv",self.tv,(1.75,-.35,.78),(1.75,-.35,.5),(1.75,-1.1,.5),
            (1.75,-1.1,.78))
        self.bedNode=self.loadCollisionPolygon(
            "bed",self.white,(1,-2.7,.17),(.5,-2.7,.17),(.5,-1.9,.17),
            (1,-1.9,.17))
        self.carpetNode=self.loadCollisionPolygon(
            "carpet",self.carpet,(1.95,-3.15,.05),(2.4,-3.15,.05),
            (2.4,-2.55,.05),(1.95,-2.55,.05))
        self.tableNode=self.loadCollisionPolygon(
            "table",self.wood,(1,-3.5,.26),(1.45,-3.5,.26),
            (1.45,-3.1,.26),(1,-3.1,.26))
        self.supportSetUpCollisionGeom()
        
    def supportSetUpCollisionGeom(self):
        self.treeNode=self.loadCollisionTube(
            "tree",self.tree,0,0,0,0,0,7,2)
        self.shelfNode=self.loadCollisionPolygon(
            "shelf",self.shelf,(.6,-0.05,.78),(.6,-0.05,0),
            (.6,-.43,0),(.6,-.43,.78))
        self.couchNode1=self.loadCollisionTube(
            "couch1",self.couches,1.05,-.96,0,1.05,-.96,.2,.2)
        self.couchNode2=self.loadCollisionTube(
            "couch2",self.couches,1.45,-.96,0,1.45,-.96,.2,.2)
        self.couchNode3=self.loadCollisionTube(
            "couch3",self.couches,1.00,-.16,.1,1.5,-.16,.1,.2)
        self.dinnerTable=self.loadCollisionPolygon(
            "dinnerTable",self.dining,(3.6,-.89,.26),(3.6,-.61,.26),
            (3.1,-.61,.26),(3.1,-.89,.26))
        self.dinnerChairNode1=self.loadCollisionTube(
            "dinnerChair1",self.dining,2.9,-.75,0,2.9,-.75,.2,.1)
        self.dinnerChairNode2=self.loadCollisionTube(
            "dinnerChair1",self.dining,3.7,-.75,0,3.7,-.75,.2,.1)
        self.chestNode=self.loadCollisionTube(
            "chest",self.treasureChest,.02,.02,.25,.07,.07,.25,.25)
        self.chestNode.setTag(
            "openChest","1")
        
        self.itemList+=(self.paintingNode,self.postNode,self.tvNode,
                        self.bedNode,self.carpetNode,self.tableNode,
                        self.treeNode,self.shelfNode,self.couchNode1,
                        self.couchNode2,self.couchNode3,self.dinnerTable,
                        self.dinnerChairNode1,self.dinnerChairNode2)
        self.setTag(self.itemList,"items")
        
    def setTag(self):
        self.itemList+=(self.paintingNode,self.postNode,self.tvNode,
                        self.bedNode,self.carpetNode,self.tableNode,
                        self.treeNode,self.shelfNode,
                        self.couchNode1,self.couchNode2,self.couchNode3,
                        self.dinnerTable,self.dinnerChairNode1,
                        self.dinnerChairNode2)
        self.setTag(self.itemList,"items")
        
    def setTag(self,node,tagKey):
        for i in xrange(len(node)):
            node[i].setTag(tagKey,str(i))
        
    def loadItems(self,modelName,texture=None,scaleX=1,scaleY=1,
                  scale=None,pos=(0,0,0)):
        if scale==None: scale=self.scale
        modelName=loader.loadModel(modelName)
        modelName.setPos(pos)
        modelName.setScale(scale,scale,scale)
        ts=TextureStage("ts")
        if texture!=None:
            modelTex=loader.loadTexture(texture)
            modelName.setTexture(ts,modelTex)
            modelName.setTexScale(ts,scaleX,scaleY)
        modelName.reparentTo(render)
        return modelName
    
    def loadCollisionPolygon(self,modelName,attachGeom,firstPts,
                             secondPts,thirdPts,fourthPts):
        modelName=CollisionNode(modelName)
        quadName=CollisionPolygon(Point3(firstPts),Point3(secondPts),
                                  Point3(thirdPts),Point3(fourthPts))
        modelName.addSolid(quadName)
        modelName=attachGeom.attachNewNode(modelName)
        return modelName
    
    def loadCollisionTube(self,modelName,attachGeom,x0,y0,z0,x1,y1,z1,
                          radius):
        modelName=CollisionNode(modelName)
        cylinder=CollisionTube(x0,y0,z0,x1,y1,z1,radius)
        modelName.addSolid(cylinder)
        modelName=attachGeom.attachNewNode(modelName)
        return modelName
    
    def homePage(self):
        self.introduction=False 
        #self.setUphomePageSFX()
        self.introButton=DirectButton(
            image=("introduction.png"),scale=.5,pos=(-0.8,0,-0.65),
            relief=None,command=self.startIntro)
        self.introButton.setTransparency(TransparencyAttrib.MAlpha)
        self.startButton=DirectButton(
            image=("beginJourney.png"),scale=.5,pos=(+0.8,0,-0.65),
            relief=None, command=self.startJourney)
        self.startButton.setTransparency(TransparencyAttrib.MAlpha)
        self.cylinder=self.loadItems(
            "cylinder","wood.png",1,1,2,(9,-1.3,20.8))
        self.hexagon=self.loadItems(
            "hexagon","wood.png",1,1,2.5,(9,1.4,20.8))
        taskMgr.add(self.rotateMenuItems, 'rotateMenuItems')
    
    #def setUphomePageSFX(self):
        #self.volume=0
        #self.circusInTheSky.setVolume(0)
        #self.circusInTheSky.setLoop(1) 
        #self.circusInTheSky.play()
        #taskMgr.doMethodLater(.5, self.playCircusInTheSky,
        #                      'Fade in Music', extraArgs = [self])
        
    #def playCircusInTheSky(self,task):
        #self.volume+=.00125
        #self.circusInTheSky.setVolume(self.volume)
        #return Task.cont
            
    def rotateMenuItems(self,task):
        self.speed=1.5
        radius=.5
        angle = radians(self.heading)
        x = cos(angle) * radius
        y = sin(angle) * radius
        z = sin(angle) * radius
        self.heading+=self.speed
        self.heading%=360
        self.cylinder.setH(self.heading)
        self.hexagon.setH(self.heading)
        if self.introduction==True:
            self.cylinder.remove()
            self.hexagon.remove()
            return task.done 
        return Task.cont

    def startJourney(self):
        #self.circusInTheSky.stop()
        self.introButton.destroy()
        self.startButton.destroy()
        self.initSetUpAssoc()
        #self.setUp3DEnvironmentIntro()
        ###########change here 
        
    def setUp3DEnvironmentIntro(self):
        self.camera.setP(25)
        self.Enviro3DDummy=self.createDummyNode("3DEnviroDummy")
        self.textBlocks,self.color,self.keyBrightenComplete=[],0.01,False
        self.displayCards()
        self.displayHelpPanel()
        taskMgr.doMethodLater(.05,self.displayUserLocation, 'Track User',
                              extraArgs = [self])
        self.setUpDirectionalLight()
        self.displayPriorityArrow()
        self.accept("arrow_down",self.playFootSteps)
        self.accept("arrow_up",self.playFootSteps)
        self.enviroTextBlocks()
        self.Enviro3DSupportText()
    
    def enviroTextBlocks(self):
        self.enviroTextBlock1=(
            "1. Here is the priority queue for the shuffled cards")
        self.enviroTextBlock2=(
            "2. Toggle displays to show/hide windows")
        self.enviroTextBlock3=(
            "3. See your location in the plan")
        self.textBlocks+=(self.enviroTextBlock1,self.enviroTextBlock2,
                               self.enviroTextBlock3)
        self.textPos=[(0,-.6),(-.6,.6),(.7,-.4)]
        
    def Enviro3DSupportText(self):
        for i in xrange(len(self.textBlocks)):
            self.titleText=OnscreenText(text=self.textBlocks[i],
            pos=self.textPos[i],scale=.058,fg=(1,1,1,1))
            self.titleText.reparentTo(self.Enviro3DDummy)
        taskMgr.doMethodLater(.1, self.init3DActiveEnviro,'3DEnviroEntry')
        taskMgr.doMethodLater(.15,self.brightenKey,"brightenKey")
    
    def init3DActiveEnviro(self,task):
        self.keyButton=DirectButton(
            image = 'key.png',scale=(.5,.2,.15),color=(0,0,0,0),pos=(-.5,0,0),
            relief=None, command=self.setUp3DEnvironmentActive)
        self.keyButton.setTransparency(TransparencyAttrib.MAlpha)
        self.keyButton.reparentTo(self.Enviro3DDummy)
        self.keyButton['state'] = DGG.DISABLED
        return task.done 
        
    def brightenKey(self,task):
        if self.keyBrightenComplete==False:
            self.brightenSpeed=0.025
            if self.color<1:
                self.color+=self.brightenSpeed
                self.keyButton.setColor(0,0,0,self.color)
                return task.again
            else:
                self.entryText=OnscreenText(text="[Click the key to begin]",
                pos=(-.7,.13),scale=.058,fg=(1,1,1,1))
                self.entryText.reparentTo(self.Enviro3DDummy)
                self.keyButton['state'] = DGG.NORMAL
                task.done
        else:
            task.done 

    def setUp3DEnvironmentActive(self):
        base.useDrive()
        self.keyBrightenComplete=True 
        self.Enviro3DDummy.removeNode()

    def setUpDirectionalLight(self):
        dlight = DirectionalLight('dlight')
        dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        dlnp = render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        render.setLight(dlnp)
        render.setShaderAuto()
        
    def startIntro(self):
        self.introduction=True 
        self.introButton.destroy()
        self.startButton.destroy()
        self.setUpHelp()

    def setUpHelp(self):
        self.titleText=OnscreenText(text="Introduction",
                                    pos=(-0.85,0.85),scale=.1)
        self.text = TextNode('helpText')
        self.textBlocks()
        self.text.setText(self.textBlock1)
        textNodePath = aspect2d.attachNewNode(self.text)
        textNodePath.setScale(0.07)
        textNodePath.setPos(-1,0,0)
        self.text.setWordwrap(30.0)
        self.nextButton=DirectButton(
            image = 'arrow.png',scale=.15,pos=(0.8,0,-0.6),relief=None,
            command=self.nextPage )
        self.nextButton.setTransparency(TransparencyAttrib.MAlpha)
    
    def textBlocks(self):
        self.textBlock1=("This project tests the effectiveness"
        +" of along established 'Method of loci', which is a"
        +" mnemonic device used for memory enhancement which uses"
        +" visualization to organize and recall information."
        +" We will be using this technique to memory a set of 13"
        +" cards (one suit)")
        
        self.textBlock2=(
        "STEP 1 \n\n We create rooms which are connected "
        + "and unique. These are provided for you."
        +"\n\n STEP 2 \n\n Associate each card with visual "
        +"objects (eg. 2 ---> Swan)"
        +"\n\n STEP 3 \n\n We 'place' the cards at specific "
        +"locations in sequence so relationship between "
        +"the location and item are made."
        +"\n\n STEP 4 \n\n Test the associations we've made")
        
    def nextPage(self):

        textNodePath = aspect2d.attachNewNode(self.text)
        textNodePath.setPos(-1,0,.5)
        self.nextButton.destroy()
        self.text.setText(self.textBlock2)
        self.nextButton=DirectButton(
            image = 'arrow.png',scale=.15,pos=(0.8,0,-0.6),relief=None,
            command=(self.clear))
        self.nextButton.setTransparency(TransparencyAttrib.MAlpha)
        
    def clear(self):
        self.text.clearText()
        self.titleText.clearText()
        self.nextButton.destroy()
        self.homePage()
        
    def initSetUpAssoc(self):
        self.bk=OnscreenImage(image="bk.png",scale=(2,1,1))
        self.inputs=dict()
        self.cardsPositions=[]
        self.imageListFaces,self.textObjs,self.entries=[],[],[]
        self.numCardsPage1=7
        self.startCard=0
        self.endCard=7
        self.cardSet=0
        self.callCards(self.startCard,self.endCard, self.cardSet)
        self.goAhead=[]
        self.button1=loader.loadMusic("button1.wav")
        self.assocTextBlocks()
        taskMgr.doMethodLater(.1, lambda task: self.createAssocHelperText(
            task,self.assocTextBlock1),'assocHelperText')
        
    def assocTextBlocks(self):
        self.assocTextBlock1=(
            "[Enter a word you strongly associated with each card]"
            +"\n Helpful Hint: Use less abstract and more descriptive words")
        self.assocTextBlock2=(
            "[That's great! Finish up the rest!]")
            
    def createAssocHelperText(self,task,text):
        self.updateFade()
        try:
            self.assocText.destroy()
            self.assocText=OnscreenText(
            text=text,
            pos=(0,-.2),scale=.05,fg=(0,0,0,self.fade))
        except:
            self.assocText=OnscreenText(
            text=text,
            pos=(0,-.2),scale=.05,fg=(0,0,0,self.fade))
        return task.again 
            
    def callCards(self,startCard,endCard,cardSet,createEntries=1,
                  scaleCards=(0.1,0.1,0.13)):
        for i in xrange(startCard,endCard):
            x=2*(i+1)/(self.numCardsPage1+1.0)-1-cardSet*1.75
            self.cardsPositions.append(x)
            self.imageListFaces.append(
                OnscreenImage(image="%s"%(cardFaces[i]),
                              pos=(x,0,.3),scale=scaleCards))
            self.textObjs.append(OnscreenText(text=str(i),pos=(x,0)))
            #we use middle numbers as coordinates
            self.cardName=cardNames[i]
            if createEntries==1:
                self.createEntries(x, cardSet)
            
    def createEntries(self,x, cardSet):
        self.entries.append(
            DirectEntry(text = "" ,scale=.02,pos=(x-0.1,0.1,0.1),
                        command=(lambda textEntered: self.storeAssoc
                                 (textEntered, x, cardSet)), numLines = 2))
    
    def clearPage(self):
        for image in self.imageListFaces:
            image.destroy()
        for textObj in self.textObjs:
            textObj.destroy()
        for entry in self.entries:
            entry.destroy()
        for image in self.goAhead:
            image.destroy()
        self.assocText.destroy()
        self.clearBK()

            
    def clearBK(self):
        self.bk.destroy()
    
    def storeAssoc(self,textEntered, x, cardSet):
        index=int((x+cardSet*1.75+.75)/0.25)
        self.inputs[cardNames[index]]=textEntered
        self.greenDot=OnscreenImage(
            image="greenDot.png",pos=(x,0,.55),scale=(.25,1,.25))
        self.greenDot.setTransparency(TransparencyAttrib.MAlpha)
        self.goAhead.append(self.greenDot)
        self.button1.play()
        if len(self.inputs)>6 and cardSet==0:
            taskMgr.remove('assocHelperText')
            taskMgr.doMethodLater(.1, lambda task: self.createAssocHelperText(
            task,self.assocTextBlock2),'assocHelperText')
            self.startCard=7
            self.endCard=13
            self.clearBK()
            self.cardSet=1
            self.bk=OnscreenImage(image="bk.png",scale=(2,1,1))
            self.callCards(self.startCard,self.endCard, self.cardSet)
        if len(self.inputs)>12 and cardSet==1:
            taskMgr.remove('assocHelperText')
            self.clearPage()
            self.setUp3DEnvironmentIntro()
    def startGame(self):
        self.bk.destroy()
class Dashboard():
    def __init__(self, gameEngine, taskMgr):
        self.gameEngine = gameEngine
        self.font_digital = loader.loadFont('models/font/SFDigitalReadout-Heavy.ttf')
        self.start_time = datetime.datetime.now()
        self.time_elapsed = datetime.timedelta(milliseconds=0)
        self.countdown_time = datetime.timedelta(minutes=8)
        #
        self.screenBtns = [] 

        self.isGameTimeOver = False

        # insert total time
        self.game_time = self.countdown_time - self.time_elapsed
        # print self.game_time

        # players is a map that holds all the players with their ranking and updates every second key= rank, value= username
        self.players={}

        self.lead1 = ""
        self.lead2 = ""
        self.lead3 = ""

        # Leaderboard Ranking
        self.leader1 = OnscreenText(text="1:", style=1, fg=(1, 1, 1, 1),
                                    pos=(-1.3, .5), align=TextNode.ALeft,
                                    scale=.07, font=self.font_digital)
        self.leader2 = OnscreenText(text="2:", style=1, fg=(1, 1, 1, 1),
                                    pos=(-1.3, .45), align=TextNode.ALeft,
                                    scale=.07, font=self.font_digital)
        self.leader3 = OnscreenText(text="3:", style=1, fg=(1, 1, 1, 1),
                                    pos=(-1.3, .4), align=TextNode.ALeft,
                                    scale=.07, font=self.font_digital)

        # Your Rank
        self.ranklabel = OnscreenText(text="Rank", style=1, fg=(1, 1, 1, 1), pos=(-.9, .89), align=TextNode.ALeft,
                     font=self.font_digital, scale=.06)
        # rank = str(self.rm.rank) + "/" + str(self.rm.racers)
        self.rank = "Rank placeholder1"
        self.display_rank = OnscreenText(text=self.rank, style=1, fg=(1, 1, 1, 1),
                                         pos=(-.8, .85), align=TextNode.ALeft,
                                         scale=.15, font=self.font_digital)
        self.playerlabel = OnscreenText(text="Players\nLeft", style=1, fg=(1, 1, 1, 1), pos=(-.5, .89), align=TextNode.ALeft,
                     font=self.font_digital, scale=.06)

        self.screenBtns.append(self.leader1)
        self.screenBtns.append(self.leader2)
        self.screenBtns.append(self.leader3)
        self.screenBtns.append(self.ranklabel)
        self.screenBtns.append(self.display_rank)
        self.screenBtns.append(self.playerlabel)



        def displayBars() :
            health = self.gameEngine.vehicleContainer.props.getHealthStatus()
            self.Health_bar['value'] = health['health']
            self.EHealth_bar['value'] = health['additionalHealth']
            armour = self.gameEngine.vehicleContainer.props.getArmorStatus()
            self.Armour_bar['value'] = armour

        # Timer
        self.display_timer = OnscreenText(text=str(self.game_time), style=1, fg=(1, 1, 1, 1), pos=(0, .9), scale=.1,
                                          font=self.font_digital)
        self.mini_map = OnscreenImage(image="models/dashb/speedometer.png", scale=.2, pos=(-1.15, 0, .8))
        self. mini_map.setTransparency(TransparencyAttrib.MAlpha)
        self.char = OnscreenImage(image='models/triangle.png', scale=.1, parent=self.mini_map,pos=(-1.15, 0, .8) )
        self.otherchar = OnscreenImage(image='models/power_ups/pow1.png', scale=.1,
                                          parent=self.mini_map ,pos=(-1.15, 0, .8))

        self.screenBtns.append(self.display_timer)
        self.screenBtns.append(self.mini_map)
        self.screenBtns.append(self.char)
        self.screenBtns.append(self.otherchar)

        self.offset = 0.13
        self.setupSpeedImages()
        self.setupBoostImages()
        self.setupStatusBars()
        taskMgr.doMethodLater(.1, self.updateSpeed, 'updateSpeed')
        taskMgr.doMethodLater(.1, self.updateBoost, 'updateBoost')
        taskMgr.doMethodLater(.1, self.updateTimer, 'updateTimer')
        taskMgr.doMethodLater(.1, self.updateStatusBars, 'updateStatusBars')
        taskMgr.doMethodLater(.1, self.show_map, 'updateminimap')
        displayBars()
        taskMgr.doMethodLater(.1, self.update_rank, 'updateRank')


    def updateStatusBars(self, task):

        health = self.gameEngine.vehicleContainer.props.getHealthStatus()
        self.Health_bar['value'] = health['health']
        self.EHealth_bar['value'] = health['additionalHealth']
        armour = self.gameEngine.vehicleContainer.props.getArmorStatus()
        self.Armour_bar['value'] = armour
        # maxScale = 0.15
        # totalWidthScaled = 163.0 * 0.15
        # currentHealth = self.gameEngine.vehicleContainer.vehicleControlState["health"]
        # # print "Current Health: ", currentHealth
        # length = currentHealth * maxScale
        # halfLengthScaled = (maxScale - length)
        # self.healthBar.destroy()
        # self.healthBar = OnscreenImage(image="models/dashb/seekBar.png", scale=(length, 1.0, 0.08), pos=(-1.125 - halfLengthScaled, 0, -.85))
        # self.healthBar.setTransparency(TransparencyAttrib.MAlpha)
        # # self.healthBar.setColorScale(1,0,0, 1-currentHealth)
        return task.cont

    def updateSpeed(self, task):
        speed, normalizedSpeed = self.gameEngine.vehicleContainer.getSpeed()
        self.speed = str(format(speed, '0.2f'))
        # print self.speed

        wheelRate = 0.75 * speed

        self.reversing = False

        self.gearSpacing = (self.gameEngine.vehicleContainer.specs['maxSpeed'] / 4)

        # Calculate which gear we're in, and what the normalised revs are
        if self.reversing:
            numberOfGears = 1
        else:
            numberOfGears = 4

        self.gear = min(int(wheelRate/ self.gearSpacing),
                    numberOfGears - 1)

        # Update Speed Display
        self.display_speed.destroy()
        self.display_speed = OnscreenText(text=self.speed, style=3, fg=(1, 1, 1, 1),
                                          pos=(1.15, -0.95), align=TextNode.ARight, scale=.13, font=self.font_digital)

        # print gear
        self.display_gear.destroy()
        self.display_gear = OnscreenText(text=str(self.gear+1), style=3, fg=(1, 1, 1, 1),
            pos=(0.917, -0.80), align=TextNode.ARight, scale=.10, font=self.font_digital)

        # Needle
        self.speedNeedleAngle = self.MaxNeedleAngle * normalizedSpeed
        self.speedNeedle_img.destroy()
        self.speedNeedle_img = OnscreenImage(image="models/dashb/meterNeedle.png", scale=.25, pos=(0.9, 0, -.65), hpr = (0,0,self.speedNeedleAngle))
        self.speedNeedle_img.setTransparency(TransparencyAttrib.MAlpha)
        # Meter Top
        self.speedTop.destroy()
        self.speedTop = OnscreenImage(image="models/dashb/meterTop.png", scale=.25, pos=(0.9, 0, -.65))
        self.speedTop.setTransparency(TransparencyAttrib.MAlpha)
        self.screenBtns.append(self.display_speed)
        self.screenBtns.append(self.display_gear)
        self.screenBtns.append(self.speedNeedle_img)
        self.screenBtns.append(self.speedTop)
        return task.cont

    def updateBoost(self, task):
        normalizedBoost = self.gameEngine.vehicleContainer.getBoost()
        # Needle
        self.boostNeedleAngle = self.MaxNeedleAngle * normalizedBoost
        self.boostNeedle_img.destroy()
        self.boostNeedle_img = OnscreenImage(image="models/dashb/meterNeedle.png", scale=self.boostScale, pos=(self.boostX, 0, self.boostY), hpr = (0,0,self.boostNeedleAngle))
        self.boostNeedle_img.setTransparency(TransparencyAttrib.MAlpha)
        # Meter Top
        self.boostTop.destroy()
        self.boostTop = OnscreenImage(image="models/dashb/meterTop.png", scale=self.boostScale, pos=(self.boostX, 0, self.boostY))
        self.boostTop.setTransparency(TransparencyAttrib.MAlpha)
        self.screenBtns.append(self.boostNeedle_img)
        self.screenBtns.append(self.boostTop)
        return task.cont

    def updateTimer(self, task):
        self.time_elapsed = datetime.datetime.now() - self.start_time
        game_time = "0.00.000"
        if(self.countdown_time <= self.time_elapsed):
            # print "Time must over here"
            self.isGameTimeOver = True
        else:
            game_time = str(self.countdown_time - self.time_elapsed)[2:11]

        # print "datetime.datetime.now(): ", datetime.datetime.now()
        # print "self.start_time:", self.start_time
        # print datetime.datetime.now(), " - ", self.start_time, " =", self.time_elapsed, "self.time_elapsed"
        # print "self.countdown_time", self.countdown_time
        # print "self.time_elapsed: ", self.time_elapsed
        # print self.countdown_time, " - ", self.time_elapsed, " ="
        # print "game_time: ", game_time
        # print "--------------------------------------------------------"

        self.display_timer.destroy()
        self.display_timer = OnscreenText(text=game_time, style=3, fg=(1, 1, 1, 1), pos=(0, .9), scale=.15,
                                          font=self.font_digital)
        self.screenBtns.append(self.display_timer)

        # updateTimer task will stop when the countdown time hits to zero
        if(self.isGameTimeOver):
            self.gameEngine.gameEnd()
            print "Time Over"
            # self.gameResult()
            return task.done
        else:
            return task.cont


    def setupSpeedImages(self):
        self.display_speed = OnscreenText(text="0", style=1, fg=(1, 1, 1, 1),
                                          pos=(1.3, -0.95), align=TextNode.ARight, scale=.07, font=self.font_digital)

        # Display Gear
        self.display_gear = OnscreenText(text="N", style=3, fg=(1, 1, 1, 1),
                                          pos=(0.917, -0.80), align=TextNode.ARight, scale=.10, font=self.font_digital)

        # Speedometer
        self.speed_img = OnscreenImage(image="models/dashb/meterBG.png", scale=.25, pos=(0.9, 0, -.65))
        self.speed_img.setTransparency(TransparencyAttrib.MAlpha)
        # Needle
        self.MaxNeedleAngle = 260
        self.speedNeedleAngle = 0
        self.speedNeedle_img = OnscreenImage(image="models/dashb/meterNeedle.png", scale=.25, pos=(0.9, 0, -.65), hpr = (0,0,self.speedNeedleAngle))
        self.speedNeedle_img.setTransparency(TransparencyAttrib.MAlpha)
        # Meter Top
        self.speedTop = OnscreenImage(image="models/dashb/meterTop.png", scale=.25, pos=(0.9, 0, -.65))
        self.speedTop.setTransparency(TransparencyAttrib.MAlpha)

        self.screenBtns.append(self.display_speed)
        self.screenBtns.append(self.display_gear)
        self.screenBtns.append(self.speed_img)
        self.screenBtns.append(self.speedNeedle_img)
        self.screenBtns.append(self.speedTop)



    def setupBoostImages(self):
        self.boostX = 1.30 # - self.offset
        self.boostY = -0.75
        self.boostScale = 0.19
        # Health meter
        self.boost_img = OnscreenImage(image="models/dashb/boostMeterBG.png", scale=self.boostScale, pos=(self.boostX, 0, self.boostY))
        self.boost_img.setTransparency(TransparencyAttrib.MAlpha)
        # Needle
        self.MaxNeedleAngle = 260
        self.boostNeedleAngle = 0
        self.boostNeedle_img = OnscreenImage(image="models/dashb/meterNeedle.png", scale=self.boostScale, pos=(self.boostX, 0, self.boostY), hpr = (0,0,self.boostNeedleAngle))
        self.boostNeedle_img.setTransparency(TransparencyAttrib.MAlpha)
        # Meter Top
        self.boostTop = OnscreenImage(image="models/dashb/meterTop.png", scale=self.boostScale, pos=(self.boostX, 0, self.boostY))
        self.boostTop.setTransparency(TransparencyAttrib.MAlpha)

        self.screenBtns.append(self.boost_img)
        self.screenBtns.append(self.boostNeedle_img)
        self.screenBtns.append(self.boostTop)



    def setupStatusBars(self):
        # Health-Bar
        # self.healthBarBG = OnscreenImage(image="models/dashb/seekBarBG.png", scale=(0.15, 1.0, 0.08), pos=(-1.125, 0, -.85))
        # self.healthBarBG.setTransparency(TransparencyAttrib.MAlpha)
        # self.healthBar = OnscreenImage(image="models/dashb/seekBar.png", scale=(0.15, 1.0, 0.08), pos=(-1.125, 0, -.85))
        # self.healthBar.setTransparency(TransparencyAttrib.MAlpha)
        self.bars = self.gameEngine.vehicleContainer.props.getBarDetails()


        # Health Bar      

        self.Health_bar = DirectWaitBar(text = "", range = self.bars["health"], pos = (0.647,0,0.558), barColor= (1,0,0,1), frameSize = (0,.475,0.29,0.34),barTexture =("models/dashb/barHealth.png"))

        self.EHealth_bar = DirectWaitBar(text = "", range = self.bars["additionalHealth"], pos = (1.133,0,0.558), barColor= (0,1,0,1), frameSize = (0,.15,0.29,0.34),barTexture =("models/dashb/barExtraHealth.png"))

        self.Armour_bar = DirectWaitBar(text = "",range = self.bars["armor"], pos = (0.74,0,0.418), barColor= (159,0,255,1), frameSize = (0,0.54,0.29,0.34),barTexture =("models/dashb/barArmor.png"))


        # Health Bar Frame
        self.frame = OnscreenImage(image = "models/dashb/frame.png", pos=(0.9, 0, 0.8), scale = (0.40, 0.15, 0.15) )
        self.frame.setTransparency(TransparencyAttrib.MAlpha)
        self.screenBtns.append(self.Health_bar)
        self.screenBtns.append(self.EHealth_bar)
        self.screenBtns.append(self.Armour_bar)
        self.screenBtns.append(self.frame)

    def show_map(self, task):

        main_char=self.gameEngine.vehicleContainer
        if main_char != None:
            x=main_char.chassisNP.getX()
            y=main_char.chassisNP.getY()
            h=main_char.chassisNP.getH()
            #temporary value
            size=200
            bound=80
            # connected player
            for i in  self.gameEngine.vehiclelist:
                car= self.gameEngine.vehiclelist[i]
                if car != None:
                    i_x=car.chassisNP.getX()
                    i_y=car.chassisNP.getY()
                    i_h=car.chassisNP.getH()
                    if(i_x<bound and i_y<bound and i_y>(bound*-1) and i_x>(bound*-1) ):
                        self.otherchar.destroy()


                        self.otherchar = OnscreenImage(image='models/power_ups/pow1.png', scale=.07, parent=self.mini_map ,
                                                   pos=(i_x/size, 0, i_y/size),color=(1,1,0,1))

                        self.otherchar.setR(-i_h)
                        self.screenBtns.append(self.otherchar)
            #powerup
            if(x<bound and y<bound and x>(bound*-1) and x>(bound*-1)):
                self.char.destroy()
                self.char = OnscreenImage(image='models/triangle.png', scale=.1, parent=self.mini_map ,pos=(x/size, 0, y/size))
                self.char.setR(-h)
                self.screenBtns.append(self.char)

        return task.cont


    # being called by ResponseRankings
    def update_ranking(self, leaders):
        self.players = leaders
        if(len(leaders)>= 3):
            self.lead1 = leaders[1]
            self.lead2 = leaders[2]
            self.lead3 = leaders[3]
        elif(len(leaders)==2):
            self.lead1 = leaders[1]
            self.lead2 = leaders[2]
        elif(len(leaders)==1):
            self.lead1 = leaders[1]


    def update_rank(self, task):
        self.display_rank.destroy()
        self.gameEngine.doRanking()
        # Your Rank
        self.rank = "Rank holder"
        for x in range(1, len(self.players)+1):
            if(self.players[x]== self.gameEngine.login):
                self.rank = str(x) + "/" + str(len(self.players))
                break

        self.display_rank = OnscreenText(text=self.rank, style=1, fg=(1, 1, 1, 1),
                                         pos=(-.8, .85), align=TextNode.ALeft,
                                         scale=.15, font=self.font_digital)

        # Leader board
        self.leader1.destroy()
        self.leader2.destroy()
        self.leader3.destroy()
        lead1 = "1:" + self.lead1
        lead2 = "2:" + self.lead2
        lead3 = "3:" + self.lead3

        self.leader1 = OnscreenText(text=lead1, style=1, fg=(1, 1, 1, 1),
                                    pos=(-1.88, .5), align=TextNode.ALeft,
                                    scale=.07, font=self.font_digital)
        self.leader2 = OnscreenText(text=lead2, style=1, fg=(1, 1, 1, 1),
                                    pos=(-1.88, .45), align=TextNode.ALeft,
                                    scale=.07, font=self.font_digital)
        self.leader3 = OnscreenText(text=lead3, style=1, fg=(1, 1, 1, 1),
                                    pos=(-1.88, .4), align=TextNode.ALeft,
                                    scale=.07, font=self.font_digital)

        self.screenBtns.append(self.display_rank)
        self.screenBtns.append(self.leader1)
        self.screenBtns.append(self.leader2)
        self.screenBtns.append(self.leader3)
        return task.cont


    def getRank(self):
        return self.rank


    def gameResult(self, isDead=False):

        #print "REsult"
        
        if isDead:
            print "Inside if"
            self.rank = len(self.gameEngine.vehiclelist) - self.gameEngine.deadCounter -1
            message = "Winner. You Won the Game!"
        else:
            rank = self.getRank().split("/")
            if rank[0]=="1" :
                message = "Winner. You Won the Game!"
            else :
                message = "Game Over. You Loose"

        self.ResultFrame = DirectFrame(frameColor=(1,0,0,0.8),frameSize = (-0.75,.75,-.5,.5),pos=(0, 0.0, 0))

        self.ResultMessage = OnscreenText(text=message, style=1, fg=(1, 1, 1, 1),
            pos=(0,0.1), align=TextNode.ACenter, scale=.1)

        position = "Position : "+str(self.getRank())

        self.ResultPosition = OnscreenText(text=position, style=1, fg=(1, 1, 1, 1),
            pos=(0,-0.1), align=TextNode.ACenter, scale=.1)

        self.backToLobby = DirectButton(image = 'IMAGES/enter.png', pos = (0.3, 0, -0.4),  scale = (.17, 1, .03), relief = None, command = self.goLobby)


        self.screenBtns.append(self.ResultFrame)
        self.screenBtns.append(self.ResultMessage)
        self.screenBtns.append(self.ResultPosition)
        self.screenBtns.append(self.backToLobby)
        # self.screenBtns.append(self.Pname)
        # self.screenBtns.append(self.Pname)


    def unloadScreen(self):
        for item in self.screenBtns:
            item.destroy()

    def goLobby(self):

        taskMgr.remove("updateSpeed")
        taskMgr.remove("updateBoost")
        taskMgr.remove("updateTimer")
        taskMgr.remove("updateStatusBars")
        taskMgr.remove("updateminimap")
        taskMgr.remove("updateRank")
        
        self.unloadScreen()
        print "Game over"

        self.gameEngine.callLobby()