Exemple #1
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)