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 from . import CogdoMazeGameGlobals as Globals from . 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