예제 #1
0
 def activatePhysics(self):
     if self.physics is not None:
         return 1
     self.physics = AeroplanePhysics(self.node)
     self.addTask(self._propellers,
                  "propeller animations",
                  taskChain="world")
     self.addTask(self._flapAnimations, "flaps animations")
예제 #2
0
class Aeroplane(AssetBase):
    """Standard aeroplane class."""
    def __init__(self, name, model=None, physics=False):
        """Arguments:
        name -- Aircraft name.

        model -- Model to load on init. Same as name if none given.
                 A string with the name of a plane in assets/planes/ is
                 expected.
                 0 or False = don't load a model

        physics -- When True, makes this plane physical.

        info:       invisible planes (without model) are for tracking only.
                    you should assign them models when they get into
                    visible range.

                    The idea behind the 'node' is pretty simple: working with
                    a virtual container prevents accidential replacement and
                    seperates things.
        """
        AssetBase.__init__(self)
        self.node = NodePath("aeroplane " + name)

        self.name = name
        self.model = None
        self.animcontrols = None
        self.hud = None
        self.ailerons = 0.0
        self.elevator = 0.0
        self.rudder = 0.0
        self.propellers = []

        if model is None:
            model = name
        if model:
            self.model, self.animcontrols = self.loadPlaneModel(model)
            self.model.reparentTo(self.node)

        self.physics = None
        if physics:
            self.activatePhysics()

    def loadPlaneModel(self, modelname):
        """Loads models and animations from the planes directory."""
        animcontrols = {}
        model = loader.loadModel("planes/{0}/{0}".format(modelname))
        actor = Actor(model,
                      setFinal=True,
                      mergeLODBundles=True,
                      allowAsyncBind=False,
                      okMissing=False)
        #actor = Actor(model, lodNode="mid")

        subparts = (
            # subpart,       joints,                   animations
            ("Doors", ["Windscreen*", "Door*"], ("Open", "Close")),
            #("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", "LG In")),
            ("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", )),
            ("Ailerons", ["Aileron*"], ("Roll Left", "Roll Right")),
            ("Rudders", ["Rudder*"], ("Head Left", "Head Right")),
            ("Elevators", ["Elevator*"], ("Pitch Up", "Pitch Down")))

        for line in subparts:
            subpart, joints, anims = line
            actor.makeSubpart(subpart, joints)

            path = "planes/{0}/{0}-{{0}}".format(modelname)
            d = dict((anim, path.format(anim)) for anim in anims)

            #actor.loadAnims(d, subpart, "mid")
            actor.loadAnims(d, subpart)
            for anim in anims:
                #actor.bindAnim(anim, subpart, "mid")
                actor.bindAnim(anim, subpart)
                #animcontrols[anim] = actor.getAnimControls(anim, subpart,
                #                                           "mid", False)[0]
                animcontrols[anim] = actor.getAnimControls(
                    anim, subpart, None, False)[0]
        actor.makeSubpart("propellers", "Propeller*")
        actor.verifySubpartsComplete()
        actor.setSubpartsComplete(True)
        for p in actor.getJoints("propellers", "Propeller*", "lodRoot"):
            self.propellers.append(
                actor.controlJoint(None, "propellers", p.getName()))
        #actor.pprint()

        cams = model.findAllMatches("**/camera ?*")
        if not cams.isEmpty():
            cameras = actor.attachNewNode("cameras")
            cams.reparentTo(cameras)

        return actor, animcontrols

    def activatePhysics(self):
        if self.physics is not None:
            return 1
        self.physics = AeroplanePhysics(self.node)
        self.addTask(self._propellers,
                     "propeller animations",
                     taskChain="world")
        self.addTask(self._flapAnimations, "flaps animations")

    def deactivatePhysics(self):
        if self.physics is None:
            return 1
        self.physics.destroy()
        self.physics = None
        self.removeTask(self._propellers)
        self.removeTask(self._flapAnimations)

    def _flapAnimations(self, task):
        if self.physics is None:
            return 1

        roll = {
            -1: self.animcontrols["Roll Left"],
            1: self.animcontrols["Roll Right"]
        }
        pitch = {
            -1: self.animcontrols["Pitch Down"],
            1: self.animcontrols["Pitch Up"]
        }
        head = {
            -1: self.animcontrols["Head Right"],
            1: self.animcontrols["Head Left"]
        }
        for flaps, state in ((roll, self.physics.ailerons),
                             (pitch, self.physics.elevator),
                             (head, self.physics.rudder)):
            if state == 0.0:
                for f in flaps:
                    if (flaps[f].isPlaying() == 1) and \
                       (flaps[f].getPlayRate() > 0):
                        flaps[f].setPlayRate(-1)
                    elif flaps[f].getFrame() == flaps[f].getNumFrames() - 1:
                        if flaps[f].getPlayRate() > 0:
                            flaps[f].setPlayRate(-1)
                        flaps[f].play()
                    if (flaps[f].isPlaying() == 1) and \
                       (flaps[f].getFrame() == 0):
                        flaps[f].stop()
            else:
                if flaps[state * -1].isPlaying() == 1:
                    if flaps[state * -1].getPlayRate() > 0:
                        flaps[state * -1].setPlayRate(-1)
                    else:
                        if flaps[state * -1].getFrame() == 0:
                            flaps[state * -1].stop()
                else:
                    if flaps[state*-1].getFrame() == \
                                             flaps[state*-1].getNumFrames()-1:
                        if flaps[state * -1].getPlayRate() > 0:
                            flaps[state * -1].setPlayRate(-1)
                        flaps[state * -1].play()
                    else:
                        if (flaps[state].isPlaying() == 0):
                            if not (flaps[state].getFrame() == \
                                             (flaps[state].getNumFrames()-1)):
                                flaps[state].setPlayRate(1)
                                flaps[state].play()
                        elif flaps[state].getPlayRate() < 0:
                            flaps[state].setPlayRate(1)

        return Task.cont

    def _propellers(self, task):
        if self.physics is None:
            return 1
        if self.physics.thrust > 0:
            delta_time = global_clock.getDt()
            for p in self.propellers:
                p.setP(p, (self.physics.thrust * delta_time * 500))
        return Task.cont

    def __str__(self):
        return self.name

    def __repr__(self):
        r = "Aeroplane {}\n"
        r += "model: {}\n"
        r += "physics: {}\n"
        r = r.format(self.name, self.model, self.physics)
        return r