def activatePhysics(self): if self.physics is not None: return 1 self.physics = AeroplanePhysics(self.node) self.addTask(self._propellers, "propeller animations for plane %s" % self.id, taskChain="world") self.addTask(self._flapAnimations, "flaps animations for plane %s" % self.id)
class Aeroplane(DirectObject): """Standard aeroplane class.""" _plane_count = 0 aircrafts = None 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. """ if Aeroplane.aircrafts is None: assert render Aeroplane.aircrafts = render.attachNewNode("aircrafts") self.id = Aeroplane._plane_count Aeroplane._plane_count += 1 self.node = Aeroplane.aircrafts.attachNewNode( "aeroplane {0} {1}".format(self.id, 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 for plane %s" % self.id, taskChain="world") self.addTask(self._flapAnimations, "flaps animations for plane %s" % self.id) 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