def getAIShip(self, shipClass): ShipAI = ShipAI import pirates.ship modelClass = ShipGlobals.getModelClass(shipClass) hull = self.getHull(modelClass, 0) root = NodePath('Ship') collisions = root.attachNewNode('collisions') mastSetup = ShipGlobals.getMastSetup(shipClass) for data in [ (0, 'location_mainmast_0'), (1, 'location_mainmast_1'), (2, 'location_mainmast_2'), (3, 'location_aftmast*'), (4, 'location_foremast*')]: mastData = mastSetup.get(data[0]) if mastData: mast = self.mastSets[mastData[0]].getMastSet(mastData[1] - 1) model = NodePath(mast.charRoot) model.setPos(hull.locators.find('**/%s' % data[1]).getPos(hull.locators)) model.setHpr(hull.locators.find('**/%s' % data[1]).getHpr(hull.locators)) model.setScale(hull.locators.find('**/%s' % data[1]).getScale(hull.locators)) if modelClass > ShipGlobals.INTERCEPTORL3 or data[0] != 3: mastCode = str(data[0]) else: mastCode = '0' mast.collisions.find('**/collision_masts').setTag('Mast Code', mastCode) collisions.node().stealChildren(mast.collisions.node()) continue collisions.node().stealChildren(hull.collisions.node()) hull.locators.reparentTo(root) ship = ShipAI.ShipAI(root, collisions, hull.locators) ship.modelRoot.setTag('Mast Code', str(255)) ship.modelRoot.setTag('Hull Code', str(255)) return ship
def draw(self): format=GeomVertexFormat.getV3n3cpt2() vdata=GeomVertexData('square', format, Geom.UHDynamic) vertex=GeomVertexWriter(vdata, 'vertex') normal=GeomVertexWriter(vdata, 'normal') color=GeomVertexWriter(vdata, 'color') circle=Geom(vdata) # Create vertices vertex.addData3f(self.pos) color.addData4f(self.color) for v in range(self._EDGES): x = self.pos.getX() + (self.size * math.cos((2*math.pi/self._EDGES)*v)) y = self.pos.getY() + (self.size * math.sin((2*math.pi/self._EDGES)*v)) z = self.pos.getZ() vertex.addData3f(x, y, z) color.addData4f(self.color) # Create triangles for t in range(self._EDGES): tri = GeomTriangles(Geom.UHDynamic) tri.addVertex(0) tri.addVertex(t+1) if (t+2) > self._EDGES: tri.addVertex(1) else: tri.addVertex(t+2) tri.closePrimitive() circle.addPrimitive(tri) gn = GeomNode('Circle') gn.addGeom(circle) np = NodePath(gn) np.setHpr(0, 90, 0) return np
def getDoorNodePath(self): if self.doorType == DoorTypes.EXT_ANIM_STANDARD: if hasattr(self, 'tempDoorNodePath'): return self.tempDoorNodePath building = self.getBuilding() doorNP = building.find('**/door_origin') self.notify.debug('creating doorOrigin at %s %s' % (str(doorNP.getPos()), str(doorNP.getHpr()))) otherNP = NodePath('doorOrigin') otherNP.setPos(doorNP.getPos()) otherNP.setHpr(doorNP.getHpr()) otherNP.reparentTo(doorNP.getParent()) self.tempDoorNodePath = otherNP else: self.notify.error('DistributedAnimDoor.getDoorNodePath with doorType=%s' % self.doorType) return otherNP
def createVisualNode(self, pos=(0, 0)): # modelNode is the actualy ship model modelNode = loader.loadModel("indicator.bam") # visualNode is the node we operate on to move and rotate the ship visualNode = NodePath('Ship: ' + self.name) visualNode.setPos(tupleToVec3(pos)) visualNode.setHpr(Vec3(0, -90, 90)) # TODO: add scale parameter to this or some other aggregator class visualNode.setScale(1) # Reparent the actual modelNode to the visualNode modelNode.reparentTo(visualNode) # Offset the model node relative to the parent modelNode.setPos(tripleToVec3(Ship.MODEL_ROTATION_OFFSET)) visualNode.reparentTo(render) return visualNode
def getDoorNodePath(self): if self.doorType == DoorTypes.EXT_ANIM_STANDARD: if hasattr(self, 'tempDoorNodePath'): return self.tempDoorNodePath else: building = self.getBuilding() doorNP = building.find('**/door_origin') self.notify.debug('creating doorOrigin at %s %s' % (str(doorNP.getPos()), str(doorNP.getHpr()))) otherNP = NodePath('doorOrigin') otherNP.setPos(doorNP.getPos()) otherNP.setHpr(doorNP.getHpr()) otherNP.reparentTo(doorNP.getParent()) self.tempDoorNodePath = otherNP else: self.notify.error('DistributedAnimDoor.getDoorNodePath with doorType=%s' % self.doorType) return otherNP
def CreateRing( self, vector, colour, rot ): # Create an arc arc = Arc( numSegs=32, degrees=180, axis=Vec3(0, 0, 1) ) arc.setH( 180 ) # Create the axis from the arc axis = Axis( self.name, vector, colour ) axis.AddGeometry( arc, sizeStyle=SCALE ) axis.AddCollisionSolid( self.collSphere, sizeStyle=SCALE ) axis.reparentTo( self ) # Create the billboard effect and apply it to the arc. We need an # extra NodePath to help the billboard effect so it orients properly. hlpr = NodePath( 'helper' ) hlpr.setHpr( rot ) hlpr.reparentTo( self ) arc.reparentTo( hlpr ) bbe = BillboardEffect.make( Vec3(0, 0, 1), False, True, 0, self.camera, (0, 0, 0) ) arc.setEffect( bbe ) return axis
def draw(self): format = GeomVertexFormat.getV3n3cpt2() vdata = GeomVertexData('square', format, Geom.UHDynamic) vertex = GeomVertexWriter(vdata, 'vertex') normal = GeomVertexWriter(vdata, 'normal') color = GeomVertexWriter(vdata, 'color') circle = Geom(vdata) # Create vertices vertex.addData3f(self.pos) color.addData4f(self.color) for v in range(self._EDGES): x = self.pos.getX() + (self.size * math.cos( (2 * math.pi / self._EDGES) * v)) y = self.pos.getY() + (self.size * math.sin( (2 * math.pi / self._EDGES) * v)) z = self.pos.getZ() vertex.addData3f(x, y, z) color.addData4f(self.color) # Create triangles for t in range(self._EDGES): tri = GeomTriangles(Geom.UHDynamic) tri.addVertex(0) tri.addVertex(t + 1) if (t + 2) > self._EDGES: tri.addVertex(1) else: tri.addVertex(t + 2) tri.closePrimitive() circle.addPrimitive(tri) gn = GeomNode('Circle') gn.addGeom(circle) np = NodePath(gn) np.setHpr(0, 90, 0) return np
class DistributedButterfly(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedButterfly') id = 0 wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6') yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1)) whiteColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0, 0.8, 0.8, 1), Vec4(0.9, 0.4, 0.6, 1), Vec4(0.9, 0.4, 0.4, 1), Vec4(0.8, 0.5, 0.9, 1), Vec4(0.4, 0.1, 0.7, 1)) paleYellowColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0.6, 0.6, 0.9, 1), Vec4(0.7, 0.6, 0.9, 1), Vec4(0.8, 0.6, 0.9, 1), Vec4(0.9, 0.6, 0.9, 1), Vec4(1, 0.6, 0.9, 1)) shadowScaleBig = Point3(0.07, 0.07, 0.07) shadowScaleSmall = Point3(0.01, 0.01, 0.01) def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying'])], 'off', 'off') self.butterfly = None self.butterflyNode = None self.curIndex = 0 self.destIndex = 0 self.time = 0.0 self.ival = None self.fsm.enterInitialState() return def generate(self): DistributedObject.DistributedObject.generate(self) if self.butterfly: return self.butterfly = Actor.Actor() self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod') self.butterfly.loadAnims({'flutter': 'phase_4/models/props/SZ_butterfly-flutter', 'glide': 'phase_4/models/props/SZ_butterfly-glide', 'land': 'phase_4/models/props/SZ_butterfly-land'}) index = self.doId % len(self.wingTypes) chosenType = self.wingTypes[index] node = self.butterfly.getGeomNode() for type in self.wingTypes: wing = node.find('**/' + type) if type != chosenType: wing.removeNode() else: if index == 0 or index == 1: color = self.yellowColors[self.doId % len(self.yellowColors)] elif index == 2 or index == 3: color = self.whiteColors[self.doId % len(self.whiteColors)] elif index == 4: color = self.paleYellowColors[self.doId % len(self.paleYellowColors)] else: color = Vec4(1, 1, 1, 1) wing.setColor(color) self.butterfly2 = Actor.Actor(other=self.butterfly) self.butterfly.enableBlend(blendType=PartBundle.BTLinear) self.butterfly.loop('flutter') self.butterfly.loop('land') self.butterfly.loop('glide') rng = RandomNumGen.RandomNumGen(self.doId) playRate = 0.6 + 0.8 * rng.random() self.butterfly.setPlayRate(playRate, 'flutter') self.butterfly.setPlayRate(playRate, 'land') self.butterfly.setPlayRate(playRate, 'glide') self.butterfly2.setPlayRate(playRate, 'flutter') self.butterfly2.setPlayRate(playRate, 'land') self.butterfly2.setPlayRate(playRate, 'glide') self.glideWeight = rng.random() * 2 lodNode = LODNode('butterfly-node') lodNode.addSwitch(100, 40) lodNode.addSwitch(40, 0) self.butterflyNode = NodePath(lodNode) self.butterfly2.setH(180.0) self.butterfly2.reparentTo(self.butterflyNode) self.butterfly.setH(180.0) self.butterfly.reparentTo(self.butterflyNode) self.__initCollisions() self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow.setColor(0, 0, 0, 0.3) self.dropShadow.setPos(0, 0.1, -0.05) self.dropShadow.setScale(self.shadowScaleBig) self.dropShadow.reparentTo(self.butterfly) def disable(self): self.butterflyNode.reparentTo(hidden) if self.ival != None: self.ival.finish() self.__ignoreAvatars() DistributedObject.DistributedObject.disable(self) return def delete(self): self.butterfly.cleanup() self.butterfly = None self.butterfly2.cleanup() self.butterfly2 = None self.butterflyNode.removeNode() self.__deleteCollisions() self.ival = None del self.fsm DistributedObject.DistributedObject.delete(self) return def uniqueButterflyName(self, name): DistributedButterfly.id += 1 return name + '-%d' % DistributedButterfly.id def __detectAvatars(self): self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter) def __ignoreAvatars(self): self.ignore('enter' + self.cSphereNode.getName()) def __initCollisions(self): self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0) self.cSphere.setTangible(0) self.cSphereNode = CollisionNode(self.uniqueButterflyName('cSphereNode')) self.cSphereNode.addSolid(self.cSphere) self.cSphereNodePath = self.butterflyNode.attachNewNode(self.cSphereNode) self.cSphereNodePath.hide() self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __deleteCollisions(self): del self.cSphere del self.cSphereNode self.cSphereNodePath.removeNode() del self.cSphereNodePath def __handleCollisionSphereEnter(self, collEntry): self.sendUpdate('avatarEnter', []) def setArea(self, playground, area): self.playground = playground self.area = area def setState(self, stateIndex, curIndex, destIndex, time, timestamp): self.curIndex = curIndex self.destIndex = destIndex self.time = time self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)]) def enterOff(self, ts = 0.0): if self.butterflyNode != None: self.butterflyNode.reparentTo(hidden) return def exitOff(self): if self.butterflyNode != None: self.butterflyNode.reparentTo(render) return def enterFlying(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex] destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.destIndex] flyHeight = max(curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground] curPosHigh = Point3(curPos[0], curPos[1], flyHeight) destPosHigh = Point3(destPos[0], destPos[1], flyHeight) if ts <= self.time: flyTime = self.time - (ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground]) self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) oldHpr = self.butterflyNode.getHpr() self.butterflyNode.headsUp(destPos) newHpr = self.butterflyNode.getHpr() self.butterflyNode.setHpr(oldHpr) takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[self.playground] self.butterfly2.loop('flutter') self.ival = Sequence(Parallel(LerpPosHprInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence(LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel(LerpPosInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence(Wait(ButterflyGlobals.BUTTERFLY_LANDING[self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly')) self.ival.start(ts) else: self.ival = None self.butterflyNode.setPos(destPos) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.loop('land') return def exitFlying(self): self.__ignoreAvatars() if self.ival != None: self.ival.finish() self.ival = None return def enterLanded(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex] self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.pose('land', random.randrange(self.butterfly2.getNumFrames('land'))) return None def exitLanded(self): self.__ignoreAvatars() return None
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2])) self._lookAtZ = self._toon.getHeight( ) + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath('CamParent') self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath('CameraLookAt') self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / ( maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[ 1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E**(dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr( smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find('col_') >= 0: np = entry.getIntoNodePath().getParent() if not np in nodesInBetween: nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if np in self._betweenCamAndToon: del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').hide() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').show() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').show() self._betweenCamAndToon = nodesInBetween
class CogdoMazeGameIntro(CogdoGameMovie): def __init__(self, maze, exit, rng): CogdoGameMovie.__init__(self) self._maze = maze self._exit = exit self._rng = RandomNumGen(rng) self._camTarget = None self._state = 0 self._suits = [] def _getRandomLine(self, lineList): return CogdoUtil.getRandomDialogueLine(lineList, self._rng) def displayLine(self, who, text): self._dialogueLabel.node().setText(text) if who == 'toon': self.toonHead.reparentTo(aspect2d) self.cogHead.reparentTo(hidden) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) else: self.toonHead.reparentTo(hidden) self.cogHead.reparentTo(aspect2d) self._cogDialogueSfx.play() self.cogHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1, 1, 2) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() def load(self): CogdoGameMovie.load(self) self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.cogHead = Suit.Suit() self.cogDNA = SuitDNA.SuitDNA() self.cogDNA.newSuit('ms') self.cogHead.setDNA(self.cogDNA) self.cogHead.getGeomNode().setDepthWrite(1) self.cogHead.getGeomNode().setDepthTest(1) self.cogHead.loop('neutral') self.cogHead.setPosHprScale(-0.73, 0, -1.46, 180, 0, 0, 0.14, 0.14, 0.14) self.cogHead.reparentTo(hidden) self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) audioMgr = base.cogdoGameAudioMgr self._cogDialogueSfx = audioMgr.createSfx('cogDialogue') self._toonDialogueSfx = audioMgr.createSfx('toonDialogue') suitData = Globals.SuitData[Globals.SuitTypes.Boss] bossSuit = Suit.Suit() bossSuit.nametag3d.stash() bossSuit.nametag.destroy() d = SuitDNA.SuitDNA() d.newSuit(suitData['dnaName']) bossSuit.setDNA(d) bossSuit.setScale(suitData['scale']) bossSuit.loop('neutral') bossSuit.reparentTo(render) bossSuit.setPos(self._exit, -5, -5, 0) bossSuit.lookAt(self._exit) self._suits.append(bossSuit) self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoMazeIntroMovieDialogue introDuration = Globals.IntroDurationSeconds waitDuration = introDuration / len(dialogue) def start(): camera.wrtReparentTo(render) self._exit.open(animate=False) def showBoss(): self._setCamTarget(bossSuit, 20, offset=Point3(0, 0, 7), angle=Point3(0, 15, 0)) bossSuit.loop('victory') self._state = 1 def showExit(): self._setCamTarget(self._exit, 10, offset=Point3(0, 0, 0), angle=Point3(0, 60, 0)) self._exit.close() self._state = 2 showExitIval = Parallel(camera.posInterval(waitDuration * 0.5, (10, -25, 20), other=self._exit, blendType='easeInOut'), Sequence(Wait(waitDuration * 0.25), Func(bossSuit.play, 'effort'), camera.hprInterval(waitDuration * 0.25, (30, -30, 0), blendType='easeInOut'), Func(self._exit.close), Wait(waitDuration * 0.5))) def showWaterCooler(): wc = self._maze.getWaterCoolers()[0] self._setCamTarget(wc, 25, angle=Point3(-30, 60, 0)) camera.wrtReparentTo(self._camHelperNode) self._state = 3 def end(): self._stopUpdateTask() self._ival = Sequence(Func(start), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[0])), showExitIval, Func(showWaterCooler), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[1])), Wait(waitDuration), Func(showBoss), bossSuit.hprInterval(1.0, bossSuit.getHpr() + Point3(180, 0, 0), blendType='easeInOut'), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[2])), Wait(waitDuration - 1.0), Func(end)) self._startUpdateTask() def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)): camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) camera.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() if self._state == 1: self._camHelperNode.setPos(self._camTarget.getPos() + self._camOffset) camera.setPos(self._camHelperNode, 0, self._camDistance, 0) camera.lookAt(self._camTarget, 0, 0, 4) elif self._state == 2: camera.lookAt(self._camTarget, 0, 0, 5) elif self._state == 3: self._camHelperNode.setHpr(self._camHelperNode, dt, dt, 0) camera.setY(camera, 0.8 * dt) camera.lookAt(self._camTarget, 0, 0, 3) return task.cont def unload(self): self._exit = None self._camTarget = None self._camHelperNode.removeNode() del self._camHelperNode for suit in self._suits: suit.cleanup() suit.removeNode() suit.delete() self._suits = [] CogdoGameMovie.unload(self) del self._cogDialogueSfx del self._toonDialogueSfx self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead self.cogHead.stop() self.cogHead.removeNode() self.cogHead.delete() del self.cogHead
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ( (levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2]), ) self._lookAtZ = self._toon.getHeight() + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath("CamParent") self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath("CameraLookAt") self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode("CameraToonRay") camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask( OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask ) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath("trans") self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin("fixed", 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / (maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E ** (dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr(smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find("col_") >= 0: np = entry.getIntoNodePath().getParent() if not nodesInBetween.has_key(np): nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if self._betweenCamAndToon.has_key(np): del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").hide() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").show() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").show() self._betweenCamAndToon = nodesInBetween
class Translation( Base ): def __init__( self, *args, **kwargs ): Base.__init__( self, *args, **kwargs ) # Create x, y, z and camera normal axes self.axes.append( self.CreateArrow( Vec3(1, 0, 0), RED ) ) self.axes.append( self.CreateArrow( Vec3(0, 1, 0), GREEN ) ) self.axes.append( self.CreateArrow( Vec3(0, 0, 1), BLUE ) ) self.axes.append( self.CreateSquare( Vec3(0, 0, 0), TEAL ) ) def CreateArrow( self, vector, colour ): # Create the geometry and collision line = NodePath( Line( (0, 0, 0), vector ) ) cone = NodePath( Cone( 0.05, 0.25, axis=vector, origin=vector * 0.125 ) ) collTube = CollisionTube( (0,0,0), Point3( vector ) * 0.95, 0.05 ) # Create the axis, add the geometry and collision axis = Axis( self.name, vector, colour ) axis.AddGeometry( line, sizeStyle=SCALE ) axis.AddGeometry( cone, vector, colour ) axis.AddCollisionSolid( collTube, sizeStyle=TRANSLATE_POINT_B ) axis.reparentTo( self ) return axis def CreateSquare( self, vector, colour ): # Create the geometry and collision self.square = NodePath( Square( 0.2, 0.2, Vec3(0, 1, 0) ) ) self.square.setBillboardPointEye() collSphere = CollisionSphere( 0, 0.125 ) # Create the axis, add the geometry and collision axis = Axis( self.name, CAMERA_VECTOR, colour, planar=True, default=True ) axis.AddGeometry( self.square, sizeStyle=NONE ) axis.AddCollisionSolid( collSphere, sizeStyle=NONE ) axis.reparentTo( self ) return axis def Transform( self ): # Get the point where the mouse clicked the axis axis = self.GetSelectedAxis() axisPoint = self.GetAxisPoint( axis ) # Get the gizmo's translation matrix and transform it newTransMat = Mat4().translateMat( self.initXform.getPos() - self.getPos() + axisPoint - self.initMousePoint ) self.setMat( self.getMat() * newTransMat ) # Get the attached node path's translation matrix transVec = axisPoint - self.initMousePoint if axis.vector != CAMERA_VECTOR: transVec = self.getRelativeVector( self.rootNp, transVec ) * self.getScale()[0] newTransMat = Mat4().translateMat( transVec ) # Transform attached node paths for i, np in enumerate( self.attachedNps ): # Perform transforms in local or world space if self.local and axis.vector != CAMERA_VECTOR: transMat, rotMat, scaleMat = commonUtils.GetTrsMatrices( self.initNpXforms[i] ) np.setMat( scaleMat * newTransMat * rotMat * transMat ) else: np.setMat( self.initNpXforms[i].getMat() * newTransMat ) def OnNodeMouse1Down( self, planar, collEntry ): Base.OnNodeMouse1Down( self, planar, collEntry ) # Store the gizmo's initial transform self.initXform = self.getTransform() # If in planar mode, clear the billboard effect on the center square # and make it face the selected axis axis = self.GetSelectedAxis() if self.planar and not axis.planar: self.square.clearBillboard() self.square.lookAt( self, Point3( axis.vector ) ) else: self.square.setHpr( Vec3(0, 0, 0) ) self.square.setBillboardPointEye() def OnMouse2Down( self ): Base.OnMouse2Down( self ) # Store the gizmo's initial transform self.initXform = self.getTransform()
class Camera(DirectObject): def __init__(self, heightfield): self.heightfield = heightfield base.camLens.setFar(25000) base.camera.setPos(Vec3(0, 6000, 3000)) self.camControlNp = NodePath("camControlNp") base.camera.reparentTo(self.camControlNp) self.camControlNp.reparentTo(render) base.camera.lookAt(self.camControlNp) self.guiposOnscreenText = OnscreenText( text="position", fg=(1, 1, 1, 1), pos=(-0.9, 0.9), scale=0.07, mayChange=True, align=TextNode.ALeft ) taskMgr.doMethodLater(0.1, self.updateGuiPosTask, "updateGuiPosTask") taskMgr.add(self.setHeight, "updateGuiPosTask") self.accept("w", self.forward) self.accept("a", self.left) self.accept("s", self.back) self.accept("d", self.right) self.accept("q", self.clockwise) self.accept("e", self.anticlockwise) self.accept("r", self.zoomIn) self.accept("f", self.zoomOut) self.accept("w-up", self.forwardOff) self.accept("a-up", self.leftOff) self.accept("s-up", self.backOff) self.accept("d-up", self.rightOff) self.accept("q-up", self.clockwiseOff) self.accept("e-up", self.anticlockwiseOff) self.accept("r-up", self.zoomInOff) self.accept("f-up", self.zoomOutOff) def forward(self): taskMgr.add( self.updateCamPosTask, "camForward", extraArgs=[Vec3(0, -1, 0), Vec3(0, 0, 0), Vec3(0, 0, 0)], appendTask=True, ) def back(self): taskMgr.add( self.updateCamPosTask, "camBack", extraArgs=[Vec3(0, 1, 0), Vec3(0, 0, 0), Vec3(0, 0, 0)], appendTask=True ) def left(self): taskMgr.add( self.updateCamPosTask, "camLeft", extraArgs=[Vec3(1, 0, 0), Vec3(0, 0, 0), Vec3(0, 0, 0)], appendTask=True ) def right(self): taskMgr.add( self.updateCamPosTask, "camRight", extraArgs=[Vec3(-1, 0, 0), Vec3(0, 0, 0), Vec3(0, 0, 0)], appendTask=True ) def clockwise(self): taskMgr.add( self.updateCamPosTask, "camClockwise", extraArgs=[Vec3(0, 0, 0), Vec3(-1, 0, 0), Vec3(0, 0, 0)], appendTask=True, ) def anticlockwise(self): taskMgr.add( self.updateCamPosTask, "camAnticlockwise", extraArgs=[Vec3(0, 0, 0), Vec3(1, 0, 0), Vec3(0, 0, 0)], appendTask=True, ) def zoomIn(self): taskMgr.add( self.updateCamPosTask, "camZoomIn", extraArgs=[Vec3(0, 0, 0), Vec3(0, 0, 0), Vec3(0, 1, 0)], appendTask=True ) def zoomOut(self): taskMgr.add( self.updateCamPosTask, "camZoomOut", extraArgs=[Vec3(0, 0, 0), Vec3(0, 0, 0), Vec3(0, -1, 0)], appendTask=True, ) def forwardOff(self): taskMgr.remove("camForward") def backOff(self): taskMgr.remove("camBack") def leftOff(self): taskMgr.remove("camLeft") def rightOff(self): taskMgr.remove("camRight") def clockwiseOff(self): taskMgr.remove("camClockwise") def anticlockwiseOff(self): taskMgr.remove("camAnticlockwise") def zoomInOff(self): taskMgr.remove("camZoomIn") def zoomOutOff(self): taskMgr.remove("camZoomOut") def updateCamPosTask(self, pos, hpr, zoom, task): timeMulti = 45.0 * globalClock.getDt() timeMultiPos = Vec3(timeMulti * pos.getX(), timeMulti * pos.getY(), timeMulti * pos.getZ()) timeMultiHpr = Vec3(timeMulti * hpr.getX(), timeMulti * hpr.getY(), timeMulti * hpr.getZ()) timeMultiZoom = Vec3(timeMulti * zoom.getX(), timeMulti * zoom.getY(), timeMulti * zoom.getZ()) self.camControlNp.setPos(self.camControlNp, timeMultiPos * 20) self.camControlNp.setHpr(self.camControlNp, timeMultiHpr) base.camera.setPos(base.camera, timeMultiZoom * 20) return task.cont def setHeight(self, task): pos = [self.camControlNp.getX(), self.camControlNp.getY()] elevation = self.heightfield.get_elevation(pos) self.camControlNp.setZ(render, elevation) return task.cont def updateGuiPosTask(self, task): text = "%s:%s" % (str(base.camera.getPos(render)), str(base.camera.getHpr(render))) self.guiposOnscreenText.setText(text) return Task.again
def createSector(self, sectorId): (sectorX, sectorY) = sectorId # print "creating sector %s" % str(sectorId) # init seed depending on quadrant we are currently in random.seed(sectorId) if self.usingLod: plantLodNpChilds = [NodePath("lod-0-%s" % str(sectorId)), NodePath("lod-1-%s" % str(sectorId))] else: tileNode = self.plantClassNp.attachNewNode("tileNode-%s" % str(sectorId)) tempTileNode = NodePath("tempTileNode-%s" % str(sectorId)) # create each plant with the given chance in the sector for ( plantName, [plantChance, plantModel, plantMinScale, plantScaleVariance, [noiseFunc, distFunc, distParams]], ) in self.plantModelDict.items(): # maximum number of plants of this type averagePlantCount = (plantChance / 100.0) * self.sizeOfTile ** 2 # well use ceil, if not some plants may never be generated plantCount = math.ceil(averagePlantCount) distFuncResultAccumulated = 0.0 # print "planning to create %i plants" % plantCount [commented by Finn] # creating plantCount number of plants placedPlantCounter = 0 for plantId in xrange(int(plantCount)): # select position the plant will have posX = random.randint(0, self.sizeOfTile) + (sectorX * self.sizeOfTile) posY = random.randint(0, self.sizeOfTile) + (sectorY * self.sizeOfTile) # get z position of ground posZ = self.heightfield.get_elevation([posX, posY]) # the absolue world position of the plant absoluteWorldPosition = Vec3(posX, posY, posZ) # decide if we want to place this plant based on the noise function noiseFuncResult = noiseFunc(posX, posY) distFuncResult = distFunc(noiseFuncResult, *distParams) # make sure the plants are placed evenly distFuncResultAccumulated += distFuncResult if distFuncResultAccumulated > 1.0: placedPlantCounter += 1 # print "plant" # place a plant distFuncResultAccumulated -= 1.0 # select scale & rotation of plant scale = random.random() rotation = random.randint(0, 360) # load model if self.usingLod: # save that we are using lod, we cant flatten if we are # usingLod = True # setup lod nodepath # plantLodNp = NodePath(FadeLODNode('lod')) # plantLodNp.reparentTo(self.plantClassNp) i = 0 for [maxLodDist, minLodDistance, lodModelName] in plantModel: # print "creating lod %i of plant %s" % (i, plantName) [commented by Finn] tempPlantNp = loader.loadModel(lodModelName + ".egg") plantNp = NodePath("model-%s" % str(absoluteWorldPosition)) tempPlantNp.getChildren().reparentTo(plantNp) # flatten the nodepath # plantNp.flattenStrong() # set position of plant plantNp.setPos(absoluteWorldPosition) plantNp.setHpr(rotation, 0, 0) finalScale = plantMinScale + scale * plantScaleVariance plantNp.setScale(finalScale) # add plant to tile plantNp.reparentTo(plantLodNpChilds[i]) # i += 1 else: # plantNp = loader.loadModelCopy( plantModel+".egg" ) # plantNp.reparentTo( tileNode ) tempPlantNp = loader.loadModelCopy(plantModel + ".egg") plantNp = NodePath("model-%s" % str(absoluteWorldPosition)) tempPlantNp.getChildren().reparentTo(plantNp) tempPlantNp.removeNode() # flatten the nodepath # plantNp.flattenStrong() # add plant to tile plantNp.reparentTo(tempTileNode) # set position of plant plantNp.setPos(absoluteWorldPosition) plantNp.setHpr(rotation, 0, 0) finalScale = plantMinScale + scale * plantScaleVariance plantNp.setScale(finalScale) # print "planted %i plants" % placedPlantCounter # flatten the tile if not using lod if self.usingLod: plantLodNpChilds[0].flattenStrong() plantLodNpChilds[1].flattenStrong() fadeLodNode = FadeLODNode("lod-%s" % str(sectorId)) absolutePosX = (sectorX * self.sizeOfTile) + self.sizeOfTile / 2.0 absolutePosY = (sectorY * self.sizeOfTile) + self.sizeOfTile / 2.0 absolutePosZ = self.heightfield.get_elevation([absolutePosX, absolutePosY]) fadeLodNode.setCenter(Point3(absolutePosX, absolutePosY, absolutePosZ)) plantLodNp = NodePath(fadeLodNode) # plantLodNp = NodePath('lod-%s' % str(sectorId)) plantLodNpChilds[0].reparentTo(plantLodNp) plantLodNp.node().addSwitch(9999, self.sizeOfTile * 2.0) plantLodNpChilds[1].reparentTo(plantLodNp) plantLodNp.node().addSwitch(self.sizeOfTile * 2.0, 0) self.tileDict[sectorId] = plantLodNp plantLodNp.reparentTo(self.plantClassNp) if FADEIN: self.makeFadeIn(plantLodNp) else: # reassign plants to sectorNode tempTileNode.getChildren().reparentTo(tileNode) tempTileNode.removeNode() tempTileNode = None # tileNode.flattenMedium() tileNode.flattenStrong() tileNode.reparentTo(self.plantClassNp) self.tileDict[sectorId] = tileNode if FADEIN: self.makeFadeIn(tileNode)
class CogdoMazeGameIntro(CogdoGameMovie): def __init__(self, maze, exit, rng): CogdoGameMovie.__init__(self) self._maze = maze self._exit = exit self._rng = RandomNumGen(rng) self._camTarget = None self._state = 0 self._suits = [] return def _getRandomLine(self, lineList): return CogdoUtil.getRandomDialogueLine(lineList, self._rng) def displayLine(self, who, text): self._dialogueLabel.node().setText(text) if who == 'toon': self.toonHead.reparentTo(aspect2d) self.cogHead.reparentTo(hidden) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) else: self.toonHead.reparentTo(hidden) self.cogHead.reparentTo(aspect2d) self._cogDialogueSfx.play() self.cogHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1, 1, 2) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() suit.loop('neutral') def load(self): CogdoGameMovie.load(self) self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.cogHead = Suit.Suit() self.cogDNA = SuitDNA.SuitDNA() self.cogDNA.newSuit('ms') self.cogHead.setDNA(self.cogDNA) self.cogHead.getGeomNode().setDepthWrite(1) self.cogHead.getGeomNode().setDepthTest(1) self.cogHead.loop('neutral') self.cogHead.setPosHprScale(-0.73, 0, -1.46, 180, 0, 0, 0.14, 0.14, 0.14) self.cogHead.reparentTo(hidden) self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) audioMgr = base.cogdoGameAudioMgr self._cogDialogueSfx = audioMgr.createSfx('cogDialogue') self._toonDialogueSfx = audioMgr.createSfx('toonDialogue') suitData = Globals.SuitData[Globals.SuitTypes.Boss] bossSuit = Suit.Suit() d = SuitDNA.SuitDNA() d.newSuit(suitData['dnaName']) bossSuit.setDNA(d) bossSuit.setScale(suitData['scale']) bossSuit.loop('neutral') bossSuit.reparentTo(render) bossSuit.setPos(self._exit, -5, -5, 0) bossSuit.lookAt(self._exit) self._suits.append(bossSuit) self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoMazeIntroMovieDialogue introDuration = Globals.IntroDurationSeconds waitDuration = introDuration / len(dialogue) def start(): base.camera.wrtReparentTo(render) self._exit.open(animate=False) def showBoss(): self._setCamTarget(bossSuit, 20, offset=Point3(0, 0, 7), angle=Point3(0, 15, 0)) bossSuit.loop('victory') self._state = 1 def showExit(): self._setCamTarget(self._exit, 10, offset=Point3(0, 0, 0), angle=Point3(0, 60, 0)) self._exit.close() self._state = 2 showExitIval = Parallel(base.camera.posInterval(waitDuration * 0.5, (10, -25, 20), other=self._exit, blendType='easeInOut'), Sequence(Wait(waitDuration * 0.25), Func(bossSuit.play, 'effort'), base.camera.hprInterval(waitDuration * 0.25, (30, -30, 0), blendType='easeInOut'), Func(self._exit.close), Wait(waitDuration * 0.5))) def showWaterCooler(): wc = self._maze.getWaterCoolers()[0] self._setCamTarget(wc, 25, angle=Point3(-30, 60, 0)) base.camera.wrtReparentTo(self._camHelperNode) self._state = 3 def end(): self._stopUpdateTask() self._ival = Sequence(Func(start), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[0])), showExitIval, Func(showWaterCooler), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[1])), Wait(waitDuration), Func(showBoss), bossSuit.hprInterval(1.0, bossSuit.getHpr() + Point3(180, 0, 0), blendType='easeInOut'), Func(self.displayLine, 'toon', self._getRandomLine(dialogue[2])), Wait(waitDuration - 1.0), Func(end)) self._startUpdateTask() def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)): base.camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) base.camera.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() if self._state == 1: self._camHelperNode.setPos(self._camTarget.getPos() + self._camOffset) base.camera.setPos(self._camHelperNode, 0, self._camDistance, 0) base.camera.lookAt(self._camTarget, 0, 0, 4) elif self._state == 2: base.camera.lookAt(self._camTarget, 0, 0, 5) elif self._state == 3: self._camHelperNode.setHpr(self._camHelperNode, dt, dt, 0) base.camera.setY(camera, 0.8 * dt) base.camera.lookAt(self._camTarget, 0, 0, 3) return task.cont def unload(self): self._exit = None self._camTarget = None self._camHelperNode.removeNode() del self._camHelperNode for suit in self._suits: suit.cleanup() suit.removeNode() suit.delete() self._suits = [] CogdoGameMovie.unload(self) del self._cogDialogueSfx del self._toonDialogueSfx self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead self.cogHead.stop() self.cogHead.removeNode() self.cogHead.delete() del self.cogHead return
class CogdoExecutiveSuiteIntro(CogdoGameMovie): notify = DirectNotifyGlobal.directNotify.newCategory( 'CogdoExecutiveSuiteIntro') introDuration = 7 cameraMoveDuration = 3 def __init__(self, shopOwner): CogdoGameMovie.__init__(self) self._shopOwner = shopOwner self._lookAtCamTarget = False self._camTarget = None self._camHelperNode = None self._toonDialogueSfx = None self.toonHead = None self.frame = None return def displayLine(self, text): self.notify.debug('displayLine') self._dialogueLabel.node().setText(text) self.toonHead.reparentTo(aspect2d) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): self.notify.debug('makeSuit()') suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1, 1, 2) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() def load(self): self.notify.debug('load()') CogdoGameMovie.load(self) backgroundGui = loader.loadModel( 'phase_5/models/cogdominium/tt_m_gui_csa_flyThru') self.bg = backgroundGui.find('**/background') self.chatBubble = backgroundGui.find('**/chatBubble') self.chatBubble.setScale(6.5, 6.5, 7.3) self.chatBubble.setPos(0.32, 0, -0.78) self.bg.setScale(5.2) self.bg.setPos(0.14, 0, -0.6667) self.bg.reparentTo(aspect2d) self.chatBubble.reparentTo(aspect2d) self.frame = DirectFrame(geom=self.bg, relief=None, pos=(0.2, 0, -0.6667)) self.bg.wrtReparentTo(self.frame) self.gameTitleText = DirectLabel( parent=self.frame, text=TTLocalizer.CogdoExecutiveSuiteTitle, scale=TTLocalizer.MRPgameTitleText * 0.8, text_align=TextNode.ACenter, text_font=getSignFont(), text_fg=(1.0, 0.33, 0.33, 1.0), pos=TTLocalizer.MRgameTitleTextPos, relief=None) self.chatBubble.wrtReparentTo(self.frame) self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) self._toonDialogueSfx = loader.loadSfx( 'phase_3.5/audio/dial/AV_dog_long.ogg') self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoExecutiveSuiteIntroMessage def start(): self.frame.show() base.setCellsAvailable( base.bottomCells + base.leftCells + base.rightCells, 0) def showShopOwner(): self._setCamTarget(self._shopOwner, -10, offset=Point3(0, 0, 5)) def end(): self._dialogueLabel.reparentTo(hidden) self.toonHead.reparentTo(hidden) self.frame.hide() base.setCellsAvailable( base.bottomCells + base.leftCells + base.rightCells, 1) self._stopUpdateTask() self._ival = Sequence( Func(start), Func(self.displayLine, dialogue), Func(showShopOwner), ParallelEndTogether( camera.posInterval(self.cameraMoveDuration, Point3(8, 0, 13), blendType='easeInOut'), camera.hprInterval(0.5, self._camHelperNode.getHpr(), blendType='easeInOut')), Wait(self.introDuration), Func(end)) self._startUpdateTask() return def _setCamTarget(self, targetNP, distance, offset=Point3(0, 0, 0), angle=Point3(0, 0, 0)): camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) self._camHelperNode.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() return task.cont def unload(self): self._shopOwner = None self._camTarget = None if hasattr(self, '_camHelperNode') and self._camHelperNode: self._camHelperNode.removeNode() del self._camHelperNode self.frame.destroy() del self.frame self.bg.removeNode() del self.bg self.chatBubble.removeNode() del self.chatBubble self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead CogdoGameMovie.unload(self) return
class DistributedButterfly(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedButterfly') id = 0 # wings_1 (solid yellow) # wings_2 (yellow w/ dots) (1, 1, 1), (0.2, 0, 1), (1, 0, 1), (0.8, 0, 1) # wings_3 (solid white) (0.8, 0, 0.8), (0, 0.8, 0.8), (0.9, 0.4, 0.6) # (0.9, 0.4, 0.4), (0.8, 0.5, 0.9), (0.4, 0.1, 0.7) # wings_4 (white w/ dots) # wings_5 (pale yellow w/ lines) (0.8, 0, 0.8), (0.6, 0.6, 0.9) # (0.7, 0.6, 0.9), (0.8, 0.6, 0.9), (0.9, 0.6, 0.9), # (1, 0.6, 0.9) # wings_6 (blue & yellow) wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6') yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1)) whiteColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0, 0.8, 0.8, 1), Vec4(0.9, 0.4, 0.6, 1), Vec4(0.9, 0.4, 0.4, 1), Vec4(0.8, 0.5, 0.9, 1), Vec4(0.4, 0.1, 0.7, 1)) paleYellowColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0.6, 0.6, 0.9, 1), Vec4(0.7, 0.6, 0.9, 1), Vec4(0.8, 0.6, 0.9, 1), Vec4(0.9, 0.6, 0.9, 1), Vec4(1, 0.6, 0.9, 1)) shadowScaleBig = Point3(0.07, 0.07, 0.07) shadowScaleSmall = Point3(0.01, 0.01, 0.01) def __init__(self, cr): """__init__(cr) """ DistributedObject.DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM( 'DistributedButterfly', [ State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying']) ], # Initial State 'off', # Final State 'off', ) self.butterfly = None self.butterflyNode = None self.curIndex = 0 self.destIndex = 0 self.time = 0.0 self.ival = None self.fsm.enterInitialState() def generate(self): """generate(self) This method is called when the DistributedObject is reintroduced to the world, either for the first time or from the cache. """ DistributedObject.DistributedObject.generate(self) if self.butterfly: return self.butterfly = Actor.Actor() self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod.bam') self.butterfly.loadAnims({ 'flutter': 'phase_4/models/props/SZ_butterfly-flutter.bam', 'glide': 'phase_4/models/props/SZ_butterfly-glide.bam', 'land': 'phase_4/models/props/SZ_butterfly-land.bam' }) # Randomly choose one of the butterfly wing patterns index = self.doId % len(self.wingTypes) chosenType = self.wingTypes[index] node = self.butterfly.getGeomNode() for type in self.wingTypes: wing = node.find('**/' + type) if (type != chosenType): wing.removeNode() else: # Choose an appropriate blend color if (index == 0 or index == 1): color = self.yellowColors[self.doId % len(self.yellowColors)] elif (index == 2 or index == 3): color = self.whiteColors[self.doId % len(self.whiteColors)] elif (index == 4): color = self.paleYellowColors[self.doId % len(self.paleYellowColors)] else: color = Vec4(1, 1, 1, 1) wing.setColor(color) # Make another copy of the butterfly model so we can LOD the # blending. Butterflies that are far away won't bother to # blend animations; nearby butterflies will use dynamic # blending to combine two or more animations at once on # playback for a nice fluttering and landing effect. self.butterfly2 = Actor.Actor(other=self.butterfly) # Allow the nearby butterfly to blend between its three # animations. All animations will be playing all the time; # we'll control which one is visible by varying the control # effect. self.butterfly.enableBlend(blendType=PartBundle.BTLinear) self.butterfly.loop('flutter') self.butterfly.loop('land') self.butterfly.loop('glide') # Make a random play rate so all the butterflies will be # flapping at slightly different rates. This doesn't affect # the rate at which the butterfly moves, just the rate at # which the animation plays on the butterfly. rng = RandomNumGen.RandomNumGen(self.doId) playRate = 0.6 + 0.8 * rng.random() self.butterfly.setPlayRate(playRate, 'flutter') self.butterfly.setPlayRate(playRate, 'land') self.butterfly.setPlayRate(playRate, 'glide') self.butterfly2.setPlayRate(playRate, 'flutter') self.butterfly2.setPlayRate(playRate, 'land') self.butterfly2.setPlayRate(playRate, 'glide') # Also, a random glide contribution ratio. We'll blend a bit # of the glide animation in with the flutter animation to # dampen the effect of flutter. The larger the number here, # the greater the dampening effect. Some butterflies will be # more active than others. (Except when seen from a long way # off, because of the LODNode, below.) self.glideWeight = rng.random() * 2 lodNode = LODNode('butterfly-node') lodNode.addSwitch(100, 40) # self.butterfly2 lodNode.addSwitch(40, 0) # self.butterfly self.butterflyNode = NodePath(lodNode) self.butterfly2.setH(180.0) self.butterfly2.reparentTo(self.butterflyNode) self.butterfly.setH(180.0) self.butterfly.reparentTo(self.butterflyNode) self.__initCollisions() # Set up the drop shadow self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow.setColor(0, 0, 0, 0.3) self.dropShadow.setPos(0, 0.1, -0.05) self.dropShadow.setScale(self.shadowScaleBig) self.dropShadow.reparentTo(self.butterfly) def disable(self): """disable(self) This method is called when the DistributedObject is removed from active duty and stored in a cache. """ self.butterflyNode.reparentTo(hidden) if (self.ival != None): self.ival.finish() self.__ignoreAvatars() DistributedObject.DistributedObject.disable(self) def delete(self): """delete(self) This method is called when the DistributedObject is permanently removed from the world and deleted from the cache. """ self.butterfly.cleanup() self.butterfly = None self.butterfly2.cleanup() self.butterfly2 = None self.butterflyNode.removeNode() self.__deleteCollisions() self.ival = None del self.fsm DistributedObject.DistributedObject.delete(self) def uniqueButterflyName(self, name): DistributedButterfly.id += 1 return (name + '-%d' % DistributedButterfly.id) def __detectAvatars(self): self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter) def __ignoreAvatars(self): self.ignore('enter' + self.cSphereNode.getName()) def __initCollisions(self): self.cSphere = CollisionSphere(0., 1., 0., 3.) self.cSphere.setTangible(0) self.cSphereNode = CollisionNode( self.uniqueButterflyName('cSphereNode')) self.cSphereNode.addSolid(self.cSphere) self.cSphereNodePath = self.butterflyNode.attachNewNode( self.cSphereNode) self.cSphereNodePath.hide() self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __deleteCollisions(self): del self.cSphere del self.cSphereNode self.cSphereNodePath.removeNode() del self.cSphereNodePath def __handleCollisionSphereEnter(self, collEntry): """ Response for a toon walking up to this NPC """ assert (self.notify.debug("Entering collision sphere...")) # Tell the server self.sendUpdate('avatarEnter', []) def setArea(self, playground, area): self.playground = playground self.area = area def setState(self, stateIndex, curIndex, destIndex, time, timestamp): self.curIndex = curIndex self.destIndex = destIndex self.time = time self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)]) ##### Off state ##### def enterOff(self, ts=0.0): if (self.butterflyNode != None): self.butterflyNode.reparentTo(hidden) return None def exitOff(self): if (self.butterflyNode != None): self.butterflyNode.reparentTo(render) return None ##### Flying state ##### def enterFlying(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.curIndex] destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.destIndex] # We'll hit the ground if we go straight from curPos to destPos flyHeight = max( curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground] curPosHigh = Point3(curPos[0], curPos[1], flyHeight) destPosHigh = Point3(destPos[0], destPos[1], flyHeight) if (ts <= self.time): flyTime = self.time - ( ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground]) self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) oldHpr = self.butterflyNode.getHpr() self.butterflyNode.headsUp(destPos) newHpr = self.butterflyNode.getHpr() self.butterflyNode.setHpr(oldHpr) takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[ self.playground] landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[ self.playground] self.butterfly2.loop('flutter') self.ival = Sequence( Parallel( LerpPosHprInterval( self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence( LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow)), ), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel( LerpPosInterval( self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence( Wait(ButterflyGlobals.BUTTERFLY_LANDING[ self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall)), ), name=self.uniqueName("Butterfly")) self.ival.start(ts) else: self.ival = None self.butterflyNode.setPos(destPos) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.loop('land') return None def exitFlying(self): self.__ignoreAvatars() if (self.ival != None): self.ival.finish() self.ival = None return None ##### Landed state ##### def enterLanded(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.curIndex] self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.pose( 'land', random.randrange(self.butterfly2.getNumFrames('land'))) return None def exitLanded(self): self.__ignoreAvatars() return None
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor("media/models/boxman", { "walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle" }) self.actor.setScale(1.0) self.actor.setH(0) #self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath('agent-%s' % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ #self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) #self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint( None, 'modelRoot', 'Hand.R') self.player_left_hand = self.actor.exposeJoint(None, 'modelRoot', 'Hand.L') self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, 'modelRoot', 'Head') self.neck = self.actor.controlJoint(None, 'modelRoot', 'Head') self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0 } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") #bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(.3, .3), pos=(0, 0, 3.6), frameColor=(.6, .2, .1, .5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1)) #self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component('text0').textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, .5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(.18, .18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component('text0').textNode.setFrameColor( 1, 1, 1, 0) self.thought_bubble.component('text0').textNode.setFrameAsMargin( 0.1, 0.1, 0.1, 0.1) self.thought_bubble.component('text0').textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera('RaphViz')) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) #self.fov.node().showFrustum() # displays a box around his head #self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=['isisobject']): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if 'x_pos' not in exclude: object_dict['x_pos'] = p3[0] if 'y_pos' not in exclude: object_dict['y_pos'] = p3[2] if 'distance' not in exclude: object_dict['distance'] = o.activeModel.getDistance( self.fov) if 'orientation' not in exclude: object_dict['orientation'] = o.activeModel.getH(self.fov) if 'actions' not in exclude: object_dict['actions'] = o.list_actions() if 'isisobject' not in exclude: object_dict['isisobject'] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = {'x_pos': p3[0],\ 'y_pos': p3[2],\ 'distance':a.actorNodePath.getDistance(self.fov),\ 'orientation': a.actorNodePath.getH(self.fov)} agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x['isisobject'] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values())) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say( "If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies #percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts['objects'] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts['position'] = self.sense__get_position() # language: get last utterances that were typed percepts['language'] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts['agents'] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble['text'] = message #self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) #self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble['text'] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [ ] #[base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print 'already holding ' + hand_slot.getName() + '.' return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() #turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag('heldBy', self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print 'right hand is not holding an object.' return False if self.right_hand_holding_object.getNetTag('heldBy') == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag('heldBy', '') self.right_hand_holding_object.setRotation( self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return 'left hand is not holding an object.' if self.left_hand_holding_object.getNetTag('heldBy') == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag('heldBy', '') self.left_hand_holding_object.setRotation( self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') print "Trying to use object", target if self.can_grasp(target): if (target.call(self, action, self.right_hand_holding_object) or (self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') if self.can_grasp(target): if (target.call(self, action, self.left_hand_holding_object) or (self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ((self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag('isisobj').name == object_name)) \ or (self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag('isisobj').name == object_name))) def empty_hand(self): if (self.left_hand_holding_object is None): return self.player_left_hand elif (self.right_hand_holding_object is None): return self.player_right_hand return False def has_empty_hand(self): return (self.empty_hand() is not False) def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() #FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return {'body_x': x, 'body_y': y, 'body_z': z,'body_h':h,\ 'body_p': p, 'body_r': r, 'in_left_hand': left_hand_obj, 'in_right_hand':right_hand_obj} def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v['actions'] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if (self.controlMap["turn_left"] != 0): self.addToH(stepSize * self.speeds[0]) if (self.controlMap["turn_right"] != 0): self.addToH(-stepSize * self.speeds[1]) if self.verticalState == 'ground': # these actions require contact with the ground if (self.controlMap["move_forward"] != 0): self.speed[1] = self.speeds[2] if (self.controlMap["move_backward"] != 0): self.speed[1] = -self.speeds[3] if (self.controlMap["move_left"] != 0): self.speed[0] = -self.speeds[4] if (self.controlMap["move_right"] != 0): self.speed[0] = self.speeds[5] if (self.controlMap["jump"] != 0): kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if (self.controlMap["look_left"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if (self.controlMap["look_right"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if (self.controlMap["look_up"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if (self.controlMap["look_down"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition( self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition( self.player_left_hand.getPos(render)) #Update the dialog box and thought windows #This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble['text_bg'] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble['frameColor'] = (.6, .2, .1, .5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble['text'] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames('walk') if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose('walk', self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose('idle', 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
class Entity(DirectObject, object): def __init__(self, model = None): self.prime = None if model != None: self.set_model(model) def get_model(self): return self.prime def set_model(self, model): if model != None: if isinstance(model, PandaNode): self.prime = NodePath(model) elif isinstance(model, NodePath): self.prime = model else: if Filename(model).exists(): self.model = Filename(model).getBasenameWoExtension() path = model else: if isinstance(model, Filename): self.model = model.getBasenameWoExtension() path = model.getFullpath() else: path = APP_PATH + model print "path: ", path if Filename(path).exists(): pass elif Filename(path + ".bam").exists(): path += ".bam" elif Filename(path + ".bam.pz").exists(): path += ".bam.pz" elif Filename(path + ".egg").exists(): path += ".egg" elif Filename(path + ".egg.pz").exists(): path += ".egg.pz" elif Filename(path + ".x").exists(): path += ".x" else: print ":object(error): can't find model", model, "!" # Probably shouldn't exit because of this sys.exit(1) self.model = model self.prime = base.loader.loadModel(path) if self.prime == None: print ":object(error): can't load model", model, "!" # Probably shouldn't exit because of this sys.exit(1) def getX(self): return self.prime.getX(base.render) def getY(self): return self.prime.getY(base.render) def getZ(self): return self.prime.getZ(base.render) def getH(self): return self.prime.getH(base.render) def getP(self): return self.prime.getP(base.render) def getR(self): return self.prime.getR(base.render) def getSx(self): return self.prime.getSx(base.render) def getSy(self): return self.prime.getSy(base.render) def getSz(self): return self.prime.getSz(base.render) def getPos(self): return self.prime.getPos(base.render) def getHpr(self): return self.prime.getHpr(base.render) def getScale(self): return self.prime.getScale(base.render) def getCollideMask(self): return self.prime.getCollideMask() def getTransparency(self): return self.prime.getTransparency() def getTwoSided(self): return self.prime.getTwoSided() def getParent(self): return self.prime.getParent() def setX(self, *v): self.prime.setX(*v) def setY(self, *v): self.prime.setY(*v) def setZ(self, *v): self.prime.setZ(*v) def setH(self, *v): self.prime.setH(*v) def setP(self, *v): self.prime.setP(*v) def setR(self, *v): self.prime.setR(*v) def setSx(self, *v): self.prime.setSx(*v) def setSy(self, *v): self.prime.setSy(*v) def setSz(self, *v): self.prime.setSz(*v) def setPos(self, *v): self.prime.setPos(*v) def setHpr(self, *v): self.prime.setHpr(*v) def setScale(self, *v): self.prime.setScale(*v) def setCollideMask(self, *v): self.prime.setCollideMask(*v) def setTransparency(self, *v): self.prime.setTransparency(*v) def setTwoSided(self, *v): self.prime.setTwoSided(*v) def removeNode(self): self.prime.removeNode() def reparentTo(self, parent): if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if parent.startswith("render/"): parent = parent[7:] tv = parent parent = base.render.find(tv) if parent == NodePath(): parent = base.render.find("**/" + tv) if parent != NodePath() and parent != None: self.prime.reparentTo(parent) def wrtReparentTo(self, parent): if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if parent.startswith("render/"): parent = parent[7:] tv = parent parent = base.render.find(tv) if parent == NodePath(): parent = base.render.find("**/" + tv) if parent != NodePath(): self.prime.reparentTo(parent) def attachTo(self, parent): """This attaches the object to another object/nodepath. The caller object stays at the same place, with the same scale and rotation, but they become relative to the other object/nodepath. This is useful with for example a character that steps onto a moving ship or so.""" if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if(parent.startswith("render/")): parent = parent[7:] tv = parent parent = base.render.find(tv) if(parent == NodePath()): parent = base.render.find("**/" + tv) if(parent != NodePath()): self.prime.setPos(self.prime.getPos(parent)) self.prime.setHpr(self.prime.getHpr(parent)) self.prime.setScale(self.prime.getScale(parent)) self.prime.reparentTo(parent) def hide(self): self.prime.hide() def show(self): self.prime.show() def __del__(self): try: if isinstance(self.prime, NodePath): self.prime.removeNode() except AttributeError: pass def __getstate__(self): return [self.model, self.getX(), self.getY(), self.getZ(), self.getH(), self.getP(), self.getR(), self.getSx(), self.getSy(), self.getSz(), self.getCollideMask().getWord(), self.getTransparency(), self.getTwoSided(), str(self.getParent())] def __setstate__(self, p): if len(p) < 14: print ":object(error): This state is not compatible with this version!" sys.exit(1) self.setModel(p[0]) self.setX(p[1]) self.setY(p[2]) self.setZ(p[3]) self.setH(p[4]) self.setP(p[5]) self.setR(p[6]) self.setSx(p[7]) self.setSy(p[8]) self.setSz(p[9]) self.setCollideMask(BitMask32(p[10])) self.setTransparency(p[11]) self.setTwoSided(p[12]) self.reparentTo(p[13])
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor( "media/models/boxman", {"walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle"} ) self.actor.setScale(1.0) self.actor.setH(0) # self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath("agent-%s" % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ # self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) # self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.R") self.player_left_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.L") self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, "modelRoot", "Head") self.neck = self.actor.controlJoint(None, "modelRoot", "Head") self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0, } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") # bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(0.3, 0.3), pos=(0, 0, 3.6), frameColor=(0.6, 0.2, 0.1, 0.5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1), ) # self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component("text0").textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, 0.5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(0.18, 0.18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5, ) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component("text0").textNode.setFrameColor(1, 1, 1, 0) self.thought_bubble.component("text0").textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1) self.thought_bubble.component("text0").textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera("RaphViz")) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) # self.fov.node().showFrustum() # displays a box around his head # self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=["isisobject"]): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if "x_pos" not in exclude: object_dict["x_pos"] = p3[0] if "y_pos" not in exclude: object_dict["y_pos"] = p3[2] if "distance" not in exclude: object_dict["distance"] = o.activeModel.getDistance(self.fov) if "orientation" not in exclude: object_dict["orientation"] = o.activeModel.getH(self.fov) if "actions" not in exclude: object_dict["actions"] = o.list_actions() if "isisobject" not in exclude: object_dict["isisobject"] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = { "x_pos": p3[0], "y_pos": p3[2], "distance": a.actorNodePath.getDistance(self.fov), "orientation": a.actorNodePath.getH(self.fov), } agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x["isisobject"] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values()) ) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say("If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies # percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts["objects"] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts["position"] = self.sense__get_position() # language: get last utterances that were typed percepts["language"] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts["agents"] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble["text"] = message # self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) # self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble["text"] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( "aimRay", 5, [pos, direction], [isisobj.geom] ) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [] # [base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print "already holding " + hand_slot.getName() + "." return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() # turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag("heldBy", self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print "right hand is not holding an object." return False if self.right_hand_holding_object.getNetTag("heldBy") == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag("heldBy", "") self.right_hand_holding_object.setRotation(self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return "left hand is not holding an object." if self.left_hand_holding_object.getNetTag("heldBy") == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag("heldBy", "") self.left_hand_holding_object.setRotation(self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "Trying to use object", target if self.can_grasp(target): if target.call(self, action, self.right_hand_holding_object) or ( self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") if self.can_grasp(target): if target.call(self, action, self.left_hand_holding_object) or ( self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ( self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag("isisobj").name == object_name) ) or ( self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag("isisobj").name == object_name) ) def empty_hand(self): if self.left_hand_holding_object is None: return self.player_left_hand elif self.right_hand_holding_object is None: return self.player_right_hand return False def has_empty_hand(self): return self.empty_hand() is not False def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() # FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return { "body_x": x, "body_y": y, "body_z": z, "body_h": h, "body_p": p, "body_r": r, "in_left_hand": left_hand_obj, "in_right_hand": right_hand_obj, } def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v["actions"] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if self.controlMap["turn_left"] != 0: self.addToH(stepSize * self.speeds[0]) if self.controlMap["turn_right"] != 0: self.addToH(-stepSize * self.speeds[1]) if self.verticalState == "ground": # these actions require contact with the ground if self.controlMap["move_forward"] != 0: self.speed[1] = self.speeds[2] if self.controlMap["move_backward"] != 0: self.speed[1] = -self.speeds[3] if self.controlMap["move_left"] != 0: self.speed[0] = -self.speeds[4] if self.controlMap["move_right"] != 0: self.speed[0] = self.speeds[5] if self.controlMap["jump"] != 0: kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if self.controlMap["look_left"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if self.controlMap["look_right"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if self.controlMap["look_up"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if self.controlMap["look_down"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition(self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition(self.player_left_hand.getPos(render)) # Update the dialog box and thought windows # This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble["text_bg"] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble["frameColor"] = (0.6, 0.2, 0.1, 0.5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble["text"] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if ( (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0) ): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames("walk") if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose("walk", self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose("idle", 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
class Character: """A character with an animated avatar that moves left, right or forward according to the controls turned on or off in self.controlMap. Public fields: self.controlMap -- The character's movement controls self.actor -- The character's Actor (3D animated model) Public functions: __init__ -- Initialise the character move -- Move and animate the character for one frame. This is a task function that is called every frame by Panda3D. setControl -- Set one of the character's controls on or off. """ def __init__(self, agent_simulator, model, actions, startPos, scale): """Initialize the character. Arguments: model -- The path to the character's model file (string) run : The path to the model's run animation (string) walk : The path to the model's walk animation (string) startPos : Where in the world the character will begin (pos) scale : The amount by which the size of the model will be scaled (float) """ self.agent_simulator = agent_simulator self.controlMap = {"turn_left":0, "turn_right":0, "move_forward":0, "move_backward":0,\ "look_up":0, "look_down":0, "look_left":0, "look_right":0} self.actor = Actor(model,actions) self.actor.reparentTo(render) self.actor.setScale(scale) self.actor.setPos(startPos) self.actor.setHpr(0,0,0) # Expose agent's right hand joint to attach objects to self.actor_right_hand = self.actor.exposeJoint(None, 'modelRoot', 'RightHand') self.actor_left_hand = self.actor.exposeJoint(None, 'modelRoot', 'LeftHand') self.right_hand_holding_object = False self.left_hand_holding_object = False # speech bubble self.last_spoke = 0 self.speech_bubble=DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3,3), relief=None, text_scale=(.5,.5), pos = (0,0,6), frameColor=(.6,.2,.1,.5), textMayChange=1, text_frame=(0,0,0,1), text_bg=(1,1,1,1)) self.speech_bubble.component('text0').textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # visual processing self.actor_eye = self.actor.exposeJoint(None, 'modelRoot', 'LeftEyeLid') # put a camera on ralph self.fov = NodePath(Camera('RaphViz')) self.fov.reparentTo(self.actor_eye) self.fov.setHpr(180,0,0) #lens = OrthographicLens() #lens.setFilmSize(20,15) #self.fov.node().setLens(lens) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) #self.fov.node().showFrustum() # displays a box around his head self.actor_neck = self.actor.controlJoint(None, 'modelRoot', 'Neck') # Define subpart of agent for when he's standing around self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) taskMgr.add(self.move,"moveTask") # Note: deriving classes DO NOT need # to add their own move tasks to the # task manager. If they override # self.move, then their own self.move # function will get called by the # task manager (they must then # explicitly call Character.move in # that function if they want it). self.prevtime = 0 self.isMoving = False self.current_frame_count = 0.0 # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.initialize_collision_handling() def initialize_collision_handling(self): self.collision_handling_mutex = Lock() self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode('ralphRay') self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(0)) self.groundCol.addSolid(self.groundRay) self.groundColNp = self.actor.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler) # Uncomment this line to see the collision rays # self.groundColNp.show() #Uncomment this line to show a visual representation of the #collisions occuring # self.cTrav.showCollisions(render) def destroy_collision_handling(self): self.collision_handling_mutex.acquire() def handle_collisions(self): self.collision_handling_mutex.acquire() self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(1)) # Now check for collisions. self.cTrav.traverse(render) # Adjust the character's Z coordinate. If the character's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.groundHandler.getNumEntries()): entry = self.groundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.actor.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.actor.setPos(self.startpos) self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(0)) self.collision_handling_mutex.release() def position(self): return self.actor.getPos() def forward_normal_vector(self): backward = self.actor.getNetTransform().getMat().getRow3(1) backward.setZ(0) backward.normalize() return -backward def step_simulation_time(self, seconds): # save the character's initial position so that we can restore it, # in case he falls off the map or runs into something. self.startpos = self.actor.getPos() def bound(i, mn = -1, mx = 1): return min(max(i, mn), mx) # enforces bounds on a numeric value # move the character if any of the move controls are activated. if (self.controlMap["turn_left"]!=0): self.actor.setH(self.actor.getH() + seconds*30) if (self.controlMap["turn_right"]!=0): self.actor.setH(self.actor.getH() - seconds*30) if (self.controlMap["move_forward"]!=0): self.actor.setPos(self.actor.getPos() + self.forward_normal_vector() * (seconds*0.5)) if (self.controlMap["move_backward"]!=0): self.actor.setPos(self.actor.getPos() - self.forward_normal_vector() * (seconds*0.5)) if (self.controlMap["look_left"]!=0): self.actor_neck.setP(bound(self.actor_neck.getP(),-60,60)+1*(seconds*50)) if (self.controlMap["look_right"]!=0): self.actor_neck.setP(bound(self.actor_neck.getP(),-60,60)-1*(seconds*50)) if (self.controlMap["look_up"]!=0): self.actor_neck.setH(bound(self.actor_neck.getH(),-60,80)+1*(seconds*50)) if (self.controlMap["look_down"]!=0): self.actor_neck.setH(bound(self.actor_neck.getH(),-60,80)-1*(seconds*50)) # allow dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += seconds self.speech_bubble['text_bg']=(1,1,1,1/(2*self.last_spoke+0.01)) self.speech_bubble['frameColor']=(.6,.2,.1,.5/(2*self.last_spoke+0.01)) if self.last_spoke > 2: self.speech_bubble['text'] = "" # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["move_forward"]!=0) or (self.controlMap["move_backward"]!=0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames('walk') if self.isMoving: self.current_frame_count = self.current_frame_count + (seconds*10.0) while (self.current_frame_count >= total_frame_num + 1): self.current_frame_count -= total_frame_num while (self.current_frame_count < 0): self.current_frame_count += total_frame_num self.actor.pose('walk', self.current_frame_count) self.handle_collisions() def move(self, task): """Move and animate the character for one frame. This is a task function that is called every frame by Panda3D. The character is moved according to which of it's movement controls are set, and the function keeps the character's feet on the ground and stops the character from moving if a collision is detected. This function also handles playing the characters movement animations. Arguments: task -- A direct.task.Task object passed to this function by Panda3D. Return: Task.cont -- To tell Panda3D to call this task function again next frame. """ elapsed = task.time - self.prevtime # Store the task time and continue. self.prevtime = task.time return Task.cont def setControl(self, control, value): """Set the state of one of the character's movement controls. Arguments See self.controlMap in __init__. control -- The control to be set, must be a string matching one of the strings in self.controlMap. value -- The value to set the control to. """ # FIXME: this function is duplicated in Camera and Character, and # keyboard control settings are spread throughout the code. Maybe # add a Controllable class? self.controlMap[control] = value # these are simple commands that can be exported over xml-rpc (or attached to the keyboard) def get_objects(self): """ Looks up all of the model nodes that are 'isInView' of the camera and returns them in the in_view dictionary (as long as they are also in the self.world_objects -- otherwise this includes points defined within the environment/terrain). TODO: 1) include more geometric information about the object (size, mass, etc) """ def map3dToAspect2d(node, point): """Maps the indicated 3-d point (a Point3), which is relative to the indicated NodePath, to the corresponding point in the aspect2d scene graph. Returns the corresponding Point3 in aspect2d. Returns None if the point is not onscreen. """ # Convert the point to the 3-d space of the camera p3 = self.fov.getRelativePoint(node, point) # Convert it through the lens to render2d coordinates p2 = Point2() if not self.fov.node().getLens().project(p3, p2): return None r2d = Point3(p2[0], 0, p2[1]) # And then convert it to aspect2d coordinates a2d = aspect2d.getRelativePoint(render2d, r2d) return a2d objs = render.findAllMatches("**/+ModelNode") in_view = {} for o in objs: o.hideBounds() # in case previously turned on o_pos = o.getPos(self.fov) if self.fov.node().isInView(o_pos): if self.agent_simulator.world_objects.has_key(o.getName()): b_min, b_max = o.getTightBounds() a_min = map3dToAspect2d(render, b_min) a_max = map3dToAspect2d(render, b_max) if a_min == None or a_max == None: continue x_diff = math.fabs(a_max[0]-a_min[0]) y_diff = math.fabs(a_max[2]-a_min[2]) area = 100*x_diff*y_diff # percentage of screen object_dict = {'x_pos': (a_min[2]+a_max[2])/2.0,\ 'y_pos': (a_min[0]+a_max[0])/2.0,\ 'distance':o.getDistance(self.fov), \ 'area':area,\ 'orientation': o.getH(self.fov)} in_view[o.getName()]=object_dict print o.getName(), object_dict return in_view def control__turn_left__start(self): self.setControl("turn_left", 1) self.setControl("turn_right", 0) def control__turn_left__stop(self): self.setControl("turn_left", 0) def control__turn_right__start(self): self.setControl("turn_left", 0) self.setControl("turn_right", 1) def control__turn_right__stop(self): self.setControl("turn_right", 0) def control__move_forward__start(self): self.setControl("move_forward", 1) self.setControl("move_backward", 0) def control__move_forward__stop(self): self.setControl("move_forward", 0) def control__move_backward__start(self): self.setControl("move_forward", 0) self.setControl("move_backward", 1) def control__move_backward__stop(self): self.setControl("move_backward", 0) def control__look_left__start(self): self.setControl("look_left", 1) self.setControl("look_right", 0) def control__look_left__stop(self): self.setControl("look_left", 0) def control__look_right__start(self): self.setControl("look_right", 1) self.setControl("look_left", 0) def control__look_right__stop(self): self.setControl("look_right", 0) def control__look_up__start(self): self.setControl("look_up", 1) self.setControl("look_down", 0) def control__look_up__stop(self): self.setControl("look_up", 0) def control__look_down__start(self): self.setControl("look_down", 1) self.setControl("look_up", 0) def control__look_down__stop(self): self.setControl("look_down", 0) def can_grasp(self, object_name): objects = self.get_objects() if objects.has_key(object_name): object_view = objects[object_name] distance = object_view['distance'] if (distance < 5.0): return True return False def control__say(self, message): self.speech_bubble['text'] = message self.last_spoke = 0 def control__pick_up_with_right_hand(self, pick_up_object): print "attempting to pick up " + pick_up_object + " with right hand.\n" if self.right_hand_holding_object: return 'right hand is already holding ' + self.right_hand_holding_object.getName() + '.' if self.can_grasp(pick_up_object): world_object = self.agent_simulator.world_objects[pick_up_object] object_parent = world_object.getParent() if (object_parent == self.agent_simulator.env): world_object.wrtReparentTo(self.actor_right_hand) world_object.setPos(0, 0, 0) world_object.setHpr(0, 0, 0) self.right_hand_holding_object = world_object return 'success' else: return 'object (' + pick_up_object + ') is already held by something or someone.' else: return 'object (' + pick_up_object + ') is not graspable (i.e. in view and close enough).' def put_object_in_empty_left_hand(self, object_name): if (self.left_hand_holding_object is not False): return False world_object = self.agent_simulator.world_objects[object_name] world_object.wrtReparentTo(self.actor_left_hand) world_object.setPos(0, 0, 0) world_object.setHpr(0, 0, 0) self.left_hand_holding_object = world_object return True def control__pick_up_with_left_hand(self, pick_up_object): print "attempting to pick up " + pick_up_object + " with left hand.\n" if self.left_hand_holding_object: return 'left hand is already holding ' + self.left_hand_holding_object.getName() + '.' if self.can_grasp(pick_up_object): world_object = self.agent_simulator.world_objects[pick_up_object] object_parent = world_object.getParent() if (object_parent == self.agent_simulator.env): self.put_object_in_empty_left_hand(pick_up_object) return 'success' else: return 'object (' + pick_up_object + ') is already held by something or someone.' else: return 'object (' + pick_up_object + ') is not graspable (i.e. in view and close enough).' def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is False: return 'right hand is not holding an object.' world_object = self.right_hand_holding_object self.right_hand_holding_object = False world_object.wrtReparentTo(self.agent_simulator.env) world_object.setHpr(0, 0, 0) world_object.setPos(self.position() + self.forward_normal_vector() * 0.5) world_object.setZ(world_object.getZ() + 1.0) return 'success' def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is False: return 'left hand is not holding an object.' world_object = self.left_hand_holding_object self.left_hand_holding_object = False world_object.wrtReparentTo(self.agent_simulator.env) world_object.setHpr(0, 0, 0) world_object.setPos(self.position() + self.forward_normal_vector() * 0.5) world_object.setZ(world_object.getZ() + 1.0) return 'success' def is_holding(self, object_name): return ((self.left_hand_holding_object and (self.left_hand_holding_object.getName() == object_name)) or (self.right_hand_holding_object and (self.right_hand_holding_object.getName() == object_name))) def empty_hand(self): if (self.left_hand_holding_object is False): return self.actor_left_hand elif (self.right_hand_holding_object is False): return self.actor_right_hand return False def has_empty_hand(self): return (self.empty_hand() is not False) def control__use_object_with_object(self, use_object, with_object): if ((use_object == 'knife') and (with_object == 'loaf_of_bread')): if self.is_holding('knife'): if self.can_grasp('loaf_of_bread'): if self.has_empty_hand(): empty_hand = self.empty_hand() new_object_name = self.agent_simulator.create_object__slice_of_bread([float(x) for x in empty_hand.getPos()]) if (empty_hand == self.actor_left_hand): self.put_object_in_empty_left_hand(new_object_name) elif (empty_hand == self.actor_right_hand): self.put_object_in_empty_right_hand(new_object_name) else: return "simulator error: empty hand is not left or right. (are there others?)" return 'success' else: return 'failure: one hand must be empty to hold loaf_of_bread in place while using knife.' else: return 'failure: loaf of bread is not graspable (in view and close enough)' else: return 'failure: must be holding knife object to use it.' return 'failure: don\'t know how to use ' + use_object + ' with ' + with_object + '.'
class CogdoExecutiveSuiteIntro(CogdoGameMovie): notify = DirectNotifyGlobal.directNotify.newCategory('CogdoExecutiveSuiteIntro') introDuration = 7 cameraMoveDuration = 3 def __init__(self, shopOwner): CogdoGameMovie.__init__(self) self._shopOwner = shopOwner self._lookAtCamTarget = False self._camTarget = None self._camHelperNode = None self._toonDialogueSfx = None self.toonHead = None self.frame = None return def displayLine(self, text): self.notify.debug('displayLine') self._dialogueLabel.node().setText(text) self.toonHead.reparentTo(aspect2d) self._toonDialogueSfx.play() self.toonHead.setClipPlane(self.clipPlane) def makeSuit(self, suitType): self.notify.debug('makeSuit()') suit = Suit.Suit() dna = SuitDNA.SuitDNA() dna.newSuit(suitType) suit.setStyle(dna) suit.isDisguised = 1 suit.generateSuit() suit.setScale(1.05, 1.05, 2.05) suit.setPos(0, 0, -4.4) suit.reparentTo(self.toonHead) for part in suit.getHeadParts(): part.hide() suit.loop('neutral') def load(self): self.notify.debug('load()') CogdoGameMovie.load(self) backgroundGui = loader.loadModel('phase_5/models/cogdominium/tt_m_gui_csa_flyThru') self.bg = backgroundGui.find('**/background') self.chatBubble = backgroundGui.find('**/chatBubble') self.chatBubble.setScale(6.5, 6.5, 7.3) self.chatBubble.setPos(0.32, 0, -0.78) self.bg.setScale(5.2) self.bg.setPos(0.14, 0, -0.6667) self.bg.reparentTo(aspect2d) self.chatBubble.reparentTo(aspect2d) self.frame = DirectFrame(geom=self.bg, relief=None, pos=(0.2, 0, -0.6667)) self.bg.wrtReparentTo(self.frame) self.gameTitleText = DirectLabel(parent=self.frame, text=TTLocalizer.CogdoExecutiveSuiteTitle, scale=TTLocalizer.MRPgameTitleText * 0.8, text_align=TextNode.ACenter, text_font=getSignFont(), text_fg=(1.0, 0.33, 0.33, 1.0), pos=TTLocalizer.MRgameTitleTextPos, relief=None) self.chatBubble.wrtReparentTo(self.frame) self.frame.hide() backgroundGui.removeNode() self.toonDNA = ToonDNA.ToonDNA() self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14, 0) self.toonHead = Toon.Toon() self.toonHead.setDNA(self.toonDNA) self.makeSuit('sc') self.toonHead.getGeomNode().setDepthWrite(1) self.toonHead.getGeomNode().setDepthTest(1) self.toonHead.loop('neutral') self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18) self.toonHead.reparentTo(hidden) self.toonHead.startBlink() self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip')) self.clipPlane.node().setPlane(Plane(0, 0, 1, 0)) self.clipPlane.setPos(0, 0, 2.45) self._toonDialogueSfx = loader.loadSfx('phase_3.5/audio/dial/AV_dog_long.ogg') self._camHelperNode = NodePath('CamHelperNode') self._camHelperNode.reparentTo(render) dialogue = TTLocalizer.CogdoExecutiveSuiteIntroMessage def start(): self.frame.show() base.setCellsActive(base.bottomCells + base.leftCells + base.rightCells, 0) def showShopOwner(): self._setCamTarget(self._shopOwner, -10, offset=Point3(0, 0, 5)) def end(): self._dialogueLabel.reparentTo(hidden) self.toonHead.reparentTo(hidden) self.frame.hide() base.setCellsActive(base.bottomCells + base.leftCells + base.rightCells, 1) self._stopUpdateTask() self._ival = Sequence(Func(start), Func(self.displayLine, dialogue), Func(showShopOwner), ParallelEndTogether(camera.posInterval(self.cameraMoveDuration, Point3(8, 0, 13), blendType='easeInOut'), camera.hprInterval(0.5, self._camHelperNode.getHpr(), blendType='easeInOut')), Wait(self.introDuration), Func(end)) self._startUpdateTask() return def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)): camera.wrtReparentTo(render) self._camTarget = targetNP self._camOffset = offset self._camAngle = angle self._camDistance = distance self._camHelperNode.setPos(self._camTarget, self._camOffset) self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2]) self._camHelperNode.setPos(self._camHelperNode, 0, self._camDistance, 0) def _updateTask(self, task): dt = globalClock.getDt() return task.cont def unload(self): self._shopOwner = None self._camTarget = None if hasattr(self, '_camHelperNode') and self._camHelperNode: self._camHelperNode.removeNode() del self._camHelperNode self.frame.destroy() del self.frame self.bg.removeNode() del self.bg self.chatBubble.removeNode() del self.chatBubble self.toonHead.stopBlink() self.toonHead.stop() self.toonHead.removeNode() self.toonHead.delete() del self.toonHead CogdoGameMovie.unload(self) return
class Game(ShowBase): ''' ''' def __init__(self): ''' ''' # loadPrcFileData("", "want-pstats 1\n pstats-host 127.0.0.1\n pstats-tasks 1\n task-timer-verbose 1") # loadPrcFileData("", "pstatshost 192.168.220.121") ShowBase.__init__(self) # PStatClient.connect() #activate to start performance measuring with pstats base.setFrameRateMeter(True) # Show the Framerate # base.toggleWireframe() self.accept("space", self.onSpace) self.accept("tab", self.onTab) self.startGame() self.cam_on = True # ----------------------------------------------------------------- # ----------------------------------------------------------------- def onSpace(self, evt=None): ''' ''' if self.trackmesh2.getParent() == render: self.trackmesh.reparentTo(render) self.trackmesh2.detachNode() else: self.trackmesh.detachNode() self.trackmesh2.reparentTo(render) # base.toggleWireframe() # ----------------------------------------------------------------- def startGame(self): ''' Start the game ''' # Create the Track self.track = trackgen3d.Track3d(1000, 800, 600, 200, 5) self.trackmesh = NodePath(self.track.createRoadMesh()) tex = loader.loadTexture('data/textures/street.png') self.trackmesh.setTexture(tex) self.trackmesh2 = NodePath(self.track.createUninterpolatedRoadMesh()) self.trackmesh2.setTexture(tex) # nodePath.setTwoSided(True) self.trackmesh.reparentTo(render) # LICHT self.plight = PointLight('kkkplight') self.plight.setColor(VBase4(21, 0, 0, 1)) self.plnp = NodePath(self.plight) self.plnp.reparentTo(render) self.plnp.setPos(0, 0, 2000) self.plnp.node().setAttenuation(Point3(0, 0, 1)) self.plnp.setScale(.5, .5, .5) # self.plnp.setHpr(0,-90,0) # print plight.getAttenuation() # plnp.setPos(-10, -800, 20) render.setLight(self.plnp) self.accept("w", self.setA, [100]) self.accept("s", self.setA, [-10]) self.accept("e", self.setB, [10]) self.accept("d", self.setB, [-10]) self.accept("r", self.setC, [100]) self.accept("f", self.setC, [-100]) self.accept("z", self.setRotation, [0, 10]) self.accept("h", self.setRotation, [0, -10]) self.accept("u", self.setRotation, [1, 10]) self.accept("j", self.setRotation, [1, -10]) self.accept("i", self.setRotation, [2, 10]) self.accept("k", self.setRotation, [2, -10]) self.accept("n", self.setExponent, [-50]) self.accept("m", self.setExponent, [50]) # load our model tron = loader.loadModel("data/models/vehicles/vehicle02") self.tron = tron # self.tron.loadAnims({"running":"models/tron_anim"}) tron.reparentTo(render) tron.setPos(0, 0, 15) tron.setHpr(0, -90, 0) # nodePath2 = self.render.attachNewNode(self.track.createBorderLeftMesh()) # tex2 = loader.loadTexture('data/textures/border.png') # nodePath2.setTexture(tex2) # # nodePath3 = self.render.attachNewNode(self.track.createBorderRightMesh()) # tex2 = loader.loadTexture('data/textures/border.png') # nodePath3.setTexture(tex2) ring = loader.loadModel("data/models/ring.egg") ring.setScale(24) ring.setZ(-25) ring.setY(100) ring.setTransparency(TransparencyAttrib.MAlpha) ring.reparentTo(render) # Load the Lights ambilight = AmbientLight('ambilight') ambilight.setColor(VBase4(0.8, 0.8, 0.8, 1)) render.setLight(render.attachNewNode(ambilight)) # ----------------------------------------------------------------- def setA(self, val): ''' ''' tpos = self.tron.getPos() tpos[0] += val self.tron.setPos(tpos) pos = self.plnp.getPos() pos[0] += val print(pos) self.plnp.setPos(pos) def setB(self, val): ''' ''' tpos = self.tron.getPos() tpos[1] += val self.tron.setPos(tpos) pos = self.plnp.getPos() pos[1] += val print(pos) self.plnp.setPos(pos) def setC(self, val): ''' ''' tpos = self.tron.getPos() tpos[2] += val self.tron.setPos(tpos) pos = self.plnp.getPos() pos[2] += val print(pos) self.plnp.setPos(pos) def setRotation(self, var, val): ''' ''' hpr = self.plnp.getHpr() hpr[var] += val print(("hpr", hpr)) self.plnp.setHpr(hpr) def setExponent(self, val): ''' ''' val = self.plight.getExponent() + val print(val) self.plight.setExponent(val) def onTab(self): ''' ''' if self.cam_on: base.disableMouse() base.camera.setPos(-293.807, 91.2993, 3984.4) base.camera.setHpr(-76.0078, -85.4581, -71.7315) # base.camera.setPos(39.3053, -376.205, -3939.89) # base.camera.setHpr(5.33686, -82.7432, 8.26239) # print base.camera.getPos(), base.camera.getHpr() self.cam_on = False else: base.enableMouse() self.cam_on = True
class DistributedButterfly(DistributedObject.DistributedObject): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedButterfly') id = 0 wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6') yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1)) whiteColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0, 0.8, 0.8, 1), Vec4(0.9, 0.4, 0.6, 1), Vec4(0.9, 0.4, 0.4, 1), Vec4(0.8, 0.5, 0.9, 1), Vec4(0.4, 0.1, 0.7, 1)) paleYellowColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0.6, 0.6, 0.9, 1), Vec4(0.7, 0.6, 0.9, 1), Vec4(0.8, 0.6, 0.9, 1), Vec4(0.9, 0.6, 0.9, 1), Vec4(1, 0.6, 0.9, 1)) shadowScaleBig = Point3(0.07, 0.07, 0.07) shadowScaleSmall = Point3(0.01, 0.01, 0.01) def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [ State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying']) ], 'off', 'off') self.butterfly = None self.butterflyNode = None self.curIndex = 0 self.destIndex = 0 self.time = 0.0 self.ival = None self.fsm.enterInitialState() return def generate(self): DistributedObject.DistributedObject.generate(self) if self.butterfly: return self.butterfly = Actor.Actor() self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod') self.butterfly.loadAnims({ 'flutter': 'phase_4/models/props/SZ_butterfly-flutter', 'glide': 'phase_4/models/props/SZ_butterfly-glide', 'land': 'phase_4/models/props/SZ_butterfly-land' }) index = self.doId % len(self.wingTypes) chosenType = self.wingTypes[index] node = self.butterfly.getGeomNode() for type in self.wingTypes: wing = node.find('**/' + type) if type != chosenType: wing.removeNode() else: if index == 0 or index == 1: color = self.yellowColors[self.doId % len(self.yellowColors)] elif index == 2 or index == 3: color = self.whiteColors[self.doId % len(self.whiteColors)] elif index == 4: color = self.paleYellowColors[self.doId % len(self.paleYellowColors)] else: color = Vec4(1, 1, 1, 1) wing.setColor(color) self.butterfly2 = Actor.Actor(other=self.butterfly) self.butterfly.enableBlend(blendType=PartBundle.BTLinear) self.butterfly.loop('flutter') self.butterfly.loop('land') self.butterfly.loop('glide') rng = RandomNumGen.RandomNumGen(self.doId) playRate = 0.6 + 0.8 * rng.random() self.butterfly.setPlayRate(playRate, 'flutter') self.butterfly.setPlayRate(playRate, 'land') self.butterfly.setPlayRate(playRate, 'glide') self.butterfly2.setPlayRate(playRate, 'flutter') self.butterfly2.setPlayRate(playRate, 'land') self.butterfly2.setPlayRate(playRate, 'glide') self.glideWeight = rng.random() * 2 lodNode = LODNode('butterfly-node') lodNode.addSwitch(100, 40) lodNode.addSwitch(40, 0) self.butterflyNode = NodePath(lodNode) self.butterfly2.setH(180.0) self.butterfly2.reparentTo(self.butterflyNode) self.butterfly.setH(180.0) self.butterfly.reparentTo(self.butterflyNode) self.__initCollisions() self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow') self.dropShadow.setColor(0, 0, 0, 0.3) self.dropShadow.setPos(0, 0.1, -0.05) self.dropShadow.setScale(self.shadowScaleBig) self.dropShadow.reparentTo(self.butterfly) def disable(self): self.butterflyNode.reparentTo(hidden) if self.ival != None: self.ival.finish() self.__ignoreAvatars() DistributedObject.DistributedObject.disable(self) return def delete(self): self.butterfly.cleanup() self.butterfly = None self.butterfly2.cleanup() self.butterfly2 = None self.butterflyNode.removeNode() self.__deleteCollisions() self.ival = None del self.fsm DistributedObject.DistributedObject.delete(self) return def uniqueButterflyName(self, name): DistributedButterfly.id += 1 return name + '-%d' % DistributedButterfly.id def __detectAvatars(self): self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter) def __ignoreAvatars(self): self.ignore('enter' + self.cSphereNode.getName()) def __initCollisions(self): self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0) self.cSphere.setTangible(0) self.cSphereNode = CollisionNode( self.uniqueButterflyName('cSphereNode')) self.cSphereNode.addSolid(self.cSphere) self.cSphereNodePath = self.butterflyNode.attachNewNode( self.cSphereNode) self.cSphereNodePath.hide() self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask) def __deleteCollisions(self): del self.cSphere del self.cSphereNode self.cSphereNodePath.removeNode() del self.cSphereNodePath def __handleCollisionSphereEnter(self, collEntry): self.sendUpdate('avatarEnter', []) def setArea(self, playground, area): self.playground = playground self.area = area def setState(self, stateIndex, curIndex, destIndex, time, timestamp): self.curIndex = curIndex self.destIndex = destIndex self.time = time self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)]) def enterOff(self, ts=0.0): if self.butterflyNode != None: self.butterflyNode.reparentTo(hidden) return def exitOff(self): if self.butterflyNode != None: self.butterflyNode.reparentTo(render) return def enterFlying(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.curIndex] destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.destIndex] flyHeight = max( curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground] curPosHigh = Point3(curPos[0], curPos[1], flyHeight) destPosHigh = Point3(destPos[0], destPos[1], flyHeight) if ts <= self.time: flyTime = self.time - ( ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground]) self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) oldHpr = self.butterflyNode.getHpr() self.butterflyNode.headsUp(destPos) newHpr = self.butterflyNode.getHpr() self.butterflyNode.setHpr(oldHpr) takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[ self.playground] landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[ self.playground] self.butterfly2.loop('flutter') self.ival = Sequence( Parallel( LerpPosHprInterval( self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence( LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel( LerpPosInterval( self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval( self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence( Wait(ButterflyGlobals.BUTTERFLY_LANDING[ self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly')) self.ival.start(ts) else: self.ival = None self.butterflyNode.setPos(destPos) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.loop('land') return def exitFlying(self): self.__ignoreAvatars() if self.ival != None: self.ival.finish() self.ival = None return def enterLanded(self, ts): self.__detectAvatars() curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][ self.curIndex] self.butterflyNode.setPos(curPos) self.dropShadow.show() self.dropShadow.setScale(self.shadowScaleBig) self.butterfly.setControlEffect('land', 1.0) self.butterfly.setControlEffect('flutter', 0.0) self.butterfly.setControlEffect('glide', 0.0) self.butterfly2.pose( 'land', random.randrange(self.butterfly2.getNumFrames('land'))) return None def exitLanded(self): self.__ignoreAvatars() return None
class itemClass(objectIdClass): def __init__( self, ground ): objectIdClass.__init__( self ) self.ground = ground # create collision object pass # create position node self.positionNp = NodePath( 'positionNp%s' % self.objectId ) #self.positionNp.reparentTo( render ) # load model self.modelNp = loader.loadModelCopy( 'data/models/box.egg' ) self.modelNp.reparentTo( self.positionNp ) self.setPos( Vec3(0,0,0) ) self.create3dObject() def destroy( self ): objectIdClass.destroy( self ) def create3dObject( self ): self.reparentTo( render ) #self.positionNp.show() self.makePickable( self.modelNp ) def setPos( self, position ): xPos, yPos, zPos = position.getX(), position.getY(), position.getZ() zGround = self.ground.get_elevation( [xPos, yPos] ) zPos = zGround #if zPos < zGround: # zPos = zGround return self.positionNp.setPos( Vec3(xPos, yPos, zPos) ) def getPos( self, relativeTo=None ): return self.positionNp.getPos( relativeTo ) def setHpr( self, hpr ): return self.positionNp.setHpr( hpr ) def reparentTo( self, object ): return self.positionNp.reparentTo( object ) def wrtReparentTo( self, object ): return self.positionNp.wrtReparentTo( object ) def putOnGround( self, xyPos ): return self.ground.get_elevation( xyPos ) def destroy3dObject( self ): self.positionNp.detachNode() #self.positionNp.hide() # destroy collision object # destroy shape #pass def create2dObject( self ): pass def destroy2dObject( self ): pass