def __init__(self):

        self.loading = LoadingScreen()

        base.setFrameRateMeter(True)
        #input states
        inputState.watchWithModifiers('forward', 'w')
        inputState.watchWithModifiers('left', 'a')
        inputState.watchWithModifiers('brake', 's')
        inputState.watchWithModifiers('right', 'd')
        inputState.watchWithModifiers('turnLeft', 'q')
        inputState.watchWithModifiers('turnRight', 'e')

        self.keyMap = {"hello": 0, "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0,
                       "chat0": 0, "powerup": 0, "reset": 0}
        base.win.setClearColor(Vec4(0, 0, 0, 1))

        # Network Setup
        #self.cManager = ConnectionManager(self)
        #self.startConnection()
        #self.cManager.sendRequest(Constants.CMSG_LOGIN, ["username", "password"])
        # chat box
        # self.chatbox = Chat(self.cManager, self)


        # Set up the environment
        #
        self.initializeBulletWorld(False)

        #self.createEnvironment()
        Track(self.bulletWorld)
        
        

        # Create the main character, Ralph

        self.mainCharRef = Swiftstar(self.bulletWorld, (0, 25, 10, 0, 0, 0), self.login)
        #self.mainCharRef = Character(self, self.bulletWorld, 0, "Me")
        self.mainChar = self.mainCharRef.chassisNP
        #self.mainChar.setPos(0, 25, 16)

#         self.characters.append(self.mainCharRef)

#         self.TestChar = Character(self, self.bulletWorld, 0, "test")
#         self.TestChar.actor.setPos(0, 0, 0)

        self.previousPos = self.mainChar.getPos()
        taskMgr.doMethodLater(.1, self.updateMove, 'updateMove')

      
          # this will be set by the server
        self.howmanyplayers = 2
        
        self.rm = RaceMaster( self, self.mainCharRef, 1, self.howmanyplayers, 0)
        sp = self.rm.getStartingPoints()
        pos =  sp[0]
        self.mainChar.setPosHpr(pos[0] ,pos[1] ,pos[2] , pos[3], pos[4], pos[5])
        
        taskMgr.doMethodLater(.1, self.rm.updateCheckpoints, 'updateRace')
              
        # Set Dashboard
        self.dashboard = Dashboard(self.mainCharRef, taskMgr, self.rm)

         
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)

        # Accept the control keys for movement and rotation
        self.accept("escape", self.doExit)
        self.accept("a", self.setKey, ["left", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("s", self.setKey, ["backward", 1])
        self.accept("arrow_left", self.setKey, ["cam-left", 1])
        self.accept("arrow_right", self.setKey, ["cam-right", 1])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("s-up", self.setKey, ["backward", 0])
        self.accept("arrow_left-up", self.setKey, ["cam-left", 0])
        self.accept("arrow_right-up", self.setKey, ["cam-right", 0])
        self.accept("h", self.setKey, ["hello", 1])
        self.accept("h-up", self.setKey, ["hello", 0])
        self.accept("0", self.setKey, ["chat0", 1])
        self.accept("0-up", self.setKey, ["chat0", 0])
        self.accept("1", self.setKey,["powerup", 1])
        self.accept("1-up", self.setKey,["powerup", 0])
        self.accept("2", self.setKey,["powerup", 2])
        self.accept("2-up", self.setKey,["powerup", 0])
        self.accept("3", self.setKey,["powerup", 3])
        self.accept("3-up", self.setKey,["powerup", 0])
        self.accept("r", self.doReset)
        self.accept("p", self.setTime)

        self.loading.finish()
        taskMgr.doMethodLater(5, self.move, "moveTask")

        # Game state variables
        self.isMoving = False

        # Sky Dome
        self.sky = SkyDome()

        # Set up the camera
        self.camera = Camera(self.mainChar, self.bulletWorld)
        #base.disableMouse()
        #base.camera.setPos(self.mainChar.getX(), self.mainChar.getY() + 10, self.mainChar.getZ() + 2)

        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(-5, -5, -5))
        directionalLight.setColor(Vec4(1, 1, 1, 1))
        directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
        directionalLight2 = DirectionalLight("directionalLight2")
        directionalLight2.setDirection(Vec3(5, 5, -5))
        directionalLight2.setColor(Vec4(1, 1, 1, 1))
        directionalLight2.setSpecularColor(Vec4(1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(directionalLight2))

        # Game initialisation
        self.gameState = self.gameStateDict["Login"]
        self.responseValue = -1

        #self.cManager.sendRequest(Constants.CMSG_LOGIN,[self.login,"1234"])
        taskMgr.add(self.enterGame,"EnterGame")
class World(DirectObject):
    gameStateDict = {"Login" : 0,"CreateLobby":4, "EnterGame": 1, "BeginGame": 2, "InitializeGame":3}
    gameState = -1
    # Login , EnterGame , BeginGame
    responseValue = -1
    currentTime = 0
    idleTime = 0
    mySequence = None
    pandaPace = None
    jumpState = False
    isWalk = False
    previousPos = None  # used to store the mainChar pos from one frame to another
    host = ""
    port = 0
    vehiclelist = {}  # Stores the list of all the others players characters
    characters = []
    login = "******"

    def __init__(self):

        self.loading = LoadingScreen()

        base.setFrameRateMeter(True)
        #input states
        inputState.watchWithModifiers('forward', 'w')
        inputState.watchWithModifiers('left', 'a')
        inputState.watchWithModifiers('brake', 's')
        inputState.watchWithModifiers('right', 'd')
        inputState.watchWithModifiers('turnLeft', 'q')
        inputState.watchWithModifiers('turnRight', 'e')

        self.keyMap = {"hello": 0, "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0,
                       "chat0": 0, "powerup": 0, "reset": 0}
        base.win.setClearColor(Vec4(0, 0, 0, 1))

        # Network Setup
        #self.cManager = ConnectionManager(self)
        #self.startConnection()
        #self.cManager.sendRequest(Constants.CMSG_LOGIN, ["username", "password"])
        # chat box
        # self.chatbox = Chat(self.cManager, self)


        # Set up the environment
        #
        self.initializeBulletWorld(False)

        #self.createEnvironment()
        Track(self.bulletWorld)
        
        

        # Create the main character, Ralph

        self.mainCharRef = Swiftstar(self.bulletWorld, (0, 25, 10, 0, 0, 0), self.login)
        #self.mainCharRef = Character(self, self.bulletWorld, 0, "Me")
        self.mainChar = self.mainCharRef.chassisNP
        #self.mainChar.setPos(0, 25, 16)

#         self.characters.append(self.mainCharRef)

#         self.TestChar = Character(self, self.bulletWorld, 0, "test")
#         self.TestChar.actor.setPos(0, 0, 0)

        self.previousPos = self.mainChar.getPos()
        taskMgr.doMethodLater(.1, self.updateMove, 'updateMove')

      
          # this will be set by the server
        self.howmanyplayers = 2
        
        self.rm = RaceMaster( self, self.mainCharRef, 1, self.howmanyplayers, 0)
        sp = self.rm.getStartingPoints()
        pos =  sp[0]
        self.mainChar.setPosHpr(pos[0] ,pos[1] ,pos[2] , pos[3], pos[4], pos[5])
        
        taskMgr.doMethodLater(.1, self.rm.updateCheckpoints, 'updateRace')
              
        # Set Dashboard
        self.dashboard = Dashboard(self.mainCharRef, taskMgr, self.rm)

         
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)

        # Accept the control keys for movement and rotation
        self.accept("escape", self.doExit)
        self.accept("a", self.setKey, ["left", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("s", self.setKey, ["backward", 1])
        self.accept("arrow_left", self.setKey, ["cam-left", 1])
        self.accept("arrow_right", self.setKey, ["cam-right", 1])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("s-up", self.setKey, ["backward", 0])
        self.accept("arrow_left-up", self.setKey, ["cam-left", 0])
        self.accept("arrow_right-up", self.setKey, ["cam-right", 0])
        self.accept("h", self.setKey, ["hello", 1])
        self.accept("h-up", self.setKey, ["hello", 0])
        self.accept("0", self.setKey, ["chat0", 1])
        self.accept("0-up", self.setKey, ["chat0", 0])
        self.accept("1", self.setKey,["powerup", 1])
        self.accept("1-up", self.setKey,["powerup", 0])
        self.accept("2", self.setKey,["powerup", 2])
        self.accept("2-up", self.setKey,["powerup", 0])
        self.accept("3", self.setKey,["powerup", 3])
        self.accept("3-up", self.setKey,["powerup", 0])
        self.accept("r", self.doReset)
        self.accept("p", self.setTime)

        self.loading.finish()
        taskMgr.doMethodLater(5, self.move, "moveTask")

        # Game state variables
        self.isMoving = False

        # Sky Dome
        self.sky = SkyDome()

        # Set up the camera
        self.camera = Camera(self.mainChar, self.bulletWorld)
        #base.disableMouse()
        #base.camera.setPos(self.mainChar.getX(), self.mainChar.getY() + 10, self.mainChar.getZ() + 2)

        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(-5, -5, -5))
        directionalLight.setColor(Vec4(1, 1, 1, 1))
        directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
        directionalLight2 = DirectionalLight("directionalLight2")
        directionalLight2.setDirection(Vec3(5, 5, -5))
        directionalLight2.setColor(Vec4(1, 1, 1, 1))
        directionalLight2.setSpecularColor(Vec4(1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(directionalLight2))

        # Game initialisation
        self.gameState = self.gameStateDict["Login"]
        self.responseValue = -1

        #self.cManager.sendRequest(Constants.CMSG_LOGIN,[self.login,"1234"])
        taskMgr.add(self.enterGame,"EnterGame")

    # Create Powerups
        #self.createPowerups()
        #taskMgr.add(self.powerups.checkPowerPickup, "checkPowerupTask")
        #taskMgr.add(self.usePowerup, "usePowerUp")

    def usePowerup(self, task):
        if self.keyMap["powerup"] == 1:
            self.mainCharRef.usePowerup(0)
        elif self.keyMap["powerup"] == 2:
            self.mainCharRef.usePowerup(1)
        elif self.keyMap["powerup"] == 3:
            self.mainCharRef.usePowerup(2)

        return task.cont

    def createPowerups(self):
        self.powerups = PowerupManager(self.cManager, self.characters)


    def use_powerup3(self):
        self.use_powerup(3)

    def setTime(self):
        self.cManager.sendRequest(Constants.CMSG_TIME)

    def use_powerup(self, num):
        if self.mainCharRef.power_ups[num - 1] == 0:
            print "power-up slot empty"
        else:
            print "power-up", num, "used"

    def doExit(self):
        self.cleanup()
        sys.exit(1)

    def cleanup(self):
        self.cManager.sendRequest(Constants.CMSG_DISCONNECT)
        self.cManager.closeConnection()
        self.world = None
        self.outsideWorldRender.removeNode()

    def doReset(self):
        self.mainCharRef.reset()

    def enterGame(self, task):
        if self.gameState == self.gameStateDict["Login"]:
            #responseValue = 1 indicates that this state has been finished
            if self.responseValue == 1:
                # Authentication succeeded
                self.cManager.sendRequest(Constants.CMSG_CREATE_LOBBY, ["raceroyal","0","1"])
                self.gameState = self.gameStateDict["CreateLobby"]
                self.responseValue = -1
        elif self.gameState == self.gameStateDict["CreateLobby"]:
            if self.responseValue == 1:
                # Lobby Created and we are already in
                self.gameState = self.gameStateDict["EnterGame"]
                self.responseValue = -1
            elif self.responseValue == 0:
                #Game already created, let's join it
                self.cManager.sendRequest(Constants.CMSG_ENTER_GAME_NAME, "raceroyal")
                self.gameState = self.gameStateDict["EnterGame"]
                self.responseValue = -1

        elif self.gameState == self.gameStateDict["EnterGame"]:
            if self.responseValue == 1:
#                 When the positions are sent, an acknowledgment is sent and we begin the InitializeGame
                self.responseValue = -1
                self.gameState = self.gameStateDict["InitializeGame"]
#               Everyone is in the game, we send ReqReady, and the server will send positions when every client did
                self.cManager.sendRequest(Constants.CMSG_READY)


        elif self.gameState == self.gameStateDict["InitializeGame"]:
            if self.responseValue == 1:
                # Set up the camera
                self.camera = Camera(self.mainChar)
                self.gameState = self.gameStateDict["BeginGame"]
                self.cManager.sendRequest(Constants.CMSG_READY)
                self.responseValue = -1

        elif self.gameState == self.gameStateDict["BeginGame"]:
            if self.responseValue == 1:
                self.loading.finish()
                taskMgr.doMethodLater(5, self.move, "moveTask")
                return task.done

        return task.cont

    def createEnvironment(self):
        self.environ = loader.loadModel("models/square")
        self.environ.reparentTo(render)
        self.environ.setPos(0, 0, 0)
        self.environ.setScale(500, 500, 1)
        self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg")
        self.environ.setTexture(self.moon_tex, 1)

        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
        node = BulletRigidBodyNode('Ground')
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(0, 0, 0)

        self.bulletWorld.attachRigidBody(node)

        self.visNP = loader.loadModel('models/track.egg')
        self.tex = loader.loadTexture("models/tex/Main.png")
        self.visNP.setTexture(self.tex)

        geom = self.visNP.findAllMatches('**/+GeomNode').getPath(0).node().getGeom(0)
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)
        trackShape = BulletTriangleMeshShape(mesh, dynamic=False)

        body = BulletRigidBodyNode('Bowl')
        self.visNP.node().getChild(0).addChild(body)
        bodyNP = render.anyPath(body)
        bodyNP.node().addShape(trackShape)
        bodyNP.node().setMass(0.0)
        bodyNP.setTexture(self.tex)

        self.bulletWorld.attachRigidBody(bodyNP.node())

        self.visNP.reparentTo(render)

        self.bowlNP = bodyNP
        self.visNP.setScale(70)

    def initializeBulletWorld(self, debug=False):
        self.outsideWorldRender = render.attachNewNode('world')

        self.bulletWorld = BulletWorld()
        self.bulletWorld.setGravity(Vec3(0, 0, -9.81))
        if debug:
            self.debugNP = self.outsideWorldRender.attachNewNode(BulletDebugNode('Debug'))
            self.debugNP.show()
            self.debugNP.node().showWireframe(True)
            self.debugNP.node().showConstraints(True)
            self.debugNP.node().showBoundingBoxes(True)
            self.debugNP.node().showNormals(False)
            self.bulletWorld.setDebugNode(self.debugNP.node())

    def makeCollisionNodePath(self, nodepath, solid):
        '''
        Creates a collision node and attaches the collision solid to the
        supplied NodePath. Returns the nodepath of the collision node.
        '''
        # Creates a collision node named after the name of the NodePath.
        collNode = CollisionNode("%s c_node" % nodepath.getName())
        collNode.addSolid(solid)
        collisionNodepath = nodepath.attachNewNode(collNode)

        return collisionNodepath

    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def getDist(self):
        mainCharX = self.mainChar.getPos().x
        mainCharY = self.mainChar.getPos().y
        pandaX = self.pandaActor2.getPos().x
        pandaY = self.pandaActor2.getPos().y
        dist = math.sqrt(abs(mainCharX - pandaX) ** 2 + abs(mainCharY - pandaY) ** 2)
        return dist

    def move(self, task):
        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        #dt = globalClock.getDt()

        #update camera
        self.camera.update(self.mainChar)

        #base.camera.lookAt(self.mainChar)
        #if (self.keyMap["cam-left"] != 0):
        #    base.camera.setX(base.camera, -20 * dt)
        #if (self.keyMap["cam-right"] != 0):
        #    base.camera.setX(base.camera, +20 * dt)

        # save mainChar's initial position so that we can restore it,
        # in case he falls off the map or runs into something.
        #
        #startpos = self.mainChar.getPos()
        #
        # If a move-key is pressed, move ralph in the specified direction.
        # If a move-key is pressed, move ralph in the specified direction.
        # Steering info
        #steering = 0.0  # degree
        #steeringClamp = 70.0  # degree
        #steeringIncrement = 180.0  # degree per second
        #
        # Process input
        #engineForce = 0.0
        #brakeForce = 0.0
        #if (self.keyMap["forward"] != 0):
        #    # checks for vehicle's max speed
        #    if self.mainCharRef.vehicle.getCurrentSpeedKmHour() <= self.mainCharRef.max_speed:
        #        engineForce = 2000.0
        #        brakeForce = 0.0
        #
        #if (self.keyMap["backward"] != 0):
        #    if self.mainCharRef.vehicle.getCurrentSpeedKmHour() <= 0:
        #        engineForce = -500.0
        #        brakeForce = 0.0
        #    else:
        #        engineForce = 0.0
        #        brakeForce = 100.0
        #
        #if (self.keyMap["left"] != 0):
        #    steering += dt * steeringIncrement
        #    steering = min(steering, steeringClamp)
        #
        #if (self.keyMap["right"] != 0):
        #    steering -= dt * steeringIncrement
        #    steering = max(steering, -steeringClamp)
        #
        # Apply steering to front wheels
        #self.mainCharRef.vehicle.setSteeringValue(steering, 0)
        #self.mainCharRef.vehicle.setSteeringValue(steering, 1)
        #
        # Apply engine and brake to rear wheels
        #self.mainCharRef.vehicle.applyEngineForce(engineForce, 2)
        #self.mainCharRef.vehicle.applyEngineForce(engineForce, 3)
        #self.mainCharRef.vehicle.setBrake(brakeForce, 2)
        #self.mainCharRef.vehicle.setBrake(brakeForce, 3)

        # If ralph is moving, loop the run animation.
        # If he is standing still, stop the animation.
        #if (self.keyMap["forward"] != 0) or (self.keyMap["backward"] != 0) or (self.keyMap["left"] != 0) or (
        #            self.keyMap["right"] != 0):
        #    if self.isMoving is False:
        #        self.mainCharRef.run()
        #        self.isMoving = True
        #
        #else:
        #    if self.isMoving:
        #        self.mainCharRef.walk()
        #        self.isMoving = False

        dt = globalClock.getDt()

        self.mainCharRef.processInput(inputState, dt)
        self.bulletWorld.doPhysics(dt, 10, 0.02)

        # If the camera is too far from ralph, move it closer.
        # If the camera is too close to ralph, move it farther.

        #camvec = self.mainChar.getPos() - base.camera.getPos()
        #camvec.setZ(0)
        #camdist = camvec.length()
        #camvec.normalize()
        #if (camdist > 10.0):
        #    base.camera.setPos(base.camera.getPos() + camvec * (camdist - 10))
        #    camdist = 10.0
        #if (camdist < 5.0):
        #    base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist))
        #    camdist = 5.0

        # The camera should look in ralph's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above ralph's head.

        #self.floater.setPos(self.mainChar.getPos())
        #self.floater.setZ(self.mainChar.getZ() + 2.0)
        #base.camera.lookAt(self.floater)

        self.bulletWorld.doPhysics(dt)

        return task.cont

    def startConnection(self):
        """Create a connection to the remote host.

        If a connection cannot be created, it will ask the user to perform
        additional retries.

        """
        if self.cManager.connection == None:
            if not self.cManager.startConnection():
                return False

        return True

    # Chat
    # def message(self, task):
    #     # hide all chatboxes
    #     if self.keyMap["chat0"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(0)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat0"] = 0
    #     if self.keyMap["chat1"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(1)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat1"] = 0
    #     elif self.keyMap["chat2"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(2)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat2"] = 0
    #     elif self.keyMap["chat3"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(3)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat3"] = 0
    #     elif self.keyMap["chat4"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(4)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat4"] = 0
    #     elif self.keyMap["chat5"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(5)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat5"] = 0
    #     return task.cont

    def listFromInputState(self, inputState):
        # index 0 == forward
        # index 1 == brake
        # index 2 == right
        # index 3 == left
        result = [0, 0, 0, 0]
        if inputState.isSet('forward'):
            result[0] = 1
        if inputState.isSet('brake'):
            result[1] = 1
        if inputState.isSet('right'):
            result[2] = 1
        if inputState.isSet('left'):
            result[3] = 1

        return result

    def updateMove(self, task):
        if self.isMoving == True:
            moving = self.mainChar.getPos() - self.previousPos

            self.cManager.sendRequest(Constants.CMSG_MOVE,
                                      [moving.getX(), moving.getY(), moving.getZ(), self.mainCharRef.actor.getH(),
                                       self.mainCharRef.actor.getP(),
                                       self.mainCharRef.actor.getR(), self.listFromInputState(inputState)])


            # self.cManager.sendRequest(Constants.RAND_FLOAT, 1.0)
            self.previousPos = self.mainChar.getPos()

        return task.again