190 lines
6.7 KiB
Python
190 lines
6.7 KiB
Python
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
|