from pandac.PandaModules import Point3, NodePath from direct.fsm.FSM import FSM from direct.interval.IntervalGlobal import ProjectileInterval, Track, ActorInterval from direct.interval.IntervalGlobal import Func, Sequence, Parallel from CogdoMazeGameObjects import CogdoMazeSplattable import CogdoMazeGameGlobals as Globals import CogdoUtil import random class CogdoMazePlayer(FSM, CogdoMazeSplattable): notify = directNotify.newCategory('CogdoMazePlayer') _key = None GagHitEventName = 'CogdoMazePlayer_GagHit' RemovedEventName = 'CogdoMazePlayer_Removed' def __init__(self, id, toon): FSM.__init__(self, 'CogdoMazePlayer') CogdoMazeSplattable.__init__(self, toon, '%s-%i' % (Globals.PlayerCollisionName, id), 0.5) self.id = id self.toon = toon self.defaultTransitions = {'Off': ['Ready'], 'Ready': ['Normal', 'Off'], 'Normal': ['Hit', 'Done', 'Off'], 'Hit': ['Normal', 'Done', 'Off'], 'Done': ['Off']} self.toon.reparentTo(render) self.gagModel = CogdoUtil.loadMazeModel('waterBalloon') self.equippedGag = None self._toonHitSfx = base.cogdoGameAudioMgr.createSfx('toonHit', self.toon) self._throwSfx = base.cogdoGameAudioMgr.createSfxIval('throw') self.accept(toon.getDisableEvent(), self.removed) self.request('Off') return def destroy(self): if self.equippedGag: self.removeGag() del self._toonHitSfx del self._throwSfx CogdoMazeSplattable.destroy(self) def enterOff(self): self.toon.setAnimState('Happy', 1.0) self.toon.setSpeed(0, 0) def exitOff(self): pass def enterReady(self): pass def exitReady(self): pass def enterNormal(self): self.toon.startSmooth() if self.equippedGag is not None: self.equippedGag.unstash() return def exitNormal(self): self.toon.stopSmooth() if self.equippedGag is not None: self.equippedGag.stash() return def enterHit(self, elapsedTime = 0.0): animationInfo = Globals.ToonAnimationInfo['hit'] self._hitIval = self._getToonAnimationIval(animationInfo[0], duration=animationInfo[1], startFrame=animationInfo[2], nextState='Normal') self._hitIval.start(elapsedTime) self._toonHitSfx.play() def exitHit(self): self._hitIval.pause() del self._hitIval if self.equippedGag is not None: self.toon.setAnimState('Catching', 1.0) else: self.toon.setAnimState('Happy', 1.0) return def enterDone(self): self.toon.setAnimState('off', 1.0) def filterDone(self, request, args): if request == 'Done': return None else: return self.defaultFilter(request, args) return None def exitDone(self): pass def handleGameStart(self): self.accept(Globals.GagCollisionName + '-into-' + self.gagCollisionName, self.handleGagHit) def hitByDrop(self): if self.state == 'Normal': self.request('Hit') if self.equippedGag != None: self.removeGag() return def handleGagHit(self, collEntry): gagNodePath = collEntry.getFromNodePath().getParent() messenger.send(self.GagHitEventName, [self.toon.doId, gagNodePath]) def hitByGag(self): self.doSplat() def equipGag(self): if self.equippedGag != None: return self.toon.setAnimState('Catching') holdingGag = self.gagModel.copyTo(self.toon.leftHand) holdingGag.setScale(Globals.GagPickupScale) color = random.choice(Globals.GagColors) holdingGag.setColorScale(color) holdingGag.setZ(-0.2) holdingGag.setX(self.toon, 0) holdingGag.setHpr(0, 0, 0) self.equippedGag = holdingGag return def removeGag(self): if self.equippedGag is None: return self.toon.setAnimState('Happy') self.equippedGag.detachNode() self.equippedGag = None return def createThrowGag(self, gag): throwGag = gag.copyTo(NodePath('gag')) return throwGag def removed(self): messenger.send(self.RemovedEventName, [self]) def showToonThrowingGag(self, heading, pos): gag = self.equippedGag if gag is None: return self.removeGag() tossTrack, flyTrack, object = self.getThrowInterval(gag, pos[0], pos[1], pos[2], heading, 0, 0) def matchRunningAnim(toon = self.toon): toon.playingAnim = None toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed) return newTossTrack = Sequence(tossTrack, Func(matchRunningAnim)) throwTrack = Parallel(newTossTrack, flyTrack) throwTrack.start(0) return object def completeThrow(self): self.toon.loop('neutral') def getThrowInterval(self, gag, x, y, z, h, p, r): toon = self.toon flyGag = self.createThrowGag(gag) throwSoundIval = self._throwSfx if throwSoundIval.isPlaying(): throwSoundIval.finish() throwSoundIval.node = toon toonThrowIval1 = ActorInterval(toon, 'throw', startFrame=Globals.ThrowStartFrame, endFrame=Globals.ThrowEndFrame, playRate=Globals.ThrowPlayRate, partName='torso') toss = Track((0, Sequence(Func(toon.setPosHpr, x, y, z, h, p, r), Func(gag.reparentTo, toon.rightHand), Func(gag.setPosHpr, 0, 0, 0, 0, 0, 0), toonThrowIval1)), (toonThrowIval1.getDuration(), Parallel(Func(gag.detachNode), Sequence(ActorInterval(toon, 'throw', startFrame=Globals.ThrowEndFrame + 1, playRate=Globals.ThrowPlayRate, partName='torso'), Func(self.completeThrow))))) def getEndPos(toon = toon): return render.getRelativePoint(toon, Point3(0, Globals.ThrowDistance, 0)) fly = Track((0, throwSoundIval), (toonThrowIval1.getDuration(), Sequence(Func(flyGag.reparentTo, render), Func(flyGag.setPosHpr, toon, 0.52, 0.97, 2.24, 0, -45, 0), ProjectileInterval(flyGag, endPos=getEndPos, duration=Globals.ThrowDuration), Func(flyGag.detachNode)))) return (toss, fly, flyGag) def _getToonAnimationIval(self, animName, startFrame = 0, duration = 1, nextState = None): totalFrames = self.toon.getNumFrames(animName) frames = totalFrames - 1 - startFrame frameRate = self.toon.getFrameRate(animName) newRate = frames / duration playRate = newRate / frameRate ival = Sequence(ActorInterval(self.toon, animName, startTime=startFrame / newRate, endTime=totalFrames / newRate, playRate=playRate)) if nextState is not None: def done(): self.request(nextState) ival.append(Func(done)) return ival