def clipOnTie(enemy, hitPoint): tie = Actor('phase_3.5/models/props/clip-on-tie-mod.bam', {'clip-on-tie': 'phase_3.5/models/props/clip-on-tie-chan.bam'}) tie.getChild(0).setHpr(23.86, -16.03, 9.18) enemyType = enemy.style.body if enemyType == 'a': throwDelay = 2.17 elif enemyType == 'b': throwDelay = 2.17 elif enemyType == 'c': throwDelay = 1.45 enemyTrack = enemy.actorInterval('throw-paper') posPoints = [Point3(0.66, 0.51, 0.28), VBase3(-69.652, -17.199, 67.96)] propTrack = Sequence( getPropAppearTrack(tie, enemy.getRightHand(), posPoints, 0.5, PNT3_ONE, scaleUpTime=0.5, poseExtraArgs=['clip-on-tie', 0]), tie.actorInterval('clip-on-tie', duration=throwDelay, startTime=1.1), Func(tie.setHpr, 0, -90, 0), getPropThrowTrack(tie, [hitPoint], hitDuration=0.4, callback=enemy.arena.damageHQ)) sound = loader.loadSfx('phase_5/audio/sfx/SA_powertie_throw.ogg') soundTrack = Sequence(Wait(throwDelay + 1), SoundInterval(sound, node=enemy)) return Parallel(enemyTrack, propTrack, soundTrack)
def makeWalkingPanda(self, root, pos=(64,128, 0), axis_pos=(128, 128, 0), scale=0.02, time=90.0): axis = root.attachNewNode('axis') axis.setPos(axis_pos) actor = Actor('panda-model', {'walk': 'panda-walk4'}) actor.setPos(pos) actor.wrtReparentTo(axis) actor.setScale(scale) walk = actor.actorInterval('walk', playRate=1.3) walk.loop() axis.hprInterval(time, LPoint3(360, 0, 0), startHpr=LPoint3(0, 0, 0)).loop() return actor
class LookingGrippingDemo(ShowBase): def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) # This code puts the standard title and instruction text on screen self.title = OnscreenText( text="Panda3D: Tutorial - Joint Manipulation", fg=(1, 1, 1, 1), parent=base.a2dBottomRight, align=TextNode.ARight, pos=(-0.1, 0.1), shadow=(0, 0, 0, .5), scale=.08) self.onekeyText = genLabelText("ESC: Quit", 1) self.onekeyText = genLabelText("[1]: Teapot", 2) self.twokeyText = genLabelText("[2]: Candy cane", 3) self.threekeyText = genLabelText("[3]: Banana", 4) self.fourkeyText = genLabelText("[4]: Sword", 5) # Set up key input self.accept('escape', sys.exit) self.accept('1', self.switchObject, [0]) self.accept('2', self.switchObject, [1]) self.accept('3', self.switchObject, [2]) self.accept('4', self.switchObject, [3]) base.disableMouse() # Disable mouse-based camera-control camera.setPos(0, -15, 2) # Position the camera self.eve = Actor( "models/eve", # Load our animated charachter {'walk': "models/eve_walk"}) self.eve.reparentTo(render) # Put it in the scene # Now we use controlJoint to get a NodePath that's in control of her neck # This must be done before any animations are played self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck') # We now play an animation. An animation must be played, or at least posed # for the nodepath we just got from controlJoint to actually effect the # model self.eve.actorInterval("walk", playRate=2).loop() # Now we add a task that will take care of turning the head taskMgr.add(self.turnHead, "turnHead") # Now we will expose the joint the hand joint. ExposeJoint allows us to # get the position of a joint while it is animating. This is different than # controlJonit which stops that joint from animating but lets us move it. # This is particularly usefull for putting an object (like a weapon) in an # actor's hand self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand') # This is a table with models, positions, rotations, and scales of objects to # be attached to our exposed joint. These are stock models and so they needed # to be repositioned to look right. positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4), ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1), ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75), ("models/sword", (.11, .19, .06), (0, 0, 90), 1)] self.models = [] # A list that will store our models objects for row in positions: np = loader.loadModel(row[0]) # Load the model np.setPos(row[1][0], row[1][1], row[1][2]) # Position it np.setHpr(row[2][0], row[2][1], row[2][2]) # Rotate it np.setScale(row[3]) # Scale it # Reparent the model to the exposed joint. That way when the joint moves, # the model we just loaded will move with it. np.reparentTo(self.rightHand) self.models.append(np) # Add it to our models list self.switchObject(0) # Make object 0 the first shown self.setupLights() # Put in some default lighting # This is what we use to change which object it being held. It just hides all of # the objects and then unhides the one that was selected def switchObject(self, i): for np in self.models: np.hide() self.models[i].show() # This task gets the position of mouse each frame, and rotates the neck based # on it. def turnHead(self, task): # Check to make sure the mouse is readable if base.mouseWatcherNode.hasMouse(): # get the mouse position as a LVector2. The values for each axis are from -1 to # 1. The top-left is (-1,-1), the bottom right is (1,1) mpos = base.mouseWatcherNode.getMouse() # Here we multiply the values to get the amount of degrees to turn # Restrain is used to make sure the values returned by getMouse are in the # valid range. If this particular model were to turn more than this, # significant tearing would be visable self.eveNeck.setP(clamp(mpos.getX()) * 50) self.eveNeck.setH(clamp(mpos.getY()) * 20) return Task.cont # Task continues infinitely def setupLights(self): # Sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 8, -2.5)) directionalLight.setColor((0.9, 0.8, 0.9, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class World(DirectObject): #subclassing here is necessary to accept events def __init__(self): #turn off default mouse control, otherwise can't reposition camera base.disableMouse() camera.setPosHpr(0, -15, 7, 0, -15, 0) self.loadModels() self.setupLights() self.setupCollisions() render.setShaderAuto() #turns on per-pixel lighting, normal mapping, etc (you probably want to use this) self.keyMap = {"left":0, "right":0, "forward":0} taskMgr.add(self.move, "moveTask") self.prevtime = 0 self.ismoving = False self.accept("escape", sys.exit) self.accept("arrow_up", self.setKey, ["forward", 1]) self.accept("arrow_right", self.setKey, ["right", 1]) self.accept("arrow_left", self.setKey, ["left", 1]) self.accept("arrow_up-up", self.setKey, ["forward", 0]) self.accept("arrow_right-up", self.setKey, ["right", 0]) self.accept("arrow_left-up", self.setKey, ["left", 0]) #"mouse1" is left mouse button is clicked #append "-up" for equivalent of for equivalent of KEYUP event self.accept("ate-smiley", self.eat) def setKey(self, key, value): self.keyMap[key] = value def loadModels(self): """loads initial models into the world.""" self.panda = Actor("models/panda-model", {"walk":"panda-walk4", "eat":"panda-eat"}) self.panda.reparentTo(render) self.panda.setScale(0.005) self.panda.setH(180) self.env = loader.loadModel("models/environment") self.env.reparentTo(render) self.env.setScale(.25) self.env.setPos(-8, 42, 0) #load targets self.targets = [] for i in range(10): target = loader.loadModel("smiley") target.setScale(.5) target.setPos(random.uniform(-20, 20), random.uniform(-15, 15), 2) target.reparentTo(render) self.targets.append(target) def setupLights(self): #ambient light self.ambientLight = AmbientLight("ambientLight") #parameter is a name #four values, RGBA, Alpha is largely irrelevant, value [0,1] self.ambientLight.setColor((.25, .25, .25, 1)) self.ambientLightNP = render.attachNewNode(self.ambientLight) #the nodepath that calls setLight is what gets illuminated by the light render.setLight(self.ambientLightNP) #call clearLight() to turn it off self.keyLight = DirectionalLight("keyLight") self.keyLight.setColor((.6, .6, .6, 1)) self.keyLightNP = render.attachNewNode(self.keyLight) self.keyLightNP.setHpr(0, -26, 0) render.setLight(self.keyLightNP) self.fillLight = DirectionalLight("fillLight") self.fillLight.setColor((.3, .3, .3, 1)) self.fillLightNP = render.attachNewNode(self.fillLight) self.fillLightNP.setHpr(30, 0, 0) render.setLight(self.fillLightNP) def walk(self): """compound interval for walking""" #self.pandaWalk = self.panda.posInterval(1, (0, -5, 0)) #some interval methods: #start(), loop(), pause(), resume(), finish() #start() can take arguments: start(starttime, endtime, playrate) dist = 5 angle = deg2Rad(self.panda.getH()) dx = dist * math.sin(angle) dy = dist * -math.cos(angle) pandaWalk = Parallel(self.panda.posInterval(1, (self.panda.getX()+dx, self.panda.getY()+dy, 0)), \ self.panda.actorInterval("walk", loop=1, duration=1)) pandaWalk.start() def turn(self, direction): pandaTurn = self.panda.hprInterval(.2, (self.panda.getH() - (10*direction), 0, 0)) pandaTurn.start() def move(self, task): elapsed = task.time - self.prevtime camera.lookAt(self.panda) if self.keyMap["left"]: self.panda.setH(self.panda.getH() + elapsed*100) if self.keyMap["right"]: self.panda.setH(self.panda.getH() - elapsed*100) if self.keyMap["forward"]: dist = 15 * elapsed angle = deg2Rad(self.panda.getH()) dx = dist * math.sin(angle) dy = dist * -math.cos(angle) self.panda.setPos(self.panda.getX()+dx, self.panda.getY()+dy, 0) if self.keyMap["left"] or self.keyMap["right"] or self.keyMap["forward"]: if self.ismoving == False: self.ismoving = True self.panda.loop("walk") else: if self.ismoving: self.ismoving = False self.panda.stop() self.panda.pose("walk",4) self.prevtime = task.time return Task.cont def setupCollisions(self): #instantiates a collision traverser and sets it to the default base.cTrav = CollisionTraverser() self.cHandler = CollisionHandlerEvent() #set pattern for event sent on collision #"%in" is substituted with the name of the into object self.cHandler.setInPattern("ate-%in") cSphere = CollisionSphere((0,0,0), 500)#because the panda is scaled way down, radius has to be huge cNode = CollisionNode("panda") cNode.addSolid(cSphere) cNode.setIntoCollideMask(BitMask32.allOff())#panda is *only* a from object cNodePath = self.panda.attachNewNode(cNode) #cNodePath.show() #registers a from object with the traverser with a corresponding handler base.cTrav.addCollider(cNodePath, self.cHandler) for target in self.targets: cSphere = CollisionSphere((0,0,0), 2) cNode = CollisionNode("smiley") cNode.addSolid(cSphere) cNodePath = target.attachNewNode(cNode) #cNodePath.show() def eat(self, cEntry): """handles panda eating a smiley""" #remove target from list of targets self.targets.remove(cEntry.getIntoNodePath().getParent()) #remove from scene graph cEntry.getIntoNodePath().getParent().remove() self.panda.play("eat")
class RainbowSplash: def __init__(self, pattern=Pattern.SQUARESTAR, colors=Colors.RGB_BANDS, pattern_freq=2, cycle_freq=10): self.pattern = pattern self.colors = colors self.pattern_freq = pattern_freq self.cycle_freq = cycle_freq def setup(self): # Store current values self.entry_background_color = VBase4(base.win.get_clear_color()) self.entry_cam_pos = VBase3(base.cam.get_pos()) self.entry_cam_hpr = VBase3(base.cam.get_hpr()) self.entry_cam_scale = VBase3(base.cam.get_scale()) self.entry_cam_fov = VBase2(base.cam.node().get_lens().get_fov()) # Set values for splash base.win.set_clear_color((0,0,0,1)) cam_dist = 2 base.cam.set_pos(0, -2.2 * cam_dist, 0) base.cam.set_hpr(0, 0, 0) base.cam.set_scale(1) base.cam.node().get_lens().set_fov(45/cam_dist) # Set up the splash itself self.logo_animation = Actor(asset_path / "panda3d_logo.bam") self.logo_animation.reparent_to(render) self.logo_animation.set_two_sided(True) shader = Shader.load( Shader.SL_GLSL, vertex=asset_path / "panda3d_logo.vert", fragment=asset_path / "panda3d_logo.frag", ) self.logo_animation.set_shader(shader) self.logo_animation.set_shader_input("fade", 0.0) self.logo_animation.set_shader_input("pattern", self.pattern.value) self.logo_animation.set_shader_input("colors", self.colors.value) self.logo_animation.set_shader_input("pattern_freq", self.pattern_freq) self.logo_animation.set_shader_input("cycle_freq", self.cycle_freq) self.logo_sound = base.loader.loadSfx(asset_path / "panda3d_logo.wav") # Build interval def shader_time(t): self.logo_animation.set_shader_input("time", t) def fade_background_to_white(t): base.win.set_clear_color((t,t,t,1)) self.logo_animation.set_shader_input("time", t/3.878) self.logo_animation.set_shader_input("fade", t) def fade_to_black(t): base.win.set_clear_color((1-t,1-t,1-t,1)) #self.logo_animation.set_shader_input("time", t/3.878) #self.logo_animation.set_shader_input("fade", t) # Timing: # 0.000 Start # 3.878 Logo is assembled, fade to black-on-whitey # 4.878 Black on white achieved # <+1.500> Begin fade to black # <+1.741> Black on black achieved # 8.119 Sound ends effects = Parallel( self.logo_animation.actorInterval( "splash", loop=False, ), SoundInterval( self.logo_sound, loop=False, ), Sequence( LerpFunc( shader_time, fromData=0, toData=1, duration=3.878, ), LerpFunc( fade_background_to_white, fromData=0, toData=1, duration=1.0, ), Wait(1.5), LerpFunc( fade_to_black, fromData=0, toData=1, duration=1.741, ), ), ) return effects def teardown(self): # Store current values base.win.set_clear_color(self.entry_background_color) base.cam.set_pos(self.entry_cam_pos) base.cam.set_hpr(self.entry_cam_hpr) base.cam.set_scale(self.entry_cam_scale) base.cam.node().get_lens().set_fov(self.entry_cam_fov) self.logo_animation.cleanup()
class Digger(enemy.Enemy): def __init__(self, mainRef): enemy.Enemy.__init__(self, mainRef, enemy.koboldSkirmisher) # Change to correct kobold self.holeModel = None def initAttributes(self, attributes): super(Digger, self).initAttributes(attributes) rangeMultiplier = 1.5 self.combatRange *= rangeMultiplier self.perceptionRange *= rangeMultiplier def loadEnemyModel(self, modelName): modelPrefix = 'models/digger-' self.enemyModel = Actor(modelPrefix + 'model', { 'attack1':modelPrefix+'attack1', 'attack2':modelPrefix+'attack2', 'attack3':modelPrefix+'attack3', 'attack4':modelPrefix+'attack4', 'special-attack':modelPrefix+'special-attack', 'pursue':modelPrefix+'pursue', 'pursue-to-idle':modelPrefix+'pursue-stop', 'idle-walk':modelPrefix+'idle-walk', 'idle-walk-to-pursue':modelPrefix+'idle-walk-to-pursue', 'idle-walk-to-dig':modelPrefix+'idle-walk-to-dig', 'idle-walk-to-dig-to-sleep':modelPrefix+'idle-walk-to-dig-to-sleep', 'hit1':modelPrefix+'hit1', 'hit2':modelPrefix+'hit2', 'death1':modelPrefix+'death1', 'death2':modelPrefix+'death2', 'death3':modelPrefix+'death3' }) self.enemyModel.reparentTo(self.enemyNode) self.enemyNode.setPos(Point3.zero()) self.enemyNode.setDepthOffset(-1) def enterIdle(self): #print 'enemy enterIdle' #idleTime = 60.0 * 3.0 stopEnemy = self.enemyModel.actorInterval('pursue-to-idle', startFrame=0, endFrame=12) idleEnemy = self.enemyModel.actorInterval('idle-walk-to-dig', startFrame=0, endFrame=60) digHole = Parallel(Func(self.createHole), self.enemyModel.actorInterval('idle-walk-to-dig-to-sleep', startFrame=0, endFrame=120)) #hideEnemy = Func(self.enemyNode.hide) #suicide = Func(self.suicide) self.stopSequence = Sequence(stopEnemy, idleEnemy, digHole) self.stopSequence.start() self.isSleeping = True #taskMgr.doMethodLater(3, self.showEnemy, 'showEnemyTask') def showEnemy(self, task): if self.state == 'Idle': self.enemyNode.show() return task.done def enterPursue(self): #print('enemy enterPursue') loopWalkEnemy = Func(self.enemyModel.loop, 'pursue', fromFrame=0, toFrame=24) # Only awake enemy if it comes from idle if self.isSleeping: self.isSleeping = False awakeEnemy = self.enemyModel.actorInterval('idle-walk-to-pursue', startFrame=0, endFrame=24) self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer)) else: self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer)) self.awakeSequence.start() def enterDeath(self): #print('enemy enterDeath') self.enemyAIBehaviors.removeAi('all') randomDeathAnim = 'death' + str(utils.getDX(3)) self.enemyModel.play(randomDeathAnim, fromFrame=0, toFrame=12) def playAttackAnimation(self): randomAttackAnim = 'attack' + str(utils.getD4()) self.enemyModel.play(randomAttackAnim, fromFrame=0, toFrame=12) def playHitAnimation(self): randomHitAnim = 'hit' + str(utils.getDX(2)) self.enemyModel.play(randomHitAnim, fromFrame=0, toFrame=12) def createHole(self): if self.holeModel == None: self.holeModel = Actor('models/hole-model', {'anim':'models/hole-anim'}) self.holeModel.reparentTo(self._mainRef.mainNode) self.holeModel.setPos(self.enemyNode, 0, -.1, 0) self.holeModel.play('anim', fromFrame=0, toFrame=120) removeHoleDelay = 12 taskMgr.doMethodLater(removeHoleDelay, self.removeHole, 'removeHoleTask') def removeHole(self, task): if self.holeModel != None: self.holeModel.cleanup() self.holeModel.delete() self.holeModel = None return task.done
class SimpleWeapon: """Provides a simple weapon system - not very sophisticaed, but good enough to test shooting things.""" def __init__(self,manager,xml): self.gunView = render.attachNewNode('gun-view') self.ray = None self.reload(manager,xml) def destroy(self): self.gunView.removeNode() if self.ray!=None: self.ray.destroy() def reload(self,manager,xml): # Get the path to load weapons from... basePath = manager.get('paths').getConfig().find('weapons').get('path') # Variables to manage the firing state (Used G36 as reference for defaults.)... bullet = xml.find('bullet') if bullet!=None: self.bulletRate = float(bullet.get('rate',1.0/12.5)) self.bulletSpeed = float(bullet.get('speed',920.0)) self.bulletWeight = float(bullet.get('mass',0.004)) else: self.bulletRate = 1.0/12.5 self.bulletSpeed = 920.0 self.bulletWeight = 0.004 # Determine the weapon meshes path... self.meshPath = posixpath.join(basePath, xml.find('egg').get('file')) # Get the camera interface, so we can zoom in when the player aims... self.camera = manager.get(xml.find('camera').get('plugin')) # Create our gun node - both the gun and the ray used for shooting track this - allows for gun jitter, kick back etc... parent = xml.find('parent') self.gunView.reparentTo(manager.get(parent.get('plugin')).getNode(parent.get('node'))) # Create a ray cast to detect what the player is looking at... and what will be shot... self.space = manager.get('ode').getSpace() if self.ray!=None: self.ray.destroy() self.ray = OdeRayGeom(100.0) self.ray.setCategoryBits(BitMask32(0xfffffffe)) self.ray.setCollideBits(BitMask32(0xfffffffe)) # Get all the stuff we need to do the muzzle flash particle effect... flash = xml.find('muzzle_flash') self.flashManager = manager.get(flash.get('plugin')) self.flashEffect = flash.get('effect') self.flashBone = flash.get('bone') # Will be swapped out for the actual node latter. self.flashPos = csp.getPos(flash.get('pos')) # Get all the stuff we need to do the bullet hit sparks effect... sparks = xml.find('sparks') self.sparksManager = manager.get(sparks.get('plugin')) self.sparksEffect = sparks.get('effect') # Create a quaternion that rotates +ve z to +ve y - used to point it in the weapon direction rather than up... self.zToY = Quat() self.zToY.setFromAxisAngle(-90.0,Vec3(1.0,0.0,0.0)) # State for the animation... self.state = False # False==casual, True==aim. self.nextState = False # Firing state... self.firing = False # True if the trigger is being held. self.triggerTime = 0.0 # How long the trigger has been held for, so we know when to eject ammo. # For bullet holes bh = xml.find('bullet_holes') if bh != None: self.bulletHoles = manager.get(bh.get('plugin')) else: self.bulletHoles = None def postInit(self): for i in self.postReload(): yield i def postReload(self): # Load the actor... self.mesh = Actor(self.meshPath) yield # Shader generator makes it shiny, plus we need it in the right places in the render graph... self.mesh.setShaderAuto() self.mesh.reparentTo(self.gunView) self.mesh.hide() yield # Set its animation going... except we pause it until needed... self.nextAni() self.interval.pause() # Gun flash requires an exposed bone... self.flashBone = self.mesh.exposeJoint(None,"modelRoot",self.flashBone) yield def gunControl(self,task): # Update the gun direction ray to follow the players view... self.ray.setPosition(self.gunView.getPos(render)) self.ray.setQuaternion(self.zToY.multiply(self.gunView.getQuat(render))) # If the gun is firing update the trigger time, if a bullet is ejected do the maths... if self.firing: dt = globalClock.getDt() self.triggerTime += dt while self.triggerTime>self.bulletRate: self.triggerTime -= self.bulletRate hit,pos,norm = ray_cast.nearestHit(self.space,self.ray) # Create a muzzle flash effect... self.flashManager.doEffect(self.flashEffect, self.flashBone, True, self.flashPos) if hit: # Create an impact sparks effect... # Calculate the reflection direction... rd = self.ray.getDirection() sparkDir = (norm * (2.0*norm.dot(rd))) - rd # Convert the reflection direction into a quaternion that will rotate +ve z to the required direction... try: ang = -math.acos(sparkDir[2]) except: print 'Angle problem', sparkDir ang = 0.0 axis = Vec3(0.0,0.0,1.0).cross(sparkDir) axis.normalize() sparkQuat = Quat() sparkQuat.setFromAxisAngleRad(ang,axis) # Set it going... self.sparksManager.doEffect(self.sparksEffect, render, False, pos, sparkQuat) # Make a bullet hole if hit.hasBody() and isinstance(hit.getBody().getData(), NodePath): self.bulletHoles.makeNew(pos, norm, hit.getBody().getData()) else: self.bulletHoles.makeNew(pos, norm, None) # Impart some energy on the object... if hit and hit.hasBody(): body = hit.getBody() # Calculate the force required to supply the energy the bullet contains to the body... force = self.bulletWeight*self.bulletSpeed/0.05 # Get the direction of travel of the bullet, multiply by force... d = self.ray.getDirection() d *= force # If the object is asleep awaken it... if not body.isEnabled(): body.enable() # Add the force to the object... body.addForceAtPos(d,pos) return task.cont def start(self): # Make the gun visible... self.mesh.show() # Set the gun animation going... self.interval.finish() # Weapon task - this primarily makes it shoot... self.task = taskMgr.add(self.gunControl,'GunControl') def stop(self): self.interval.pause() self.mesh.hide() taskMgr.remove(self.task) def nextAni(self): self.state = self.nextState if self.state: ani = random.choice(('aim_wiggle_a','aim_wiggle_b','aim_wiggle_c')) else: ani = random.choice(('casual_wiggle_a','casual_wiggle_b','casual_wiggle_c')) self.mesh.pose(ani,0) self.interval = Sequence(self.mesh.actorInterval(ani),Func(self.nextAni)) self.interval.start() def setAiming(self,s): if self.nextState!=s: self.interval.pause() self.nextState = s self.camera.setZoomed(s) def wib(): self.interval.finish() if s: ani = 'casual_aim' else: ani = 'aim_casual' transition = Sequence(self.mesh.actorInterval(ani),Func(wib)) transition.start() def setFiring(self,s): self.firing = s if self.firing: self.triggerTime = 0.0
class Enemy(FSM, Unit): # Declare private variables _enemyActive = False _removeCorpseDelay = 2 # seconds before corpse is cleaned def __init__(self, mainRef, attributes): print("Enemy instantiated") Unit.__init__(self) FSM.__init__(self, 'playerFSM') self._mainRef = mainRef self._playerRef = mainRef.player self._AIworldRef = mainRef.AIworld self._enemyListRef = mainRef.enemyList self._ddaHandlerRef = mainRef.DDAHandler self._stateHandlerRef = mainRef.stateHandler self._scenarioHandlerRef = mainRef.scenarioHandler #self.topEnemyNode = mainRef.mainNode.attachNewNode('topEnemyNode') self.initEnemyNode(mainRef.mainNode) utils.enemyDictionary[self.enemyNode.getName()] = self self.loadEnemyModel(attributes.modelName) self.initAttributes(attributes) self.initEnemyAi() self.initEnemyDDA() self.initEnemyCollisionHandlers() self.initEnemyCollisionSolids() #self.request('Idle') self.request('Disabled') # Start enemy updater task self.enemyUpdaterTask = taskMgr.add(self.enemyUpdater, 'enemyUpdaterTask') def initEnemyNode(self, parentNode): enemyName = 'enemy' + str(len(self._enemyListRef)) self.enemyNode = parentNode.attachNewNode(enemyName) self._enemyListRef.append(self) def loadEnemyModel(self, modelName): modelPrefix = 'models/' + modelName self.enemyModel = Actor( modelPrefix + '-model', { 'walk': modelPrefix + '-walk', 'attack': modelPrefix + '-attack', 'idle': modelPrefix + '-idle', 'awake': modelPrefix + '-awake', 'stop': modelPrefix + '-stop', 'hit': modelPrefix + '-hit', 'death1': modelPrefix + '-death1', 'death2': modelPrefix + '-death2' }) self.enemyModel.reparentTo(self.enemyNode) self.enemyNode.setPos(Point3.zero()) self.enemyNode.setDepthOffset(-1) def initAttributes(self, attributes): perceptionRangeMultiplier = 1.2 combatRangeMultiplier = .3 speedMultiplier = .1 self.strength = attributes.strength self.constitution = attributes.constitution self.dexterity = attributes.dexterity self.mass = attributes.mass self.movementSpeed = speedMultiplier * attributes.movementSpeed self.perceptionRange = perceptionRangeMultiplier * attributes.perceptionRange self.combatRange = combatRangeMultiplier * attributes.combatRange self.attackBonus = attributes.attackBonus self.damageBonus = attributes.damageBonus self.damageRange = attributes.damageRange self.initiativeBonus = attributes.initiativeBonus self.fixedHealthPoints = attributes.fixedHealthPoints self.armorClass = attributes.armorClass if attributes.startLevel > 1: for i in range(attributes.startLevel - 1): self.increaseLevel() self.expAward = attributes.expAward self.initHealth() def initEnemyDDA(self): if self._scenarioHandlerRef.getHasDDA(): maxLevelDifference = self._ddaHandlerRef.maxLevelDifference # Level enemy up to player's level minus maxLevelDifference levelDifference = self._playerRef.level - self.level if levelDifference >= maxLevelDifference: for i in range(levelDifference - maxLevelDifference): self.increaseLevel() def getAttackBonus(self): modifier = self.getStrengthModifier() if self.getStrengthModifier( ) > self.getDexterityModifier() else self.getDexterityModifier() ab = self.attackBonus + (self.level / 2) + modifier # + utils.getD20() if self._scenarioHandlerRef.getHasDDA(): attackBonusModifier = self._ddaHandlerRef.attackBonusModifier if attackBonusModifier < 0: ab -= attackBonusModifier if ab < 1: ab = 1 return ab + utils.getD20() def initEnemyAi(self): self.enemyAI = AICharacter( 'enemy', self.enemyNode, self.mass, # Mass 0.1, # Movt force self.movementSpeed) # Max force self._AIworldRef.addAiChar(self.enemyAI) self.enemyAIBehaviors = self.enemyAI.getAiBehaviors() #self.enemyAIBehaviors.obstacleAvoidance(1.0) def initEnemyCollisionHandlers(self): self.groundHandler = CollisionHandlerQueue() self.collPusher = CollisionHandlerPusher() def initEnemyCollisionSolids(self): # Enemy ground ray groundRay = CollisionRay(0, 0, 2, 0, 0, -1) groundColl = CollisionNode('enemyGroundRay') groundColl.addSolid(groundRay) groundColl.setIntoCollideMask(BitMask32.allOff()) groundColl.setFromCollideMask(BitMask32.bit(1)) self.groundRayNode = self.enemyNode.attachNewNode(groundColl) #self.groundRayNode.show() base.cTrav.addCollider(self.groundRayNode, self.groundHandler) # Enemy collision sphere collSphereNode = CollisionNode('enemyCollSphere') collSphere = CollisionSphere(0, 0, 0.1, 0.2) collSphereNode.addSolid(collSphere) collSphereNode.setIntoCollideMask(BitMask32.allOff()) collSphereNode.setFromCollideMask(BitMask32.bit(2)) self.sphereNode = self.enemyNode.attachNewNode(collSphereNode) #sphereNode.show() base.cTrav.addCollider(self.sphereNode, self.collPusher) self.collPusher.addCollider(self.sphereNode, self.enemyNode) # Enemy picker collision sphere pickerSphereCollNode = CollisionNode(self.enemyNode.getName()) pickerCollSphere = CollisionSphere(0, 0, 0, 0.5) pickerSphereCollNode.addSolid(pickerCollSphere) pickerSphereCollNode.setFromCollideMask(BitMask32.allOff()) pickerSphereCollNode.setIntoCollideMask(BitMask32.bit(1)) self.pickerNode = self.enemyNode.attachNewNode(pickerSphereCollNode) #sphereNodePath.show() # Enemy attack collision sphere attackCollSphereNode = CollisionNode(self.enemyNode.getName() + 'atkSph') attackCollSphere = CollisionSphere(0, 0, 0.1, 0.15) attackCollSphereNode.addSolid(attackCollSphere) attackCollSphereNode.setIntoCollideMask(BitMask32.bit(3)) attackCollSphereNode.setFromCollideMask(BitMask32.allOff()) attackSphereNode = self.enemyNode.attachNewNode(attackCollSphereNode) #attackSphereNode.show() def slowMovementByPercentage(self, percentage=30, slowDuration=20): #print self.enemyNode.getName(), ' slowed by ', percentage, ' %' oldSpeed = self.movementSpeed newSpeed = ((100.0 - percentage) / 100.0) * oldSpeed if newSpeed < 1.0: newSpeed = 1.0 self.movementSpeed = newSpeed taskMgr.doMethodLater(slowDuration, self.removeSlowMovement, 'removeSlowMovementTask', extraArgs=[oldSpeed], appendTask=True) def removeSlowMovement(self, oldSpeed, task): self.movementSpeed = oldSpeed return task.done def checkGroundCollisions(self): if self.groundHandler.getNumEntries() > 0: self.groundHandler.sortEntries() entries = [] for i in range(self.groundHandler.getNumEntries()): entry = self.groundHandler.getEntry(i) #print('entry:', entry) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) for i in range(len(entries)): if entries[i].getIntoNode().getName()[:6] == 'ground': #print('entryFound:', entries[0]) newZ = entries[i].getSurfacePoint(base.render).getZ() self.enemyNode.setZ(newZ) #print('enemyZ:', newZ) break def enemyUpdater(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive: self.enemyModel.stop() # Do not do anything when paused return task.cont self.checkGroundCollisions() if self.getIsDead(): self.onDeath() return task.done if self._playerRef.getIsDead(): return task.cont playerPos = self._playerRef.playerNode.getPos() enemyPos = self.enemyNode.getPos() # If player is within enemy perception range if utils.getIsInRange(playerPos, enemyPos, self.perceptionRange): # If enemy is not doing anything if self.state == 'Idle': # Start pursuing if self.state != 'Pursue': self.request('Pursue') # If enemy is already pursueing elif self.state == 'Pursue': # If player is within combat range if utils.getIsInRange(playerPos, enemyPos, self.combatRange): #print 'enemy go to combat' # Go to combat if self.state != 'Combat': self.request('Combat') # If enemy is already in combat elif self.state == 'Combat': # If player has moved out of combat range if not utils.getIsInRange(playerPos, enemyPos, self.combatRange): # Start pursuing if self.state != 'Pursue': self.request('Pursue') # If enemy is disabled elif self.state == 'Disabled': if self.enemyAI.getMaxForce() != self.movementSpeed: self.enemyAI.setMaxForce(self.movementSpeed) # If player is not within perception range else: if self.state != 'Idle': self.request('Idle') return task.cont def pursuePlayer(self): taskMgr.add(self.pursue, 'pursueTask') def pursue(self, task): if self.state == 'Pursue' and not self.getIsDead(): pitchRoll = self.enemyNode.getP(), self.enemyNode.getR() self.enemyNode.headsUp(self._playerRef.playerNode) self.enemyNode.setHpr(self.enemyNode.getH() - 180, *pitchRoll) speed = -self.movementSpeed * globalClock.getDt() self.enemyNode.setFluidPos(self.enemyNode, 0, speed, 0) return task.cont else: task.done def enterIdle(self): #print 'enemy enterIdle' stopEnemy = self.enemyModel.actorInterval('stop', loop=0) idleEnemy = self.enemyModel.actorInterval('idle', startFrame=0, endFrame=1, loop=0) self.stopSequence = Sequence(stopEnemy, idleEnemy) self.stopSequence.start() self.isSleeping = True def exitIdle(self): #print('enemy exitIdle') self.stopSequence.finish() def enterPursue(self): #print('enemy enterPursue') loopWalkEnemy = Func(self.enemyModel.loop, 'walk', fromFrame=0, toFrame=12) # Only awake enemy if it comes from idle if self.isSleeping: self.isSleeping = False awakeEnemy = self.enemyModel.actorInterval('awake', loop=0) self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer)) else: self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer)) self.awakeSequence.start() def exitPursue(self): #print('enemy exitPursue') self.awakeSequence.finish() def enterCombat(self): #print('enemy enterCombat') self.enemyModel.stop() attackDelay = self.getInitiativeRoll() self.attackTask = taskMgr.doMethodLater(attackDelay, self.attackPlayer, 'attackPlayerTask') def enterDisabled(self): #print 'enterDisable' pass def exitDisabled(self): #print 'exitDisable' pass def exitCombat(self): #print('enemy exitCombat') taskMgr.remove(self.attackTask) def enterDeath(self): #print('enemy enterDeath') self.enemyAIBehaviors.removeAi('all') randomDeathAnim = 'death' + str(utils.getD2()) self.enemyModel.play(randomDeathAnim) def attack(self, other): if not self.getIsDead() and not other.getIsDead(): if self.getAttackBonus() >= other.getArmorClass(): dmg = self.getDamageBonus() #print(self.getName(), ' damaged ', other.getName(), ' for ', dmg, ' damage') other.receiveDamage(dmg) return 2 # Returns 2 when self damages other return 1 # Returns 1 when self attacks other, but misses return 0 # Returns 0 when either self or other is dead def attackPlayer(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive: # Do not do anything when paused return task.again if self._playerRef.getIsDead(): print('player is already dead') self.request('Idle') return task.done elif self.getIsDead(): return task.done else: #print('Attack player!') # Make sure enemy is facing player when attacking pitchRoll = self.enemyNode.getP(), self.enemyNode.getR() self.enemyNode.headsUp(self._playerRef.playerNode) self.enemyNode.setHpr(self.enemyNode.getH() - 180, *pitchRoll) attacked = self.attack(self._playerRef) if attacked != 0: self.playAttackAnimation() if attacked == 2: self._playerRef.playerModel.play('hit') return task.again def playAttackAnimation(self): self.enemyModel.play('attack', fromFrame=0, toFrame=12) def playHitAnimation(self): self.enemyModel.play('hit') def moveEnemy(self, x, y): self.enemyNode.setPos(x, y, .01) def handleHealthGlobe(self): global dropChanceFactor global dropChance global maxDropChance # if we drop, create health goblet chance = dropChanceFactor + dropChance if self._scenarioHandlerRef.getHasDDA(): chance *= self._ddaHandlerRef.healthGobletModifier if utils.getD100() <= chance: HealthGoblet(self._mainRef, self) print 'dropping health goblet' # Otherwise, increase dropChance else: if dropChance + dropChanceFactor <= maxDropChance: dropChance += dropChanceFactor def suicide(self): print('suicide: ', self) # Remove AI behavior self.enemyAIBehaviors.removeAi('all') # Remove enemy picker sphere (handlerQueue) self.pickerNode.removeNode() taskMgr.add(self.removeCorpse, 'removeCorpseTask') def onDeath(self): if self.getIsDead(): # Remove AI behavior self.enemyAIBehaviors.removeAi('all') # Award the player exp self._playerRef.receiveEXP(self.expAward) # Remove enemy picker sphere (handlerQueue) self.pickerNode.removeNode() # Change state self.request('Death') # Increase DDA death count if self._scenarioHandlerRef.getHasDDA(): self._ddaHandlerRef.enemyDeathCount += 1 # Handle health globe self.handleHealthGlobe() # Remove enemy corpse and clean up taskMgr.doMethodLater(self._removeCorpseDelay, self.removeCorpse, 'removeCorpseTask') def removeCorpse(self, task): # Remove enemy collision sphere (pusher) self.sphereNode.removeNode() # Stop the collision pusher self.collPusher = None # Remove enemy from enemyList self._enemyListRef.remove(self) # Cleanup the enemy model self.enemyModel.cleanup() self.enemyModel.delete() # Cleanup FSM self.cleanup() # Remove the enemy node self.enemyNode.removeNode() #self.topEnemyNode.removeNode() # Remove enemy updater tasks taskMgr.remove(self.enemyUpdaterTask) # Remove the passive regeneration task (from Unit class) self.removePassiveRegeneration() # Remove references self._mainRef = None self._playerRef = None self._AIworldRef = None self._enemyListRef = None self._stateHandlerRef = None return task.done
class ArmorPlate: """An active shield locomotive upgrade. Represents an active defense upgrade - plate, which can cover one of the locomotive sides: left, right, top. Args: loc_model (panda3d.core.NodePath): The locomotive model - parent for the plate. """ def __init__(self, loc_model): self._is_on_move = False self.cur_position = "top" self._snd = base.sound_mgr.loadSfx( # noqa: F821 "sounds/train/armor_plate_move.ogg" ) base.sound_mgr.attachSoundToObject(self._snd, loc_model) # noqa: F821 self._model = Actor(address("armor_plate")) self._model.reparentTo(loc_model) self._right_to_left = Sequence( Parallel( self._model.actorInterval("right", playRate=-2.5), SoundInterval(self._snd), ), Parallel( self._model.actorInterval("left", playRate=2.5), SoundInterval(self._snd), ), ) self._left_to_right = Sequence( Parallel( self._model.actorInterval("left", playRate=-2.5), SoundInterval(self._snd), ), Parallel( self._model.actorInterval("right", playRate=2.5), SoundInterval(self._snd), ), ) base.accept("4", self._turn_left) # noqa: F821 base.accept("5", self._turn_top) # noqa: F821 base.accept("6", self._turn_right) # noqa: F821 def _cover_side(self, side): """Actually change the plate position. Args: side (str): Side of the locomotive, which is now covered by the plate. """ self.cur_position = side def _stop_move(self, task): """Release the plate moving block.""" self._is_on_move = False return task.done def _turn_left(self): """Cover the left side of the locomotive with the plate.""" if self.cur_position == "left" or self._is_on_move: return if self.cur_position == "top": self._model.actorInterval("left", playRate=2.5).start() delay = 0.9 cover_delay = 0.45 self._snd.play() else: self._right_to_left.start() delay = 1.8 cover_delay = 1.35 self._is_on_move = True taskMgr.doMethodLater(delay, self._stop_move, "stop_move_plate") # noqa: F821 taskMgr.doMethodLater( # noqa: F821 cover_delay, self._cover_side, "cover_side", extraArgs=["left"] ) taskMgr.doMethodLater( # noqa: F821 cover_delay, base.train.cover_part, # noqa: F821 "cover_part", extraArgs=["part_left"], ) taskMgr.doMethodLater( # noqa: F821 0.5, base.train.uncover_part, # noqa: F821 "uncover_part", extraArgs=[self.cur_position], ) def _turn_right(self): """Cover the right side of the locomotive with the plate.""" if self.cur_position == "right" or self._is_on_move: return if self.cur_position == "top": self._model.actorInterval("right", playRate=2.5).start() delay = 0.9 cover_delay = 0.45 self._snd.play() else: self._left_to_right.start() delay = 1.8 cover_delay = 1.35 self._is_on_move = True taskMgr.doMethodLater(delay, self._stop_move, "stop_move_plate") # noqa: F821 taskMgr.doMethodLater( # noqa: F821 cover_delay, self._cover_side, "cover_side", extraArgs=["right"] ) taskMgr.doMethodLater( # noqa: F821 cover_delay, base.train.cover_part, # noqa: F821 "cover_part", extraArgs=["part_right"], ) taskMgr.doMethodLater( # noqa: F821 0.5, base.train.uncover_part, # noqa: F821 "uncover_part", extraArgs=[self.cur_position], ) def _turn_top(self): """Cover the top side of the Train with the plate.""" if self.cur_position == "top" or self._is_on_move: return if self.cur_position == "left": self._snd.play() self._model.actorInterval("left", playRate=-2.5).start() elif self.cur_position == "right": self._snd.play() self._model.actorInterval("right", playRate=-2.5).start() self._is_on_move = True taskMgr.doMethodLater(0.9, self._stop_move, "stop_move_plate") # noqa: F821 taskMgr.doMethodLater( # noqa: F821 0.45, self._cover_side, "cover_side", extraArgs=["top"] ) taskMgr.doMethodLater( # noqa: F821 0.5, base.train.uncover_part, # noqa: F821 "uncover_part", extraArgs=[self.cur_position], )
class ToontownCentral(DirectObject): def __init__(self): self.scene = render.getPythonTag('SceneManager').createScene("TTC") self.build() def build(self): self.skybox = loader.loadModel("phase_3.5/models/props/TT_sky.bam") self.skybox.set_depth_write(False) self.skybox.find("**/Sky").setBin("background", 0) self.skybox.find('**/cloud1').setBin("background", 3) self.skybox.find('**/cloud2').setBin("background", 5) self.skybox.reparentTo(render) self.environ = loader.loadModel('ttc.bam') def __animateEnv(self): TTC = self.environ toonHall = TTC.find('**/sz13:toon_landmark_TT_toonhall_DNARoot') render.setPythonTag( "ToonHall", ToonHall(toonHall, toonHall.find('**/door_double_round_ur'))) phase_4 = 'phase_4/models/props/' self.fish = TTC.find( '**/animated_prop_PetShopFishAnimatedProp_DNARoot') self.fish.removeNode() self.fish = Actor(phase_4 + 'exteriorfish-zero.bam', {'anim': phase_4 + 'exteriorfish-swim.bam'}) self.fish.reparentTo( TTC.find('**/sz22:toon_landmark_TT_pet_shop_DNARoot')) self.fish.loop('anim') self.periscope = Actor( TTC.find('**/animated_prop_HQPeriscopeAnimatedProp_DNARoot'), copy=0) self.periscope.reparentTo(render) self.periscope.loadAnims( {'anim': 'phase_3.5/models/props/HQ_periscope-chan.bam'}) self.periscope.pose('anim', 0) self.periscopeTrack = Sequence( Wait(2.0), self.periscope.actorInterval('anim', startFrame=0, endFrame=40), Wait(0.7), self.periscope.actorInterval('anim', startFrame=40, endFrame=90), Wait(0.7), self.periscope.actorInterval('anim', startFrame=91, endFrame=121), Wait(0.7), self.periscope.actorInterval('anim', startFrame=121, endFrame=91), Wait(0.7), self.periscope.actorInterval('anim', startFrame=90, endFrame=40), Wait(0.7), self.periscope.actorInterval('anim', startFrame=40, endFrame=90), Wait(0.7), self.periscope.actorInterval('anim', startFrame=91, endFrame=121), Wait(0.5), self.periscope.actorInterval('anim', startFrame=121, endFrame=148), Wait(3.0)) self.periscopeTrack.loop() self.telescope = Actor( TTC.find('**/animated_prop_HQTelescopeAnimatedProp_DNARoot'), copy=0) self.telescope.reparentTo(render) self.telescope.loadAnims( {'anim': 'phase_3.5/models/props/HQ_telescope-chan.bam'}) self.telescope.pose('anim', 0) self.telescopeTrack = Sequence( Wait(5.0), self.telescope.actorInterval('anim', startFrame=0, endFrame=32), Wait(0.5), self.telescope.actorInterval('anim', startFrame=32, endFrame=78), Wait(0.5), self.telescope.actorInterval('anim', startFrame=79, endFrame=112), Wait(0.5), self.telescope.actorInterval('anim', startFrame=112, endFrame=79), Wait(0.5), self.telescope.actorInterval('anim', startFrame=78, endFrame=32), Wait(0.5), self.telescope.actorInterval('anim', startFrame=32, endFrame=78), Wait(0.5), self.telescope.actorInterval('anim', startFrame=79, endFrame=112), Wait(0.5), self.telescope.actorInterval('anim', startFrame=112, endFrame=148), Wait(4.0)) self.telescopeTrack.loop() #base.taskMgr.add(self.__moveClouds, "Move Clouds") self.__fixTrashcans() self.environ.flattenStrong() self.scene.addModel(self.environ) render.find('**/TTC').setPythonTag('Class', self) def __fixTrashcans(self): TTC = self.environ trashcans = TTC.findAllMatches('**/prop_trashcan_metal_DNARoot') for trashcan in trashcans: pos = trashcan.getPos() hpr = trashcan.getHpr() trashcan.removeNode() new_trashcan = loader.loadModel( 'phase_5/models/props/trashcan_TT.bam') new_trashcan.setPos(pos) new_trashcan.setHpr(hpr) new_trashcan.reparentTo(TTC) def __moveClouds(self, task): model = self.skybox model.find("**/cloud1").setHpr(task.time * 0.3, 0, 0) model.find("**/cloud2").setHpr(task.time * -0.3, 0, 0) return Task.cont def doFade(self): TTC = render.find('**/TTC') skyFade = self.skybox.colorScaleInterval(4, Vec4(0.1, 0.1, 0.1, 1), startColorScale=Vec4( 1, 1, 1, 1), blendType='easeInOut') TTCFade = TTC.colorScaleInterval(3.8, Vec4(0.2509803921568627, 0.2509803921568627, 0.2509803921568627, 1), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut') skyFade.start() TTCFade.start() def loadScene(self): self.scene.loadScene() self.__animateEnv() def unloadScene(self): base.taskMgr.remove("Move Clouds") self.scene.delete()
class Player(FSM, Unit): # Declare private variables _cameraYModifier = -6 # Relative to player Y position _cameraZModifier = 4.5 # Relative to player Z position _currentTarget = None #------------------- CONSTRUCTOR ----------------------# def __init__(self, mainRef): print("Player instantiated") Unit.__init__(self) FSM.__init__(self, 'playerFSM') self._hudRef = None self._mainRef = mainRef self._enemyListRef = mainRef.enemyList self._ddaHandlerRef = mainRef.DDAHandler self._mapHandlerRef = mainRef.mapHandler self._stateHandlerRef = mainRef.stateHandler self._scenarioHandlerRef = mainRef.scenarioHandler self.playerNode = mainRef.mainNode.attachNewNode('playerNode') self.initPlayerAttributes() self.initPlayerModel() self.initPlayerCamera() self.initPlayerAbilities() self.initPlayerCollisionHandlers() self.initPlayerCollisionSolids() self.initPlayerDDA() # Start mouse picking and movement self.mouseHandler = utils.MouseHandler(self) # Start player update task playerUpdateTask = taskMgr.add(self.playerUpdate, 'playerUpdateTask') # Initialize player FSM state self.request('Idle') DO = DirectObject() DO.accept('shift-mouse1', self.onShiftDown) DO.accept('shift-up', self.onShiftUp) self._shiftButtonDown = False def onShiftDown(self): self._shiftButtonDown = True attackDelay = self.getInitiativeRoll() taskMgr.doMethodLater(attackDelay, self.shiftAttack, 'shiftAttackTask') def onShiftUp(self): self._shiftButtonDown = False taskMgr.remove('shiftAttackTask') #----------------------------- INITIALIZATION ---------------------------------# def initPlayerAttributes(self): # Initialize player attributes self.strength = 16 self.constitution = 14 self.dexterity = 10 self.combatRange = 0.75 # Melee self.movementSpeed = 1 # ? self.attackBonus = 6 # ? self.damageBonus = 0 # ? self.damageRange = 8 # = Longsword self.initiativeBonus = 1 # ? self.armorClass = 10 + 8 # Base armor class + fullplate armor self.mass = 90 self.startLevel = 3 for i in range(1, self.startLevel): self.increaseLevel() self.initHealth() # Used by area transition system self.areaTransitioning = False def initPlayerModel(self): # Initialize the player model (Actor) modelPrefix = 'models/player-' self.playerModel = Actor(modelPrefix + 'model', { 'run':modelPrefix+'run', 'attack':modelPrefix+'attack', 'stop':modelPrefix+'stop', 'hit':modelPrefix+'hit', 'defense':modelPrefix+'defense', 'death':modelPrefix+'death', 'idle':modelPrefix+'idle', 'bull-rush':modelPrefix+'bull-rush', 'thicket-blades':modelPrefix+'thicket-blades', 'level-up':modelPrefix+'level-up' }) self.playerModel.reparentTo(self.playerNode) # Make sure that visible geometry does not collide self.playerModel.setCollideMask(BitMask32.allOff()) # Model is backwards, fix by changing the heading self.playerModel.setH(180) def initPlayerCamera(self): # Initialize the camera base.disableMouse() base.camera.setPos(self.playerNode, (0, self._cameraYModifier, self._cameraZModifier)) base.camera.lookAt(self.playerNode) self.stopCamera = False def initStartPosition(self, playerStartPos, playerExitPos): self.exitPos = playerExitPos self.startPos = playerStartPos self.initPlayerMovement() def initPlayerMovement(self): # Make sure the player starts at the starting position self.playerNode.setPos(self.startPos) self.destination = Point3(self.startPos) self.velocity = Vec3.zero() self.playerNode.headsUp(self.exitPos) def initPlayerAbilities(self): DO = DirectObject() DO.accept('1', self.fireAbility, [1]) DO.accept('2', self.fireAbility, [2]) DO.accept('3', self.fireAbility, [3]) DO.accept('4', self.fireAbility, [4]) self.abilityDict = {'offensive':1, 'defensive':1, 'evasive':1, 'area':1} def initPlayerDDA(self): if self._scenarioHandlerRef.getHasDDA(): self.damageHistory = [] self.healthHistory = [] self.deathHistory = [] self.damageReceived = 0 self.deathCount = 0 self._ddaHandlerRef.initPlayerDDA(self) ddaMonitorTask = taskMgr.doMethodLater(1, self.ddaMonitor, 'ddaMonitorTask') ddaMonitorTask.count = 0 #-------------------- COLLISION INITIALIZATION ---------------------------# def initPlayerCollisionHandlers(self): self.groundHandler = CollisionHandlerQueue() self.collPusher = CollisionHandlerPusher() self.attackCollisionHandler = CollisionHandlerQueue() self.cameraGroundHandler = CollisionHandlerQueue() def initPlayerCollisionSolids(self): # Player ground ray # groundRay = CollisionRay(0, 0, 1, 0, 0, -1) groundColl = CollisionNode('playerGroundRay') groundColl.addSolid(groundRay) groundColl.setIntoCollideMask(BitMask32.allOff()) groundColl.setFromCollideMask(BitMask32.bit(1)) self.groundRayNode = self.playerNode.attachNewNode(groundColl) #self.groundRayNode.show() base.cTrav.addCollider(self.groundRayNode, self.groundHandler) # Player collision sphere # collSphereNode = CollisionNode('playerCollSphere') collSphere = CollisionSphere(0, 0, 0.1, 0.2) collSphereNode.addSolid(collSphere) #collSphereNode.setCollideMask(BitMask32.bit(2)) collSphereNode.setIntoCollideMask(BitMask32.allOff()) collSphereNode.setFromCollideMask(BitMask32.bit(2)) sphereNode = self.playerNode.attachNewNode(collSphereNode) #sphereNode.show() base.cTrav.addCollider(sphereNode, self.collPusher) self.collPusher.addCollider(sphereNode, self.playerNode) # Player attack collision sphere # attackCollSphereNode = CollisionNode('playerAttackCollSphere') attackCollSphere = CollisionSphere(0, 0.3, 0.1, 0.2) attackCollSphereNode.addSolid(attackCollSphere) attackCollSphereNode.setIntoCollideMask(BitMask32.allOff()) attackCollSphereNode.setFromCollideMask(BitMask32.bit(3)) attackSphereNode = self.playerNode.attachNewNode(attackCollSphereNode) #attackSphereNode.show() base.cTrav.addCollider(attackSphereNode, self.attackCollisionHandler) #---------------------------- EXPERIENCE ----------------------------------------# def getEXPToNextLevel(self): return self._prevEXP + (self.level * 1000) def receiveEXP(self, value): expGain = value * self._ddaHandlerRef.EXPFactor self.experience += expGain self._hudRef.printFeedback('Experience gained: ' + str(int(expGain)), False) if self.experience >= self.getEXPToNextLevel(): self.increaseLevel() self._hudRef.printFeedback('Level gained!', False) self.playerModel.play('level-up', fromFrame=0, toFrame=25) def getEXPToNextLevelInPercentage(self): currentEXP = self.experience - self._prevEXP expToNextLevel = self.level * 1000.0 result = int(currentEXP / expToNextLevel * 100.0) return result #-------------------------- PLAYER MOVEMENT -------------------------------------# def setPlayerDestination(self, destination): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY: # Do not do anything when paused return if self.getIsDead(): return pitchRoll = self.playerNode.getP(), self.playerNode.getR() self.playerNode.headsUp(destination) self.playerNode.setHpr(self.playerNode.getH(), *pitchRoll) distance = abs(self.playerNode.getX() - destination.getX()) + abs(self.playerNode.getY() - destination.getY()) if distance > .5: self.destination = destination self.velocity = self.destination - self.playerNode.getPos() self.velocity.normalize() self.velocity *= self.movementSpeed #-------------------- PLAYER TARGET ------------------------------------# def setCurrentTarget(self, target): self._currentTarget = target def getCurrentTarget(self): return self._currentTarget def removeCurrentTarget(self): self.setCurrentTarget(None) #-------------------- PLAYER ABILITIES ----------------------------------# def startCooldown(self, ability, cooldown, task): task.count += 1 if task.count >= cooldown: self.abilityDict[ability] = 1 if ability == 'offensive': self._hudRef.activateIcon(1) elif ability == 'defensive': self._hudRef.activateIcon(2) elif ability == 'evasive': self._hudRef.activateIcon(3) elif ability == 'area': self._hudRef.activateIcon(4) return task.done else: return task.again def fireAbility(self, ability): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY: # Do not do anything when paused return self.playerModel.stop() # Offensive ability - Bull Rush 10 sec cd if ability == 1: off = 'offensive' if self.abilityDict[off] == 1: if self.bullRush(): self.abilityDict[off] = 0 cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[off, 10], appendTask=True) cd.count = 0 self._hudRef.deactivateIcon(1) self.playerModel.play('bull-rush', fromFrame=0, toFrame=25) else: #print 'Bull Rush in cd' self._hudRef.printFeedback('Bull Rush is in cooldown') # Defensive - Unstoppable 10 sec cd elif ability == 2: defe = 'defensive' if self.abilityDict[defe] == 1: if self.unstoppable(): self.abilityDict[defe] = 0 cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[defe, 10], appendTask=True) cd.count = 0 self._hudRef.deactivateIcon(2) self.playerModel.play('defense', fromFrame=0, toFrame=12) else: #print 'Unstoppable in cd' self._hudRef.printFeedback('Unstoppable is in cooldown') # Evasive - Thicket of Blades 20 sec cd elif ability == 3: eva = 'evasive' if self.abilityDict[eva] == 1: if self.thicketOfBlades(): self.abilityDict[eva] = 0 cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[eva, 20], appendTask=True) cd.count = 0 self._hudRef.deactivateIcon(3) self.playerModel.play('thicket-blades', fromFrame=0, toFrame=27) else: #print 'Thicket of Blades in cd' self._hudRef.printFeedback('Thicket of Blades is in cooldown') # Area of Effect - Shift the Battlefield 30 sec cd elif ability == 4: aoe = 'area' if self.abilityDict[aoe] == 1: if self.shiftTheBattlefield(): self.abilityDict[aoe] = 0 cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[aoe, 30], appendTask=True) cd.count = 0 self._hudRef.deactivateIcon(4) else: #print 'Shift the Battlefield in cd' self._hudRef.printFeedback('Shift the Battlefield is in cooldown') def bullRush(self): bSuccess = False enemy = self.getCurrentTarget() if enemy is not None and not enemy.getIsDead(): if self.state == 'Combat': node = enemy.enemyNode print 'Bull rush:', node bSuccess = True if self.getStrengthModifier() + utils.getD20() > enemy.armorClass: self._hudRef.printFeedback('Bull Rush hit', True) self.enemyFleeFromPlayer(enemy) self.playerModel.play('attack') enemy.playHitAnimation() else: #print 'bullRush missed' self._hudRef.printFeedback('Bull Rush missed') return bSuccess def unstoppable(self): tempHp = utils.getD6() + utils.getD6() + self.getConstitutionModifier() self.receiveTemporaryHealth(tempHp) print 'unstoppable:', tempHp taskMgr.doMethodLater(1.5, self.stopDefenseAnimation, 'stopDefenseAnimationTask') self._hudRef.printFeedback('Unstoppable activated', False) duration = 30.0 # Half a minute (30 seconds) duration of temp hp taskMgr.doMethodLater(duration, self.removeTempHp, 'removeTempHpTask') return True def stopDefenseAnimation(self, task): #print('stop defense animation') self.playerModel.loop('idle') return task.done def removeTempHp(self, task): print 'removeTempHp' self.removeTemporaryHealth() return task.done def thicketOfBlades(self): bSuccess = False numEntries = self.attackCollisionHandler.getNumEntries() if numEntries > 0: self.attackCollisionHandler.sortEntries() for i in range(numEntries): entry = self.attackCollisionHandler.getEntry(i).getIntoNode() entryName = entry.getName()[:-6] #print('entryFound:', entryName) enemy = utils.enemyDictionary[entryName] if enemy is not None and not enemy.getIsDead(): if utils.getIsInRange(self.playerNode.getPos(), enemy.enemyNode.getPos(), self.combatRange): bSuccess = True if self.getStrengthModifier() + utils.getD20() > enemy.armorClass: self._hudRef.printFeedback('Thicket of Blades hit', True) enemy.slowMovementByPercentage(50, 10) # slow by 50 % in 10 seconds, automatically removes it again enemy.enemyModel.play('hit') else: #print 'thicketOfBlades missed' self._hudRef.printFeedback('Thicket of Blades missed') return bSuccess def shiftTheBattlefield(self): bSuccess = False playerPos = self.playerNode.getPos() for enemy in self._enemyListRef: enemyPos = enemy.enemyNode.getPos() if utils.getIsInRange(playerPos, enemyPos, self.combatRange): bSuccess = True if self.getStrengthModifier() + utils.getD20() > enemy.armorClass: self._hudRef.printFeedback('Shift the Battlefield hit', True) self.enemyFleeFromPlayer(enemy) # Might want to replace the getD8 to depend on the player's weapon dmg = 2 * utils.getD8() + self.getStrengthModifier() enemy.receiveDamage(dmg) enemy.enemyModel.play('hit') else: #print 'shiftTheBattlefield missed' self._hudRef.printFeedback('Shift the Battlefield missed') dmg = (2 * utils.getD8() + self.getStrengthModifier()) / 2 enemy.receiveDamage(dmg) enemy.enemyModel.play('hit') return bSuccess def enemyFleeFromPlayer(self, enemy): if enemy.state != 'Disabled': #print 'enemyFleeFromPlayer:', enemy enemy.enemyAIBehaviors.removeAi('all') enemy.enemyAIBehaviors.flee(self.playerNode) enemy.enemyModel.loop('walk', fromFrame=0, toFrame=12) enemy.request('Disabled') taskMgr.doMethodLater(1.5, self.removeEnemyFlee, 'removeEnemyFleeTask', extraArgs=[enemy], appendTask=True) def removeEnemyFlee(self, enemy, task): if enemy.state == 'Disabled': #print 'removeEnemyFlee' enemy.enemyModel.stop() enemy.enemyAIBehaviors.removeAi('flee') enemy.request('Idle') return task.done #------------------ UPDATE FUNCTIONS ---------------------------------# def checkGroundCollisions(self): numEntries = self.groundHandler.getNumEntries() if numEntries > 0: self.groundHandler.sortEntries() entries = [] for i in range(numEntries): entry = self.groundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) for i in range(numEntries): entry = entries[i] if entry.getIntoNode().getName()[:6] == 'ground': newZ = entry.getSurfacePoint(base.render).getZ() self.playerNode.setZ(newZ) break; def updateCameraPosition(self): pos = self.playerNode.getPos() base.camera.setPos(pos.getX(), pos.getY() + self._cameraYModifier, pos.getZ() + self._cameraZModifier) def updatePlayerPosition(self, deltaTime): if not self._shiftButtonDown: #print('updatePlayerPosition') newX = self.playerNode.getX() + self.velocity.getX() * deltaTime newY = self.playerNode.getY() + self.velocity.getY() * deltaTime newZ = self.playerNode.getZ() self.playerNode.setFluidPos(newX, newY, newZ) self.velocity = self.destination - self.playerNode.getPos() #print('distance to dest: ', self.velocity.lengthSquared()) if self.velocity.lengthSquared() < .2: self.velocity = Vec3.zero() if self.state == 'Run': self.request('Idle') else: self.velocity.normalize() self.velocity *= self.movementSpeed if self.state != 'Run': self.request('Run') else: self.destination = self.playerNode.getPos() def playerUpdate(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY: # Do not do anything when paused return task.cont if self._hudRef == None: self._hudRef = self._mainRef.hud self.checkGroundCollisions() self.updateCameraPosition() if self.getIsDead(): if self.state != 'Death': self.request('Death') return task.cont self.updatePlayerPosition(globalClock.getDt()) return task.cont def ddaMonitor(self, task): task.count += 1 self.healthHistory.append(self.currentHealthPoints) self.damageHistory.append(self.damageReceived) self.damageReceived = 0 #print self.healthHistory #print self.damageHistory if (task.count + 1) % 60 == 0: self.deathHistory.append(self.deathCount) self.deathCount = 0 print self.deathHistory return task.again def receiveDamage(self, damageAmount): super(Player, self).receiveDamage(damageAmount) if self._scenarioHandlerRef.getHasDDA(): self.damageReceived += damageAmount #------------------------------- COMBAT ------------------------------# def shiftAttack(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY: return task.done #print 'shiftAttack. shift:', self._shiftButtonDown if self._shiftButtonDown and base.mouseWatcherNode.hasMouse(): #print 'attack!' self.playerModel.play('attack') self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0)) mousePos = base.mouseWatcherNode.getMouse() pos3d = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mousePos, nearPoint, farPoint) if self.plane.intersectsLine(pos3d, base.render.getRelativePoint(camera, nearPoint), base.render.getRelativePoint(camera, farPoint)): #print('Mouse ray intersects ground at ', pos3d) destination = pos3d pitchRoll = self.playerNode.getP(), self.playerNode.getR() self.playerNode.headsUp(destination) self.playerNode.setHpr(self.playerNode.getH(), *pitchRoll) numEntries = self.attackCollisionHandler.getNumEntries() if numEntries > 0: self.attackCollisionHandler.sortEntries() bAttacked = 0 for i in range(numEntries): entry = self.attackCollisionHandler.getEntry(i).getIntoNode() entryName = entry.getName()[:-6] #print('entryFound:', entryName) enemy = utils.enemyDictionary[entryName] if enemy is not None and not enemy.getIsDead(): if utils.getIsInRange(self.playerNode.getPos(), enemy.enemyNode.getPos(), self.combatRange): bAttacked = self.attack(enemy) # Returns 1 if player attacked but did not hit, returns 2 on hit if bAttacked != 0: #print('attackEnemies') for i in range(numEntries): enemyTargetName = self.attackCollisionHandler.getEntry(i).getIntoNode().getName()[:-6] enemyTarget = utils.enemyDictionary[enemyTargetName] if enemyTarget is not None and not enemyTarget.getIsDead(): self.setCurrentTarget(enemyTarget) break; return task.again else: self.playerModel.stop() return task.done def attackEnemies(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY: return task.done if self._shiftButtonDown: return task.again numEntries = self.attackCollisionHandler.getNumEntries() if numEntries > 0: self.attackCollisionHandler.sortEntries() bAttacked = 0 for i in range(numEntries): entry = self.attackCollisionHandler.getEntry(i).getIntoNode() entryName = entry.getName()[:-6] #print('entryFound:', entryName) enemy = utils.enemyDictionary[entryName] if enemy is not None and not enemy.getIsDead(): if utils.getIsInRange(self.playerNode.getPos(), enemy.enemyNode.getPos(), self.combatRange): bAttacked = self.attack(enemy) # Returns 1 if player attacked but did not hit, returns 2 on hit if bAttacked == 2: enemy.enemyModel.play('hit') # Only play animations if player actually attacked if bAttacked != 0: #print('attackEnemies') self.playerModel.play('attack') for i in range(numEntries): enemyTargetName = self.attackCollisionHandler.getEntry(i).getIntoNode().getName()[:-6] enemyTarget = utils.enemyDictionary[enemyTargetName] if enemyTarget is not None and not enemyTarget.getIsDead(): self.setCurrentTarget(enemyTarget) break; return task.again else: #print('go to idle') self.removeCurrentTarget() if self.state == 'Combat': self.request('Idle') return task.done #----------------------- PLAYER STATES --------------------------------------# def enterRun(self): self.playerModel.loop('run', fromFrame=0, toFrame=12) def exitRun(self): self.playerModel.stop() def enterCombat(self): #print('enterCombat') self.playerModel.stop() self.destination = self.playerNode.getPos() attackDelay = self.getInitiativeRoll() self.combatTask = taskMgr.doMethodLater(attackDelay, self.attackEnemies, 'combatTask') self._hudRef.printFeedback('In combat', True) def exitCombat(self): #print('exitCombat') taskMgr.remove(self.combatTask) self._hudRef.printFeedback('Combat ended', False) def enterIdle(self): stopPlayer = self.playerModel.actorInterval('stop', loop=0) idlePlayer = Func(self.playerModel.loop, 'idle', fromFrame=0, toFrame=50) self.stopMovingSequence = Sequence(stopPlayer, idlePlayer) self.stopMovingSequence.start() def exitIdle(self): self.stopMovingSequence.finish() def enterDeath(self): self.playerModel.play('death') self.deathCount += 1 taskMgr.doMethodLater(3, self.respawn, 'respawnTask') def exitDeath(self): print('exitDeath') #--------------------- PLAYER DEATH ---------------------------# def respawn(self, task): self._hudRef.printFeedback('Respawning') # Move player back to start pos self.destination = self.startPos self.playerNode.setPos(self.startPos) # Heal the player again self.fullHeal() # Make sure that isDead variable is set to false self.setIsNotDead() # Reset state back to idle self.request('Idle') return task.done
class Golem(FSM, DirectObject): def __init__(self): FSM.__init__(self, "FSM-Golem") random.seed() self.golem = loader.loadModel("Golem") self.golem = Actor("Golem", { "Idle":"Golem-Idle", "Walk":"Golem-Walk", "Attack":"Golem-Attack", "Destroyed":"Golem-Destroyed"}) self.golem.setBlend(frameBlend = True) golemViewSphere = CollisionSphere(0, 0, 0.5, 6) golemViewSphere.setTangible(False) golemViewColNP = self.golem.attachNewNode(CollisionNode('golemViewField')) golemViewColNP.node().addSolid(golemViewSphere) golemHitSphere = CollisionSphere(0, 0, 0.5, 1) golemHitColNP = self.golem.attachNewNode(CollisionNode('golemHitField')) golemHitColNP.node().addSolid(golemHitSphere) # a collision segment to check attacks self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1) self.golemAttackRay = self.golem.attachNewNode(CollisionNode("golemAttackCollision")) self.golemAttackRay.node().addSolid(self.attackCheckSegment) self.golemAttackRay.node().setIntoCollideMask(0) self.attackqueue = CollisionHandlerQueue() base.cTrav.addCollider(self.golemAttackRay, self.attackqueue) attackAnim = self.golem.actorInterval("Attack", playRate = 2) self.AttackSeq = Parallel( attackAnim, Sequence( Wait(0.5), Func(self.ceckAttack) )) self.lookatFloater = NodePath(PandaNode("golemTracker")) self.lookatFloater.setPos(self.golem, 0, 0, 3.4) self.lookatFloater.hide() self.lookatFloater.reparentTo(render) self.trackerObject = loader.loadModel("misc/Pointlight") self.trackerObject.setColor(0, 1, 0) self.trackerObject.setScale(0.25) self.trackerObject.reparentTo(self.lookatFloater) def start(self, startPos): self.golem.setPos(startPos.getPos()) self.golem.setHpr(startPos.getHpr()) self.golem.reparentTo(render) self.trackedEnemy = None self.health = 5 self.accept("playerCollision-in-golemViewField", lambda extraArgs: base.messenger.send("golemSeesPlayer", [self.golem])) def stop(self): self.trackedEnemy = None taskMgr.remove("GolemAI_task") self.golem.hide() self.ignoreAll() def cleanup(self): self.stop() self.lookatFloater.removeNode() self.golem.cleanup() self.golem.removeNode() def activate(self, trackedEnemy): self.trackedEnemy = trackedEnemy taskMgr.add(self.aiTask, "GolemAI_task") self.lookatFloater.show() def aiTask(self, task): dt = globalClock.getDt() if self.AttackSeq.isPlaying(): return task.cont self.lookatFloater.setPos(self.golem, 0, 0, 3.4) self.lookatFloater.lookAt(self.trackedEnemy) self.lookatFloater.setH(self.lookatFloater.getH() + 180) self.lookatFloater.setP(0) self.lookatFloater.setR(0) self.golem.lookAt(self.trackedEnemy) self.golem.setH(self.golem.getH() + 180) distanceVec = self.golem.getPos() - self.trackedEnemy.getPos() enemyDist = distanceVec.length() if enemyDist < 2.0: # close enough for combat action = random.choice(["Attack", "Idle"]) if action == "Attack": self.request("Attack") else: if self.state != "Idle": self.request("Idle") else: self.golem.setY(self.golem, -0.5 * dt) if self.state != "Walk": self.request("Walk") return task.cont def hit(self): hitInterval = Sequence( Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15)) self.health -= 1 if self.health == 4: self.trackerObject.setColor(0, 1, 0) hitInterval.start() elif self.health == 3: self.trackerObject.setColor(0.25, 0.75, 0) hitInterval.start() elif self.health == 2: self.trackerObject.setColor(0.5, .5, 0) hitInterval.start() elif self.health == 1: self.trackerObject.setColor(0.75, 0.25, 0) hitInterval.start() elif self.health == 0: self.trackerObject.setColor(0, 0, 0) self.request("Destroyed") def ceckAttack(self): for i in range(self.attackqueue.getNumEntries()): entry = self.attackqueue.getEntry(i) into = entry.getIntoNode() if "playerCollision" in into.getName(): if random.random() > .5: base.messenger.send("HitPlayer") def enterIdle(self): self.golem.loop("Idle") def enterWalk(self): self.golem.setPlayRate(2, "Walk") self.golem.loop("Walk") def enterAttack(self): self.AttackSeq.start() def enterDestroyed(self): self.ignoreAll() taskMgr.remove("GolemAI_task") self.AttackSeq.finish() self.golem.play("Destroyed") self.lookatFloater.hide() base.messenger.send("GolemDestroyed")
class Character(Shooter, Unit): """A game character. Represents a unit controlled by a player. Args: id_ (int): This character unique id. name (str): This character name. class_ (str): This character class. sex (str): This character gender. team (crew.Crew): The Crew object. desc (dict): Optional. This character description (used for loading character from a saved game). """ def __init__(self, id_, name, class_, sex, team, desc=None): Unit.__init__( self, "character_" + str(id_), class_, CLASSES[sex + "_" + class_] ) Shooter.__init__(self) self._team = team self._current_pos = None self._current_anim = None self._idle_seq = None self._cohesion_ball = None self._is_stunned = False self._is_stimulated = False self._health_bar = None self.inhale = 15 self.damage_range = [5, 8] self.clear_damage = [5, 8] self.effects = {} self._yeah_snds = [] self.name = name self.sex = sex if sex == "male": self.heshe = base.labels.PRONOUNS[0] # noqa: F821 self.hisher = base.labels.PRONOUNS[1] # noqa: F821 self.himher = base.labels.PRONOUNS[2] # noqa: F821 else: self.heshe = base.labels.PRONOUNS[3] # noqa: F821 self.hisher = base.labels.PRONOUNS[4] # noqa: F821 self.himher = base.labels.PRONOUNS[5] # noqa: F821 if desc: self._energy = desc["energy"] self.is_diseased = desc["is_diseased"] self.get_well_score = desc["get_well_score"] self.traits = desc["traits"] self.disabled_traits = desc["disabled_traits"] if self.is_diseased: taskMgr.doMethodLater( # noqa: F821 60, self.get_well, self.id + "_get_well" ) else: self._energy = 100 self.is_diseased = False self.get_well_score = 0 self.disabled_traits = [] self.traits = [] traits = copy.copy(base.labels.TRAITS) # noqa: F821 for _ in range(random.randint(0, 2)): self.traits.append(random.choice(take_random(traits))) @property def clear_delay(self): """ Delay between this character death and clearing the character object. Returns: float: Seconds to wait before clearing. """ return 3.5 @property def damage(self): """This character one-time calculated damage. Returns: float: Damage one-time made by this character. """ return random.uniform(*self.damage_range) * self.damage_factor @property def damage_factor(self): """This character damage factor. The damage factor depends on cohesion with another character on the same part of the Train. Returns: float: Damage one-time made by this character. """ factor = self._team.calc_cohesion_factor(self.current_part.chars, self) if ( # Loner base.labels.TRAITS[4][1] in self.traits # noqa: F821 and len(self.current_part.chars) == 1 ): return factor * 1.3 return factor @property def description(self): """This character state in saveable form. Used for saving the character. Returns: dict: This character description. """ return { "id": int(self.id.split("_")[1]), "name": self.name, "sex": self.sex, "class": self.class_, "health": self.health, "energy": self.energy, "place": self.current_part.name, "traits": self.traits, "disabled_traits": self.disabled_traits, "is_diseased": self.is_diseased, "get_well_score": self.get_well_score, } @property def energy(self): """This character energy. Returns: int: This character energy points. """ return self._energy @energy.setter def energy(self, value): """This character energy setter. Args: value (int): New energy value. """ self._energy = min(max(value, 0), 80 if self.is_diseased else 100) @property def shooting_speed(self): """Delay between shots of this unit. Returns: float: Delay between shots in seconds. """ if base.labels.TRAITS[0][0] in self.traits: # noqa: F821 # Fast hands return 1.1 + random.uniform(0.1, 0.8) if base.labels.TRAITS[0][1] in self.traits: # noqa: F821 # Snail return 2 + random.uniform(0.1, 1.1) return 1.7 + random.uniform(0.1, 0.9) @property def statuses(self): """Return strings describing the current character status. Returns: list: Status description lines. """ statuses = [] if base.world.sun.is_dark: # noqa: F821 if base.labels.TRAITS[1][0] in self.traits: # noqa: F821 statuses.append(base.labels.STATUSES[0]) # noqa: F821 elif base.train.lights_on: # noqa: F821 if "Floodlights" not in base.train.upgrades: # noqa: F821 statuses.append(base.labels.STATUSES[1]) # noqa: F821 else: statuses.append(base.labels.STATUSES[2]) # noqa: F821 if self.energy <= 95: statuses.append( base.labels.STATUSES[3].format((100 - self.energy) // 5) # noqa: F821 ) if not base.world.is_in_city and self.current_part is not None: # noqa: F821 factor = round(self.damage_factor, 2) if factor != 1: statuses.append(base.labels.STATUSES[4].format(factor)) # noqa: F821 if self.health < 50 and base.labels.TRAITS[2][1] in self.traits: # noqa: F821 statuses.append(base.labels.STATUSES[5]) # noqa: F821 if self.is_diseased: statuses.append(base.labels.STATUSES[6]) # noqa: F821 if ( base.labels.TRAITS[6][1] in self.traits # noqa: F821 and base.train.ctrl.current_speed > 0.75 # noqa: F821 ): statuses.append(base.labels.STATUSES[7]) # noqa: F821 return statuses[:4] @property def tooltip(self): """Tooltip to show on this character mouse pointing. Returns: str: This character name. """ return self.name def attack(self, enemy_unit): """Make the given enemy unit this character's target. Args: enemy_unit (units.enemy.EnemyUnit): Enemy unit to attack. """ if enemy_unit in self.current_part.enemies: self._target = enemy_unit def prepare(self): """Load the character model and positionate it. Tweak collision solid and sounds. """ animations = { name: address(self.class_ + "-" + name) for name in ( "die", "gun_up", "incline1", "release_gun", "stand_and_aim", "stand", "surrender", "tread1", "turn_head1", "stunned", "cough", "celebrate", ) } self.model = Actor(address(self.sex + "_" + self.class_), animations) self.model.enableBlend() self.model.setControlEffect("stand", 1) self.model.setPlayRate(0.8, "stand_and_aim") self.model.setPlayRate(0.6, "stand") self.model.loop("stand") self._current_anim = "stand" self._health_bar = HealthBar(self) base.team.init_relations(self) # noqa: F821 taskMgr.doMethodLater( # noqa: F821 random.randint(40, 60), self._idle_animation, self.id + "_idle_anim" ) self._col_node = self._init_col_node( NO_MASK, MOUSE_MASK, CollisionCapsule(0, 0, 0, 0, 0, 0.035, 0.035) ) self.shot_snd = self._set_shoot_snd(self.class_data["shot_snd"]) self._cough_snd = base.sound_mgr.loadSfx( # noqa: F821 "sounds/{sex}_cough.ogg".format(sex=self.sex) ) base.sound_mgr.attachSoundToObject(self._cough_snd, self.model) # noqa: F821 self._die_snd = base.sound_mgr.loadSfx( # noqa: F821 "sounds/combat/{sex}_death.ogg".format(sex=self.sex) ) base.sound_mgr.attachSoundToObject(self._die_snd, self.model) # noqa: F821 for i in range(1, 4): yeah_snd1 = base.sound_mgr.loadSfx( # noqa: F821 "sounds/{sex}_yes{num}.ogg".format(sex=self.sex, num=str(i)) ) base.sound_mgr.attachSoundToObject(yeah_snd1, self.model) # noqa: F821 self._yeah_snds.append(yeah_snd1) if self.class_ == "soldier": z = 0.064 if self.sex == "male" else 0.062 elif self.class_ == "raider": z = 0.047 elif self.class_ == "anarchist": z = 0.06 if self.sex == "male" else 0.057 self._shoot_anim = self._set_shoot_anim( (0.004, 0.045, z), 97, self.class_data["shots_num"] ) taskMgr.doMethodLater( # noqa: F821 self.class_data["energy_spend"], self._reduce_energy, self.id + "_reduce_energy", ) self._prepare_cohesion_particles() self._prepare_auras() def _prepare_cohesion_particles(self): """Prepare cohesion skills particle effects.""" effect = ParticleEffect() effect.loadConfig("effects/recall_the_past.ptf") self.effects["recall_the_past"] = {"length": 0.7, "effect": effect} effect = ParticleEffect() effect.loadConfig("effects/not_leaving_ours.ptf") self.effects["not_leaving_ours"] = {"length": 2, "effect": effect} effect = ParticleEffect() effect.loadConfig("effects/common_rage.ptf") self.effects["common_rage"] = {"length": 90, "effect": effect} def _prepare_auras(self): """Prepare cohesion skills aura effects.""" aura = loader.loadModel(address("cover_fire_aura")) # noqa: F821 aura.hide() aura.reparentTo(self.model) aura.setY(0.007) self.effects["cover_fire"] = { "model": aura, "seq": Sequence( LerpScaleInterval(aura, 1.5, (2, 2, 2), (1, 1, 1)), LerpScaleInterval(aura, 1.5, (1, 1, 1), (2, 2, 2)), ), } aura = loader.loadModel(address("common_rage_aura")) # noqa: F821 aura.hide() aura.reparentTo(self.model) aura.setY(0.007) self.effects["common_rage_aura"] = { "model": aura, "seq": Sequence( LerpScaleInterval(aura, 1.5, (2, 2, 2), (1, 1, 1)), LerpScaleInterval(aura, 1.5, (1, 1, 1), (2, 2, 2)), ), } aura = loader.loadModel(address("hold_together_aura")) # noqa: F821 aura.hide() aura.reparentTo(self.model) aura.setY(0.007) self.effects["hold_together"] = { "model": aura, "seq": Sequence( LerpScaleInterval(aura, 1.5, (2, 2, 2), (1, 1, 1)), LerpScaleInterval(aura, 1.5, (1, 1, 1), (2, 2, 2)), ), } def play_cohesion_effect(self, name): """Play the given cohesion skill effect. Args: name (str): Name of the skill. """ self.effects[name]["effect"].start(self.model, self.model) self.effects[name]["effect"].softStart() taskMgr.doMethodLater( # noqa: F821 self.effects[name]["length"], self.effects[name]["effect"].softStop, "stop_cohesion_effect", extraArgs=[], ) def play_cohesion_aura(self, name): """Play the given aura effect. Args: name (str): The effect name. """ self.effects[name]["model"].show() self.effects[name]["seq"].loop() def play_yes(self): """Play a voice sound, when the character is chosen.""" random.choice(self._yeah_snds).play() def stop_aura_effect(self, name): """Stop the given aura effect. Args: name (str): The effect name. """ self.effects[name]["model"].hide() self.effects[name]["seq"].finish() def celebrate(self, task): """Play victory celebration animation.""" if self.current_part.name == "part_rest": return task.done LerpAnimInterval(self.model, 0.1, self._current_anim, "celebrate").start() self._current_anim = "celebrate" self.model.play("celebrate") return task.done def move_to(self, part, to_pos=None): """Move this Character to the given Train part. If the movement is done with a positions exchange between two characters, the method doesn't take or release characters cells, just replaces one character with another one. Args: part (train.part.TrainPart): Train part to move this Character to. to_pos (dict): Position to move this Character to. Returns: bool: True, if the character was moved. """ if to_pos: part.chars.append(self) pos = to_pos else: pos = part.give_cell(self) if not pos: # no free cells on the chosen part return if self.current_part is not None: if to_pos: self.current_part.chars.remove(self) else: self.current_part.release_cell(self._current_pos, self) if self.current_part.name == "part_rest": self.stop_rest() if part.name == "part_rest": self.rest() self.model.wrtReparentTo(part.parent) self.model.setPos(pos) self.model.setH(part.angle) self.current_part = part self._current_pos = pos if part.name == "part_rest" and base.char_gui.rest_list_shown: # noqa: F821 base.char_gui.update_resting_chars(part) # noqa: F821 return True def do_effects(self, effects): """Do outing effects to this character. Effects are: adding traits, changing health and energy. Args: effects (dict): Effects and their values. """ if effects is None: return effects = copy.deepcopy(effects) self.get_damage(-effects.pop("health", 0)) if "add_trait" in effects and len(self.traits + self.disabled_traits) < 3: ind1, ind2 = effects["add_trait"] trait = base.labels.TRAITS[ind1][ind2] # noqa: F821 if trait and trait not in self.traits + self.disabled_traits: self.traits.append(trait) base.char_gui.move_status_label(-1) # noqa: F821 effects.pop("add_trait") for key, value in effects.items(): if hasattr(self, key): setattr(self, key, getattr(self, key) + value) def prepare_to_fight(self): """Prepare this character for a fight. Switch animations and run a task to choose a target. """ self._stop_tasks("_idle_anim") if self._idle_seq is not None: self._idle_seq.finish() self.model.loop("stand_and_aim") LerpAnimInterval(self.model, 0.8, self._current_anim, "stand_and_aim").start() LerpAnimInterval(self.model, 0.8, "stand", "stand_and_aim").start() self._current_anim = "stand_and_aim" taskMgr.doMethodLater( # noqa: F821 0.5, self._choose_target, self.id + "_choose_target" ) self._health_bar.show_health() def rest(self): """Make this character rest. Stops all the active tasks and starts energy regaining/healing. """ self._stop_tasks( "_reduce_energy", "_shoot", "_aim", "_choose_target", "_idle_anim" ) self.model.hide() self._col_node.stash() taskMgr.doMethodLater( # noqa: F821 0.05, self._calm_down, self.id + "_calm_down", extraArgs=[True], ) taskMgr.doMethodLater( # noqa: F821 self.class_data["energy_gain"], self._gain_energy, self.id + "_gain_energy" ) if self.health < self.class_data["health"]: taskMgr.doMethodLater( # noqa: F821 self.class_data["healing"], self._heal, self.id + "_heal" ) def surrender(self): """Stop fighting, surrender.""" self._stop_tasks("_shoot", "_aim", "_choose_target") self._col_node.removeNode() self._shoot_anim.finish() LerpAnimInterval(self.model, 0.5, "stand_and_aim", "surrender").start() self.model.play("surrender") def stop_rest(self): """Stop this character rest.""" self.model.show() self._col_node.unstash() base.char_gui.destroy_char_button(self.id) # noqa: F821 self._stop_tasks("_gain_energy", "_heal") taskMgr.doMethodLater( # noqa: F821 self.class_data["energy_spend"], self._reduce_energy, self.id + "_reduce_energy", ) if base.world.enemy.active_units: # noqa: F821 self.prepare_to_fight() def _reduce_energy(self, task): """ Reduce the character energy according to day part and status: fighting or not. """ if base.world.sun.is_dark: # noqa: F821 if not base.train.lights_on: # noqa: F821 task.delayTime = 15 elif "Floodlights" in base.train.upgrades: # noqa: F821 task.delayTime = self.class_data["energy_spend"] else: task.delayTime = 20 if base.labels.TRAITS[1][1] in self.traits: # noqa: F821 # Fear of dark task.delayTime /= 2 elif self._target: # Nervousness task.delayTime = ( 15 if base.labels.TRAITS[5][1] in self.traits else 20 # noqa: F821 ) else: task.delayTime = self.class_data["energy_spend"] if ( base.labels.TRAITS[2][1] in self.traits # noqa: F821 and self.health < self.class_data["health"] / 2 ): # Hemophobia task.delayTime *= 0.75 self.energy -= 1 if base.labels.TRAITS[7][0] in self.traits: # noqa: F821 # Mechanic base.train.get_damage(-3) # noqa: F821 return task.again def _gain_energy(self, task): """Regain this character energy. Used as a timed task while the character is resting. """ if ( base.labels.TRAITS[6][1] in self.traits # noqa: F821 and base.train.ctrl.current_speed > 0.75 # noqa: F821 ): # Motion sickness return task.again self.energy += 3 for char in self.current_part.chars: if char.sex == "female" and self.id != char.id: task.delayTime = self.class_data["energy_gain"] - 5 return task.again return task.again def _heal(self, task): """Regain this character health. Used as a timed task while the character is resting. """ if ( base.labels.TRAITS[6][1] in self.traits # noqa: F821 and base.train.ctrl.current_speed > 0.75 # noqa: F821 ): # Motion sickness return task.again if base.labels.TRAITS[7][1] in self.traits and chance(40): # noqa: F821 # Pharmacophobia return task.again if self.health < self.class_data["health"]: self.health += 1 return task.again return task.done def _choose_target(self, task): """Choose an enemy to shoot. Only an enemy from the Train part shooting range can be chosen as a target. """ if self.current_part and self.current_part.enemies: self._target = random.choice(self.current_part.enemies) taskMgr.doMethodLater(0.1, self._aim, self.id + "_aim") # noqa: F821 taskMgr.doMethodLater(1, self._shoot, self.id + "_shoot") # noqa: F821 return task.done # enemies retreated - return to passive state if not base.world.enemy.active_units: # noqa: F821 taskMgr.doMethodLater( # noqa: F821 7, self._calm_down, self.id + "_calm_down", extraArgs=[False], ) return task.done return task.again def _aim(self, task): """Rotate the character to aim on enemy.""" if ( self._target and self._target.is_dead and base.labels.TRAITS[5][0] in self.traits # noqa: F821 ): # Bloodthirsty self.health += 7 if self.current_part and self._target in self.current_part.enemies: self.model.headsUp(self._target.model) return task.again self._stop_tasks("_shoot") self._target = None if base.world.enemy.active_units: # noqa: F821 taskMgr.doMethodLater( # noqa: F821 0.5, self._choose_target, self.id + "_choose_target" ) return task.done taskMgr.doMethodLater( # noqa: F821 7, self._calm_down, self.id + "_calm_down", extraArgs=[False] ) return task.done def _calm_down(self, force): """Return to passive state on a combat over. Args: force (bool): If True, change to passive animation fast. Change animation in usual speed otherwise. """ self._stop_tasks("_shoot", "_calm_down") if self.current_part: self.model.hprInterval( 0.1 if force else 2, (self.current_part.angle, 0, 0) ).start() if force: for anim in self.model.get_anim_names(): self.model.setControlEffect(anim, 0) self.model.stop() self.model.setControlEffect("stand", 1) self.model.loop("stand") else: LerpAnimInterval(self.model, 2, self._current_anim, "stand").start() self._current_anim = "stand" taskMgr.doMethodLater( # noqa: F821 random.randint(40, 60), self._idle_animation, self.id + "_idle_anim" ) self._health_bar.hide_health() def _idle_animation(self, task): """Play one of the idle animations. Args: task (panda3d.core.PythonTask): Task object. """ if self.is_diseased and chance(80): self._current_anim = "cough" self._cough_snd.play() else: self._current_anim = random.choice( ("incline1", "gun_up", "release_gun", "tread1", "turn_head1") ) LerpAnimInterval(self.model, 0.2, "stand", self._current_anim).start() self._idle_seq = Sequence( self.model.actorInterval(self._current_anim, playRate=0.75), Func(self._stand), ) self._idle_seq.start() task.delayTime = random.randint(40, 60) return task.again def _stand(self): """Return to the idle stand animation.""" LerpAnimInterval(self.model, 0.2, self._current_anim, "stand").start() self._current_anim = "stand" def _die(self): """Character death sequence. Stop all the character's tasks, play death animation and plan the character object clearing. """ if self._team.hold_together: self.health = 1 return False if not Shooter._die(self): return False Unit._die(self) if base.common_ctrl.chosen_char == self: # noqa: F821 base.common_ctrl.deselect(clear_resting=False) # noqa: F821 self._health_bar.hide_health() self._stop_tasks( "_reduce_energy", "_get_well", "_infect", "_stop_stimul", "_gain_energy" ) base.char_gui.destroy_char_button(self.id) # noqa: F821 self._team.delete_relations(self.id) LerpAnimInterval(self.model, 0.3, "stand_and_aim", "die").start() LerpAnimInterval(self.model, 0.3, self._current_anim, "die").start() self.model.hprInterval(1, (self.current_part.angle, 0, 0)).start() self.model.play("die") self._die_snd.play() taskMgr.doMethodLater(3, self._hide, self.id + "_hide") # noqa: F821 def _hide(self, task): """Hide the main model.""" self.model.hide() return task.done def leave(self): """Make this character leave, plan clearing. Used only when sending a character away in a city. """ self._stop_tasks("_calm_down", "_gain_energy", "_heal", "_infect", "_get_well") taskMgr.doMethodLater(0.05, self.clear, self.id + "_clear") # noqa: F821 def clear(self, task): """Clear this character. Release models and sounds memory, release the part cell and delete the character from the team list. """ self.model.cleanup() self._health_bar.removeNode() self.model.removeNode() base.sound_mgr.detach_sound(self.shot_snd) # noqa: F821 base.sound_mgr.detach_sound(self._cough_snd) # noqa: F821 base.sound_mgr.detach_sound(self._die_snd) # noqa: F821 for snd in self._yeah_snds: base.sound_mgr.detach_sound(snd) # noqa: F821 self._team.chars.pop(self.id) base.res_gui.update_chars() # noqa: F821 self.current_part.release_cell(self._current_pos, self) self.current_part = None return task.done def exchange_pos(self, char): """Exchange positions of this Character and the given one. Args: char (units.character.Character): Character to exchange the positions with. """ o_part, o_pos = self.current_part, self._current_pos self.move_to(char.current_part, char._current_pos) char.move_to(o_part, o_pos) def hide_relations_ball(self): """Hide the relations ball of this character.""" if self._cohesion_ball is not None: self._cohesion_ball.removeNode() self._cohesion_ball = None def show_relation(self, cohesion): """Show a relations ball above this character. The color of the ball shows the strength of cohesion between the chosen character and this one. Args: cohesion (float): Value of the cohesion between the chosen character and this one. """ if self._cohesion_ball is None: self._cohesion_ball = loader.loadModel( # noqa: F821 address("relation_ball") ) self._cohesion_ball.clearLight() base.world.sun.ignore_shadows(self._cohesion_ball) # noqa: F821 self._cohesion_ball.reparentTo(self.model) self._cohesion_ball.setZ(0.14) self._cohesion_ball.setColorScale(*RELATION_COLORS[cohesion // 20]) def _missed_shot(self): """Calculate if character missed the current shot. Returns: bool: True if character missed, False otherwise. """ miss_chance = 0 if self.class_ == "soldier": if ( abs(self._target.node.getX()) < 0.56 and abs(self._target.node.getY()) < 0.95 ): miss_chance += 20 elif self.class_ == "raider": if ( abs(self._target.node.getX()) > 0.56 and abs(self._target.node.getY()) > 0.95 ): miss_chance += 20 if base.world.sun.is_dark: # noqa: F821 if base.labels.TRAITS[1][0] in self.traits: # noqa: F821 # Cat eyes miss_chance -= 5 elif base.train.lights_on: # noqa: F821 if "Floodlights" not in base.train.upgrades: # noqa: F821 miss_chance += 10 else: miss_chance += 20 miss_chance += (100 - self.energy) // 5 if self._team.cover_fire: miss_chance = min(100, max(0, miss_chance - 25)) return chance(miss_chance) def get_stunned(self): """Make this character stunned for some time. Stunned unit can't shoot. """ if self._is_stunned or self._is_stimulated: return self._is_stunned = True self._stop_tasks("_aim", "_shoot") self._current_anim = "stunned" self.model.play("stunned") LerpAnimInterval(self.model, 0.05, "stand_and_aim", "stunned").start() taskMgr.doMethodLater( # noqa: F821 6, self._stop_stunning, self.id + "_stop_stunning" ) def get_sick(self, is_infect=False): """Calculations to get this character sick. The worse condition the character has the higher is the chance for him to get sick. Sick character has lower energy maximum, and all his positive traits are disabled until getting well. Args: is_infect (bool): True if the disease came from a character on the same Train part. """ if self.is_diseased: return cond_percent = (self.energy + self.health) / (100 + self.class_data["health"]) percent = (1 - cond_percent) * 30 sick_chance = max( 0, # not less than zero ( percent + (20 if is_infect else 0) # Immunity - (40 if base.labels.TRAITS[3][0] in self.traits else 0) # noqa: F821 # Weak immunity + (20 if base.labels.TRAITS[3][1] in self.traits else 0) # noqa: F821 ), ) if chance(sick_chance): self.is_diseased = True self.get_well_score = 0 for traits_pair in base.labels.TRAITS: # noqa: F821 if traits_pair[0] in self.traits: self.traits.remove(traits_pair[0]) self.disabled_traits.append(traits_pair[0]) taskMgr.doMethodLater( # noqa: F821 60, self.get_well, self.id + "_get_well" ) taskMgr.doMethodLater(240, self.infect, self.id + "_infect") # noqa: F821 self.energy = min(self.energy, 80) def get_stimulated(self): """Use a stimulator on this character. Disables all the negative traits for some time. """ for traits_pair in base.labels.TRAITS: # noqa: F821 if traits_pair[1] in self.traits: self.traits.remove(traits_pair[1]) self.disabled_traits.append(traits_pair[1]) self._is_stimulated = True taskMgr.doMethodLater( # noqa: F821 300, self._stop_stimul, self.id + "_stop_stimul" ) def _stop_stimul(self, task): """Stop stimulation of this character. Returns back all the disabled negative traits. """ for trait_pair in base.labels.TRAITS: # noqa: F821 if trait_pair[1] in self.disabled_traits: self.traits.append(trait_pair[1]) self.disabled_traits.remove(trait_pair[1]) self._is_stimulated = False return task.done def get_well(self, task): """Get this character well. When the character got well, his energy maximum is restored to the default value, and his positive traits are back operational. """ self.get_well_score += 1 if self.get_well_score < 20: return task.again self.is_diseased = False for trait_pair in base.labels.TRAITS: # noqa: F821 if trait_pair[0] in self.disabled_traits: self.traits.append(trait_pair[0]) self.disabled_traits.remove(trait_pair[0]) self._stop_tasks("_infect") return task.done def infect(self, task): """Infect other characters on the same Train part.""" for char in self.current_part.chars: if char.id != self.id: char.get_sick(is_infect=True) return task.again def _shoot(self, task): """Play shooting animation and sound, make damage.""" if self.current_part and not self.current_part.is_covered: return Shooter._shoot(self, task) return task.again def _stop_stunning(self, task): """Stop this character stun and continue fighting.""" self._is_stunned = False LerpAnimInterval(self.model, 0.8, self._current_anim, "stand_and_aim").start() self._current_anim = "stand_and_aim" self.model.loop("stand_and_aim") taskMgr.doMethodLater(0.1, self._aim, self.id + "_aim") # noqa: F821 taskMgr.doMethodLater(1, self._shoot, self.id + "_shoot") # noqa: F821 return task.done def get_damage(self, damage): """Getting damage. Args: damage (int): Damage points to get. """ if base.labels.TRAITS[2][0] in self.traits: # noqa: F821 # Masochism self.energy += 1 Unit.get_damage(self, damage) def get_stench_damage(self): """Get damage from the Stench.""" if base.labels.TRAITS[6][0] in self.traits and self.inhale > 0: # noqa: F821 # Deep breath self.inhale -= 1 return if ( self.current_part and self.current_part.name == "part_rest" and "Window Frames" in base.train.upgrades # noqa: F821 ): return self.get_damage(1)
class ToontownCentral(DirectObject): def __init__(self): self.scene = render.getPythonTag('SceneManager').createScene("TTC") self.build() def build(self): self.skybox = loader.loadModel("phase_3.5/models/props/TT_sky.bam") self.skybox.set_depth_write(False) self.skybox.find("**/Sky").setBin("background", 0) self.skybox.find('**/cloud1').setBin("background", 3) self.skybox.find('**/cloud2').setBin("background", 5) self.skybox.reparentTo(render) self.environ = loader.loadModel('ttc.bam') def __animateEnv(self): TTC = self.environ toonHall = TTC.find('**/sz13:toon_landmark_TT_toonhall_DNARoot') render.setPythonTag("ToonHall", ToonHall(toonHall, toonHall.find('**/door_double_round_ur'))) phase_4 = 'phase_4/models/props/' self.fish = TTC.find('**/animated_prop_PetShopFishAnimatedProp_DNARoot') self.fish.removeNode() self.fish = Actor(phase_4 + 'exteriorfish-zero.bam', {'anim' : phase_4 + 'exteriorfish-swim.bam'}) self.fish.reparentTo(TTC.find('**/sz22:toon_landmark_TT_pet_shop_DNARoot')) self.fish.loop('anim') self.periscope = Actor(TTC.find('**/animated_prop_HQPeriscopeAnimatedProp_DNARoot'), copy = 0) self.periscope.reparentTo(render) self.periscope.loadAnims({'anim': 'phase_3.5/models/props/HQ_periscope-chan.bam'}) self.periscope.pose('anim', 0) self.periscopeTrack = Sequence(Wait(2.0), self.periscope.actorInterval('anim', startFrame=0, endFrame=40), Wait(0.7), self.periscope.actorInterval('anim', startFrame=40, endFrame=90), Wait(0.7), self.periscope.actorInterval('anim', startFrame=91, endFrame=121), Wait(0.7), self.periscope.actorInterval('anim', startFrame=121, endFrame=91), Wait(0.7), self.periscope.actorInterval('anim', startFrame=90, endFrame=40), Wait(0.7), self.periscope.actorInterval('anim', startFrame=40, endFrame=90), Wait(0.7), self.periscope.actorInterval('anim', startFrame=91, endFrame=121), Wait(0.5), self.periscope.actorInterval('anim', startFrame=121, endFrame=148), Wait(3.0)) self.periscopeTrack.loop() self.telescope = Actor(TTC.find('**/animated_prop_HQTelescopeAnimatedProp_DNARoot'), copy = 0) self.telescope.reparentTo(render) self.telescope.loadAnims({'anim': 'phase_3.5/models/props/HQ_telescope-chan.bam'}) self.telescope.pose('anim', 0) self.telescopeTrack = Sequence(Wait(5.0), self.telescope.actorInterval('anim', startFrame=0, endFrame=32), Wait(0.5), self.telescope.actorInterval('anim', startFrame=32, endFrame=78), Wait(0.5), self.telescope.actorInterval('anim', startFrame=79, endFrame=112), Wait(0.5), self.telescope.actorInterval('anim', startFrame=112, endFrame=79), Wait(0.5), self.telescope.actorInterval('anim', startFrame=78, endFrame=32), Wait(0.5), self.telescope.actorInterval('anim', startFrame=32, endFrame=78), Wait(0.5), self.telescope.actorInterval('anim', startFrame=79, endFrame=112), Wait(0.5), self.telescope.actorInterval('anim', startFrame=112, endFrame=148), Wait(4.0)) self.telescopeTrack.loop() #base.taskMgr.add(self.__moveClouds, "Move Clouds") self.__fixTrashcans() self.environ.flattenStrong() self.scene.addModel(self.environ) render.find('**/TTC').setPythonTag('Class', self) def __fixTrashcans(self): TTC = self.environ trashcans = TTC.findAllMatches('**/prop_trashcan_metal_DNARoot') for trashcan in trashcans: pos = trashcan.getPos() hpr = trashcan.getHpr() trashcan.removeNode() new_trashcan = loader.loadModel('phase_5/models/props/trashcan_TT.bam') new_trashcan.setPos(pos) new_trashcan.setHpr(hpr) new_trashcan.reparentTo(TTC) def __moveClouds(self, task): model = self.skybox model.find("**/cloud1").setHpr(task.time * 0.3, 0, 0) model.find("**/cloud2").setHpr(task.time * -0.3, 0, 0) return Task.cont def doFade(self): TTC = render.find('**/TTC') skyFade = self.skybox.colorScaleInterval(4, Vec4(0.1, 0.1, 0.1, 1), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut') TTCFade = TTC.colorScaleInterval(3.8, Vec4(0.2509803921568627, 0.2509803921568627, 0.2509803921568627, 1), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut') skyFade.start() TTCFade.start() def loadScene(self): self.scene.loadScene() self.__animateEnv() def unloadScene(self): base.taskMgr.remove("Move Clouds") self.scene.delete()
class Lvl02(DirectObject): #constructor def start(self): base.disableMouse() #turn off mouse camera control camera.setPosHpr(Vec3(0,-55,30), Vec3(0,-20,0)) self.ballNum = 34 self.loadModels() self.setupLighting() self.setupCollisions() self.setupIntervals() #self.clock = ClockObject self.gameLen = 60 self.music = loader.loadMusic("models/gamedev/DFC.mp3") self.music.play() self.hud = DirectFrame(image = 'models/gamedev/lvl2hud.jpg') self.hud['pos'] = (-100,0,-100) self.hud['frameSize'] = (0,0,0,0) self.hud['image_pos'] = (0,-10,24.5) self.hud['image_scale'] = (22.25,1,2) self.hud['image_hpr'] = (0,-45,0) self.hud.reparentTo(render) globalClock.reset() self.drop() self.timer = DirectFrame(text = "%d" % (self.gameLen-globalClock.getRealTime(),), pos = Vec3(0,-11.5,23.5),text_fg = (1,1,1,1),text_scale=4.0) self.timer['frameSize'] = (0,0,0,0) self.timer.reparentTo(render) taskMgr.add(self.clockTask,"clockTask") self.player1Score = 0 self.player2Score = 0 self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 self.ignoreColl= 0 self.player1IsColliding = 0 self.player2IsColliding = 0 taskMgr.doMethodLater(self.gameLen, self.endGame,'gameFinished') taskMgr.doMethodLater(self.gameLen/2.0,self.changeMusic,'musicSwitch') #setup key controls self.accept("escape",sys.exit) # Player 1 movement self.acceptOnce("w",self.walk) self.acceptOnce("a",self.turn,[-1]) self.acceptOnce("d",self.turn,[1]) self.accept("w-up",self.stopWalk) self.accept("a-up",self.stopTurn) self.accept("d-up",self.stopTurn) # Player 2 movement self.acceptOnce("o",self.walk2,) self.acceptOnce("k",self.turn2,[-1]) self.acceptOnce(";",self.turn2,[1]) self.accept("o-up",self.stopWalk2) self.accept("k-up",self.stopTurn2) self.accept(";-up",self.stopTurn2) def loadModels(self): self.environment = loader.loadModel("models/gamedev/grassy") self.environment.reparentTo(render) self.environment.setScale(3.4) self.environment.setPos(0,12,-0.45) self.environment.setH(78) self.background = OnscreenImage(image = 'models/gamedev/lvl2background.jpg', pos = (0,40,0),scale=42.5, hpr = (0,-1,0)) self.background.reparentTo(render) bounds = self.environment.getChild(0).getBounds() radius = bounds.getRadius()*1.5 center = bounds.getCenter()+Vec3(0,12,0) #print center self.ball = [] for i in range(self.ballNum+1): balls.define(self.ball,i,render,center,radius) # ** Load male character that will represent first player** # self.playerModel = Actor("models/gamedev/redguy-model",{"walk":"models/gamedev/redguy-run"}) self.playerModel.reparentTo(render) self.playerModel.setScale(.1) self.playerModel.setH(90) # ** Position player at center of the field with it lying directly above the field. ** # self.playerModel.setPos(-10,0,0.76) # ** Load female character that will represent second player** # self.playerModel2 = Actor("models/gamedev/bluegirl-model",{"walk2":"models/gamedev/bluegirl-run"}) self.playerModel2.reparentTo(render) self.playerModel2.setScale(.1) self.playerModel2.setH(0) # ** Position player at center of the field with it lying directly above the field. ** # self.playerModel2.setPos(10,0,1.0) def setupLighting(self): ambientLight = AmbientLight('ambientLight') ambientLight.setColor(Vec4(0.55,0.55,0.55,1.0)) ambientLightNP = render.attachNewNode(ambientLight) render.setLight(ambientLightNP) dirLight = DirectionalLight('dirLight') dirLight.setColor(Vec4(0.6,0.6,0.6,1)) dirLightNP = render.attachNewNode(dirLight) dirLightNP.setHpr(Vec3(0.0,-26.0,0.0)) render.setLight(dirLightNP) def setupIntervals(self): self.charWalk1 = self.playerModel.actorInterval("walk") self.charWalk1.loop() self.charWalk1.pause() self.charWalk2 = self.playerModel2.actorInterval("walk2") self.charWalk2.loop( ) self.charWalk2.pause( ) def drop(self): dist = 49 for i in range(self.ballNum+1): ballDrop = self.ball[i].posInterval(5.0,Vec3(self.ball[i].getX(),self.ball[i].getY(),self.ball[i].getZ()-dist)) ballDrop.start() def dropSingle(self): dist = 49 ballDrop = self.ball[self.ballNum].posInterval(5.0,Vec3(self.ball[self.ballNum].getX(),self.ball[self.ballNum].getY(),self.ball[self.ballNum].getZ()-dist)) ballDrop.start() # ################# # Begin definitions for tasks: # # ################# def walk(self): taskMgr.add(self.walkTask,'walkTask') self.charWalk1.loop() # end walk def stopWalk(self): taskMgr.remove('walkTask') self.charWalk1.pause() self.acceptOnce("w",self.walk) # end stopWalk def walkTask(self,task): dt = globalClock.getDt() dist = self.speed1*dt angle = (self.playerModel.getH())*math.pi/180.0 dx = dist*math.sin(angle) dy = dist*-math.cos(angle) self.playerModel.setPos(Vec3(self.playerModel.getX()+dx,self.playerModel.getY()+dy,self.playerModel.getZ())) return Task.cont # end walkTask def turn(self,dir): taskMgr.add(self.turnTask,'turnTask',extraArgs=[dir]) #self.charTurn1.loop() self.ignore("a") self.ignore("d") # end turn def stopTurn(self): taskMgr.remove('turnTask') self.acceptOnce("a",self.turn,[-1]) self.acceptOnce("d",self.turn,[1]) # end stopTurn def turnTask(self,dir): dt = globalClock.getDt() angle = dir*self.turnSpeed1*dt self.playerModel.setH(self.playerModel.getH()-angle) return Task.cont # end turnTask # Player 2's Movement # def walk2(self): taskMgr.add(self.walkTask2,'walkTask2') self.charWalk2.loop() # end walk def stopWalk2(self): taskMgr.remove('walkTask2') self.charWalk2.pause() self.acceptOnce("o",self.walk2) # end stopWalk def walkTask2(self,task): dt = globalClock.getDt() dist = self.speed2*dt angle = (self.playerModel2.getH()-90)*math.pi/180.0 dx = dist*math.sin(angle) dy = dist*-math.cos(angle) self.playerModel2.setPos(Vec3(self.playerModel2.getX()+dx,self.playerModel2.getY()+dy,self.playerModel2.getZ())) return Task.cont # end walkTask def turn2(self,dir): taskMgr.add(self.turnTask2,'turnTask2',extraArgs=[dir]) self.ignore("k") self.ignore(";") # end turn def stopTurn2(self): taskMgr.remove('turnTask2') self.acceptOnce("k",self.turn2,[-1]) self.acceptOnce(";",self.turn2,[1]) # end stopTurn def turnTask2(self,dir): dt = globalClock.getDt() angle = dir*self.turnSpeed2*dt self.playerModel2.setH(self.playerModel2.getH()-angle) return Task.cont # end turnTask def setupCollisions(self): self.cHandler = CollisionHandlerEvent() self.cHandler.setInPattern("ate-%in") self.cHandler.addInPattern('%fn-into-%in') self.cHandler.setAgainPattern('%fn-again-%in') self.cHandler.setOutPattern('%fn-outof-%in') self.cTrav = CollisionTraverser() base.cTrav = self.cTrav #Player 1 collision solid bounds = self.playerModel.getChild(0).getBounds() center = bounds.getCenter()-Vec3(0,0,12) radius = bounds.getRadius()-18 boundsB = self.playerModel.getChild(0).getBounds() centerB = bounds.getCenter()-Vec3(0,0,-4) radiusB = bounds.getRadius()-20 cSphere = CollisionSphere(center,radius) cSphereB = CollisionSphere(centerB,radiusB) cNode = CollisionNode("player1") cNode.addSolid(cSphere) cNode.addSolid(cSphereB) cNodePath = self.playerModel.attachNewNode(cNode) #cNodePath.show() #Player 2 collision solid bounds2 = self.playerModel2.getChild(0).getBounds() center2 = bounds2.getCenter()-Vec3(0,0,-4) radius2 = bounds2.getRadius()-20 cSphere2 = CollisionSphere(center2,radius2) bounds2B = self.playerModel2.getChild(0).getBounds() center2B = bounds2B.getCenter()-Vec3(0,0,12) radius2B = bounds2B.getRadius()-18 cSphere2B = CollisionSphere(center2B,radius2B) cNode2 = CollisionNode("player2") cNode2.addSolid(cSphere2) cNode2.addSolid(cSphere2B) cNodePath2 = self.playerModel2.attachNewNode(cNode2) #cNodePath2.show() self.cTrav.addCollider(cNodePath,self.cHandler) self.cTrav.addCollider(cNodePath2,self.cHandler) self.cTrav.addCollider(cNodePath,self.cHandler) self.cTrav.addCollider(cNodePath2,self.cHandler) bounds = self.environment.getChild(0).getBounds() center = bounds.getCenter() radius = bounds.getRadius()*.71 #print radius cSphere = CollisionInvSphere(center,radius) cNode = CollisionNode("Arena") cNode.addSolid(cSphere) cNodePath = self.environment.attachNewNode(cNode) #cNodePath.show() for i in range(self.ballNum+1): boundsB = self.ball[i].getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*.8 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("ball") cNodeB.addSolid(cSphereB) cNodePathB = self.ball[i].attachNewNode(cNodeB) #cNodePath3.show() self.accept("ate-ball", self.eat) self.accept( 'player1-into-Arena', self.colliding1) self.accept( 'player1-again-Arena', self.colliding1) self.accept( 'player1-outof-Arena', self.notColliding1) self.accept( 'player2-into-Arena', self.colliding2) self.accept( 'player2-again-Arena', self.colliding2) self.accept( 'player2-outof-Arena', self.notColliding2) self.accept( 'player1-into-player2', self.colliding1) self.accept( 'player1-again-player2', self.colliding1) self.accept( 'player1-outof-player2', self.notColliding1) self.accept( 'player2-into-player1', self.colliding2) self.accept( 'player2-again-player1', self.colliding2) self.accept( 'player2-outof-player1', self.notColliding2) def eat(self,cEntry): if str(cEntry.getIntoNodePath().getParent()) == "render/blueball": #Blue ball picked up, update score self.player2Score+=1 elif str(cEntry.getIntoNodePath().getParent()) == "render/redball": #Red ball picked up, update score self.player1Score+=1 elif str(cEntry.getIntoNodePath().getParent()) == "render/crystalball": #Freezes the field (Ice) self.environment.setColor(0,.9,1) taskMgr.doMethodLater(10, self.switch, 'changeStage') self.speed1 = 14 self.speed2 = 14 self.turnSpeed1 = 110 self.turnSpeed2 = 110 taskMgr.doMethodLater(10, self.returnSpeeds, 'returnSpeedsToNormal') elif str(cEntry.getIntoNodePath().getParent()) == "render/red_blue": #Switch Sphere Colors for i in self.ball: if i.getName() == "blueball": i.removeNode() children = i.getGeomNode().getChildren() children.detach() i.loadModel("models/gamedev/redball") i.setName("redball") i.reparentTo(render) elif i.getName() == "redball": i.removeNode() children = i.getGeomNode().getChildren() children.detach() i.loadModel("models/gamedev/blueball") i.setName("blueball") i.reparentTo(render) elif str(cEntry.getIntoNodePath().getParent()) == "render/fireball": #Stop your opponent for a few seconds if (str(cEntry.getFromNodePath().getParent()) == "render/redgirl") or (str(cEntry.getFromNodePath().getParent()) == "render/redguy"): self.speed2 = 0 self.turnSpeed2 = 0 self.ignore("o") taskMgr.doMethodLater(3, self.returnSpeeds2, 'returnSpeedsToNormal') else: self.speed1 = 0 self.turnSpeed1 = 0 self.ignore("w") taskMgr.doMethodLater(3, self.returnSpeeds2, 'returnSpeedsToNormal') elif str(cEntry.getIntoNodePath().getParent()) == "render/black_white": self.ignoreColl = 1 x = Vec3(self.playerModel.getPos()) y = Vec3(self.playerModel2.getPos()) self.playerModel.setPos(y) self.playerModel2.setPos(x) self.ignoreColl = 0 elif str(cEntry.getIntoNodePath().getParent()) == "render/golden": if (str(cEntry.getFromNodePath().getParent()) == "render/redgirl") or (str(cEntry.getFromNodePath().getParent()) == "render/redguy"): self.speed1 = 14 self.turnSpeed1 = 110 taskMgr.doMethodLater(8, self.returnSpeeds3, 'returnSpeedsToNormal') else: self.speed2 = 14 self.turnSpeed2 = 110 taskMgr.doMethodLater(8, self.returnSpeeds3, 'returnSpeedsToNormal') elif str(cEntry.getIntoNodePath().getParent()) == "render/greenball": if (str(cEntry.getFromNodePath().getParent()) == "render/redgirl") or (str(cEntry.getFromNodePath().getParent()) == "render/redguy"): self.player1Score += 5 else: self.player2Score += 5 elif str(cEntry.getIntoNodePath().getParent()) == "render/blackball": camera.setPosHpr(Vec3(0,-55,110), Vec3(0,-20,0)) taskMgr.doMethodLater(5,self.restoreCamera,'restoreCamera') elif str(cEntry.getIntoNodePath().getParent()) == "render/translucent": for i in self.ball: i.hide() taskMgr.doMethodLater(6,self.showBalls,'returnBallsToNormal') cEntry.getIntoNodePath().getParent().removeNode() #Drop a New Ball bounds = self.environment.getChild(0).getBounds() radius = bounds.getRadius()*1.8 center = bounds.getCenter()+Point3(0,10,0) self.ballNum+=1 balls.define(self.ball,self.ballNum,render,center,radius) boundsB = self.ball[self.ballNum].getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*.8 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("ball") cNodeB.addSolid(cSphereB) cNodePathB = self.ball[self.ballNum].attachNewNode(cNodeB) self.dropSingle() def showBalls(self,task): for i in self.ball: i.show() def restoreCamera(self,task): camera.setPosHpr(Vec3(0,-55,30), Vec3(0,-20,0)) def switch(self,task): self.environment.removeNode() self.environment = loader.loadModel("models/gamedev/grassy") self.environment.reparentTo(render) self.environment.setScale(3.4) self.environment.setPos(0,12,-0.45) self.environment.setH(78) def colliding1( self, collEntry ): # accept a collision entry argument if self.ignoreColl == 0: self.player1IsColliding = 1 # we are colliding self.stopWalk( ) # pause all walking animation and movement disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) ) newPos = self.playerModel.getPos( ) + disp # get new position self.playerModel.setPos( newPos ) # and set it to tiny's position # end colliding def notColliding1( self, collEntry ): self.player1IsColliding = 0 def colliding2( self, collEntry ): # accept a collision entry argument if self.ignoreColl == 0: self.player2IsColliding = 1 # we are colliding self.stopWalk2( ) # pause all walking animation and movement disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) ) newPos = self.playerModel2.getPos( ) + disp # get new position self.playerModel2.setPos( newPos ) # and set it to tiny's position # end colliding def notColliding2( self, collEntry ): self.player2IsColliding = 0 def returnSpeeds(self,task): self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 def returnSpeeds2(self,task): self.acceptOnce("w",self.walk) self.acceptOnce("o",self.walk2) self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 def returnSpeeds3(self,task): self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 def changeMusic(self,task): self.music.stop() self.music2 = loader.loadMusic("models/gamedev/ADRENALINE.mp3") self.music2.play() def clockTask(self,task): self.timer.removeNode() self.timer = DirectFrame(text = "%d" % (self.gameLen-globalClock.getRealTime(),), pos = Vec3(0,-11.5,23.5),text_fg = (1,1,1,1),text_scale= 4.0) self.timer['frameSize'] = (0,0,0,0) self.timer.reparentTo(render) return Task.cont def endGame(self,task): taskMgr.removeTasksMatching('returnSpeedsToNormal') taskMgr.removeTasksMatching('restoreCamera') taskMgr.removeTasksMatching('clockTask') taskMgr.removeTasksMatching('walkTask') taskMgr.removeTasksMatching('walkTask2') taskMgr.removeTasksMatching('turnTask') taskMgr.removeTasksMatching('turnTask2') self.music2.stop() self.music3 = loader.loadMusic("models/gamedev/CSTAR.mp3") self.music3.play() self.speed1 = 0 self.speed2 = 0 self.turnSpeed1 = 0.0 self.turnSpeed2 = 0.0 def getScores(self): return (self.player1Score, self.player2Score) def getGameLen(self): return self.gameLen def stopMusic(self): self.music3.stop() def destroy(self): self.hud.destroy() self.timer.destroy() self.environment.removeNode() self.playerModel.removeNode() self.playerModel2.removeNode() self.background.destroy() for i in range(self.ballNum+1): self.ball[i].removeNode() #lvl02 = Lvl02() #run()
class Lvl01(DirectObject): #constructor def start(self): base.disableMouse() #turn off mouse camera control #camera.setPosHpr(Vec3(93,-90,0), Vec3(0,0,0)) # Turn off the default camera and replace it with two new cameras, with # side-by-side DisplayRegions. base.camNode.setActive(0) base.makeCamera(base.win, displayRegion = (0, 0.48, 0, 1)) base.makeCamera(base.win, displayRegion = (0.52, 1, 0, 1)) base.makeCamera(base.win, displayRegion = (0.48,0.52,0,1)) base.camList[3].setPos(Vec3(144,0,-1000)) self.gameLen = 100 self.numActuator = 10 self.music = loader.loadMusic("models/gamedev/AD.mp3") self.music.play() globalClock.reset() self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0) self.timer.setColor(1,1,1) taskMgr.add(self.clockTask,"clockTask") self.actCount = 0 self.speed1 = 3 self.speed2 = 3 self.climbSpeed1 = 1 self.climbSpeed2 = 1 self.climbing1 = 0 self.climbing2 = 0 self.array = [] self.loadModels() self.setupLighting() self.setupStage() self.setupCollisions() self.setupIntervals() self.player1Score = 0 self.player2Score = 0 self.dir1 = 1 self.dir2 = 1 self.nodeCount1 = 0 self.nodeCount2 = 0 taskMgr.add(self.cameraFollowTask,"cameraFollowTask") taskMgr.add(self.boulderTask,"boulderTask") taskMgr.doMethodLater(self.gameLen,self.endGame,'endGame') #setup key controls self.accept("escape",sys.exit) #self.accept("w",self.rise) #self.accept("o",self.rise2) #Player 1 movement keys #self.accept("s",self.fall) self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.acceptOnce("w", self.jump) self.acceptOnce("o", self.jumpT2) #Player 2 movement keys #self.accept("l",self.fall2) self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft2) self.accept(";-up",self.stopRight2) self.jumpOK = 1 def loadModels(self): print "start loadModels" self.playerModel = Actor("models/gamedev/redguy-model",{"walk":"models/gamedev/redguyrun", "jump":"models/gamedev/redguy-jump","climb":"models/gamedev/redguy-climb"}) self.playerModel.reparentTo(render) self.playerModel.setScale(.7) self.playerModel.setPosHpr(Vec3(46,0,0),Vec3(0,0,0)) self.playerModel.setH(90) self.playerModel2 = Actor("models/gamedev/bluegirl-model",{"walk2":"models/gamedev/bluegirlrun", "jump2":"models/gamedev/bluegirl-jump","climb2":"models/gamedev/bluegirl-climb"}) self.playerModel2.reparentTo(render) self.playerModel2.setScale(.7) self.playerModel2.setPosHpr(Vec3(333,0,0),Vec3(0,0,0)) self.playerModel2.setH(270) self.divider = loader.loadModel("models/gamedev/divider") self.divider.setPos(144,0,-1000) self.divider.setScale(5.0) self.divider.reparentTo(render) self.boulder1 = loader.loadModel("models/gamedev/boulder") self.boulder1.reparentTo(render) self.boulder1.setScale(7) self.boulder1.setPos(46,0,-50) self.boulder2 = loader.loadModel("models/gamedev/boulder") self.boulder2.reparentTo(render) self.boulder2.setScale(7) self.boulder2.setPos(333,0,-50) #loader.loadModel("models/gamedev/actuatorOn") bounds = self.boulder1.getChild(0).getBounds() center = bounds.getCenter() radius = bounds.getRadius()*.7 cSphere = CollisionSphere(center,radius) cNode = CollisionNode("boulder") cNode.addSolid(cSphere) cNodePath = self.boulder1.attachNewNode(cNode) #cNodePath.show() cNodePath = self.boulder2.attachNewNode(cNode) #cNodePath.show() print "end loadModels" def setupStage(self): print "start setupStage" self.background = OnscreenImage(image = 'models/gamedev/lvl1background.jpg', pos = (175,5,0),scale=500) self.background.reparentTo(render) x1= 4.9 x2 = -4.9 len = 9.8 h = 0 a = 0 p = 0 j=0 m=0 x1b=0 x2b=0 while self.actCount < self.numActuator: if j > 0: lOld = l rOld = r x1Old = x1 x2Old = x2 x1 = (x1Old+x2Old)/2 + 4.9 x2 = (x1Old+x2Old)/2 - 4.9 x1o=x1 x2o=x2 for count in range(1): l = random.randint(0,(10-lOld)+((10+rOld)-(10-lOld))/2) r = random.randint(0,20-((10-lOld)+((10+rOld)-(10-lOld))/2)) if r+2 <= 20-((10-lOld)+((10+rOld)-(10-lOld))/2): r += 2 if l+2 < (10-lOld)+((10+rOld)-(10-lOld))/2: l += 2 if l+r < 4: count = 0 p = random.randint(0,1) else: l = 10 r = 10 c = 10 #while a == 0: a = random.randint(-l,r) if j > 0: if j % 2 == 0: self.ladder = loader.loadModel("models/gamedev/ladder") self.ladder.reparentTo(render) self.ladder.setScale(1.5) self.ladder.setPos(x1+m,0,h-20) self.ladder2 = loader.loadModel("models/gamedev/ladder") self.ladder2.reparentTo(render) self.ladder2.setScale(1.5) self.ladder2.setPos(x1+286+m,0,h-20) self.array.append(self.ladder) self.array.append(self.ladder2) else: self.ladder = loader.loadModel("models/gamedev/ladder") self.ladder.reparentTo(render) self.ladder.setScale(1.5) self.ladder.setPos(x2,0,h-20) self.ladder2 = loader.loadModel("models/gamedev/ladder") self.ladder2.reparentTo(render) self.ladder2.setScale(1.5) self.ladder2.setPos(x2+286,0,h-20) self.array.append(self.ladder) self.array.append(self.ladder2) k=-10 while k <= 13: cSphere = CollisionSphere(Point3(1.5,0,k),.5) cNode = CollisionNode("ladder") cNode.addSolid(cSphere) cNodePath = self.ladder.attachNewNode(cNode) cNodePath = self.ladder2.attachNewNode(cNode) #cNodePath.show() k+=1 self.array.append(self.ladder) #cSphere = CollisionSphere(Point3(1.5,0,h-40),.5) #cNodeB = CollisionNode("canWalk") #cNodeB.addSolid(cSphere) #cNodePath = self.ladder.attachNewNode(cNodeB) #cNodePath = self.ladder2.attachNewNode(cNodeB) for i in range(r): '''Right half of stage''' self.environment = loader.loadModel("models/gamedev/platform") self.environment.reparentTo(render) self.environment.setScale(5) self.environment.setPos(x1,0,h) self.environment2 = loader.loadModel("models/gamedev/platform") self.environment2.reparentTo(render) self.environment2.setScale(5) self.environment2.setPos(x1+286,0,h) self.array.append(self.environment) self.array.append(self.environment2) #if i == 0 and j > 0: # cSphere = CollisionSphere(Point3((m/9.8)*1.9,0,0),.5) # cNode = CollisionNode("platform") # cNode.addSolid(cSphere) # cNodePath = self.environment.attachNewNode(cNode) # cNodePath = self.environment2.attachNewNode(cNode) # cNodePath.show() if r == i+1: cSphere = CollisionSphere(Point3(2,0,0),2) if i == 9: cNode = CollisionNode("rwall") else: cNode = CollisionNode("redge") cNode.addSolid(cSphere) cNodePath = self.environment.attachNewNode(cNode) cNodePath = self.environment2.attachNewNode(cNode) #cNodePath.show() if a == i: self.actCount+=1 self.actuator = Actor("models/gamedev/actuator") self.actuator.reparentTo(render) self.actuator.setPos(self.environment.getPos()) if p == 1: self.actuator.setZ(self.actuator.getZ()) self.actuator.setP(self.actuator.getP()+180) self.actuator.setScale(2) self.actuator.setH(self.actuator.getH()+180) self.array.append(self.actuator) bounds = self.actuator.getChild(0).getBounds() center = bounds.getCenter() radius = bounds.getRadius()-.5 cSphere = CollisionSphere(center,radius) cNode = CollisionNode("actuator") cNode.addSolid(cSphere) cNodePath = self.actuator.attachNewNode(cNode) #cNodePath.show() self.actuator2 = Actor("models/gamedev/actuator") self.actuator2.reparentTo(render) self.actuator2.setPos(self.environment2.getPos()) if p == 1: self.actuator2.setZ(self.actuator2.getZ()) self.actuator2.setP(self.actuator2.getP()+180) self.actuator2.setScale(2) self.actuator2.setH(self.actuator2.getH()+180) self.array.append(self.actuator2) bounds = self.actuator2.getChild(0).getBounds() center = bounds.getCenter() radius = bounds.getRadius()-.5 cSphere = CollisionSphere(center,radius) cNode = CollisionNode("actuator") cNode.addSolid(cSphere) cNodePath = self.actuator2.attachNewNode(cNode) #cNodePath.show() x1 = x1 + len for i in range(l): '''Left Half of stage''' self.environment = loader.loadModel("models/gamedev/platform") self.environment.reparentTo(render) self.environment.setScale(5) self.environment.setPos(x2,0,h) self.array.append(self.environment) self.environment2 = loader.loadModel("models/gamedev/platform") self.environment2.reparentTo(render) self.environment2.setScale(5) self.environment2.setPos(x2+286,0,h) self.array.append(self.environment2) if l == i+1: cSphere = CollisionSphere(Point3(-2,0,0),2) if i == 9: cNode = CollisionNode("lwall") else: cNode = CollisionNode("ledge") cNode.addSolid(cSphere) cNodePath = self.environment.attachNewNode(cNode) cNodePath = self.environment2.attachNewNode(cNode) #cNodePath.show() if a == -i: self.actCount+=1 self.actuator = Actor("models/gamedev/actuator") self.actuator.reparentTo(render) self.actuator.setPos(self.environment.getPos()) self.actuator.setScale(2) self.array.append(self.actuator) bounds = self.actuator.getChild(0).getBounds() center = bounds.getCenter() radius = bounds.getRadius()-.5 cSphere = CollisionSphere(center,radius) cNode = CollisionNode("actuator") cNode.addSolid(cSphere) cNodePath = self.actuator.attachNewNode(cNode) #cNodePath.show() self.actuator = Actor("models/gamedev/actuator") self.actuator.reparentTo(render) self.actuator.setPos(self.environment2.getPos()) self.actuator.setScale(2) self.array.append(self.actuator) bounds = self.actuator.getChild(0).getBounds() center = bounds.getCenter() radius = bounds.getRadius()-.5 cSphere = CollisionSphere(center,radius) cNode = CollisionNode("actuator") cNode.addSolid(cSphere) cNodePath = self.actuator.attachNewNode(cNode) #cNodePath.show() x2 = x2 - len j+=1 h = h+40 #x1 = 4.9 #x2 = -4.9 a = 0 self.h = h+50 x2b=x2o x1b=x1o print "end setupStage" def setupLighting(self): print "start setupLighting" ambientLight = AmbientLight('ambientLight') ambientLight.setColor(Vec4(0.55,0.55,0.55,1.0)) ambientLightNP = render.attachNewNode(ambientLight) render.setLight(ambientLightNP) dirLight = DirectionalLight('dirLight') dirLight.setColor(Vec4(0.6,0.6,0.6,1)) dirLightNP = render.attachNewNode(dirLight) dirLightNP.setHpr(Vec3(0.0,-26.0,0.0)) render.setLight(dirLightNP) print "end setupLighting" def setupIntervals(self): print "start setupIntervals" self.charWalk1 = self.playerModel.actorInterval("walk") self.charWalk1.loop( ) self.charWalk1.pause( ) self.charWalk2 = self.playerModel2.actorInterval("walk2") self.charWalk2.loop( ) self.charWalk2.pause( ) self.jump1 = self.playerModel.actorInterval("jump") self.jump1.loop() self.jump1.pause() self.jump2 = self.playerModel2.actorInterval("jump2") self.jump2.loop() self.jump2.pause() self.climb1 = self.playerModel.actorInterval("climb") self.climb1.loop() self.climb1.pause() self.climb2 = self.playerModel2.actorInterval("climb2") self.climb2.loop() self.climb2.pause() print "end setupIntervals" # PLAYER ONE # def left(self): taskMgr.add(self.leftTask,'leftTask') self.charWalk1.loop() #end left def leftTask(self,task): if self.climbing1 == 0: self.playerModel.setH(270) self.playerModel.setPos(Vec3(self.playerModel.getX()-self.speed1, self.playerModel.getY(), self.playerModel.getZ())) return Task.cont def right(self): taskMgr.add(self.rightTask,'rightTask') self.charWalk1.loop() #end right def rightTask(self,task): if self.climbing1 == 0: self.playerModel.setH(90) self.playerModel.setPos(Vec3(self.playerModel.getX()+self.speed1, self.playerModel.getY(), self.playerModel.getZ())) return Task.cont def climbable(self,cEntry): self.nodeCount1+=1 print self.nodeCount1 self.ignore("w") self.ignore("w-up") self.ignore("s") self.ignore("s-up") self.acceptOnce("w",self.climb,[1]) self.accept("w-up",self.noClimb) self.acceptOnce("s",self.climb,[-1]) self.accept("s-up",self.noClimb) def climb(self,dir): self.dir1 = dir self.climbing1 = 1 self.climbSpeed1 = 1 self.ignore("a") self.ignore("a-up") self.ignore("d") self.ignore("d-up") taskMgr.add(self.climbTask,'climbTask') self.climb1.loop() def noClimb(self): taskMgr.remove('climbTask') self.climb1.pause() if self.nodeCount1 == 0: self.climbing = 0 self.climbSpeed1 = 0 self.acceptOnce("w",self.climb,[1]) self.acceptOnce("s",self.climb,[-1]) def jumpable(self,cEntry): self.nodeCount1+=-1 print self.nodeCount1 if self.nodeCount1 == 0: taskMgr.remove('climbTask') self.ignore("w") self.ignore("w-up") self.ignore("s") self.ignore("s-up") self.acceptOnce("w",self.jump) self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.climbing1 = 0 self.climbSpeed1 = 0 self.climb1.pause() def walkable(self,cEntry): self.ignore("w") self.ignore("w-up") self.ignore("s") self.ignore("s-up") self.acceptOnce("w",self.climb,[1]) self.accept("w-up",self.noClimb) self.acceptOnce("s",self.climb,[-1]) self.accept("s-up",self.noClimb) self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.climbing1 = 0 self.climbSpeed1 = 0 self.climb1.pause() def climbTask(self,task): if self.playerModel.getZ() >=0: self.playerModel.setH(0) self.playerModel.setPos(Vec3(self.playerModel.getX(), self.playerModel.getY(), self.playerModel.getZ()+self.climbSpeed1*self.dir1)) return Task.cont def jump(self): if self.nodeCount1 == 0: self.ignore("w") self.ignore("w-up") z = self.playerModel.getZ() j = ProjectileInterval(self.playerModel, startPos = self.playerModel.getPos(), startVel = Point3(0,0,27), endZ = z) j.start() taskMgr.doMethodLater(3,self.jumpTask,"jumpTask") else: self.acceptOnce("w",self.climb,[1]) def jumpTask(self, task): if self.climbing1 == 0: self.jump1.pause() self.acceptOnce("w",self.jump) #return task.cont def allowRight(self): self.acceptOnce("d",self.right) def noRight(self): taskMgr.remove('rightTask') self.charWalk1.pause() self.acceptOnce("d",self.right) def stopRight(self): self.noRight() #self.allowRight() def rightWall(self,cEntry): self.ignore("d") self.noRight() def rightEdge(self,cEntry): self.ignore("d") self.noRight() def rightOK(self,cEntry): self.allowRight() def allowLeft(self): self.acceptOnce("a",self.left) def noLeft(self): taskMgr.remove('leftTask') self.charWalk1.pause() self.acceptOnce("a",self.left) def stopLeft(self): self.noLeft() #self.allowLeft() def leftWall(self,cEntry): self.ignore("a") self.noLeft() def leftEdge(self,cEntry): self.ignore("a") self.noLeft() def leftOK(self,cEntry): self.allowLeft() # PLAYERTWO # def left2(self): taskMgr.add(self.leftTask2,'leftTask2') self.charWalk2.loop() #end left def leftTask2(self,task): if self.climbing2 == 0: self.playerModel2.setH(0) self.playerModel2.setPos(Vec3(self.playerModel2.getX()-self.speed2, self.playerModel2.getY(), self.playerModel2.getZ())) return Task.cont def right2(self): taskMgr.add(self.rightTask2,'rightTask2') self.charWalk2.loop() #end right def rightTask2(self,task): if self.climbing2 == 0: self.playerModel2.setH(180) self.playerModel2.setPos(Vec3(self.playerModel2.getX()+self.speed2, self.playerModel2.getY(), self.playerModel2.getZ())) return Task.cont def climbable2(self,cEntry): self.nodeCount2+=1 #print self.nodeCount1 self.ignore("o") self.ignore("o-up") self.ignore("l") self.ignore("l-up") self.acceptOnce("o",self.climbT2,[1]) self.accept("o-up",self.noClimb2) self.acceptOnce("l",self.climbT2,[-1]) self.accept("l-up",self.noClimb2) def climbT2(self,dir): self.dir2 = dir self.climbing2 = 1 self.climbSpeed2 = 1 self.ignore("k") self.ignore("k-up") self.ignore(";") self.ignore(";-up") taskMgr.add(self.climbTask2,'climbTask2') self.climb2.loop() def noClimb2(self): taskMgr.remove('climbTask2') self.climb2.pause() if self.nodeCount2 == 0: self.climbing2 = 0 self.climbSpeed2 = 0 self.acceptOnce("o",self.climbT2,[1]) self.acceptOnce("l",self.climbT2,[-1]) def jumpable2(self,cEntry): self.nodeCount2+=-1 #print self.nodeCount2 if self.nodeCount2 == 0: taskMgr.remove('climbTask2') self.ignore("o") self.ignore("o-up") self.ignore("l") self.ignore("l-up") self.acceptOnce("o",self.jumpT2) self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft2) self.accept(";-up",self.stopRight2) self.climbing2 = 0 self.climbSpeed2 = 0 self.climb2.pause() def walkable2(self,cEntry): self.ignore("o") self.ignore("o-up") self.ignore("l") self.ignore("l-up") self.acceptOnce("o",self.climbT2,[1]) self.accept("o-up",self.noClimb2) self.acceptOnce("l",self.climbT2,[-1]) self.accept("l-up",self.noClimb2) self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft) self.accept(";-up",self.stopRight) self.climbing2 = 0 self.climbSpeed2 = 0 self.climb2.pause() def climbTask2(self,task): if self.playerModel2.getZ() >=0: self.playerModel2.setH(90) self.playerModel2.setPos(Vec3(self.playerModel2.getX(), self.playerModel2.getY(), self.playerModel2.getZ()+self.climbSpeed2*self.dir2)) return Task.cont def jumpT2(self): if self.nodeCount2 == 0: self.ignore("o") self.ignore("o-up") z = self.playerModel2.getZ() j = ProjectileInterval(self.playerModel2, startPos = self.playerModel2.getPos(), startVel = Point3(0,0,27), endZ = z) j.start() taskMgr.doMethodLater(3,self.jumpTask2,"jumpTask2") else: self.acceptOnce("w",self.climb,[1]) def jumpTask2(self, task): if self.climbing2 == 0: self.jump2.pause() self.acceptOnce("o",self.jumpT2) #return task.cont def allowRight2(self): self.acceptOnce(";",self.right2) def noRight2(self): taskMgr.remove('rightTask2') self.charWalk2.pause() self.acceptOnce(";",self.right2) def stopRight2(self): self.noRight2() #self.allowRight() def rightWall2(self,cEntry): self.ignore(";") self.noRight2() def rightEdge2(self,cEntry): self.ignore(";") self.noRight2() def rightOK2(self,cEntry): self.allowRight2() def allowLeft2(self): self.acceptOnce("k",self.left2) def noLeft2(self): taskMgr.remove('leftTask2') self.charWalk2.pause() self.acceptOnce("k",self.left2) def stopLeft2(self): self.noLeft2() #self.allowLeft() def leftWall2(self,cEntry): self.ignore("k") self.noLeft2() def leftEdge2(self,cEntry): self.ignore("k") self.noLeft2() def leftOK2(self,cEntry): self.allowLeft2() def cameraFollowTask(self,task): base.camList[1].setPos(Vec3(self.playerModel.getX(),-200,self.playerModel.getZ()+30)) base.camList[2].setPos(Vec3(self.playerModel2.getX(),-200,self.playerModel2.getZ()+30)) return task.cont def activate(self,cEntry): i = cEntry.getIntoNodePath().getParent() where = i.getPos() which = i.getHpr() i.detachNode() i = Actor("models/gamedev/actuatorOn") i.setName("actuatorOn") i.setPosHpr(where,which) i.setScale(2) i.reparentTo(render) self.array.append(i) if i.getX() < 144: self.player1Score += 3 else: self.player2Score += 3 def stun(self,cEntry): ow = Sequence(Func(self.startStun), Wait(3), Func(self.stopStun)) ow.start() def startStun(self): self.speed1 = 0 self.climbspeed1 = 0 self.ignore("w") self.ignore("w-up") self.ignore("a") self.ignore("d") self.ignore("a-up") self.ignore("d-up") taskMgr.remove('leftTask') taskMgr.remove('rightTask') taskMgr.remove('climbTask') taskMgr.remove('jumpTask') self.playerModel.stop() #self.ignore("player1-ladder") def stopStun(self): self.speed1 = 3 self.climbspeed1 = 1 self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.acceptOnce("w",self.jump) #self.accept("player1-ladder", self.climbable) def stun2(self,cEntry): ow = Sequence(Func(self.startStun2), Wait(3), Func(self.stopStun2)) ow.start() def startStun2(self): self.speed2 = 0 self.climbspeed2 = 0 self.ignore("k") self.ignore(";") self.ignore("k-up") self.ignore(";-up") self.ignore("o") self.ignore("o-up") taskMgr.remove('leftTask2') taskMgr.remove('rightTask2') taskMgr.remove('climbTask2') taskMgr.remove('jumpTask2') self.playerModel2.stop() #self.ignore("player2-ladder") def stopStun2(self): self.speed2 = 3 self.climbspeed2 = 1 self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft2) self.accept(";-up",self.stopRight2) self.acceptOnce("o",self.jumpT2) #self.accept("player2-ladder", self.climbable2) def setupCollisions(self): print "start setupCollisions" self.cHandler = CollisionHandlerEvent() self.cHandler = CollisionHandlerEvent() self.cHandler.setInPattern("%fn-%in") self.cHandler.setAgainPattern("%fn-is-on-%in") self.cHandler.setOutPattern("%fn-left-%in") self.cTrav = CollisionTraverser() base.cTrav = self.cTrav #Player 1 collision solid bounds = self.playerModel.getChild(0).getBounds() center = bounds.getCenter()-Vec3(0,0,12.5) radius = bounds.getRadius()-21 cSphere = CollisionSphere(center,radius) cNode = CollisionNode("player1") cNode.addSolid(cSphere) centerB = bounds.getCenter()-Vec3(0,0,-11) radiusB = bounds.getRadius()-21 cSphereB = CollisionSphere(centerB,radiusB) cNode.addSolid(cSphereB) cNodePath = self.playerModel.attachNewNode(cNode) #cNodePath.show() #centerBB = bounds.getCenter()-Vec3(0,0,25) #radiusBB = bounds.getRadius()-28 #cSphereBB = CollisionSphere(centerB,radiusB) #cNodeT = CollisionNode("player1B") #cNodeT.addSolid(cSphereBB) #cNodePath = self.playerModel.attachNewNode(cNodeT) #cNodePath.show() #Player 2 collision solid bounds2 = self.playerModel2.getChild(0).getBounds() center2 = bounds2.getCenter()-Vec3(0,0,12.5) radius2 = bounds2.getRadius()-21 cSphere2 = CollisionSphere(center2,radius2) cNode2 = CollisionNode("player2") cNode2.addSolid(cSphere2) bounds2B = self.playerModel2.getChild(0).getBounds() center2B = bounds2B.getCenter()-Vec3(0,0,-11) radius2B = bounds2B.getRadius()-21 cSphere2B = CollisionSphere(center2B,radius2B) cNode2.addSolid(cSphere2B) cNodePath2 = self.playerModel2.attachNewNode(cNode2) #cNodePath2.show() self.cTrav.addCollider(cNodePath,self.cHandler) self.cTrav.addCollider(cNodePath2,self.cHandler) self.cTrav.addCollider(cNodePath,self.cHandler) self.cTrav.addCollider(cNodePath2,self.cHandler) self.accept("player1-ladder", self.climbable) self.accept("player1-left-ladder", self.jumpable) #self.accept("player1b-canWalk", self.walkable) self.accept("player2-ladder", self.climbable2) self.accept("player2-left-ladder", self.jumpable2) #self.accept("player1-platform", self.climbable) #self.accept("player1-left-platform",self. #self.accept("player1-left-ladder-down", self.noDrop) #self.accept("player2-ladder-down", self.drop2) #self.accept("player2-left-ladder-down", self.noDrop2) self.accept("player1-actuator", self.activate) self.accept("player2-actuator", self.activate) self.accept("player1-boulder", self.stun) self.accept("player2-boulder", self.stun2) self.accept("boulder-player1", self.stun) self.accept("boulder-player2", self.stun2) self.accept("player1-is-on-ledge", self.leftEdge) self.accept("player2-is-on-ledge", self.leftEdge2) self.accept("player1-is-on-redge", self.rightEdge) self.accept("player2-is-on-redge", self.rightEdge2) self.accept("player1-is-on-lwall", self.leftWall) self.accept("player2-is-on-lwall", self.leftWall2) self.accept("player1-is-on-rwall", self.rightWall) self.accept("player2-is-on-rwall", self.rightWall2) self.accept("player1-left-ledge", self.leftOK) self.accept("player2-left-ledge", self.leftOK2) self.accept("player1-left-redge", self.rightOK) self.accept("player2-left-redge", self.rightOK2) self.accept("player1-left-lwall", self.leftOK) self.accept("player2-left-lwall", self.leftOK2) self.accept("player1-left-rwall", self.rightOK) self.accept("player2-left-rwall", self.rightOK2) print "end setupCollisions" def boulderTask(self,task): drop1 = ProjectileInterval(self.boulder1, startPos = Point3(46+random.randint(-9,9)*9.8,0,self.h), startVel = Point3(0,0,0), endZ = -50) drop2 = ProjectileInterval(self.boulder2, startPos = Point3(253+random.randint(-9,9)*9.8,0,self.h),startVel = Point3(0,0,0), endZ = -50) dropBoth = Parallel(drop1,drop2) if self.boulder1.getZ() <= -50.0: drop1.start() if self.boulder2.getZ() <= -50.0: drop2.start() return task.cont def clockTask(self,task): self.timer.detachNode() self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0) self.timer.setColor(1,1,1) self.timer.reparentTo(render) return Task.cont def endGame(self,task): taskMgr.removeTasksMatching('cameraFollowTask') taskMgr.removeTasksMatching('boulderTask') taskMgr.removeTasksMatching('clockTask') #base.camList[3].removeNode() #base.camList[2].removeNode() #base.camList[1].removeNode() base.makeCamera(base.win, displayRegion = (0, 1, 0, 1)) self.music.stop() #self.destroy() self.music3 = loader.loadMusic("models/gamedev/CSTAR.mp3") self.music3.play() def getScores(self): return (self.player1Score, self.player2Score) def getGameLen(self): return self.gameLen def stopMusic(self): self.music3.stop() def destroy(self): self.playerModel.detachNode() self.playerModel2.detachNode() self.divider.detachNode() self.background.destroy() self.timer.destroy() while len(self.array) > 0: print len(self.array) self.array[0].remove() del self.array[0] #world = World() #run()
class CharGen(DirectObject): def __init__(self, common): self.common = common self.common['chargen'] = self self.load() def load(self): self.newGame = True self.font = loader.loadFont('Bitter-Bold.otf') self.common['font'] = self.font self.common['pc_stat1'] = 50 self.common['pc_stat2'] = 50 self.common['pc_stat3'] = 50 #render.setShaderAuto() #base.disableMouse() #render.setAntialias(AntialiasAttrib.MMultisample) #base.setBackgroundColor(0, 0, 0) wp = base.win.getProperties() winX = wp.getXSize() winY = wp.getYSize() self.campmap = loader.loadModel("models/camp3") self.campmap.reparentTo(render) #music self.common['music'] = MusicPlayer(self.common) self.common['music'].loop(0) #self.common['music']=base.loadMusic("music/LuridDeliusion.ogg") #self.common['music'].setLoop(True) #self.common['music'].play() self.common["random-objects-freq"] = 0.65 self.node = render.attachNewNode("node") self.cameraNode = self.node.attachNewNode("cameraNode") self.cameraNode.setZ(-1) base.camera.setY(-8) base.camera.setZ(5) base.camera.lookAt((0, 3, 0)) base.camera.wrtReparentTo(self.cameraNode) self.pointer = self.cameraNode.attachNewNode("pointerNode") #light self.pLight = PointLight('plight') self.pLight.setColor(VBase4(1, .95, .9, 1)) self.pLight.setAttenuation(Point3(.5, 0, 0.1)) self.pLightNode = self.node.attachNewNode(self.pLight) self.pLightNode.setZ(1.0) render.setLight(self.pLightNode) self.sLight = Spotlight('sLight') self.sLight.setColor(VBase4(.4, .25, .25, 1)) if self.common['extra_ambient']: self.sLight.setColor(VBase4(.7, .5, .5, 1)) spot_lens = PerspectiveLens() spot_lens.setFov(40) self.sLight.setLens(spot_lens) self.Ambient = self.cameraNode.attachNewNode(self.sLight) self.Ambient.setPos(base.camera.getPos(render)) self.Ambient.lookAt((0, 3, 0)) render.setLight(self.Ambient) self.fire_node = self.node.attachNewNode("fireNode") self.fire = vfx(self.fire_node, texture='vfx/big_fire3.png', scale=.29, Z=.5, depthTest=True, depthWrite=True) self.fire.show() self.fire.loop(0.02) self.character1 = Actor( "models/pc/male", { "attack": "models/pc/male_attack2", "idle": "models/pc/male_ready2", "block": "models/pc/male_block" }) self.character1.reparentTo(self.node) self.character1.setBlend(frameBlend=True) self.character1.setPos(1, 2, 0) self.character1.setScale(.025) self.character1.setH(-25.0) self.character1.setBin("opaque", 10) self.character1.loop("idle") self.swingSound = base.loader.loadSfx("sfx/swing2.ogg") coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(1, 2, 1, 1)) coll_sphere.setTag("class", "1") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) self.character2 = Actor("models/pc/female", { "attack": "models/pc/female_attack1", "idle": "models/pc/female_idle" }) #self.character2.setPlayRate(.4, "attack") self.character2.reparentTo(self.node) self.character2.setBlend(frameBlend=True) self.character2.setPos(-1, 2, 0) self.character2.setScale(.026) self.character2.setH(25.0) #self.character2.setBin("opaque", 10) self.character2.loop("idle") self.char2_magic = loader.loadModel('vfx/vfx3') self.char2_magic.setPos(self.character2.getPos()) self.char2_magic.setH(self.character2.getH()) self.char2_magic.setP(-10.0) self.char2_magic.setZ(0.71) self.char2_magic.setScale(1, 2, 1) self.char2_magic.wrtReparentTo(self.character2) self.char2_magic.setY(-10) self.char2_magic.setDepthWrite(False) self.char2_magic.setDepthTest(False) self.char2_magic.setLightOff() self.char2_magic.hide() self.vfxU = -0.125 self.vfxV = 0 self.magicSound = base.loader.loadSfx("sfx/thunder3.ogg") coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(-1, 2, 1, 1)) coll_sphere.setTag("class", "2") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) self.character3 = Actor( "models/pc/female2", { "attack": "models/pc/female2_arm", "reset": "models/pc/female2_fire", "idle": "models/pc/female2_idle" }) #self.character2.setPlayRate(.4, "attack") self.character3.reparentTo(self.node) self.character3.setBlend(frameBlend=True) self.character3.setPos(-1.8, 0.9, 0) self.character3.setScale(.026) self.character3.setH(40.0) #self.character2.setBin("opaque", 10) self.character3.loop("idle") coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(-1.8, 0.9, 0, 1)) coll_sphere.setTag("class", "3") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) self.arrow_bone = self.character3.exposeJoint(None, 'modelRoot', 'arrow_bone') self.arrow = loader.loadModel('models/arrow') self.arrow.reparentTo(self.arrow_bone) self.arrow.setP(-45) self.movingArrow = None self.arrowTime = 0.0 self.drawSound = base.loader.loadSfx("sfx/draw_bow2.ogg") self.fireSound = base.loader.loadSfx("sfx/fire_arrow3.ogg") self.character4 = Actor("models/pc/male2", { "attack": "models/pc/male2_aura", "idle": "models/pc/male2_idle" }) #self.character2.setPlayRate(.4, "attack") self.character4.reparentTo(self.node) self.character4.setBlend(frameBlend=True) self.character4.setPos(1.8, 0.9, 0) self.character4.setScale(.024) self.character4.setH(-60.0) #self.character2.setBin("opaque", 10) self.character4.loop("idle") self.FFSound = base.loader.loadSfx("sfx/teleport.ogg") #self.FFSound = base.loader.loadSfx("sfx/walk_new3.ogg") coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(1.8, 0.9, 0, 1)) coll_sphere.setTag("class", "4") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) #gui self.mp_logo = DirectFrame(frameSize=(-512, 0, 0, 128), frameColor=(1, 1, 1, 1), frameTexture='images/mp_logo.png', state=DGG.NORMAL, parent=pixel2d) self.mp_logo.setPos(256 + winX / 2, 0, -winY) self.mp_logo.setBin('fixed', 1) self.mp_logo.hide() self.mp_logo.setTransparency(TransparencyAttrib.MDual) self.mp_logo.bind(DGG.B1PRESS, self.open_www, ['http://www.matthewpablo.com/']) #self.mp_logo.bind(DGG.WITHIN, self.GUIOnEnter, ["MP"]) #self.mp_logo.bind(DGG.WITHOUT, self.GUIOnExit) self.title = DirectFrame(frameSize=(-512, 0, 0, 128), frameColor=(1, 1, 1, 1), frameTexture='images/select.png', parent=pixel2d) self.title.setPos(256 + winX / 2, 0, -128) self.title.setBin('fixed', 1) self.title.setTransparency(TransparencyAttrib.MDual) #self.title.hide() self.close = DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/close.png', state=DGG.NORMAL, parent=pixel2d) self.close.setPos(winX, 0, -32) self.close.setBin('fixed', 1) self.close.bind(DGG.B1PRESS, self.exit) self.new_game_button = DirectButton( frameSize=(-0.2, 0.2, 0, 0.08), frameColor=(1, 1, 1, 1), frameTexture='images/level_select.png', text_font=self.font, text='START NEW GAME', text_pos=(-0.16, 0.026, 0), text_scale=0.035, text_fg=(0, 0, 0, 1), text_align=TextNode.ALeft, textMayChange=1, state=DGG.FLAT, relief=DGG.FLAT, pos=(0, 0, 0.5), command=self.onStart, parent=aspect2d) self.new_game_button.setBin('fixed', 1) self.new_game_button.hide() self.continue_button = DirectButton( frameSize=(-0.2, 0.2, 0, 0.08), frameColor=(1, 1, 1, 1), frameTexture='images/level_select.png', text_font=self.font, text='CONTINUE GAME', text_pos=(-0.16, 0.026, 0), text_scale=0.035, text_fg=(0, 0, 0, 1), text_align=TextNode.ALeft, textMayChange=1, state=DGG.FLAT, relief=DGG.FLAT, pos=(0, 0, 0.4), command=self.loadAndStart, parent=aspect2d) self.continue_button.setBin('fixed', 1) self.continue_button.hide() self.cursor = DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/cursor1.png', parent=pixel2d) self.cursor.setPos(32, 0, -32) self.cursor.flattenLight() self.cursor.setBin('fixed', 10) self.cursor.setTransparency(TransparencyAttrib.MDual) self.frameDesc = DirectFrame(frameSize=(0, 1, 0, 0.3), frameColor=(1, 1, 1, 1), frameTexture='images/frame1.png', state=DGG.NORMAL, pos=(-0.5, 0, 0.6), parent=aspect2d) self.labelDesc = DirectLabel( text="", text_fg=(1, 1, 1, 1), frameColor=(0, 0, 0, 0), #text_font=self.font, text_scale=0.06, text_align=TextNode.ALeft, pos=(0.1, 0, 0.2), parent=self.frameDesc) self.frameDesc.setBin('fixed', 1) self.frameDesc.hide() self.frameDesc.bind(DGG.WITHIN, self.GUIOnEnter, ["3B"]) self.frameDesc.bind(DGG.WITHOUT, self.GUIOnExit) #tooltip #self.font.setPixelsPerUnit(16) #self.font.setMinfilter(Texture.FTNearest ) #self.font.setMagfilter(Texture.FTNearest ) #self.font.setAnisotropicDegree(4) #self.font.setNativeAntialias(False) #self.font.setPageSize(1024,1024) self.Tooltip = DirectLabel( frameColor=(0, 0, 0, 0), text_font=self.font, text= 'Lorem ipsum dolor sit amet,\n consectetur adipisicing elit,\n sed do eiusmod tempor incididunt \nut labore et dolore magna aliqua.', #pos = (0, 0,-35), text_scale=16, text_fg=(1, 1, 1, 1), text_align=TextNode.ALeft, textMayChange=1, parent=pixel2d) self.Tooltip.flattenLight() self.Tooltip.setBin('fixed', 300) self.Tooltip.hide() #collisions #self.traverser=CollisionTraverser("playerTrav") #self.traverser.setRespectPrevTransform(True) #self.queue = CollisionHandlerQueue() self.MousePickerNode = CollisionNode('mouseRay') self.pickerNP = base.camera.attachNewNode(self.MousePickerNode) self.MousePickerNode.setFromCollideMask(BitMask32.bit(1)) self.MousePickerNode.setIntoCollideMask(BitMask32.allOff()) self.pickerRay = CollisionSegment() #Make our ray self.MousePickerNode.addSolid( self.pickerRay) #Add it to the collision node self.common['traverser'].addCollider(self.pickerNP, self.common['queue']) self.accept("mouse1", self.onClick) taskMgr.doMethodLater(0.2, self.flicker, 'flicker') #taskMgr.add(self.camera_spin, "camera_spin") taskMgr.add(self.__getMousePos, "chargenMousePos") self.current_class = None self.currentLevel = 0 self.camLoop = Sequence( LerpHprInterval(self.cameraNode, 10.0, VBase3(-20, 0, 0), bakeInStart=0), LerpHprInterval(self.cameraNode, 10.0, VBase3(20, 0, 0), bakeInStart=0)) self.camLoop.loop() self.accept('window-event', self.windowEventHandler) def selectLevel(self, next, event=None): self.currentLevel += next if self.currentLevel < 0: self.currentLevel = 0 if self.currentLevel > self.common['max_level']: self.currentLevel = self.common['max_level'] self.start_main['text'] = "Start in Level " + str(self.currentLevel + 1) def moveArrow(self, task): if self.movingArrow: self.arrowTime += task.time if self.arrowTime > 3.0: self.movingArrow.removeNode() self.arrowTime = 0.0 return task.done dt = globalClock.getDt() self.movingArrow.setX(self.movingArrow, 400 * dt) return task.again else: return task.done def fireArrow(self): self.movingArrow = loader.loadModel('models/arrow') self.movingArrow.reparentTo(self.arrow_bone) self.movingArrow.setP(-45) self.movingArrow.wrtReparentTo(render) self.arrow.hide() self.fireSound.play() taskMgr.add(self.moveArrow, "moveArrowTask") Sequence(Wait(0.5), Func(self.arrow.show)).start() def loadAndStart(self): self.newGame = False self.common['levelLoader'].loadGame(PCLoad=False) self.onStart() def onStart(self, event=None): #unload stuff self.camLoop.pause() self.camLoop = None base.camera.reparentTo(render) self.campmap.removeNode() self.node.removeNode() self.fire.remove_loop() if taskMgr.hasTaskNamed('flicker'): taskMgr.remove('flicker') if taskMgr.hasTaskNamed('chargenMousePos'): taskMgr.remove('chargenMousePos') self.common['traverser'].removeCollider(self.pickerNP) self.pickerNP.removeNode() self.Ambient.removeNode() self.frameDesc.destroy() self.labelDesc.destroy() self.Tooltip.destroy() self.cursor.destroy() self.new_game_button.destroy() self.continue_button.destroy() self.close.destroy() self.title.destroy() self.mp_logo.destroy() render.setLightOff() self.ignoreAll() #self.common['music'].stop() #self.common['spawner']=Spawner(self.common) #self.common['levelLoader']=LevelLoader(self.common) if not self.newGame and 'max_level' in self.common: self.currentLevel = self.common['max_level'] else: self.currentLevel = 0 self.common['levelLoader'].load(self.currentLevel, PCLoad=False) #render.ls() if self.newGame or not 'current_class' in self.common: self.common['current_class'] = self.current_class else: self.current_class = self.common['current_class'] if self.current_class == "1": self.common['PC'] = Knight(self.common) #self.common['PC'].node.setPos(-12, 0, 0) elif self.current_class == "2": self.common['PC'] = Witch(self.common) #self.common['PC'].node.setPos(-12, 0, 0) elif self.current_class == "3": self.common['PC'] = Archer(self.common) #self.common['PC'].node.setPos(-12, 0, 0) elif self.current_class == "4": self.common['PC'] = Wizard(self.common) #self.common['PC'].node.setPos(-12, 0, 0) pos = (data.levels[self.currentLevel]["enter"][0], data.levels[self.currentLevel]["enter"][1], data.levels[self.currentLevel]["enter"][2]) self.common['PC'].node.setPos(pos) self.common['music'].loop(1, fadeIn=True) if not self.newGame: self.common['levelLoader'].loadGame(PCLoad=True) def open_www(self, url, event=None): webbrowser.open_new(url) def windowEventHandler(self, window=None): #print "resize" if window is not None: # window is none if panda3d is not started wp = base.win.getProperties() X = wp.getXSize() / 2 Y = wp.getYSize() # self.frameDesc.setPos(-96+X, 0, -32) self.title.setPos(256 + X, 0, -128) self.close.setPos(X * 2, 0, -32) self.mp_logo.setPos(256 + X, 0, -Y) def GUIOnEnter(self, object, event=None): if object[0] == "4": if object[1] == "A": self.Tooltip['text'] = "Click to start!" elif object[1] == "B": self.Tooltip['text'] = "Next level" elif object[1] == "C": self.Tooltip['text'] = "Previous level" self.Tooltip['text_pos'] = (10, -40, 0) self.Tooltip['text_align'] = TextNode.ACenter self.Tooltip.show() return if not self.current_class: return #print int(self.current_class) def GUIOnExit(self, event=None): self.Tooltip.hide() #print "out" def start_lightning(self, time=0.03): taskMgr.doMethodLater(time, self.lightning, 'vfx') self.magicSound.play() def lightning(self, task): self.char2_magic.show() self.vfxU = self.vfxU + 0.5 if self.vfxU >= 1.0: self.vfxU = 0 self.vfxV = self.vfxV - 0.125 if self.vfxV <= -1: self.char2_magic.hide() self.vfxU = 0 self.vfxV = 0 return task.done self.char2_magic.setTexOffset(TextureStage.getDefault(), self.vfxU, self.vfxV) return task.again def loopAnim(self, actor, anim): actor.loop(anim) def set_slider(self, id): #self.current_class=id #print id, if id == "1": self.common['pc_stat1'] = int(self.slider1['value']) #print self.common['pc_stat1'] elif id == "2": self.common['pc_stat2'] = int(self.slider2['value']) #print self.common['pc_stat2'] elif id == "3": self.common['pc_stat3'] = int(self.slider3['value']) #print self.common['pc_stat3'] def onClick(self): self.common['traverser'].traverse(render) my_class = None for entry in self.common['queue'].getEntries(): if entry.getIntoNodePath().hasTag("class"): my_class = entry.getIntoNodePath().getTag("class") if Path("save.dat").exists(): self.continue_button.show() if my_class == "1": self.current_class = my_class self.title.hide() self.labelDesc.setText( "Knight:\nHe has greater resistance.\nHe can attack with the sword\nand defend with a shield." ) self.frameDesc.show() self.new_game_button.show() Sequence(self.character1.actorInterval("attack"), self.character1.actorInterval("block"), Func(self.loopAnim, self.character1, "idle")).start() self.swingSound.play() #self.character1.play("attack") self.character2.loop("idle") elif my_class == "2": self.current_class = my_class self.title.hide() self.labelDesc.setText( "Witch:\nShe can throw energy balls and\na long distance beam." ) self.frameDesc.show() self.new_game_button.show() Sequence(self.character2.actorInterval("attack", playRate=0.8), Func(self.loopAnim, self.character2, "idle")).start() Sequence(Wait(0.3), Func(self.start_lightning, 0.05)).start() #self.character2.play("attack") self.character1.loop("idle") #RayVfx(self.character2, texture='vfx/lightning.png').start() elif my_class == "3": self.current_class = my_class self.title.hide() self.labelDesc.setText( "Archer:\nShe can throw arrows\nand run faster.") self.frameDesc.show() self.new_game_button.show() self.drawSound.play() self.character3.play("attack") Sequence(Wait(1.5), Func(self.fireArrow), Func(self.character3.play, "reset"), Wait(1.0), Func(self.loopAnim, self.character3, "idle")).start() elif my_class == "4": self.current_class = my_class self.title.hide() self.labelDesc.setText( "Wizard:\nHe can throw magma balls\nand teleport himself.") self.frameDesc.show() self.new_game_button.show() self.character4.loop("attack") aura = vfx(self.character4, texture='vfx/tele2.png', scale=.5, Z=.85, depthTest=False, depthWrite=False) aura.show() aura.start() self.FFSound.play() Sequence(Wait(2.2), Func(self.loopAnim, self.character4, "idle")).start() def exit(self, event=None): self.common['root'].save_and_exit() #sys.exit() def __getMousePos(self, task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) pos2d = Point3(mpos.getX(), 0, mpos.getY()) self.cursor.setPos(pixel2d.getRelativePoint(render2d, pos2d)) self.Tooltip.setPos(self.cursor.getPos()) return task.again def flicker(self, task): self.pLight.setAttenuation(Point3(1, 0, random.uniform(.1, 0.15))) self.pLightNode.setZ(random.uniform(.9, 1.1)) #self.pLight.setColor(VBase4(random.uniform(.9, 1.0), random.uniform(.9, 1.0), .9, 1)) return task.again def camera_spin(self, task): H = self.cameraNode.getH() #Z=self.cameraNode.getZ() #print H if H <= -20.0 or H >= 20.0: if self.reverse_spin: self.reverse_spin = False else: self.reverse_spin = True if self.reverse_spin: self.cameraNode.setH(self.cameraNode, 4 * globalClock.getDt()) #self.cameraNode.setZ(Z+0.1*globalClock.getDt()) else: self.cameraNode.setH(self.cameraNode, -4 * globalClock.getDt()) #self.cameraNode.setZ(Z-0.1*globalClock.getDt()) return task.again
class LookingGrippingDemo(ShowBase): def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Panda3D: Tutorial - Joint Manipulation", fg=(1, 1, 1, 1), parent=base.a2dBottomRight, align=TextNode.ARight, pos=(-0.1, 0.1), shadow=(0, 0, 0, .5), scale=.08) self.onekeyText = genLabelText("ESC: Quit", 1) self.onekeyText = genLabelText("[1]: Teapot", 2) self.twokeyText = genLabelText("[2]: Candy cane", 3) self.threekeyText = genLabelText("[3]: Banana", 4) self.fourkeyText = genLabelText("[4]: Sword", 5) # Set up key input self.accept('escape', sys.exit) self.accept('1', self.switchObject, [0]) self.accept('2', self.switchObject, [1]) self.accept('3', self.switchObject, [2]) self.accept('4', self.switchObject, [3]) base.disableMouse() # Disable mouse-based camera-control camera.setPos(0, -15, 2) # Position the camera self.eve = Actor("models/eve", # Load our animated charachter {'walk': "models/eve_walk"}) self.eve.reparentTo(render) # Put it in the scene # Now we use controlJoint to get a NodePath that's in control of her neck # This must be done before any animations are played self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck') # We now play an animation. An animation must be played, or at least posed # for the nodepath we just got from controlJoint to actually effect the # model self.eve.actorInterval("walk", playRate=2).loop() # Now we add a task that will take care of turning the head taskMgr.add(self.turnHead, "turnHead") # Now we will expose the joint the hand joint. ExposeJoint allows us to # get the position of a joint while it is animating. This is different than # controlJonit which stops that joint from animating but lets us move it. # This is particularly usefull for putting an object (like a weapon) in an # actor's hand self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand') # This is a table with models, positions, rotations, and scales of objects to # be attached to our exposed joint. These are stock models and so they needed # to be repositioned to look right. positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4), ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1), ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75), ("models/sword", (.11, .19, .06), (0, 0, 90), 1)] self.models = [] # A list that will store our models objects for row in positions: np = loader.loadModel(row[0]) # Load the model np.setPos(row[1][0], row[1][1], row[1][2]) # Position it np.setHpr(row[2][0], row[2][1], row[2][2]) # Rotate it np.setScale(row[3]) # Scale it # Reparent the model to the exposed joint. That way when the joint moves, # the model we just loaded will move with it. np.reparentTo(self.rightHand) self.models.append(np) # Add it to our models list self.switchObject(0) # Make object 0 the first shown self.setupLights() # Put in some default lighting # This is what we use to change which object it being held. It just hides all of # the objects and then unhides the one that was selected def switchObject(self, i): for np in self.models: np.hide() self.models[i].show() # This task gets the position of mouse each frame, and rotates the neck based # on it. def turnHead(self, task): # Check to make sure the mouse is readable if base.mouseWatcherNode.hasMouse(): # get the mouse position as a LVector2. The values for each axis are from -1 to # 1. The top-left is (-1,-1), the bottom right is (1,1) mpos = base.mouseWatcherNode.getMouse() # Here we multiply the values to get the amount of degrees to turn # Restrain is used to make sure the values returned by getMouse are in the # valid range. If this particular model were to turn more than this, # significant tearing would be visable self.eveNeck.setP(clamp(mpos.getX()) * 50) self.eveNeck.setH(clamp(mpos.getY()) * 20) return Task.cont # Task continues infinitely def setupLights(self): # Sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 8, -2.5)) directionalLight.setColor((0.9, 0.8, 0.9, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class application( ShowBase ): # begin of '__init__' member function # this sets it all up for the scene def __init__( self ): # fog and background colors self.mRed = 0.2 self.mGreen = 0.2 self.mBlue = 0.2 # the fog density 0 = none & 1 = full self.mDen = .01 # setup the fog for the scene self.fogSetup( ) # setup the background color for the scene self.backgroundSetup( ) # setup the camera for the scene self.cameraSetup( ) # setup the needed models for the scene self.loadModels( ) # setup the needed light for the scene self.setupLights( ) # setup the needed intervals for the scene self.setupIntervals( ) # setup the needed states self.setupStates( ) # setup the key events needed for the scene self.keyBoardSetup( ) # begin collision code # here we create the collision traverser base.cTrav = CollisionTraverser() # here we create the event collision handler self.collHandEvent = CollisionHandlerEvent() # now we add an 'in' pattern # this consists of a string of an 'into' object self.collHandEvent.addInPattern('into-%in') # now we add an 'in' again pattern self.collHandEvent.addAgainPattern('again-%in') # now we add an 'out' pattern # this consists of a string of an outof with an into object self.collHandEvent.addOutPattern('outof-%in') # set this variable to zero for start # this aids in naming are collision nodes self.collCount = 0 # add a collision sphere around tiny # tiny is a 'from' object self.tinyColl = self.initCollisionSphere( self.tiny ) # add this collision sphere to the colllision traverser base.cTrav.addCollider( self.tinyColl[0], self.collHandEvent ) # create 4 planes used for collision solids # each point in the z up position from their respective local # space not the world space self.planes = [ Plane( Vec3( 0, 0, 1 ), Point3( 0, 0, 0 ) ), Plane( Vec3( 0, 0, 1 ), Point3( 0, 0, 0 ) ), Plane( Vec3( 0, 0, 1 ), Point3( 0, 0, 0 ) ), Plane( Vec3( 0, 0, 1 ), Point3( 0, 0, 0 ) ) ] # create four infinite collision planes in front of the wall models # each uses the corresponding planes up above self.wallColl = [ self.initCollisionPlane( self.walls[0], self.planes[0] ), self.initCollisionPlane( self.walls[1], self.planes[1] ), self.initCollisionPlane( self.walls[2], self.planes[2] ), self.initCollisionPlane( self.walls[3], self.planes[3] ) ] # set up the events needed for the messenger # each passes the second element in the tuple in the list # also passes the needed functions for each into, again, and outof event self.accept( 'into-' + self.wallColl[0][2], self.colliding) self.accept( 'again-' + self.wallColl[0][2], self.colliding) self.accept( 'outof-' + self.wallColl[0][2], self.notColliding) # self.accept( 'into-' + self.wallColl[1][2], self.colliding) self.accept( 'again-' + self.wallColl[1][2], self.colliding) self.accept( 'outof-' + self.wallColl[1][2], self.notColliding) # self.accept( 'into-' + self.wallColl[2][2], self.colliding) self.accept( 'again-' + self.wallColl[2][2], self.colliding) self.accept( 'outof-' + self.wallColl[2][2], self.notColliding) # self.accept( 'into-' + self.wallColl[3][2], self.colliding) self.accept( 'again-' + self.wallColl[3][2], self.colliding) self.accept( 'outof-' + self.wallColl[3][2], self.notColliding) ShowBase.__init__(self) #self.props = WindowProperties() #self.props.setSize(1024,768) # end __init__ # begin the colliding member function # this function is called when a 'from' object collides with an 'into' object def colliding( self, collEntry ): # accept a collision entry argument self.isColliding = 1 # we are colliding self.pauseWalk( ) # pause all walking animation and movement # here we calculate the displacement of how far the collision entry is in # in other words we are finding out how far the tiny collision sphere # is into the wall collision plane disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) ) # ok we now know how much tiny is into the wall # so we add this number to tiny's current position # making tiny sit right in front of the wall and not into it newPos = self.tiny.getPos( ) + disp # get new position self.tiny.setPos( newPos ) # and set it to tiny's position # end colliding # begin the notColliding member function # this function is called when tiny is no longer colliding with the wall def notColliding( self, collEntry ): # accept a collision entry argument self.isColliding = 0 # not colliding any more # end notColliding # begin the initCollisionSphere member function # this function creates a sphere used for collision # around the object passed to it as a argument def initCollisionSphere( self, obj, show = False ): # accept an object and a defaulted to false # show variable as an argument bounds = obj.getChild( 0 ).getBounds( ) # get the boundries of the passed object center = bounds.getCenter( ) # get the center of these boundries radius = bounds.getRadius( ) # get the radius of these boundries # here we construct a string based on the current collision count and the object name collSphereStr = 'CollisionHull' + str( self.collCount ) + "_" + obj.getName( ) # increase the collision count to one more for the next call of this function self.collCount += 1 # create a collision node with a the name or string created above cNode=CollisionNode( collSphereStr ) # add a solid to this newly created node # we pass it a collision sphere with the center and radius of the boundries of the passed object cNode.addSolid( CollisionSphere( center, radius ) ) # now we attach this collision node to the object node we were passed cNodepath = obj.attachNewNode(cNode) # here we save the collision node path for easy reference if show: # if show is true cNodepath.show() # render or show the collision node # now we return a tuple that contains the collision node and it's label return ( cNodepath, cNode, collSphereStr ) # end initCollisionSphere # begin the initCollisionPlane member function # this code creates a collision plane in front of the object passed to it def initCollisionPlane( self, obj, plane, show=False ): # accept an object, plane, and a defaulted # to false show variable as an argument # here we construct a string based on the current collision count and the object name collPlaneStr = 'CollisionPlane' + str( self.collCount ) + "_" + obj.getName( ) # increase the collision count for the next call self.collCount += 1 # here we create a collision node and assign the string or name to the node cNode = CollisionNode( collPlaneStr ) # here we a add a solid or geometry to the node # we pass the collision plane function the plane we were passed cNode.addSolid( CollisionPlane( plane ) ) # now we attach the newly created collision node the the object node we were passed cNodepath = obj.attachNewNode( cNode ) # here we save the collison node path for easy reference if show: # if show equals true cNodepath.show( ) # show the collision geometry or render it to screen # here we return a tuple which contains the collision node and it's label return ( cNodepath, cNode, collPlaneStr ) # end initCollisionPlane # begin the fogSetup member function # this function creates the fog, sets its color, density and makes it affect # all in the scene def fogSetup( self ): self.mFog = Fog( "fog" ) # create self.mFog.setColor( self.mRed, self.mGreen, self.mBlue ) # set color self.mFog.setExpDensity( self.mDen ) #set density render.setFog( self.mFog ) # set to affect all in scene graph # end fogSetup # begin backgroundSetup member function # this sets the color to match that of the fog def backgroundSetup( self ): base.setBackgroundColor( self.mRed, self.mGreen, self.mBlue ) # set the color # end backgroundSetup # begin the cameraSetup member function def cameraSetup( self ): base.disableMouse( ) # disable the default camera controls that are created for us # set the position (x, y, and z), heading (cardinal direction), pitch (tilt foward backward), roll (rotation left or right) # here we set it a hundred units back from center on the y axis and 30 units up the z axis # then we pitch (tilt) the camera foward 15 units in degree camera.setPosHpr( Vec3( 0, -100, 30 ), Vec3( 0, -15, 0 ) ) # ok now tell the task manager to add our camera following task taskMgr.add( self.cameraFollowTask, 'cameraFollowTask', sort=30 ) # end cameraSetup # begin the loadModels member function # here we load all the models needed for our scene def loadModels( self ): # load the tiny actor # we use actor instead of model because we need to use animations self.tiny = Actor( "models/tiny", { "walk" : "models/tiny" } ) # dictionary that defines the walk animation self.tiny.reparentTo( render ) # parent 'tiny' to the renderer self.tiny.setH( -180 ) # here we change it's heading to face away from the camera # a hundred and eighty degrees # remember this later # now we scale tiny down a lot for it is a big mesh self.tiny.setScale( .1 ) # number achieved through trial and error # now we load the floor for tiny to walk on self.floor = loader.loadModel( "models/floor" ) # load static model (no animations) self.floor.reparentTo( render ) # parent to renderer self.floor.setScale( 5 ) # scale it up to match with tiny self.floor.setPos( 0, 0, -26 ) # set it's position down 26 units on the z axis # now we create the foor walls we need for tiny to walk into # this is a list similiar to an array in other languages self.walls = [ loader.loadModel( "models/wall" ), loader.loadModel( "models/wall" ), loader.loadModel( "models/wall" ), loader.loadModel( "models/wall" ) ] # ok now we parent to renderer, scale, and position self.walls[0].reparentTo( render ) # parent to renderer self.walls[0].setScale( 9 ) # scale up to match with others self.walls[0].setPos( 0, 900, 64 ) # 90 units y axis (into scene) self.walls[0].setP( 90 ) # pitch it up 90 degrees otherwise it would be laying down # self.walls[1].reparentTo( render ) # same self.walls[1].setScale( 9 ) # same self.walls[1].setPos( 900, 0, 64 ) # now we position 90 units along the positive x axis # and 64 units up the positive z axis self.walls[1].setH( -90 ) # then we turn it to face us from the left self.walls[1].setP( 90 ) # same # self.walls[2].reparentTo( render ) # same self.walls[2].setScale( 9 ) # same self.walls[2].setPos( 0, -900, 64 ) # the same but put it in the back of us down the # the negative y axis self.walls[2].setH( 0 ) # turn it around to face the back of us self.walls[2].setP( -90 ) # same # self.walls[3].reparentTo( render ) # same self.walls[3].setScale( 9 ) # same self.walls[3].setPos( -900, 0, 64 ) # down neg x axis 90 units same for z axis self.walls[3].setH( 90 ) # make it face us from the right self.walls[3].setP( 90 ) # same # ok four walls are up lets move on #end loadModels # begin the setupLights member function # this function creates a signle point light for our scene def setupLights( self ): # create a point light plight = PointLight('plight') # set its color plight.setColor(VBase4( 0.2, 0.2, 0.2, 1 ) ) # attach it to the render as a new node # 'upcast' to a node otherwise Panda will crash # heard this will change in version 1.1.? plnp = render.attachNewNode( plight ) # set the position of the node plnp.setPos( 0, 0, 0 ) # set the light or 'turn' it on render.setLight( plnp ) # the following code makes the 'shadows' less black or dark # same as above but we create a ambient light that affects all faces alight = AmbientLight( 'alight' ) # light alight.setColor( VBase4( 0.2, 0.2, 0.2, 1 ) ) # color alnp = render.attachNewNode( alight ) # attach render.setLight( alnp ) # turn on # end setupLights # begin the setupIntervals member function # this function setups up the needed intervals for the scene def setupIntervals( self ): # create a actor interval that calls the member function walk # to handle the grunt work self.tinyWalk = self.tiny.actorInterval( "walk" ) # loop then pause to create a more fluid animation start and stop # later on (thanks russ) self.tinyWalk.loop( ) self.tinyWalk.pause( ) # end setupIntervals #begin the setupStates member function # this creates and sets the states for the scene def setupStates( self ): self.tinyWalking = 0 # is tiny walking, no self.turning = 0 # is tiny turning, no self.isColliding = 0 # is tiny colliding, no # end setupStates # begin the walk member function # this function is called in an actor interval each frame def walk( self ): if self.tinyWalking == 0: # if tiny is not walking taskMgr.add( self.walkTask,'walkTask' ) # add the walk task look below if self.turning == 0: # if tiny is not turning self.tinyWalk.resume( ) # pick up where we last left off in # in the walk animation self.tinyWalking = 1 # flag that tiny is walking now # begin the walkTask member function # this function is called each frame by the task manager def walkTask( self, task ): # accept a task as an argument # ok now for some math particulary trigonometry dist = 1.0 # the hypotenuse defined by r = sqrt( a^2 + b^2 ) # here we get the current heading of tiny and convert that degree measurement # to radians because the math.sin/cos function needs it to be radians angle = self.tiny.getH( ) * math.pi / 180.0 # convert degrees to radians correction = math.pi / 2 # ninety degrees in radians # this is needed for the cofunction formulas # in trigonometry x is defined as x = r * cos( angle ) # y is defined as y = r * sin( angle ) # remember that tiny was turned 180 degrees? And would now be facing # 270 degrees (3pi/2 for radians) on the unit circle # so we need to use the cofuntion formulas defined as: # sin(pi/2 - angle) = cos(angle) # cos(pi/2 - angle) = sin(angle) # now knowing these we substitute # x = r * sin( angle ) # y = r * cos( angle) # however I left it un-substituted for clearity dx = dist * math.cos( correction - angle ) # one more thing, because we want tiny to walk into the scene we # make it negative to walk into the scene # remove the negative and she walks backwards # remember this if you want to make your avatar walk backwards dy = dist * -math.sin( correction - angle ) # now that we know x and y we just add it to the current values since last frame self.tiny.setPos( Vec3( self.tiny.getX( ) + dx, self.tiny.getY( ) + dy, 0 ) ) # on a side note, if you had trouble with the math I recommend # "Trigonometry the Easy Way" third edition by Douglas Downing # easy read and you should be up and running with trig in no time # and we continue on to the next frame return Task.cont # end walkTask # begin the pauseWalk member function # this function stops tiny from walking any further def pauseWalk( self ): if self.tinyWalking == 1: # if tiny is walking taskMgr.remove( 'walkTask' ) # remove the walk task now tiny stops moving if self.turning == 0: # if tiny is not turning self.tinyWalk.pause( ) # now walking animation stops self.tinyWalking = 0 # set flag to not walking # accept only once to listen for the up arrow pressed # if it is call the walk member function self.acceptOnce( "arrow_up", self.walk ) # end pauseWalk # begin the turn member function # this function sets up the turn task and walk animation def turn( self, dir ): # accept a direction as an argument if self.turning == 0: # if tiny is not turning # add the turn task and pass the direction to the # turnTask member function taskMgr.add( self.turnTask, 'turnTask', extraArgs = [ dir ] ) # tiny is now turning self.turning = 1 if self.tinyWalking == 0: # if tiny is not walking # we check this because we # don't want to loop it because # it's already looping by the walk function self.tinyWalk.resume( ) # pick up where we left off in the animation self.ignore( "arrow_left" ) # ignore the left arrow being pressed self.ignore( "arrow_right" ) # ignore the right arrow being pressed # end turn # begin the turnTask member function # this function turns makes tiny walk in a circle if tiny isn't # already walking or colliding in a wall def turnTask( self, dir ): # accept direction (+/-) as an argument speed = 50.0 # degrees/s # here we get the time since the beginning of the application # not sure about this however dt = globalClock.getDt( ) # here we create the angle of rotation based on the direction, # speed or rate, and time angle = dir * speed * dt # now we subtract this angle from tiny's current heading or angle self.tiny.setH( self.tiny.getH( ) - angle ) if self.tinyWalking == 0: # if tiny is not already walking # below allows us to make tiny walk # in a circle instead of turning # in place # however we don't want to do this if # tiny is colliding with a wall # because then tiny could penetrate the # wall which we don't want # and we don't want to do this if tiny's # position is already being updated by # walkTask if self.isColliding == 0: # if tiny is not colliding # the following is the same math as before # please see 'walkTask' for details dist = .0 angle = self.tiny.getH( ) * math.pi / 180.0 correction = math.pi / 2 dx = dist * math.cos( correction - angle ) dy = dist * -math.sin( correction - angle ) self.tiny.setPos( Vec3( self.tiny.getX( ) + dx, self.tiny.getY( ) + dy, 0 ) ) # continue on to next frame return Task.cont # end turnTask # begin the turnPause member function # this function stops tiny from turning in place or in a circle def turnPause( self ): if self.turning == 1: # if tiny is turning taskMgr.remove( 'turnTask' ) # remove task self.turning = 0 # set flag, not turning if self.tinyWalking == 0: # if tiny is not already walking self.tinyWalk.pause( ) # pause the walk animation # accept only once the left and right arrow buttons corresponding # to each direction respecitively self.acceptOnce( "arrow_left", self.turn, [ -1 ] ) self.acceptOnce( "arrow_right", self.turn, [ 1 ] ) # begin the cameraFollowTask member function # this function creates a third person view of the avatar at all times def cameraFollowTask( self, task ): print self.getSize() print self.winList #if base.mouseWatcherNode.hasMouse() and self.props.hasSize(): # x=(base.mouseWatcherNode.getMouseX() - (self.props.getXSize()/2)) * 0.05 # y=(base.mouseWatcherNode.getMouseY() - (self.props.getYSize()/2)) * 0.05 # cx = getpointerx - halfwindowsize * 0.05 # cy = getpointery - halfwindowsize * 0.05 # camera.setHpr(x, y, 0) # window.movepointer(0,0) return Task.cont speed = 100.0 # the speed at which the camera reaches its # desired position offset = Vec3( 0, 0, 40 ) # the offset between the camera and tiny dt = globalClock.getDt( ) # time since beginning of application currPos = camera.getPos( ) # current position of camera # this calculates the desired position that camera should be at # there we get the current position of tiny and add that to the # x axis Quaternion rotation passing the desired offset # thus if tiny is able to face the camera, the camera will rotate to the # back of tiny # Quat is short for "Quaternion." This is a mathematical concept that # allows rotations on an arbitrary axis avoiding what is called "gimbal # lock." desiredPos = self.tiny.getPos( ) + self.tiny.getQuat( ).xform( offset ) # now that we have the desired position vector we create a new direction vector # by subtracting the current position from the desired position # for example say our desired position is Vec3( 0, -100, 0) and we are at # Vec3(0, -20, 0) so we need to move in a foward direction down the # negative y axis eighty units direction = Vec3( desiredPos - currPos ) if ( direction.length( ) > speed * dt ): # if the direction's length # is greater than the speed # times the time direction.normalize( ) # here we normalize the vector # which means we get a unit vector (magnitude of 1) # in the same direction as before normalization # here we update the camera's position (getting ever closer to the desired position) # by getting the current pos + the normlized (magnitude or length of 1 in the same direction) # * the speed or rate at which the camera catches up * the time camera.setPos( camera.getPos( ) + direction * speed * dt ) else: # the directions length is less than speed * the time # we do this because the length is so close to the desired position # that if we just updated the camera's position like in the conditional # statement above then we would over shoot the desired position # come next frame of rendering which we do not want camera.setPos( desiredPos ) # set to desired position because we are so close to it camera.setHpr( 90., 0., 0. ) # always be 'looking' at the model tiny # continue this task on to next frame return Task.cont # end cameraFollowTask # begin the keyBoardSetup member function # this function sets up the keys we need to control tiny # and application it self def keyBoardSetup( self ): # set escape key to exit the application self.accept( "escape", sys.exit ) # set the up arrow key to call the walk member function self.acceptOnce( "arrow_up", self.walk ) # set the left arrow key to call the turn member function with a left direction self.acceptOnce( "arrow_left", self.turn, [ -1 ] ) # set the right arrow key to call the turn member function with a right direction self.acceptOnce( "arrow_right", self.turn, [ 1 ] ) # when the player lets up on the arrow keys call their respective pause functions self.accept( "arrow_up-up", self.pauseWalk ) self.accept( "arrow_left-up", self.turnPause ) self.accept( "arrow_right-up", self.turnPause )
class ControllerPepper(ShowBase): def __init__(self, scene, size=(960, 720), zNear=0.1, zFar=1000.0, fov=40.0, shadowing=False, showPosition=False, cameraTransform=None, cameraMask=None, take_num=None): ShowBase.__init__(self) self.__dict__.update(scene=scene, size=size, fov=fov, zNear=zNear, zFar=zFar, shadowing=shadowing, showPosition=showPosition, cameraTransform=cameraTransform, cameraMask=cameraMask) # Find agent and reparent camera to it self.agent = self.scene.scene.find('**/agents/agent*/+BulletRigidBodyNode') self.camera.reparentTo(self.agent) if self.cameraTransform is not None: self.camera.setTransform(cameraTransform) if cameraMask is not None: self.cam.node().setCameraMask(self.cameraMask) lens = self.cam.node().getLens() lens.setFov(self.fov) lens.setNear(self.zNear) lens.setFar(self.zFar) # Change window size wp = WindowProperties() wp.setSize(size[0], size[1]) wp.setTitle("Pepper") wp.setCursorHidden(True) self.win.requestProperties(wp) self.disableMouse() self.time = 0 self.centX = wp.getXSize() / 2 self.centY = wp.getYSize() / 2 self.win.movePointer(0, int(self.centX), int(self.centY)) # key controls self.forward = False self.backward = False self.fast = 1.2 self.left = False self.right = False self.rotateXl = False self.rotateXr = False self.rotateYu = False self.rotateYd = False self.ss = False self.cv = False self.openpose = False self.visible_human = True # sensitivity settings self.sensTranslate = 3 self.sensTranslateFast = self.sensTranslate * 5 self.sensRotate = 0.005 # Reparent the scene to render. self.scene.scene.reparentTo(self.render) self.render.setAntialias(AntialiasAttrib.MAuto) self.take_num = take_num # Task self.globalClock = ClockObject.getGlobalClock() self.taskMgr.add(self.update, 'pepper-update') self._addDefaultLighting() self._setupEvents() self.drawHuman() def _addDefaultLighting(self): alight = AmbientLight('alight') alight.setColor(VBase4(0.2, 0.2, 0.2, 1)) alnp = self.render.attachNewNode(alight) self.render.setLight(alnp) # NOTE: Point light following the camera plight = PointLight('plight') plight.setColor(VBase4(0.4, 0.4, 0.4, 1)) plnp = self.cam.attachNewNode(plight) self.render.setLight(plnp) if self.shadowing: # Use a 512x512 resolution shadow map plight.setShadowCaster(True, 512, 512) # Enable the shader generator for the receiving nodes self.render.setShaderAuto() self.render.setAntialias(AntialiasAttrib.MAuto) def _setupEvents(self): self.escapeEventText = OnscreenText(text="ESC: Quit", style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.95), align=TextNode.ALeft, scale=.05) if self.showPosition: self.positionText = OnscreenText(text="Position: ", style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.85), align=TextNode.ALeft, scale=.05) self.orientationText = OnscreenText(text="Orientation: ", style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.80), align=TextNode.ALeft, scale=.05) # Set up the key input self.accept('escape', sys.exit) self.accept("w", setattr, [self, "forward", True]) self.accept("w-up", setattr, [self, "forward", False]) self.accept("s", setattr, [self, "backward", True]) self.accept("s-up", setattr, [self, "backward", False]) self.accept("a", setattr, [self, "left", True]) self.accept("a-up", setattr, [self, "left", False]) self.accept("d", setattr, [self, "right", True]) self.accept("d-up", setattr, [self, "right", False]) self.accept("q", setattr, [self, "rotateXl", True]) self.accept("q-up", setattr, [self, "rotateXl", False]) self.accept("e", setattr, [self, "rotateXr", True]) self.accept("e-up", setattr, [self, "rotateXr", False]) self.accept("r", setattr, [self, "rotateYu", True]) self.accept("r-up", setattr, [self, "rotateYu", False]) self.accept("f", setattr, [self, "rotateYd", True]) self.accept("f-up", setattr, [self, "rotateYd", False]) self.accept("c", setattr, [self, "ss", True]) self.accept("c-up", setattr, [self, "ss", False]) self.accept("o", setattr, [self, "openpose", True]) self.accept("o-up", setattr, [self, "openpose", False]) self.accept("m", setattr, [self, "cv", True]) self.accept("m-up", setattr, [self, "cv", False]) self.accept("h", setattr, [self, "visible_human", not self.visible_human]) def update(self, task): # dt = self.globalClock.getDt() dt = task.time - self.time # handle key strokes if self.visible_human: self.pActor.show() else: self.pActor.hide() # rotational: if self.rotateXl == True: self.agent.setH(self.agent, self.agent.getH(self.agent) + self.centX * self.sensRotate) if self.rotateXr == True: self.agent.setH(self.agent, self.agent.getH(self.agent) - self.centX * self.sensRotate) if self.rotateYu == True: self.agent.setP(self.agent, self.agent.getP(self.agent) + 20 * self.sensRotate) self.agent.setR(self.agent, 0) if self.rotateYd == True: self.agent.setP(self.agent, self.agent.getP(self.agent) - 20 * self.sensRotate) self.agent.setR(self.agent, 0) # translational: linearVelocityX = 0.0 linearVelocityY = 0.0 if self.forward == True: linearVelocityY += self.sensTranslate * self.fast if self.backward == True: linearVelocityY -= self.sensTranslate * self.fast if self.left == True: linearVelocityX -= self.sensTranslate * self.fast if self.right == True: linearVelocityX += self.sensTranslate * self.fast linearVelocity = LVector3f(linearVelocityX, linearVelocityY, 0.0) # Apply the local transform to the velocity # XXX: use BulletCharacterControllerNode class, which already handles local transform? rotMat = self.agent.node().getTransform().getMat().getUpper3() linearVelocity = rotMat.xformVec(linearVelocity) linearVelocity.z = 0.0 self.agent.node().setLinearVelocity(linearVelocity) # take screenshots: if self.ss == True: ShowBase.screenshot(self, namePrefix='SS', defaultFilename= True, source=None, imageComment="") # capture video: # if duration=2, fps=16, the total capture video: 32 png files. if self.cv == True: if self.take_num is not None: self.movie(namePrefix='take_{:02d}_frame'.format(self.take_num), duration=9, fps=30, format='png') else: print('take_num is not set.') # invoke OpenPose # if self.openpose == True: # p = subprocess.Popen( # ('./build/examples/openpose/openpose.bin ' # '--display 0 ' # '--image_dir /home/teerawat/openpose/ ' # '--render_pose 1 ' # '--keypoint_scale 4 ' # '--write_images /home/teerawat/Documents/Work/imagesOpenpose/ ' # '--write_keypoint_json /home/teerawat/Documents/Work/keypointOpenposeJSON/'), # shell=True, stdin=subprocess.PIPE) # p.wait() # for i in glob.glob(os.path.join('/home/teerawat/openpose/', "*.jpg")): # try: # os.chmod(i, 0o777) # os.remove(i) # except OSError: # pass # for i in glob.glob(os.path.join('/home/teerawat/openpose/', "*.png")): # try: # os.chmod(i, 0o777) # os.remove(i) # except OSError: # pass if self.showPosition: position = self.agent.getNetTransform().getPos() hpr = self.agent.getNetTransform().getHpr() self.positionText.setText( 'Position: (x = %4.2f, y = %4.2f, z = %4.2f)' % (position.x, position.y, position.z)) self.orientationText.setText('Orientation: (h = %4.2f, p = %4.2f, r = %4.2f)' % (hpr.x, hpr.y, hpr.z)) self.time = task.time # Simulate physics if 'physics' in self.scene.worlds: self.scene.worlds['physics'].step(dt) # Rendering if 'render' in self.scene.worlds: self.scene.worlds['render'].step(dt) # Simulate acoustics if 'acoustics' in self.scene.worlds: self.scene.worlds['acoustics'].step(dt) return task.cont def step(self): self.taskMgr.step() def destroy(self): self.taskMgr.remove('peppers-update') ShowBase.destroy(self) # this should only be destroyed by the Python garbage collector # StaticShowBase.instance.destroy() #------------------edit------------------------- def drawHuman(self): # self.pActor = Actor( # "/home/teerawat/Documents/Human Motions/Activities/Human.egg", # {'Crouch': '/home/teerawat/Documents/Human Motions/Activities/Human-Crouch.egg'}) # self.pActor.setScale(0.085, 0.085, 0.085) # self.pActor.setPos(41, -41, 0.025) # self.pActor.setPos(39.5, -42, 0.025) # self.pActor.setPos(40, -40, 0.025) # self.pActor.setHpr(90, 0, 0) # self.pActor.setPos(40.5, -41, 0.025) # self.pActor.reparentTo(self.scene.scene) # self.pActor.loop("look")#, fromFrame=500, toFrame=650) #------Play Multi Animation at the same time. # self.pActor = Actor( # "/home/teerawat/Documents/Human Motions/Activities/Human.egg", # {'Crouch': '/home/teerawat/Documents/Human Motions/Activities/Human-Crouch.egg', # 'Walk': '/home/teerawat/Documents/Human Motions/Activities/Human-Walk.egg'}) # self.pActor.setScale(0.085, 0.085, 0.085) # self.pActor.setPos(40, -40, 0.025) # self.pActor.reparentTo(self.scene.scene) # self.pActor.enableBlend() # self.pActor.setControlEffect('Crouch', 0.2) # self.pActor.setControlEffect('Walk', 0.8) # self.pActor.loop('Crouch') # self.pActor.loop('Walk') #------End Play Multi Animation at the same time. self.pActor = Actor( "/Users/hikoyu/src/crest-home/human-models/Human.egg", {'Move': '/Users/hikoyu/src/crest-home/human-models/Human-Crouch.egg'}) self.pActor.setScale(0.085, 0.085, 0.085) self.pActor.setPos(43.22, -36.80, 0.025) self.pActor.setHpr(-126.4, 0., 0.) self.pActor.reparentTo(self.scene.scene) self.actionSequence = Sequence( self.pActor.actorInterval('Move'), name = 'crouchSequence') self.actionSequence.loop()
class Enemy(FSM, Unit): # Declare private variables _enemyActive = False _removeCorpseDelay = 2 # seconds before corpse is cleaned def __init__(self, mainRef, attributes): print("Enemy instantiated") Unit.__init__(self) FSM.__init__(self, 'playerFSM') self._mainRef = mainRef self._playerRef = mainRef.player self._AIworldRef = mainRef.AIworld self._enemyListRef = mainRef.enemyList self._ddaHandlerRef = mainRef.DDAHandler self._stateHandlerRef = mainRef.stateHandler self._scenarioHandlerRef = mainRef.scenarioHandler #self.topEnemyNode = mainRef.mainNode.attachNewNode('topEnemyNode') self.initEnemyNode(mainRef.mainNode) utils.enemyDictionary[self.enemyNode.getName()] = self self.loadEnemyModel(attributes.modelName) self.initAttributes(attributes) self.initEnemyAi() self.initEnemyDDA() self.initEnemyCollisionHandlers() self.initEnemyCollisionSolids() #self.request('Idle') self.request('Disabled') # Start enemy updater task self.enemyUpdaterTask = taskMgr.add(self.enemyUpdater, 'enemyUpdaterTask') def initEnemyNode(self, parentNode): enemyName = 'enemy' + str(len(self._enemyListRef)) self.enemyNode = parentNode.attachNewNode(enemyName) self._enemyListRef.append(self) def loadEnemyModel(self, modelName): modelPrefix = 'models/' + modelName self.enemyModel = Actor(modelPrefix + '-model', { 'walk':modelPrefix+'-walk', 'attack':modelPrefix+'-attack', 'idle':modelPrefix+'-idle', 'awake':modelPrefix+'-awake', 'stop':modelPrefix+'-stop', 'hit':modelPrefix+'-hit', 'death1':modelPrefix+'-death1', 'death2':modelPrefix+'-death2' }) self.enemyModel.reparentTo(self.enemyNode) self.enemyNode.setPos(Point3.zero()) self.enemyNode.setDepthOffset(-1) def initAttributes(self, attributes): perceptionRangeMultiplier = 1.2 combatRangeMultiplier = .3 speedMultiplier = .1 self.strength = attributes.strength self.constitution = attributes.constitution self.dexterity = attributes.dexterity self.mass = attributes.mass self.movementSpeed = speedMultiplier * attributes.movementSpeed self.perceptionRange = perceptionRangeMultiplier * attributes.perceptionRange self.combatRange = combatRangeMultiplier * attributes.combatRange self.attackBonus = attributes.attackBonus self.damageBonus = attributes.damageBonus self.damageRange = attributes.damageRange self.initiativeBonus = attributes.initiativeBonus self.fixedHealthPoints = attributes.fixedHealthPoints self.armorClass = attributes.armorClass if attributes.startLevel > 1: for i in range(attributes.startLevel-1): self.increaseLevel() self.expAward = attributes.expAward self.initHealth() def initEnemyDDA(self): if self._scenarioHandlerRef.getHasDDA(): maxLevelDifference = self._ddaHandlerRef.maxLevelDifference # Level enemy up to player's level minus maxLevelDifference levelDifference = self._playerRef.level - self.level if levelDifference >= maxLevelDifference: for i in range (levelDifference-maxLevelDifference): self.increaseLevel() def getAttackBonus(self): modifier = self.getStrengthModifier() if self.getStrengthModifier() > self.getDexterityModifier() else self.getDexterityModifier() ab = self.attackBonus + (self.level / 2) + modifier# + utils.getD20() if self._scenarioHandlerRef.getHasDDA(): attackBonusModifier = self._ddaHandlerRef.attackBonusModifier if attackBonusModifier < 0: ab -= attackBonusModifier if ab < 1: ab = 1 return ab + utils.getD20() def initEnemyAi(self): self.enemyAI = AICharacter('enemy', self.enemyNode, self.mass, # Mass 0.1, # Movt force self.movementSpeed) # Max force self._AIworldRef.addAiChar(self.enemyAI) self.enemyAIBehaviors = self.enemyAI.getAiBehaviors() #self.enemyAIBehaviors.obstacleAvoidance(1.0) def initEnemyCollisionHandlers(self): self.groundHandler = CollisionHandlerQueue() self.collPusher = CollisionHandlerPusher() def initEnemyCollisionSolids(self): # Enemy ground ray groundRay = CollisionRay(0, 0, 2, 0, 0, -1) groundColl = CollisionNode('enemyGroundRay') groundColl.addSolid(groundRay) groundColl.setIntoCollideMask(BitMask32.allOff()) groundColl.setFromCollideMask(BitMask32.bit(1)) self.groundRayNode = self.enemyNode.attachNewNode(groundColl) #self.groundRayNode.show() base.cTrav.addCollider(self.groundRayNode, self.groundHandler) # Enemy collision sphere collSphereNode = CollisionNode('enemyCollSphere') collSphere = CollisionSphere(0, 0, 0.1, 0.2) collSphereNode.addSolid(collSphere) collSphereNode.setIntoCollideMask(BitMask32.allOff()) collSphereNode.setFromCollideMask(BitMask32.bit(2)) self.sphereNode = self.enemyNode.attachNewNode(collSphereNode) #sphereNode.show() base.cTrav.addCollider(self.sphereNode, self.collPusher) self.collPusher.addCollider(self.sphereNode, self.enemyNode) # Enemy picker collision sphere pickerSphereCollNode = CollisionNode(self.enemyNode.getName()) pickerCollSphere = CollisionSphere(0, 0, 0, 0.5) pickerSphereCollNode.addSolid(pickerCollSphere) pickerSphereCollNode.setFromCollideMask(BitMask32.allOff()) pickerSphereCollNode.setIntoCollideMask(BitMask32.bit(1)) self.pickerNode = self.enemyNode.attachNewNode(pickerSphereCollNode) #sphereNodePath.show() # Enemy attack collision sphere attackCollSphereNode = CollisionNode(self.enemyNode.getName()+'atkSph') attackCollSphere = CollisionSphere(0, 0, 0.1, 0.15) attackCollSphereNode.addSolid(attackCollSphere) attackCollSphereNode.setIntoCollideMask(BitMask32.bit(3)) attackCollSphereNode.setFromCollideMask(BitMask32.allOff()) attackSphereNode = self.enemyNode.attachNewNode(attackCollSphereNode) #attackSphereNode.show() def slowMovementByPercentage(self, percentage=30, slowDuration=20): #print self.enemyNode.getName(), ' slowed by ', percentage, ' %' oldSpeed = self.movementSpeed newSpeed = ((100.0 - percentage) / 100.0) * oldSpeed if newSpeed < 1.0: newSpeed = 1.0 self.movementSpeed = newSpeed taskMgr.doMethodLater(slowDuration, self.removeSlowMovement, 'removeSlowMovementTask', extraArgs=[oldSpeed], appendTask=True) def removeSlowMovement(self, oldSpeed, task): self.movementSpeed = oldSpeed return task.done def checkGroundCollisions(self): if self.groundHandler.getNumEntries() > 0: self.groundHandler.sortEntries() entries = [] for i in range(self.groundHandler.getNumEntries()): entry = self.groundHandler.getEntry(i) #print('entry:', entry) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) for i in range(len(entries)): if entries[i].getIntoNode().getName()[:6] == 'ground': #print('entryFound:', entries[0]) newZ = entries[i].getSurfacePoint(base.render).getZ() self.enemyNode.setZ(newZ) #print('enemyZ:', newZ) break; def enemyUpdater(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive: self.enemyModel.stop() # Do not do anything when paused return task.cont self.checkGroundCollisions() if self.getIsDead(): self.onDeath() return task.done if self._playerRef.getIsDead(): return task.cont playerPos = self._playerRef.playerNode.getPos() enemyPos = self.enemyNode.getPos() # If player is within enemy perception range if utils.getIsInRange(playerPos, enemyPos, self.perceptionRange): # If enemy is not doing anything if self.state == 'Idle': # Start pursuing if self.state != 'Pursue': self.request('Pursue') # If enemy is already pursueing elif self.state == 'Pursue': # If player is within combat range if utils.getIsInRange(playerPos, enemyPos, self.combatRange): #print 'enemy go to combat' # Go to combat if self.state != 'Combat': self.request('Combat') # If enemy is already in combat elif self.state == 'Combat': # If player has moved out of combat range if not utils.getIsInRange(playerPos, enemyPos, self.combatRange): # Start pursuing if self.state != 'Pursue': self.request('Pursue') # If enemy is disabled elif self.state == 'Disabled': if self.enemyAI.getMaxForce() != self.movementSpeed: self.enemyAI.setMaxForce(self.movementSpeed) # If player is not within perception range else: if self.state != 'Idle': self.request('Idle') return task.cont def pursuePlayer(self): taskMgr.add(self.pursue, 'pursueTask') def pursue(self, task): if self.state == 'Pursue' and not self.getIsDead(): pitchRoll = self.enemyNode.getP(), self.enemyNode.getR() self.enemyNode.headsUp(self._playerRef.playerNode) self.enemyNode.setHpr(self.enemyNode.getH()-180, *pitchRoll) speed = -self.movementSpeed * globalClock.getDt() self.enemyNode.setFluidPos(self.enemyNode, 0, speed, 0) return task.cont else: task.done def enterIdle(self): #print 'enemy enterIdle' stopEnemy = self.enemyModel.actorInterval('stop', loop=0) idleEnemy = self.enemyModel.actorInterval('idle', startFrame=0, endFrame=1, loop=0) self.stopSequence = Sequence(stopEnemy, idleEnemy) self.stopSequence.start() self.isSleeping = True def exitIdle(self): #print('enemy exitIdle') self.stopSequence.finish() def enterPursue(self): #print('enemy enterPursue') loopWalkEnemy = Func(self.enemyModel.loop, 'walk', fromFrame=0, toFrame=12) # Only awake enemy if it comes from idle if self.isSleeping: self.isSleeping = False awakeEnemy = self.enemyModel.actorInterval('awake', loop=0) self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer)) else: self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer)) self.awakeSequence.start() def exitPursue(self): #print('enemy exitPursue') self.awakeSequence.finish() def enterCombat(self): #print('enemy enterCombat') self.enemyModel.stop() attackDelay = self.getInitiativeRoll() self.attackTask = taskMgr.doMethodLater(attackDelay, self.attackPlayer, 'attackPlayerTask') def enterDisabled(self): #print 'enterDisable' pass def exitDisabled(self): #print 'exitDisable' pass def exitCombat(self): #print('enemy exitCombat') taskMgr.remove(self.attackTask) def enterDeath(self): #print('enemy enterDeath') self.enemyAIBehaviors.removeAi('all') randomDeathAnim = 'death' + str(utils.getD2()) self.enemyModel.play(randomDeathAnim) def attack(self, other): if not self.getIsDead() and not other.getIsDead(): if self.getAttackBonus() >= other.getArmorClass(): dmg = self.getDamageBonus() #print(self.getName(), ' damaged ', other.getName(), ' for ', dmg, ' damage') other.receiveDamage(dmg) return 2 # Returns 2 when self damages other return 1 # Returns 1 when self attacks other, but misses return 0 # Returns 0 when either self or other is dead def attackPlayer(self, task): if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive: # Do not do anything when paused return task.again if self._playerRef.getIsDead(): print('player is already dead') self.request('Idle') return task.done elif self.getIsDead(): return task.done else: #print('Attack player!') # Make sure enemy is facing player when attacking pitchRoll = self.enemyNode.getP(), self.enemyNode.getR() self.enemyNode.headsUp(self._playerRef.playerNode) self.enemyNode.setHpr(self.enemyNode.getH()-180, *pitchRoll) attacked = self.attack(self._playerRef) if attacked != 0: self.playAttackAnimation() if attacked == 2: self._playerRef.playerModel.play('hit') return task.again def playAttackAnimation(self): self.enemyModel.play('attack', fromFrame=0, toFrame=12) def playHitAnimation(self): self.enemyModel.play('hit') def moveEnemy(self, x, y): self.enemyNode.setPos(x, y, .01) def handleHealthGlobe(self): global dropChanceFactor global dropChance global maxDropChance # if we drop, create health goblet chance = dropChanceFactor + dropChance if self._scenarioHandlerRef.getHasDDA(): chance *= self._ddaHandlerRef.healthGobletModifier if utils.getD100() <= chance: HealthGoblet(self._mainRef, self) print 'dropping health goblet' # Otherwise, increase dropChance else: if dropChance+dropChanceFactor <= maxDropChance: dropChance += dropChanceFactor def suicide(self): print('suicide: ', self) # Remove AI behavior self.enemyAIBehaviors.removeAi('all') # Remove enemy picker sphere (handlerQueue) self.pickerNode.removeNode() taskMgr.add(self.removeCorpse, 'removeCorpseTask') def onDeath(self): if self.getIsDead(): # Remove AI behavior self.enemyAIBehaviors.removeAi('all') # Award the player exp self._playerRef.receiveEXP(self.expAward) # Remove enemy picker sphere (handlerQueue) self.pickerNode.removeNode() # Change state self.request('Death') # Increase DDA death count if self._scenarioHandlerRef.getHasDDA(): self._ddaHandlerRef.enemyDeathCount += 1 # Handle health globe self.handleHealthGlobe() # Remove enemy corpse and clean up taskMgr.doMethodLater(self._removeCorpseDelay, self.removeCorpse, 'removeCorpseTask') def removeCorpse(self, task): # Remove enemy collision sphere (pusher) self.sphereNode.removeNode() # Stop the collision pusher self.collPusher = None # Remove enemy from enemyList self._enemyListRef.remove(self) # Cleanup the enemy model self.enemyModel.cleanup() self.enemyModel.delete() # Cleanup FSM self.cleanup() # Remove the enemy node self.enemyNode.removeNode() #self.topEnemyNode.removeNode() # Remove enemy updater tasks taskMgr.remove(self.enemyUpdaterTask) # Remove the passive regeneration task (from Unit class) self.removePassiveRegeneration() # Remove references self._mainRef = None self._playerRef = None self._AIworldRef = None self._enemyListRef = None self._stateHandlerRef = None return task.done
class Npc(): def __init__(self,controlPointId,id, anchorx, anchory, anchorz,render,team): self.id = id self.anchorx = anchorx self.anchory = anchory self.anchorz = anchorz self.controlPointId = controlPointId self.target = None self.isMoving = False self.health = 200 self.isCurrentUser = False self.damage = 8 self.attackTimer = 0 self._is_dead = False self._team = team self.render = render '''Initializing NPC actors''' self.npc = Actor("models/priest", {"walk": "models/priest-walk", "attack":"models/priest-attack", "hurt":"models/priest-hit", "die":"models/priest-die"}) if self._team==0: self.npcTex = loader.loadTexture("models/tex/guard_red.png") else: self.npcTex = loader.loadTexture("models/tex/guard_blue.png") self.npc.setTexture(self.npcTex) self.npc.setScale(0.5, 0.5, 0.5) self.npc.clearColor() self.npc.clearColorScale() self.npc.setColor(255, 0, 0, 0) self.npc.setColorScale(255, 0, 0, 0) self.npc.reparentTo(self.render) self.npc.setPos(anchorx,anchory,anchorz) self.AIchar = AICharacter("npc"+str(self.id),self.npc, 100, 0.05, 5) self.AIbehaviors = self.AIchar.getAiBehaviors() self.hb = HealthBar(1.5, value=self.health) #self._floater = NodePath(PandaNode("char_info")) #self._floater.reparentTo(self.npc) self.hb.setPos(0, 0, 11.9) self.hb.reparentTo(self.npc) #self.hb.reparentTo(self.npc) def renderBlue(self,AIworld): if not self._is_dead: self.AIbehaviors.removeAi("pursue") self.npc.detachNode() print "Started delete procedure for npc ", print self.id self.npc.delete() self.npc = Actor("models/priest", {"walk": "models/priest-walk", "attack":"models/priest-attack", "hurt":"models/priest-hit", "die":"models/priest-die"}) self.npcTex = loader.loadTexture("models/tex/guard_blue.png") self.npc.setTexture(self.npcTex) self.npc.setScale(0.5, 0.5, 0.5) self.npc.clearColor() self.npc.clearColorScale() self.npc.setColor(255, 0, 0, 0) self.npc.setColorScale(255, 0, 0, 0) self.npc.reparentTo(self.render) self.npc.setPos(self.anchorx,self.anchory,self.anchorz) AIworld.removeAiChar("npc"+str(self.id)) self.AIchar = AICharacter("npc"+str(self.id),self.npc, 100, 0.05, 5) self.AIbehaviors = self.AIchar.getAiBehaviors() AIworld.addAiChar(self.AIchar) self.hb = HealthBar(1.5, value=self.health) self.hb.setPos(0, 0, 18.1) self.hb.reparentTo(self.npc) #self.hb.reparentTo(self.npc) def renderRed(self,AIworld): if not self._is_dead: self.AIbehaviors.removeAi("pursue") self.npc.detachNode() self.npc.delete() self.npc = Actor("models/priest", {"walk": "models/priest-walk", "attack":"models/priest-attack", "hurt":"models/priest-hit", "die":"models/priest-die"}) self.npcTex = loader.loadTexture("models/tex/guard_red.png") self.npc.setTexture(self.npcTex) self.npc.setScale(0.5, 0.5, 0.5) self.npc.clearColor() self.npc.clearColorScale() self.npc.setColor(255, 0, 0, 0) self.npc.setColorScale(255, 0, 0, 0) self.npc.reparentTo(self.render) self.npc.setPos(self.anchorx,self.anchory,self.anchorz) AIworld.removeAiChar("npc"+str(self.id)) self.AIchar = AICharacter("npc"+str(self.id),self.npc, 100, 0.05, 5) self.AIbehaviors = self.AIchar.getAiBehaviors() AIworld.addAiChar(self.AIchar) AIworld.update() self.hb = HealthBar(1.5, value=self.health) self.hb.setPos(0, 0, 8.1) self.hb.reparentTo(self.npc) def switchTeam(self,AIworld): print self.id, print " from team ", print self._team, print " getting deleted." if self._team==0: self._team=1 self.renderBlue(AIworld) else: self._team=0 self.renderRed(AIworld) if self.isCurrentUser: main.freeDeadNpc(self.id) self.target = None self.isMoving = False self.health = 200 self.isCurrentUser = False self.damage = 8 self.attackTimer = 0 self._is_dead = False def set_health(self, health): self.health = health def take_damage(self, health_change): health = self.health if health <= health_change and not self._is_dead: self.killNpc() else: health = health-health_change self.set_health(health) self.hb.setValue(self.health) self.npc.play("hurt") def killNpc(self): self.set_health(0) self.hb.setValue(0) self.AIbehaviors.removeAi("pursue") hurt_interval = self.npc.actorInterval("hurt") death_interval = self.npc.actorInterval("die") seq = Sequence(hurt_interval, death_interval) seq.start() self.npc.pose("die",45) self._is_dead = True self.npc.detachNode() if self.isCurrentUser: main.freeDeadNpc(self.id) #main.cManager.sendRequest(Constants.CMSG_NPCDEATH, [self.id]) print Constants.CMSG_NPCDEATH, print " + ", print self.id def chaseTarget(self, target, status = False): if(not self.isMoving): self.target = target self.AIbehaviors.pursue(self.target) self.npc.loop("walk") self.isMoving = True self.isCurrentUser = status def stopChase(self): #self.AIbehaviors.pauseAi("pursue") if not self._is_dead: self.AIbehaviors.removeAi("pursue") p1 = LerpHprInterval(self.npc, 4, Point3(180,0,0)) p2 = LerpPosInterval(self.npc, 4, Point3(self.anchorx, self.anchory, self.anchorz)) animInterval = self.npc.actorInterval("walk", loop = 1, duration=4) p2.start() p1.start() animInterval.start() self.isMoving = False self.target = None self.isCurrentUser = False def givNPCDistance(self,charachter): x = self.npc.getX() y = self.npc.getY() z = self.npc.getZ() minDist = math.sqrt( (charachter.getX()-x)*(charachter.getX()-x) + (charachter.getY()-y)*(charachter.getY()-y) + (charachter.getZ()-z)*(charachter.getZ()-z) ) return minDist def checkNpcIsAlive(self): if(self.health>0): return True else: return False def shouldAttack(self,currentTime,cManager): if not self._is_dead: if self.isMoving: if self.attackTimer>0: self.attackTimer = self.attackTimer-currentTime #print self.attackTimer if self.AIbehaviors.behaviorStatus("pursue")=="done": #self.npc.stop("walk") #print self.npc.getAnimControl("walk") if self.attackTimer<=0: if self.npc.getAnimControl("walk").isPlaying(): self.npc.stop("walk") if not self.npc.getAnimControl("attack").isPlaying(): #self.npc.loop("attack") self.npc.play("attack") self.attackTimer = 2 #myInterval = self.npc.actorInterval("attack") #seq = Sequence(myInterval) #seq.append(Wait(3)) #seq.start() if self.isCurrentUser: cManager.sendRequest(Constants.CMSG_NPCATTACK, [self.id, self.damage]) if self.AIbehaviors.behaviorStatus("pursue")=="active": if self.npc.getAnimControl("attack").isPlaying(): self.npc.stop("attack") if not self.npc.getAnimControl("walk").isPlaying(): self.npc.loop("walk")
class Lvl03(DirectObject): def start(self): base.disableMouse() #turn off mouse camera control base.enableParticles() self.music = loader.loadMusic("models/gamedev/DEC.mp3") self.music.play() camera.setPosHpr(Vec3(98,-390,90), Vec3(0,-5,0)) self.ballNum = 10 self.setupStage() self.loadModels() self.setupLighting() self.setupCollisions() self.setupIntervals() taskMgr.add(self.ballMovementTask,'ballMoveTask') self.gameLen = 30 self.player1Weapon = "" self.player2Weapon = "" #hud = OnscreenImage(image = 'models/gamedev/lvl2hud.jpg', pos = (0,1,20),scale=5.0) #hud.reparentTo(render) globalClock.reset() self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0) self.timer.setColor(1,1,1) taskMgr.add(self.clockTask,"clockTask") self.player1Score = 0 self.player2Score = 0 self.nodeCount1 = 0 self.nodeCount2 = 0 self.player1Invincible = 0 self.player2Invincible = 0 self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2") self.jNP2 = self.playerModel2.exposeJoint(None,"modelRoot","ikHandle2") self.climbing1 = 0 self.climbing2 = 0 self.speed1 = 3.0 self.speed2 = 3.0 self.ignoreColl= 0 self.player1IsColliding = 0 self.player2IsColliding = 0 taskMgr.doMethodLater(self.gameLen, self.endGame,'gameFinished') #taskMgr.doMethodLater(self.gameLen/2.0,self.changeMusic,'musicSwitch') #setup key controls self.accept("escape",sys.exit) #self.acceptOnce("space",self.drop) # Player 1 movement self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.acceptOnce("w", self.jump) #Player 2 movement keys #self.accept("l",self.fall2) self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft2) self.accept(";-up",self.stopRight2) self.acceptOnce("o", self.jumpT2) def setupStage(self): self.ball = [] self.movement = [] for i in range(self.ballNum+1): z=random.randint(1,2) if z ==1: z=-1 else: z=1 weapBalls.define(self.ball,i,render) self.movement.append(Vec3(random.random()*z,0,random.random()*z)) #self.movement[i].Vec3(random.randint(1,3),0,random.randint(1,3)) self.background2 = OnscreenImage(image = 'models/gamedev/frozenbg.JPG', pos = (98,10,0),scale=500) self.background2.detachNode() self.background = OnscreenImage(image = 'models/gamedev/moltenbg.JPG', pos = (98,10,0),scale=500) self.background.reparentTo(render) self.lava = loader.loadModel("models/gamedev/lava") self.lava.setPosHpr(Vec3(98,0,-18),Vec3(0,5,0)) self.lava.setScale(50) self.lava.reparentTo(render) x1= 196 x2 = 0 m1 = 98 m2 = 107.8 len = 9.8 h = 0 a = 0 p = 0 for j in range(4): if j > 0: x1Old = x1 x2Old = x2 x1 = 196-(random.randint(0,3)*9.8) x2 = 0+random.randint(0,3)*9.8 m1=98-(random.randint(0,3)*9.8) m2= 107.8+random.randint(0,3)*9.8 for count in range(1): l = random.randint(2,5) r = random.randint(2,5) c1 = random.randint(2,5) c2 = random.randint(2,5) if l+r < 4: count = 0 else: l = 4 r = 4 c1 = 2 c2 = 2 ''' if j ==1 or j == 3: self.ladder = loader.loadModel("models/gamedev/ladder") self.ladder.reparentTo(render) self.ladder.setScale(1.5) self.ladder.setPos(x2+4.9,0,h-20) self.ladder2 = loader.loadModel("models/gamedev/ladder") self.ladder2.reparentTo(render) self.ladder2.setScale(1.5) self.ladder2.setPos(x1-4.9,0,h-20) if j == 2: self.ladder = loader.loadModel("models/gamedev/ladder") self.ladder.reparentTo(render) self.ladder.setScale(1.5) self.ladder.setPos(m1-4.9,0,h-20) self.ladder2 = loader.loadModel("models/gamedev/ladder") self.ladder2.reparentTo(render) self.ladder2.setScale(1.5) self.ladder2.setPos(m2+4.9,0,h-20) ''' self.first = 1 for i in range(r): '''Right half of stage''' self.environment = loader.loadModel("models/gamedev/platform") self.environment.reparentTo(render) self.environment.setScale(5) self.environment.setPos(x1,0,h) if self.first == 1: self.first = 0 bounds = self.environment.getChild(0).getBounds() center = bounds.getCenter() poly1 = Point3(center.getX()+1, center.getY()-.5, center.getZ()+.2) poly2 = Point3(center.getX()-(2*r-1), center.getY()-.5, center.getZ()+.2) poly3 = Point3(center.getX()+1, center.getY()+.5, center.getZ()+.2) poly4 = Point3(center.getX()-(2*r-1), center.getY()+.5, center.getZ()+.2) cPoly = CollisionPolygon(poly4, poly2, poly1, poly3) cNode = CollisionNode("platform") cNode.addSolid(cPoly) cNodePath = self.environment.attachNewNode(cNode) cNodePath.show() x1 = x1 - len self.first = 1 for i in range(l): '''Left Half of stage''' self.environment = loader.loadModel("models/gamedev/platform") self.environment.reparentTo(render) self.environment.setScale(5) self.environment.setPos(x2,0,h) if self.first == 1: self.first = 0 bounds = self.environment.getChild(0).getBounds() center = bounds.getCenter() poly1 = Point3(center.getX()+(2*l-1), center.getY()-.5, center.getZ()+.2) poly2 = Point3(center.getX()-1, center.getY()-.5, center.getZ()+.2) poly3 = Point3(center.getX()+(2*l-1), center.getY()+.5, center.getZ()+.2) poly4 = Point3(center.getX()-1, center.getY()+.5, center.getZ()+.2) cPoly = CollisionPolygon(poly4, poly2, poly1, poly3) cNode = CollisionNode("platform") cNode.addSolid(cPoly) cNodePath = self.environment.attachNewNode(cNode) cNodePath.show() x2 = x2 + len self.first = 1 for i in range(c1): '''Right half of stage''' self.environment = loader.loadModel("models/gamedev/platform") self.environment.reparentTo(render) self.environment.setScale(5) self.environment.setPos(m1,0,h) if self.first == 1: self.first = 0 bounds = self.environment.getChild(0).getBounds() center = bounds.getCenter() poly1 = Point3(center.getX()+1, center.getY()-.5, center.getZ()+.2) poly2 = Point3(center.getX()-(2*c1-1), center.getY()-.5, center.getZ()+.2) poly3 = Point3(center.getX()+1, center.getY()+.5, center.getZ()+.2) poly4 = Point3(center.getX()-(2*c1-1), center.getY()+.5, center.getZ()+.2) cPoly = CollisionPolygon(poly4, poly2, poly1, poly3) cNode = CollisionNode("platform") cNode.addSolid(cPoly) cNodePath = self.environment.attachNewNode(cNode) cNodePath.show() m1 = m1 - len self.first = 1 for i in range(c2): '''Left Half of stage''' self.environment = loader.loadModel("models/gamedev/platform") self.environment.reparentTo(render) self.environment.setScale(5) self.environment.setPos(m2,0,h) if self.first == 1: self.first = 0 bounds = self.environment.getChild(0).getBounds() center = bounds.getCenter() poly1 = Point3(center.getX()+(2*c2-1), center.getY()-.5, center.getZ()+.2) poly2 = Point3(center.getX()-1, center.getY()-.5, center.getZ()+.2) poly3 = Point3(center.getX()+(2*c2-1), center.getY()+.5, center.getZ()+.2) poly4 = Point3(center.getX()-1, center.getY()+.5, center.getZ()+.2) cPoly = CollisionPolygon(poly4, poly2, poly1, poly3) cNode = CollisionNode("platform") cNode.addSolid(cPoly) cNodePath = self.environment.attachNewNode(cNode) cNodePath.show() m2 = m2 + len h = h+40 a = 0 def loadModels(self): # ** Load female character that will represent first player** # self.playerModel = Actor("models/gamedev/redguy-model",{"walk":"models/gamedev/redguy-run"}) self.playerModel.reparentTo(render) self.playerModel.setScale(.6) self.playerModel.setH(90) # ** Position player at center of the field with it lying directly above the field. ** # self.playerModel.setPos(0,0,1.76) # ** Load female character that will represent second player** # self.playerModel2 = Actor("models/gamedev/bluegirl-model",{"walk2":"models/gamedev/bluegirl-run"}) self.playerModel2.reparentTo(render) self.playerModel2.setScale(.6) self.playerModel2.setH(0) # ** Position player at center of the field with it lying directly above the field. ** # self.playerModel2.setPos(196,0,2.0) def reset(self): self.an1.getPhysicsObject().setVelocity(Vec3(0,0,0)) self.an2.getPhysicsObject().setVelocity(Vec3(0,0,0)) self.an1.getPhysicsObject().setPosition(Point3(0,0,11.76)) self.an2.getPhysicsObject().setPosition(Point3(196,0,22.0)) self.playerModel.setH(90) self.playerModel.detachNode() self.playerModel.setPos(0,0,1.76) self.anp.setFluidPos(Point3(0,0,1.76)) self.playerModel.reparentTo(self.anp) self.playerModel2.setH(0) self.playerModel2.detachNode() self.playerModel2.setPos(196,0,22.0) self.anp2.setFluidPos(Point3(196,0,22.0)) self.playerModel2.reparentTo(self.anp2) def setupLighting(self): ambientLight = AmbientLight('ambientLight') ambientLight.setColor(Vec4(0.55,0.55,0.55,1.0)) ambientLightNP = render.attachNewNode(ambientLight) render.setLight(ambientLightNP) dirLight = DirectionalLight('dirLight') dirLight.setColor(Vec4(0.6,0.6,0.6,1)) dirLightNP = render.attachNewNode(dirLight) dirLightNP.setHpr(Vec3(0.0,-26.0,0.0)) render.setLight(dirLightNP) def setupIntervals(self): self.charWalk1l = self.playerModel.actorInterval("walk") self.charWalk1l.loop( ) self.charWalk1l.pause( ) self.charWalk1r = self.playerModel.actorInterval("walk") self.charWalk1r.loop( ) self.charWalk1r.pause( ) self.charWalk2l = self.playerModel2.actorInterval("walk2") self.charWalk2l.loop( ) self.charWalk2l.pause( ) self.charWalk2r = self.playerModel2.actorInterval("walk2") self.charWalk2r.loop( ) self.charWalk2r.pause( ) self.jump1 = self.playerModel.actorInterval("jump") self.jump1.loop() self.jump1.pause() self.jump2 = self.playerModel2.actorInterval("jump2") self.jump2.loop() self.jump2.pause() self.climb1 = self.playerModel.actorInterval("climb") self.climb1.loop() self.climb1.pause() self.climb2 = self.playerModel2.actorInterval("climb2") self.climb2.loop() self.climb2.pause() # end setupIntervals # ############################ # Actual Working movement code # ############################ def rise(self): dist = 40 self.playerModel.setH(0) playerJump = self.playerModel.posInterval(1.0,Vec3(self.playerModel.getX(), self.playerModel.getY(),self.playerModel.getZ()+dist)) playerJump.start() def rise2(self): dist = 40 self.playerModel2.setH(90) playerJump2 = self.playerModel2.posInterval(1.0,Vec3(self.playerModel2.getX(), self.playerModel2.getY(),self.playerModel2.getZ()+dist)) playerJump2.start() # PLAYER ONE # def left(self): taskMgr.add(self.leftTask,'leftTask') self.charWalk1l.loop() #end left def leftTask(self,task): if self.climbing1 == 0: self.playerModel.setH(270) self.playerModel.setPos(Vec3(self.playerModel.getX()-self.speed1, self.playerModel.getY(), self.playerModel.getZ())) return Task.cont def right(self): taskMgr.add(self.rightTask,'rightTask') self.charWalk1r.loop() #end right def rightTask(self,task): if self.climbing1 == 0: self.playerModel.setH(90) self.playerModel.setPos(Vec3(self.playerModel.getX()+self.speed1, self.playerModel.getY(), self.playerModel.getZ())) return Task.cont def climbable(self,cEntry): self.nodeCount1+=1 print self.nodeCount1 self.ignore("w") self.ignore("w-up") self.ignore("s") self.ignore("s-up") self.acceptOnce("w",self.climb,[1]) self.accept("w-up",self.noClimb) self.acceptOnce("s",self.climb,[-1]) self.accept("s-up",self.noClimb) def climb(self,dir): self.dir1 = dir self.climbing1 = 1 self.climbSpeed1 = 1 self.ignore("a") self.ignore("a-up") self.ignore("d") self.ignore("d-up") taskMgr.add(self.climbTask,'climbTask') self.climb1.loop() def noClimb(self): taskMgr.remove('climbTask') self.climb1.pause() if self.nodeCount1 == 0: self.climbing = 0 self.climbSpeed1 = 0 self.acceptOnce("w",self.climb,[1]) self.acceptOnce("s",self.climb,[-1]) def jumpable(self,cEntry): self.nodeCount1+=-1 print self.nodeCount1 if self.nodeCount1 == 0: taskMgr.remove('climbTask') self.ignore("w") self.ignore("w-up") self.ignore("s") self.ignore("s-up") self.acceptOnce("w",self.jump) self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.climbing1 = 0 self.climbSpeed1 = 0 self.climb1.pause() def walkable(self,cEntry): self.ignore("w") self.ignore("w-up") self.ignore("s") self.ignore("s-up") self.acceptOnce("w",self.climb,[1]) self.accept("w-up",self.noClimb) self.acceptOnce("s",self.climb,[-1]) self.accept("s-up",self.noClimb) self.acceptOnce("a",self.left) self.acceptOnce("d",self.right) self.accept("a-up",self.stopLeft) self.accept("d-up",self.stopRight) self.climbing1 = 0 self.climbSpeed1 = 0 self.climb1.pause() def climbTask(self,task): if self.playerModel.getZ() >=0: self.playerModel.setH(0) self.playerModel.setPos(Vec3(self.playerModel.getX(), self.playerModel.getY(), self.playerModel.getZ()+self.climbSpeed1*self.dir1)) return Task.cont def jump(self): if self.nodeCount1 == 0: self.ignore("w") self.ignore("w-up") z = self.playerModel.getZ() j = ProjectileInterval(self.playerModel, startPos = self.playerModel.getPos(), startVel = Point3(5,0,30), duration = 2.0) j.start() taskMgr.doMethodLater(2,self.jumpTask,"jumpTask") else: self.acceptOnce("w",self.climb,[1]) def jumpTask(self, task): if self.climbing1 == 0: self.jump1.pause() self.acceptOnce("w",self.jump) #return task.cont def allowRight(self): self.acceptOnce("d",self.right) def noRight(self): taskMgr.remove('rightTask') self.charWalk1r.pause() self.acceptOnce("d",self.right) def stopRight(self): self.noRight() #self.allowRight() def rightWall(self,cEntry): self.ignore("d") self.noRight() def rightEdge(self,cEntry): self.ignore("d") self.noRight() def rightOK(self,cEntry): self.allowRight() def allowLeft(self): self.acceptOnce("a",self.left) def noLeft(self): taskMgr.remove('leftTask') self.charWalk1l.pause() self.acceptOnce("a",self.left) def stopLeft(self): self.noLeft() #self.allowLeft() def leftWall(self,cEntry): self.ignore("a") self.noLeft() def leftEdge(self,cEntry): self.ignore("a") self.noLeft() def leftOK(self,cEntry): self.allowLeft() # PLAYERTWO # def left2(self): taskMgr.add(self.leftTask2,'leftTask2') self.charWalk2l.loop() #end left def leftTask2(self,task): if self.climbing2 == 0: self.playerModel2.setH(0) self.playerModel2.setPos(Vec3(self.playerModel2.getX()-self.speed2, self.playerModel2.getY(), self.playerModel2.getZ())) return Task.cont def right2(self): taskMgr.add(self.rightTask2,'rightTask2') self.charWalk2r.loop() #end right def rightTask2(self,task): if self.climbing2 == 0: self.playerModel2.setH(180) self.playerModel2.setPos(Vec3(self.playerModel2.getX()+self.speed2, self.playerModel2.getY(), self.playerModel2.getZ())) return Task.cont def climbable2(self,cEntry): self.nodeCount2+=1 #print self.nodeCount1 self.ignore("o") self.ignore("o-up") self.ignore("l") self.ignore("l-up") self.acceptOnce("o",self.climbT2,[1]) self.accept("o-up",self.noClimb2) self.acceptOnce("l",self.climbT2,[-1]) self.accept("l-up",self.noClimb2) def climbT2(self,dir): self.dir2 = dir self.climbing2 = 1 self.climbSpeed2 = 1 self.ignore("k") self.ignore("k-up") self.ignore(";") self.ignore(";-up") taskMgr.add(self.climbTask2,'climbTask2') self.climb2.loop() def noClimb2(self): taskMgr.remove('climbTask2') self.climb2.pause() if self.nodeCount2 == 0: self.climbing2 = 0 self.climbSpeed2 = 0 self.acceptOnce("o",self.climbT2,[1]) self.acceptOnce("l",self.climbT2,[-1]) def jumpable2(self,cEntry): self.nodeCount2+=-1 #print self.nodeCount2 if self.nodeCount2 == 0: taskMgr.remove('climbTask2') self.ignore("o") self.ignore("o-up") self.ignore("l") self.ignore("l-up") self.acceptOnce("o",self.jumpT2) self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft2) self.accept(";-up",self.stopRight2) self.climbing2 = 0 self.climbSpeed2 = 0 self.climb2.pause() def walkable2(self,cEntry): self.ignore("o") self.ignore("o-up") self.ignore("l") self.ignore("l-up") self.acceptOnce("o",self.climbT2,[1]) self.accept("o-up",self.noClimb2) self.acceptOnce("l",self.climbT2,[-1]) self.accept("l-up",self.noClimb2) self.acceptOnce("k",self.left2) self.acceptOnce(";",self.right2) self.accept("k-up",self.stopLeft) self.accept(";-up",self.stopRight) self.climbing2 = 0 self.climbSpeed2 = 0 self.climb2.pause() def climbTask2(self,task): if self.playerModel2.getZ() >=0: self.playerModel2.setH(90) self.playerModel2.setPos(Vec3(self.playerModel2.getX(), self.playerModel2.getY(), self.playerModel2.getZ()+self.climbSpeed2*self.dir2)) return Task.cont def jumpT2(self): if self.nodeCount2 == 0: self.ignore("o") self.ignore("o-up") z = self.playerModel2.getZ() j = ProjectileInterval(self.playerModel2, startPos = self.playerModel2.getPos(), startVel = Point3(3,0,30), duration = 2.0) j.start() taskMgr.doMethodLater(3,self.jumpTask2,"jumpTask2") else: self.acceptOnce("w",self.climb,[1]) def jumpTask2(self, task): if self.climbing2 == 0: self.jump2.pause() self.acceptOnce("o",self.jumpT2) #return task.cont def allowRight2(self): self.acceptOnce(";",self.right2) def noRight2(self): taskMgr.remove('rightTask2') self.charWalk2r.pause() self.acceptOnce(";",self.right2) def stopRight2(self): self.noRight2() #self.allowRight() def rightWall2(self,cEntry): self.ignore(";") self.noRight2() def rightEdge2(self,cEntry): self.ignore(";") self.noRight2() def rightOK2(self,cEntry): self.allowRight2() def allowLeft2(self): self.acceptOnce("k",self.left2) def noLeft2(self): taskMgr.remove('leftTask2') self.charWalk2l.pause() self.acceptOnce("k",self.left2) def stopLeft2(self): self.noLeft2() #self.allowLeft() def leftWall2(self,cEntry): self.ignore("k") self.noLeft2() def leftEdge2(self,cEntry): self.ignore("k") self.noLeft2() def leftOK2(self,cEntry): self.allowLeft2() def setupCollisions(self): self.cHandler = PhysicsCollisionHandler() #self.cHandler.setInPattern("ate-%in") self.cHandler.addInPattern('%fn-into-%in') #self.cHandler2.addInPattern('%fn-into-%in') self.cHandler.setAgainPattern('%fn-again-%in') self.cHandler.setOutPattern('%fn-outof-%in') self.cTrav = CollisionTraverser() #self.cTrav2 = CollisionTraverser() base.cTrav = self.cTrav #Player 1 collision solid bounds = self.playerModel.getChild(0).getBounds() center = bounds.getCenter()-Vec3(0,0,12) radius = bounds.getRadius()-18 boundsB = self.playerModel.getChild(0).getBounds() centerB = bounds.getCenter()-Vec3(0,0,-4) radiusB = bounds.getRadius()-20 cSphere = CollisionSphere(center,radius) cSphereB = CollisionSphere(centerB,radiusB) cNode = CollisionNode("player1") #print radius, radiusB cNode.addSolid(cSphere) cNode.addSolid(cSphereB) cNodePath = self.playerModel.attachNewNode(cNode) cNodePath.show() Node=NodePath(PandaNode("PhysicsNode")) Node.reparentTo(render) self.an1=ActorNode("player1-physics") self.anp=Node.attachNewNode(self.an1) base.physicsMgr.attachPhysicalNode(self.an1) self.playerModel.reparentTo(self.anp) #self.anp.reparentTo(self.playerModel) #Player 2 collision solid bounds2 = self.playerModel2.getChild(0).getBounds() center2 = bounds2.getCenter()-Vec3(0,0,-4) radius2 = bounds2.getRadius()-20 cSphere2 = CollisionSphere(center2,radius2) bounds2B = self.playerModel2.getChild(0).getBounds() center2B = bounds2B.getCenter()-Vec3(0,0,12) radius2B = bounds2B.getRadius()-18 cSphere2B = CollisionSphere(center2B,radius2B) cNode2 = CollisionNode("player2") #print radius2, radius2B cNode2.addSolid(cSphere2) cNode2.addSolid(cSphere2B) cNodePath2 = self.playerModel2.attachNewNode(cNode2) cNodePath2.show() Node2=NodePath(PandaNode("PhysicsNode")) Node2.reparentTo(render) self.an2=ActorNode("player2-physics") self.anp2=Node2.attachNewNode(self.an2) base.physicsMgr.attachPhysicalNode(self.an2) self.playerModel2.reparentTo(self.anp2) #self.anp2.reparentTo(self.playerModel2) gravityFN=ForceNode('world-forces') gravityFNP=render.attachNewNode(gravityFN) gravityForce=LinearVectorForce(0,0,-9.8) #gravity acceleration gravityFN.addForce(gravityForce) base.physicsMgr.addLinearForce(gravityForce) self.an1.getPhysicsObject().setMass(15) self.an2.getPhysicsObject().setMass(15) gravityForce.setMassDependent(1) self.cHandler.addCollider(cNodePath, self.anp) self.cHandler.addCollider(cNodePath2, self.anp2) self.cTrav.addCollider(cNodePath,self.cHandler) self.cTrav.addCollider(cNodePath2,self.cHandler) self.cTrav.addCollider(cNodePath,self.cHandler) self.cTrav.addCollider(cNodePath2,self.cHandler) #self.cTrav.addCollider(cNodePath,self.cHandler2) #self.cTrav.addCollider(cNodePath2,self.cHandler2) #self.cTrav2.addCollider(cNodePath,self.cHandler2) #self.cTrav2.addCollider(cNodePath2,self.cHandler2) #cHandler2 = CollisionHandlerEvent() #cHandler2.addInPattern('%fn-into-%in') #self.cTrav.addCollider(cNodePath1,cHandler2) #self.cTrav.addCollider(cNodePath2,cHandler2) for i in range(self.ballNum+1): boundsB = self.ball[i].getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*0.65 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("ball") cNodeB.addSolid(cSphereB) cNodePathB = self.ball[i].attachNewNode(cNodeB) #self.cTrav.addCollider(cNodePathB,self.cHandler) #cNodePathB.show() self.accept("player1-into-ball",self.acquire1) #self.accept("ball-into-player1",self.acquire1) self.accept("player2-into-ball",self.acquire2) #self.accept("ball-into-player2",self.acquire2) #self.accept( 'player1-into2-platform', self.wall1) #self.accept( 'player2-into2-platform', self.wall2) def wall1(self,cEntry): self.an1.getPhysicsObject().setVelocity(Vec3(0,0,0)) def wall2(self,cEntry): self.an2.getPhysicsObject().setVelocity(Vec3(0,0,0)) def player1Wins(self,cEntry): if self.player2Invincible == 0: self.player1Score+=10 self.reset() def player2Wins(self,cEntry): if self.player1Invincible == 0: self.player2Score+=10 self.reset() def acquire1(self,cEntry): self.playerModel.setY(0) if str(cEntry.getIntoNodePath().getParent()) == "render/sawball": self.player1Weapon = "saw" saw = loader.loadModel("models/gamedev/saw") saw.setScale(2.5) self.jNP.getChildren().detach() saw.reparentTo(self.jNP) self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/moltovball": self.player1Weapon = "molotov" molo = loader.loadModel("models/gamedev/moltov") molo.setScale(2.5) #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2") self.jNP.getChildren().detach() molo.reparentTo(self.jNP) self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/grenadeball": self.player1Weapon = "grenade" gren = loader.loadModel("models/gamedev/grenade") gren.setScale(2.5) #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2") self.jNP.getChildren().detach() gren.reparentTo(self.jNP) self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/pogo": #done self.jNP.getChildren().detach() self.player1Weapon = "jump" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/golden": #done self.jNP.getChildren().detach() self.player1Weapon = "speedUp" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/crystalball": self.jNP.getChildren().detach() self.player1Weapon = "icestage" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/fireball": #done self.jNP.getChildren().detach() self.player1Weapon = "meteo" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/blackball": #done self.jNP.getChildren().detach() self.player1Weapon = "blind" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/translucent": self.jNP.getChildren().detach() self.player1Weapon = "invis" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/superball": #done self.jNP.getChildren().detach() self.player1Weapon = "invincible" self.acceptOnce("e",self.useWeapon1) self.acceptOnce("q",self.useWeapon1) elif str(cEntry.getIntoNodePath().getParent()) == "render/death": #done self.jNP.getChildren().detach() if self.player1Invincible == 0: self.player2Deaths+= 1 self.reset() cEntry.getIntoNodePath().getParent().removeNode() #Drop a New Ball self.ballNum+=1 z=random.randint(1,2) if z ==1: z=-1 else: z=1 self.movement.append(Vec3(random.random()*z,0,random.random()*z)) weapBalls.define(self.ball,self.ballNum,render) boundsB = self.ball[self.ballNum].getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*.65 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("ball") cNodeB.addSolid(cSphereB) cNodePathB = self.ball[self.ballNum].attachNewNode(cNodeB) def acquire2(self,cEntry): if str(cEntry.getIntoNodePath().getParent()) == "render/sawball": self.player2Weapon = "saw" saw = loader.loadModel("models/gamedev/saw") saw.setScale(2.5) self.jNP2.getChildren().detach() saw.reparentTo(self.jNP2) self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/moltovball": self.player2Weapon = "molotov" molo = loader.loadModel("models/gamedev/moltov") molo.setScale(2.5) #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2") self.jNP.getChildren().detach() molo.reparentTo(self.jNP) self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/grenadeball": self.player2Weapon = "grenade" gren = loader.loadModel("models/gamedev/grenade") gren.setScale(2.5) #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2") self.jNP.getChildren().detach() gren.reparentTo(self.jNP) self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/pogo": #done self.jNP.getChildren().detach() self.player2Weapon = "jump" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/golden": #done self.jNP.getChildren().detach() self.player2Weapon = "speedUp" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/crystalball": self.jNP.getChildren().detach() self.player2Weapon = "icestage" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/fireball": #done self.jNP.getChildren().detach() self.player2Weapon = "meteo" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/blackball": #done self.jNP.getChildren().detach() self.player2Weapon = "blind" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/translucent": self.jNP.getChildren().detach() self.player2Weapon = "invis" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/superball": #done self.jNP.getChildren().detach() self.player2Weapon = "invincible" self.acceptOnce("e",self.useWeapon2) self.acceptOnce("q",self.useWeapon2) elif str(cEntry.getIntoNodePath().getParent()) == "render/death": #done self.jNP.getChildren().detach() if self.player2Invincible == 0: self.player1Score+=3 self.reset() cEntry.getIntoNodePath().getParent().removeNode() #Drop a New Ball self.ballNum+=1 z=random.randint(1,2) if z ==1: z=-1 else: z=1 self.movement.append(Vec3(random.random()*z,0,random.random()*z)) weapBalls.define(self.ball,self.ballNum,render) boundsB = self.ball[self.ballNum].getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*.65 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("ball") cNodeB.addSolid(cSphereB) cNodePathB = self.ball[self.ballNum].attachNewNode(cNodeB) def useWeapon1(self): if self.player1Weapon == "meteo": fireRain = Sequence(Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain)) fireRain.start() elif self.player1Weapon == "jump": self.playerModel.detachNode() self.playerModel.reparentTo(render) angle = (self.playerModel.getH())*math.pi/180.0 ProjectileInterval(self.playerModel, startPos = Point3(self.playerModel.getPos()),startVel = Point3(math.sin(angle)*30,0,100), duration= 4.0).start() elif self.player1Weapon == "speedUp": self.speed1 = 6 taskMgr.doMethodLater(5,self.restoreSpeedBG,"restoreStuff") elif self.player1Weapon == "blind": camera.setPos(Vec3(-50,0,0)) taskMgr.doMethodLater(5,self.restoreCamera,"restoreCamera") elif self.player1Weapon == "invincible": self.player1Invincible = 1 taskMgr.doMethodLater(5,self.notInvince1,"mortal1") elif self.player1Weapon == "grenade": self.jNP.getChildren().detach() gren = loader.loadModel("models/gamedev/grenade") gren.setScale(2.5) gren.reparentTo(render) angle = (self.playerModel.getH())*math.pi/180.0 ProjectileInterval(gren, startPos = Point3(self.playerModel.getPos()),startVel = Point3(math.sin(angle)*30,0,10), endZ = -50).start() if gren.getZ() == -50: gren.removeNode() cHandler = CollisionHandlerEvent() cHandler.addInPattern('%fn-into-%in') boundsB = gren.getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*0.65 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("grenade") cNodeB.addSolid(cSphereB) cNodePathB = gren.attachNewNode(cNodeB) self.cTrav.addCollider(cNodePathB,cHandler) self.acceptOnce("grenade-into-platform",self.explode) elif self.player1Weapon == "molotov": self.jNP.getChildren().detach() elif self.player1Weapon == "saw": self.jNP.getChildren().detach() elif self.player1Weapon == "invis": self.jNP.getChildren().detach() self.playerModel2.hide() taskMgr.doMethodLater(4.0,self.showPlayer,"showPlayer") elif self.player1Weapon == "icestage": self.jNP.getChildren().detach() self.speed1 = 6 self.speed2 = 6 self.background.detachNode() self.background2.reparentTo(render) taskMgr.doMethodLater(5,self.restoreSpeedBG,"restoreStuff") def restoreSpeedBG(self,task): self.speed1 = 3 self.speed2 = 3 self.background2.detachNode() self.background.reparentTo(render) def showPlayer(self,task): self.playerModel.show() self.playerModel2.show() def useWeapon2(self): if self.player2Weapon == "meteo": fireRain = Sequence(Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain)) fireRain.start() elif self.player2Weapon == "jump": angle = self.playerModel2.getH()/90 ProjectileInterval(self.playerModel2, startPos = Point3(self.playerModel2.getPos()),startVel = Point3(angle*30,0,100), endZ = self.playerModel2.getZ()).start() elif self.player2Weapon == "speedUp": self.speed2 = 6 elif self.player2Weapon == "blind": camera.setPos(Vec3(-50,0,0)) taskMgr.doMethodLater(5,self.restoreCamera,"restoreCamera") elif self.player2Weapon == "invincible": self.player2Invincible = 1 taskMgr.doMethodLater(5,self.notInvince2,"mortal2") elif self.player2Weapon == "grenade": self.jNP2.getChildren().detach() gren = loader.loadModel("models/gamedev/grenade") gren.setScale(2.5) gren.reparentTo(render) angle = (self.playerModel2.getH())*math.pi/180.0 ProjectileInterval(gren, startPos = Point3(self.playerModel2.getPos()),startVel = Point3(math.sin(angle)*30,0,10), endZ = -50).start() if gren.getZ() == -50: gren.removeNode() cHandler = CollisionHandlerEvent() cHandler.addInPattern('%fn-into-%in') boundsB = gren.getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*0.65 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("grenade") cNodeB.addSolid(cSphereB) cNodePathB = gren.attachNewNode(cNodeB) self.cTrav.addCollider(cNodePathB,cHandler) self.acceptOnce("grenade-into-platform",self.explode) elif self.player2Weapon == "molotov": self.jNP.getChildren().detach() elif self.player2Weapon == "saw": self.jNP.getChildren().detach() elif self.player2Weapon == "invis": self.jNP.getChildren().detach() self.playerModel1.hide() taskMgr.doMethodLater(4.0,self.showPlayer,"showPlayer") elif self.player2Weapon == "icestage": self.jNP2.getChildren().detach() self.speed1 = 6 self.speed2 = 6 self.background.detachNode() self.background2.reparentTo(render) taskMgr.doMethodLater(5,self.restoreSpeedBG,"restoreStuff") def rain(self): meteoBall = Actor("models/gamedev/fireball") meteoBall.reparentTo(render) meteoBall.setScale(2) meteoBall.setH(-15) boundsB = meteoBall.getChild(0).getBounds() centerB = boundsB.getCenter() radiusB = boundsB.getRadius()*0.65 cSphereB = CollisionSphere(centerB,radiusB) cNodeB = CollisionNode("meteor") cNodeB.addSolid(cSphereB) cNodePathB = meteoBall.attachNewNode(cNodeB) #cNodePathB.show() ProjectileInterval(meteoBall, startPos = Point3(random.randint(15,211),0,170),startVel = Point3(-12,0,0), endZ = -50).start() cHandler = CollisionHandlerEvent() cHandler.addInPattern('%fn-into-%in') self.cTrav.addCollider(cNodePathB,cHandler) self.accept("meteor-into-player1",self.player2Wins) self.accept("meteor-into-player2",self.player1Wins) def showBalls(self,task): for i in self.ball: i.show() def notInvince1(self,task): self.player1Invincible = 0 def notInvince2(self,task): self.player2Invincible = 0 def restoreCamera(self,task): camera.setPosHpr(Vec3(98,-390,90), Vec3(0,-5,0)) def switch(self,task): self.environment.setColor(0,1,0.3) def colliding1( self, collEntry ): # accept a collision entry argument if self.ignoreColl == 0: self.player1IsColliding = 1 # we are colliding self.stopWalk( ) # pause all walking animation and movement disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) ) newPos = self.playerModel2.getPos( ) + disp # get new position self.playerModel2.setPos( newPos ) # and set it to tiny's position # end colliding def notColliding1( self, collEntry ): self.player1IsColliding = 0 def colliding2( self, collEntry ): # accept a collision entry argument if self.ignoreColl == 0: self.player2IsColliding = 1 # we are colliding self.stopWalk2( ) # pause all walking animation and movement disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) ) newPos = self.playerModel2B.getPos( ) + disp # get new position self.playerModel2B.setPos( newPos ) # and set it to tiny's position # end colliding def notColliding2( self, collEntry ): self.player2IsColliding = 0 def returnSpeeds(self,task): self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 def returnSpeeds2(self,task): self.acceptOnce("w",self.walk) self.acceptOnce("o",self.walk2) self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 def returnSpeeds3(self,task): self.speed1 = 8.0 self.speed2 = 8.0 self.turnSpeed1 = 80.0 self.turnSpeed2 = 80.0 def changeMusic(self,task): self.music.stop() self.music2 = loader.loadMusic("models/gamedev/ADRENALINE.mp3") self.music2.play() def clockTask(self,task): self.timer.detachNode() self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0) self.timer.setColor(1,1,1) self.timer.reparentTo(render) return Task.cont def ballMovementTask(self,task): self.anp.setY(0) self.anp2.setY(0) for i in range(self.ballNum+1): if i < len(self.ball): if self.ball[i].getX() > 234 or self.ball[i].getX() < -38 or self.ball[i].getZ() < -10 or self.ball[i].getZ() > 132: self.ball[i].setPos(self.ball[i].getPos()/1.005) z=random.randint(1,2) if z ==1: z=-1 else: z=1 self.movement[i]=Vec3(random.random()*z,0,random.random()*z) else: self.ball[i].setPos(self.ball[i].getPos()+self.movement[i]) return Task.cont def fire(self): self.fire = ParticleEffect() self.fire.reset() self.fire.setPos(0.000, 0.000, 0.000) self.fire.setHpr(0.000, 0.000, 0.000) self.fire.setScale(10.000, 10.000, 10.000) p0 = Particles('particles-1') # Particles parameters p0.setFactory("PointParticleFactory") p0.setRenderer("SpriteParticleRenderer") p0.setEmitter("DiscEmitter") p0.setPoolSize(1024) p0.setBirthRate(0.0200) p0.setLitterSize(10) p0.setLitterSpread(0) p0.setSystemLifespan(1200.0000) p0.setLocalVelocityFlag(1) p0.setSystemGrowsOlderFlag(0) # Factory parameters p0.factory.setLifespanBase(2.0000) p0.factory.setLifespanSpread(0.0000) p0.factory.setMassBase(1.0000) p0.factory.setMassSpread(0.0000) p0.factory.setTerminalVelocityBase(400.0000) p0.factory.setTerminalVelocitySpread(0.0000) # Point factory parameters # Renderer parameters p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT) p0.renderer.setUserAlpha(0.22) # Sprite parameters p0.renderer.addTextureFromFile('models/gamedev/sparkle.png') p0.renderer.setColor(Vec4(1.00, 1.00, 1.00, 1.00)) p0.renderer.setXScaleFlag(1) p0.renderer.setYScaleFlag(1) p0.renderer.setAnimAngleFlag(0) p0.renderer.setInitialXScale(0.5000) p0.renderer.setFinalXScale(2.0000) p0.renderer.setInitialYScale(1.0000) p0.renderer.setFinalYScale(2.0000) p0.renderer.setNonanimatedTheta(0.0000) p0.renderer.setAlphaBlendMethod(BaseParticleRenderer.PPNOBLEND) p0.renderer.setAlphaDisable(0) # Emitter parameters p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE) p0.emitter.setAmplitude(1.0000) p0.emitter.setAmplitudeSpread(0.0000) p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 3.0000)) p0.emitter.setExplicitLaunchVector(Vec3(1.0000, 0.0000, 0.0000)) p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000)) # Disc parameters p0.emitter.setRadius(0.5000) self.fire.addParticles(p0) self.fire.setPos(self.playerModel2.getPos()) t = Sequence(Func(self.fire.start, render, render),Wait(20),Func(self.cleanFire)) t.start() def cleanFire(self): self.fire.cleanup() def explode(self,cEntry): self.explosion = ParticleEffect() self.explosion.reset() self.explosion.setPos(cEntry.getIntoNodePath().getParent().getPos()) self.explosion.setHpr(0.000, 0.000, 0.000) self.explosion.setScale(10.000, 10.000, 10.000) p0 = Particles('particles-1') # Particles parameters p0.setFactory("PointParticleFactory") p0.setRenderer("LineParticleRenderer") p0.setEmitter("SphereVolumeEmitter") p0.setPoolSize(10000) p0.setBirthRate(0.0500) p0.setLitterSize(10000) p0.setLitterSpread(0) p0.setSystemLifespan(2.0000) p0.setLocalVelocityFlag(1) p0.setSystemGrowsOlderFlag(1) # Factory parameters p0.factory.setLifespanBase(2.0000) p0.factory.setLifespanSpread(0.0000) p0.factory.setMassBase(.5000) p0.factory.setMassSpread(0.0500) p0.factory.setTerminalVelocityBase(400.0000) p0.factory.setTerminalVelocitySpread(0.0000) # Point factory parameters # Renderer parameters p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT) p0.renderer.setUserAlpha(1.00) # Line parameters p0.renderer.setHeadColor(Vec4(1.00, 0.00, 0.00, 1.00)) p0.renderer.setTailColor(Vec4(1.00, 1.00, 0.00, 1.00)) p0.renderer.setLineScaleFactor(3.00) # Emitter parameters p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE) p0.emitter.setAmplitude(10.0000) p0.emitter.setAmplitudeSpread(0.0000) p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, -0.4930)) p0.emitter.setExplicitLaunchVector(Vec3(1.0000, 0.0000, 0.0000)) p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000)) # Sphere Volume parameters p0.emitter.setRadius(0.5000) self.explosion.addParticles(p0) f0 = ForceGroup('gravity') # Force parameters self.explosion.addForceGroup(f0) cHandler = CollisionHandlerEvent() cHandler.addInPattern('%fn-into-%in') cSphereB = CollisionSphere(cEntry.getIntoNodePath().getParent().getPos(),1) cNodeB = CollisionNode("explosion") cNodeB.addSolid(cSphereB) cNodePathB = self.explosion.attachNewNode(cNodeB) self.cTrav.addCollider(cNodePathB,cHandler) cNodePathB.show() self.accept("player1-into-explosion",self.player2Wins) self.accept("player2-into-explosion",self.player1Wins) #f.reparentTo(self.playerModel) #self.explosion.setPos(self.playerModel.getPos()) t = Sequence(Func(self.explosion.start, render, render),Wait(2),Func(self.cleanExplo)) t.start() cEntry.getFromNodePath().getParent().removeNode() def cleanExplo(self): self.explosion.cleanup() def endGame(self,task): taskMgr.removeTasksMatching('returnSpeedsToNormal') taskMgr.removeTasksMatching('restoreCamera') taskMgr.removeTasksMatching('clockTask') taskMgr.removeTasksMatching('ballMoveTask') self.music.stop() self.music3 = loader.loadMusic("models/gamedev/CSTAR.mp3") self.music3.play() self.speed1 = 0 self.speed2 = 0 def getScores(self): return (self.player1Score, self.player2Score) def getGameLen(self): return self.gameLen def stopMusic(self): self.music3.stop() def destroy(self): self.playerModel.detachNode() self.playerModel2.detachNode() self.background.destroy() self.lava.detachNode() self.ladder.detachNode() self.ladder2.detachNode() for i in range(self.ballNum+1): self.ball[i].detachNode() def stopMusic(self): self.music3.stop() #world = Lvl03() #world.start() #run()
class DBoard(DistributedObject): def __init__(self, cr): DistributedObject.__init__(self, cr) self.accept("checkBoardAnimationDone", self.checkBoardAnimationDone) base.messenger.send("registerLoadEvent", ["loadBoardDone"]) base.messenger.send("registerLoadEvent", ["loadTableDone"]) self.modelLoadList = {"board": False, "table": False} self.boardAnimation = None self.boardAnimationStarted = False self.lightSun = DirectionalLight('light_sun') self.lightSun.setColorTemperature(5300) self.lightSun.setShadowCaster(True, 2048, 2048) self.lightSunNP = render.attachNewNode(self.lightSun) self.lightSunNP.setPos(-2, 2, 2) self.lightSunNP.lookAt(2, -2, -0.5) self.lightAmb = AmbientLight('light_ambient') #self.lightAmb.setColor((0.1, 0.1, 0.1, 1)) self.lightAmb.setColorTemperature(4500) c = self.lightAmb.getColor() self.lightAmb.setColor((c.x / 2, c.y / 2, c.z / 2, 1)) self.lightAmbNP = render.attachNewNode(self.lightAmb) self.accept("loadDone", self.loadDone) self.boardSceneLoadTask = loader.loadModel( "assets/models/board/BoardScene.bam", callback=self.boardLoaded) self.tableLoadTask = loader.loadModel("assets/models/table/Table.bam", callback=self.tableLoaded) # render lights render.setLight(self.lightSunNP) render.setLight(self.lightAmbNP) def boardLoaded(self, boardScene): """Callback event for when the board model has fully loaded""" self.boardScene = boardScene self.boardFlip = Actor(self.boardScene.find("**/BoardArmature"), copy=False) self.boardFlip.reparentTo(self.boardScene) self.camFly = Actor(self.boardScene.find("**/CameraArmature"), copy=False) self.camFly.reparentTo(self.boardScene) bone = self.camFly.exposeJoint(None, "modelRoot", "CamHolder") base.camLens.setNear(0.01) base.camLens.setFar(100) base.camera.reparentTo(bone) base.camera.setP(-90) # render board self.boardSceneNP = self.boardScene.reparentTo(render) self.setupCollisions() base.messenger.send("loadBoardDone") base.messenger.send("loadDone", ["board"]) def tableLoaded(self, table): """Callback event for when the table model has fully loaded""" self.table = table # render table self.tableNP = self.table.reparentTo(render) base.messenger.send("loadTableDone") base.messenger.send("loadDone", ["table"]) def loadDone(self, model): """Check function to determine if all models have loaded. If all models have been loaded, the boardDone event will be fired.""" self.modelLoadList[model] = True for key, value in self.modelLoadList.items(): if value == False: return self.ignore("loadDone") base.messenger.send("boardDone") def announceGenerate(self): # tell everyone interested, that the board DO has been generated base.messenger.send(self.cr.uniqueName("board_generated"), [self.doId]) # call the base class method DistributedObject.announceGenerate(self) def disable(self): self.ignoreAll() self.boardScene.detachNode() self.table.detachNode() DistributedObject.disable(self) def delete(self): """Cleanup just before deletion of the DO""" # cleanup events self.ignoreAll() # cleanup models self.boardFlip.cleanup() self.camFly.cleanup() self.boardFlip.removeNode() self.camFly.removeNode() self.table.removeNode() self.boardAnimation = None # cleanup light try: render.clearLight(self.lightSunNP) render.clearLight(self.lightAmbNP) except: print("clear lights failed.") self.lightSunNP.removeNode() self.lightAmbNP.removeNode() # cleanup collisions for field in BoardMap.gameMap: field.collisionNP.removeNode() # cleanup other variables self.modelLoadList = {"board": False, "table": False} self.boardAnimation = None self.boardAnimationStarted = False DistributedObject.delete(self) def start(self): """Start the board animation""" taskMgr.step() self.boardAnimationStarted = True self.boardAnimation = Sequence( Parallel(self.boardFlip.actorInterval("BoardFlipUp"), self.camFly.actorInterval("CamFly")), Func(base.messenger.send, "BoardAnimationDone")) self.boardAnimation.start() def checkBoardAnimationDone(self): """Check if the board animation has been stopped and resend the respective event if it has.""" # check if we have an animation and it has actually been started once if self.boardAnimation is not None and self.boardAnimationStarted: # now check if the animation is done if self.boardAnimation.isStopped(): # resend the event base.messenger.send("BoardAnimationDone") def setupCollisions(self): """Setup the collision solids for all fields. NOTE: This can be removed once blend2bam supports invisible collision model export""" for field in BoardMap.gameMap: # create a sphere collision solid cs = CollisionSphere(0, 0, 0, 0.01) cn = CollisionNode("{}-collision".format(field.name)) cn.addSolid(cs) fieldNP = self.boardScene.find("**/{}".format(field.name)) field.collisionNP = fieldNP.attachNewNode(cn) field.collisionNP.setCollideMask(BitMask32(0x80))
class Npc(): def __init__(self, controlPointId, id, anchorx, anchory, anchorz, render, team): self.id = id self.anchorx = anchorx self.anchory = anchory self.anchorz = anchorz self.controlPointId = controlPointId self.target = None self.isMoving = False self.health = 200 self.isCurrentUser = False self.damage = 8 self.attackTimer = 0 self._is_dead = False self._team = team self.render = render '''Initializing NPC actors''' self.npc = Actor( "models/priest", { "walk": "models/priest-walk", "attack": "models/priest-attack", "hurt": "models/priest-hit", "die": "models/priest-die" }) if self._team == 0: self.npcTex = loader.loadTexture("models/tex/guard_red.png") else: self.npcTex = loader.loadTexture("models/tex/guard_blue.png") self.npc.setTexture(self.npcTex) self.npc.setScale(0.5, 0.5, 0.5) self.npc.clearColor() self.npc.clearColorScale() self.npc.setColor(255, 0, 0, 0) self.npc.setColorScale(255, 0, 0, 0) self.npc.reparentTo(self.render) self.npc.setPos(anchorx, anchory, anchorz) self.AIchar = AICharacter("npc" + str(self.id), self.npc, 100, 0.05, 5) self.AIbehaviors = self.AIchar.getAiBehaviors() self.hb = HealthBar(1.5, value=self.health) #self._floater = NodePath(PandaNode("char_info")) #self._floater.reparentTo(self.npc) self.hb.setPos(0, 0, 11.9) self.hb.reparentTo(self.npc) #self.hb.reparentTo(self.npc) def renderBlue(self, AIworld): if not self._is_dead: self.AIbehaviors.removeAi("pursue") self.npc.detachNode() print "Started delete procedure for npc ", print self.id self.npc.delete() self.npc = Actor( "models/priest", { "walk": "models/priest-walk", "attack": "models/priest-attack", "hurt": "models/priest-hit", "die": "models/priest-die" }) self.npcTex = loader.loadTexture("models/tex/guard_blue.png") self.npc.setTexture(self.npcTex) self.npc.setScale(0.5, 0.5, 0.5) self.npc.clearColor() self.npc.clearColorScale() self.npc.setColor(255, 0, 0, 0) self.npc.setColorScale(255, 0, 0, 0) self.npc.reparentTo(self.render) self.npc.setPos(self.anchorx, self.anchory, self.anchorz) AIworld.removeAiChar("npc" + str(self.id)) self.AIchar = AICharacter("npc" + str(self.id), self.npc, 100, 0.05, 5) self.AIbehaviors = self.AIchar.getAiBehaviors() AIworld.addAiChar(self.AIchar) self.hb = HealthBar(1.5, value=self.health) self.hb.setPos(0, 0, 18.1) self.hb.reparentTo(self.npc) #self.hb.reparentTo(self.npc) def renderRed(self, AIworld): if not self._is_dead: self.AIbehaviors.removeAi("pursue") self.npc.detachNode() self.npc.delete() self.npc = Actor( "models/priest", { "walk": "models/priest-walk", "attack": "models/priest-attack", "hurt": "models/priest-hit", "die": "models/priest-die" }) self.npcTex = loader.loadTexture("models/tex/guard_red.png") self.npc.setTexture(self.npcTex) self.npc.setScale(0.5, 0.5, 0.5) self.npc.clearColor() self.npc.clearColorScale() self.npc.setColor(255, 0, 0, 0) self.npc.setColorScale(255, 0, 0, 0) self.npc.reparentTo(self.render) self.npc.setPos(self.anchorx, self.anchory, self.anchorz) AIworld.removeAiChar("npc" + str(self.id)) self.AIchar = AICharacter("npc" + str(self.id), self.npc, 100, 0.05, 5) self.AIbehaviors = self.AIchar.getAiBehaviors() AIworld.addAiChar(self.AIchar) AIworld.update() self.hb = HealthBar(1.5, value=self.health) self.hb.setPos(0, 0, 8.1) self.hb.reparentTo(self.npc) def switchTeam(self, AIworld): print self.id, print " from team ", print self._team, print " getting deleted." if self._team == 0: self._team = 1 self.renderBlue(AIworld) else: self._team = 0 self.renderRed(AIworld) if self.isCurrentUser: main.freeDeadNpc(self.id) self.target = None self.isMoving = False self.health = 200 self.isCurrentUser = False self.damage = 8 self.attackTimer = 0 self._is_dead = False def set_health(self, health): self.health = health def take_damage(self, health_change): health = self.health if health <= health_change and not self._is_dead: self.killNpc() else: health = health - health_change self.set_health(health) self.hb.setValue(self.health) self.npc.play("hurt") def killNpc(self): self.set_health(0) self.hb.setValue(0) self.AIbehaviors.removeAi("pursue") hurt_interval = self.npc.actorInterval("hurt") death_interval = self.npc.actorInterval("die") seq = Sequence(hurt_interval, death_interval) seq.start() self.npc.pose("die", 45) self._is_dead = True self.npc.detachNode() if self.isCurrentUser: main.freeDeadNpc(self.id) #main.cManager.sendRequest(Constants.CMSG_NPCDEATH, [self.id]) print Constants.CMSG_NPCDEATH, print " + ", print self.id def chaseTarget(self, target, status=False): if (not self.isMoving): self.target = target self.AIbehaviors.pursue(self.target) self.npc.loop("walk") self.isMoving = True self.isCurrentUser = status def stopChase(self): #self.AIbehaviors.pauseAi("pursue") if not self._is_dead: self.AIbehaviors.removeAi("pursue") p1 = LerpHprInterval(self.npc, 4, Point3(180, 0, 0)) p2 = LerpPosInterval( self.npc, 4, Point3(self.anchorx, self.anchory, self.anchorz)) animInterval = self.npc.actorInterval("walk", loop=1, duration=4) p2.start() p1.start() animInterval.start() self.isMoving = False self.target = None self.isCurrentUser = False def givNPCDistance(self, charachter): x = self.npc.getX() y = self.npc.getY() z = self.npc.getZ() minDist = math.sqrt((charachter.getX() - x) * (charachter.getX() - x) + (charachter.getY() - y) * (charachter.getY() - y) + (charachter.getZ() - z) * (charachter.getZ() - z)) return minDist def checkNpcIsAlive(self): if (self.health > 0): return True else: return False def shouldAttack(self, currentTime, cManager): if not self._is_dead: if self.isMoving: if self.attackTimer > 0: self.attackTimer = self.attackTimer - currentTime #print self.attackTimer if self.AIbehaviors.behaviorStatus("pursue") == "done": #self.npc.stop("walk") #print self.npc.getAnimControl("walk") if self.attackTimer <= 0: if self.npc.getAnimControl("walk").isPlaying(): self.npc.stop("walk") if not self.npc.getAnimControl("attack").isPlaying(): #self.npc.loop("attack") self.npc.play("attack") self.attackTimer = 2 #myInterval = self.npc.actorInterval("attack") #seq = Sequence(myInterval) #seq.append(Wait(3)) #seq.start() if self.isCurrentUser: cManager.sendRequest(Constants.CMSG_NPCATTACK, [self.id, self.damage]) if self.AIbehaviors.behaviorStatus("pursue") == "active": if self.npc.getAnimControl("attack").isPlaying(): self.npc.stop("attack") if not self.npc.getAnimControl("walk").isPlaying(): self.npc.loop("walk")
class WindowSplash: def setup(self): x_size, y_size = base.win.get_x_size(), base.win.get_y_size() bg_buffer = base.win.makeTextureBuffer( "Background Scene", x_size, y_size, ) bg_buffer.set_clear_color_active(True) bg_buffer.set_clear_color(VBase4(0, 1, 0, 1)) bg_buffer.set_sort(-100) # render buffer before main scene. bg_texture = bg_buffer.get_texture() self.bg_texture = bg_texture bg_camera = base.make_camera(bg_buffer) self.setup_background_scene(bg_camera) # Foreground Scene base.win.set_clear_color((0, 0, 0, 1)) cam_dist = 2 base.cam.set_pos(0, -2.2 * cam_dist, 0) base.cam.node().get_lens().set_fov(45/cam_dist) self.logo_animation = Actor(asset_path / "panda3d_logo.bam") self.logo_animation.reparent_to(render) self.logo_animation.set_two_sided(True) shader = Shader.load( Shader.SL_GLSL, vertex=asset_path / "splash_window.vert", fragment=asset_path / "splash_window.frag", ) self.logo_animation.set_shader(shader) self.logo_animation.set_shader_input("background", bg_texture) self.logo_animation.set_shader_input("fade", 0.0) self.logo_sound = base.loader.loadSfx(asset_path / "panda3d_logo.wav") # Build interval def fade_background_to_white(t): base.win.set_clear_color((t,t,t,1)) self.logo_animation.set_shader_input("fade", t) def set_background_texture(t): self.logo_animation.set_shader_input( "background", self.bg_texture, ) effects = Parallel( self.logo_animation.actorInterval( "splash", loop=False, ), SoundInterval( self.logo_sound, loop=False, ), Sequence( LerpFunc( set_background_texture, fromData=0, toData=1, duration=3.878, ), LerpFunc( fade_background_to_white, fromData=0, toData=1, duration=1.0, ), ), ) return effects def teardown(self): self.teardown_background_scene() self.logo_animation.cleanup() # FIXME: Destroy self.logo_sound # FIXME: Destroy the extra buffer stuff def setup_background_scene(self, bg_camera): """ Override this to set up the scene that will be seen through the splash's shards. bg_camera The camera watching the background scene """ # The scene to be rendered to texture bg_scene = NodePath("My Scene") bg_camera.reparent_to(bg_scene) bg_camera.set_pos(0, -100, 50) bg_camera.look_at(0, 0, 0) model = base.loader.loadModel('models/environment') model.reparent_to(bg_scene) model.set_scale(0.25) def teardown_background_scene(self): """ Override this to tear down your scene again. """ pass
class Player(FSM, DirectObject): NormalMode = "Normal" FightMode = "Fight" GAMEPADMODE = "Gamepad" MOUSEANDKEYBOARD = "MouseAndKeyboard" def __init__(self): FSM.__init__(self, "FSM-Player") random.seed() # # PLAYER CONTROLS AND CAMERA # self.player = Actor( "Character", { "Idle": "Character-Idle", "Run": "Character-Run", "Activate": "Character-Activate", "Death": "Character-Death", "Jump": "Character-Jump", "Hit": "Character-Hit", "Fight_Attack": "Character-FightAttack", "Fight_Idle": "Character-FightIdle", "Fight_Left": "Character-FightLeft", "Fight_Right": "Character-FightRight", }, ) self.player.setBlend(frameBlend=True) # the initial cam distance self.fightCamDistance = 3.0 # the next two vars will set the min and max distance the cam can have # to the node it is attached to self.maxCamDistance = 4.0 self.minCamDistance = 1.2 # the initial cam distance self.camDistance = (self.maxCamDistance - self.minCamDistance) / 2.0 + self.minCamDistance # the next two vars set the min and max distance on the Z-Axis to the # node the cam is attached to self.maxCamHeightDist = 3.0 self.minCamHeightDist = 1.5 # the average camera height self.camHeightAvg = (self.maxCamHeightDist - self.minCamHeightDist) / 2.0 + self.minCamHeightDist # an invisible object which will fly above the player and will be used to # track the camera on it self.camFloater = NodePath(PandaNode("playerCamFloater")) self.camFloater.setPos(0, 0, 1.5) self.camFloater.reparentTo(self.player) # screen sizes self.winXhalf = base.win.getXSize() / 2 self.winYhalf = base.win.getYSize() / 2 # Interval for the jump animation self.jumpInterval = None self.jumpstartFloater = NodePath(PandaNode("jumpstartFloater")) self.jumpstartFloater.reparentTo(render) self.deathComplete = None # Joystick/Gamepad support self.hasJoystick = False if gamepadSupport: # initialize controls joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())] if len(joysticks) > 0: self.mainJoystick = joysticks[0] self.mainJoystick.init() self.hasJoystick = True # # WEAPONS AND ACCESSORIES # self.RightHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_R") self.spear = loader.loadModel("Spear") self.spear.setP(90) self.spear.setR(180) self.spear.reparentTo(self.RightHandAttach) self.LeftHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_L") self.shield = loader.loadModel("Shield") self.shield.setZ(0.05) self.shield.setH(-90) self.shield.reparentTo(self.LeftHandAttach) # # PLAYER COLLISION DETECTION AND PHYSICS # self.playerSphere = CollisionSphere(0, 0, 0.8, 0.7) self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision")) self.playerCollision.node().addSolid(self.playerSphere) base.pusher.addCollider(self.playerCollision, self.player) base.cTrav.addCollider(self.playerCollision, base.pusher) # The foot collision checks self.footRay = CollisionRay(0, 0, 0, 0, 0, -1) self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision")) self.playerFootRay.node().addSolid(self.footRay) self.playerFootRay.node().setIntoCollideMask(0) self.lifter = CollisionHandlerFloor() self.lifter.addCollider(self.playerFootRay, self.player) self.lifter.setMaxVelocity(5) base.cTrav.addCollider(self.playerFootRay, self.lifter) # a collision segment slightly in front of the player to check for jump ledges self.jumpCheckSegment = CollisionSegment(0, -0.2, 0.5, 0, -0.2, -2) self.playerJumpRay = self.player.attachNewNode(CollisionNode("playerJumpCollision")) self.playerJumpRay.node().addSolid(self.jumpCheckSegment) self.playerJumpRay.node().setIntoCollideMask(0) self.jumper = CollisionHandlerEvent() self.jumper.addOutPattern("%fn-out") base.cTrav.addCollider(self.playerJumpRay, self.jumper) # a collision segment to check attacks self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1) self.playerAttackRay = self.player.attachNewNode(CollisionNode("playerAttackCollision")) self.playerAttackRay.node().addSolid(self.attackCheckSegment) self.playerAttackRay.node().setIntoCollideMask(0) self.attackqueue = CollisionHandlerQueue() base.cTrav.addCollider(self.playerAttackRay, self.attackqueue) # # SOUNDEFFECTS # self.footstep = loader.loadSfx("Footstep.ogg") self.footstep.setLoop(True) self.footstep.setPlayRate(1.5) self.footstep.setVolume(0.5) self.spearAttackSfx = loader.loadSfx("SpearAttack.ogg") self.spearAttackSfx.setVolume(0.5) # # START/STOP # def start(self, startPoint): self.player.setPos(startPoint.getPos()) self.player.setHpr(startPoint.getHpr()) self.player.reparentTo(render) self.jumpstartFloater.setPos(self.player.getPos()) self.keyMap = {"horizontal": 0, "vertical": 0} self.health = 3 self.trackedEnemy = None # this mode will be used to determine in which move mode the player currently is self.mode = Player.NormalMode # the initial cam height self.camHeight = self.camHeightAvg # a time to keep the cam zoom at a specific speed independent of # current framerate self.camElapsed = 0.0 self.mouseSpeedX = 15.0 * base.mouseSensitivity self.mouseSpeedY = 0.2 * base.mouseSensitivity self.speed = 1.0 self.camCenterEvents = ["centerCam", "home", "q"] self.camZoomInEvents = ["zoomIn", "+", "wheel_up"] self.camZoomOutEvents = ["zoomOut", "-", "wheel_down"] self.actionEvents = ["doAction", "enter", "e"] self.accept("arrow_left", self.setKey, ["horizontal", 1]) self.accept("arrow_right", self.setKey, ["horizontal", -1]) self.accept("arrow_up", self.setKey, ["vertical", -1]) self.accept("arrow_down", self.setKey, ["vertical", 1]) self.accept("arrow_left-up", self.setKey, ["horizontal", 0]) self.accept("arrow_right-up", self.setKey, ["horizontal", 0]) self.accept("arrow_up-up", self.setKey, ["vertical", 0]) self.accept("arrow_down-up", self.setKey, ["vertical", 0]) self.accept("a", self.setKey, ["horizontal", 1]) self.accept("d", self.setKey, ["horizontal", -1]) self.accept("w", self.setKey, ["vertical", -1]) self.accept("s", self.setKey, ["vertical", 1]) self.accept("a-up", self.setKey, ["horizontal", 0]) self.accept("d-up", self.setKey, ["horizontal", 0]) self.accept("w-up", self.setKey, ["vertical", 0]) self.accept("s-up", self.setKey, ["vertical", 0]) for event in self.camCenterEvents: self.acceptOnce(event, self.center) for event in self.camZoomInEvents: self.acceptOnce(event, self.zoom, [True]) for event in self.camZoomOutEvents: self.acceptOnce(event, self.zoom, [False]) for event in self.actionEvents: self.acceptOnce(event, self.request, ["Action"]) self.accept("ActionDone", self.request, ["Idle"]) self.accept("playerJumpCollision-out", self.jump) taskMgr.add(self.move, "task_movement", priority=-10) taskMgr.add(self.updateCam, "task_camActualisation", priority=-4) if self.hasJoystick: taskMgr.add(self.gamepadLoop, "task_gamepad_loop", priority=-5) camera.setPos(self.player, 0, self.camDistance, self.camHeightAvg) self.hasJumped = False self.isActionmove = False self.request("Idle") def stop(self): taskMgr.remove("task_movement") taskMgr.remove("task_camActualisation") taskMgr.remove("task_gamepad_loop") self.ignoreAll() self.player.hide() def cleanup(self): self.stop() if self.deathComplete is not None: self.deathComplete.finish() if self.jumpInterval is not None: self.jumpInterval.finish() self.spear.removeNode() self.shield.removeNode() self.player.cleanup() self.player.removeNode() self.jumpstartFloater.removeNode() self.camFloater.removeNode() # # BASIC FUNCTIONS # def die(self): self.health -= 1 base.messenger.send("setHealth", [self.health]) self.request("Death") def heal(self): if self.health >= 3: return self.health += 1 base.messenger.send("setHealth", [self.health]) def hit(self): self.health -= 1 base.messenger.send("setHealth", [self.health]) if self.health == 0: self.request("Death") else: self.request("Hit") def resetPlayerPos(self): self.player.setPos(self.jumpstartFloater.getPos()) self.jumper.clear() self.request("Idle") def gameOver(self): base.messenger.send("GameOver", ["loose"]) def enterFightMode(self, trackedEnemy): self.trackedEnemy = trackedEnemy self.mode = Player.FightMode base.messenger.send("EnterFightMode") def exitFightMode(self): self.trackedEnemy = None self.mode = Player.NormalMode base.messenger.send("ExitFightMode") def gamepadLoop(self, task): joymap = {0: "doAction", 5: "centerCam", 6: "zoomIn", 4: "zoomOut", 9: "escape"} for event in pygame.event.get(): for button in range(self.mainJoystick.get_numbuttons()): if button in joymap and self.mainJoystick.get_button(button): base.messenger.send(joymap[button]) if event.type == pygame.JOYAXISMOTION: for axis in range(self.mainJoystick.get_numaxes()): axisChange = 0.0 axisChange = self.mainJoystick.get_axis(axis) if axis == 0: self.setKey("horizontal", -axisChange) if axis == 1: self.setKey("vertical", axisChange) return task.cont def setAnimationSpeed(self, requestedState): if requestedState == "Run": self.player.setPlayRate(3 * self.speed, "Run") elif requestedState == "RunReverse": self.player.setPlayRate(-3 * self.speed, "Run") elif requestedState == "FightLeft": self.player.setPlayRate(2 * self.speed, "Fight_Left") elif requestedState == "FightRight": self.player.setPlayRate(2 * self.speed, "Fight_Right") # # MOVE FUNCTIONS # def setKey(self, key, value): self.keyMap[key] = value def move(self, task): dt = globalClock.getDt() resetMouse = False def resetMouse(): if base.controlType == Player.MOUSEANDKEYBOARD: base.win.movePointer(0, self.winXhalf, self.winYhalf) if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying(): resetMouse() return task.cont if self.deathComplete is not None: if self.deathComplete.isPlaying(): resetMouse() return task.cont if self.jumpInterval is not None: if self.jumpInterval.isPlaying(): resetMouse() return task.cont if self.isActionmove: resetMouse() return task.cont if self.mode == Player.NormalMode: self.__normalMove(dt) else: self.__fightMove(dt) return task.cont def __normalMove(self, dt): requestState = "Idle" move = False if self.keyMap["horizontal"] != 0: requestState = "Run" move = True if self.keyMap["vertical"] != 0: requestState = "Run" move = True if move and base.controlType == Player.GAMEPADMODE: movementVec = Vec3(self.keyMap["horizontal"], self.keyMap["vertical"], 0) self.speed = max(abs(self.keyMap["horizontal"]), abs(self.keyMap["vertical"])) angle = math.atan2(-movementVec.getX(), movementVec.getY()) rotation = angle * (180.0 / math.pi) self.player.setH(camera, rotation) self.player.setP(0) self.player.setR(0) self.player.setPos(self.player, (0, -2 * self.speed * dt, 0)) elif base.controlType == Player.MOUSEANDKEYBOARD: if not base.mouseWatcherNode.hasMouse(): return self.pointer = base.win.getPointer(0) mouseX = self.pointer.getX() mouseY = self.pointer.getY() if base.win.movePointer(0, self.winXhalf, self.winYhalf): z = camera.getZ() + (mouseY - self.winYhalf) * self.mouseSpeedY * dt camera.setZ(z) h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX * dt if h < -360: h = 360 elif h > 360: h = -360 self.player.setH(h) if move: self.player.setPos( self.player, (2 * dt * self.keyMap["horizontal"], 2 * dt * self.keyMap["vertical"], 0) ) self.center() if self.state != requestState: self.request(requestState) self.setAnimationSpeed(requestState) def __fightMove(self, dt): if self.trackedEnemy == None: return requestState = "Idle" self.player.lookAt(self.trackedEnemy) self.player.setH(self.player, 180) if self.keyMap["horizontal"] > 0: self.player.setX(self.player, 2 * self.speed * dt) requestState = "FightLeft" elif self.keyMap["horizontal"] < 0: self.player.setX(self.player, -2 * self.speed * dt) requestState = "FightRight" elif self.keyMap["vertical"] < 0: self.player.setY(self.player, -2 * self.speed * dt) requestState = "Run" elif self.keyMap["vertical"] > 0: self.player.setY(self.player, 2 * self.speed * dt) requestState = "RunReverse" if self.state != requestState: self.request(requestState) self.setAnimationSpeed(requestState) def jump(self, extraArg): intoName = extraArg.getIntoNode().getName().lower() if not "floor" in intoName and not "plate" in intoName: return # setup the projectile interval startPos = self.player.getPos() self.jumpstartFloater.setPos(self.player, 0, 0.5, 0) tempFloater = NodePath(PandaNode("tempJumpFloater")) tempFloater.setPos(self.player, 0, -3.2, 0.1) endPos = tempFloater.getPos() tempFloater.removeNode() self.jumpInterval = ProjectileInterval( self.player, startPos=startPos, endPos=endPos, duration=1.5, gravityMult=0.25 ) self.request("Jump") self.jumpInterval.start() # # CAMERA FUNCTIONS # def updateCam(self, task): if self.mode == Player.NormalMode: self.__normalCam() else: self.__fightCam() return task.cont def zoom(self, zoomIn): # Camera Movement Updates camvec = self.player.getPos() - camera.getPos() camvec.setZ(0) camdist = camvec.length() zoom = 0 if zoomIn: if camdist > self.minCamDistance + 0.5: zoom = 0.5 for event in self.camZoomInEvents: self.acceptOnce(event, self.zoom, [True]) else: if camdist < self.maxCamDistance - 0.5: zoom = -0.5 for event in self.camZoomOutEvents: self.acceptOnce(event, self.zoom, [False]) camera.setPos(camera, 0, zoom, 0) def center(self): # Camera Movement Updates camvec = self.player.getPos() - camera.getPos() camvec.setZ(0) camdist = camvec.length() # get the cameras current offset to the player model on the z-axis offsetZ = camera.getZ() - self.player.getZ() camera.setPos(self.player, 0, camdist, offsetZ) for event in self.camCenterEvents: self.acceptOnce(event, self.center) def __normalCam(self): """This function will check the min and max distance of the camera to the defined model and will correct the position if the cam is to close or to far away""" # Camera Movement Updates camvec = self.player.getPos() - camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() # If far from player start following if camdist > self.maxCamDistance: camera.setPos(camera.getPos() + camvec * (camdist - self.maxCamDistance)) camdist = self.maxCamDistance # If player to close move cam backwards if camdist < self.minCamDistance: camera.setPos(camera.getPos() - camvec * (self.minCamDistance - camdist)) camdist = self.minCamDistance # get the cameras current offset to the player model on the z-axis offsetZ = camera.getZ() - self.player.getZ() # check if the camera is within the min and max z-axis offset if offsetZ < self.minCamHeightDist: camera.setZ(self.player.getZ() + self.minCamHeightDist) offsetZ = self.minCamHeightDist elif offsetZ > self.maxCamHeightDist: camera.setZ(self.player.getZ() + self.maxCamHeightDist) offsetZ = self.maxCamHeightDist if offsetZ != self.camHeightAvg and not base.controlType == Player.MOUSEANDKEYBOARD: # if we are not moving up or down, set the cam to an average position if offsetZ != self.camHeightAvg: if offsetZ > self.camHeightAvg: # the cam is higher then the average cam height above the player # so move it slowly down camera.setZ(camera.getZ() - 5 * globalClock.getDt()) newOffsetZ = camera.getZ() - self.player.getZ() # check if the cam has reached the desired offset if newOffsetZ < self.camHeightAvg: # set the cam z position to exactly the desired offset camera.setZ(self.player.getZ() + self.camHeightAvg) else: # the cam is lower then the average cam height above the player # so move it slowly up camera.setZ(camera.getZ() + 5 * globalClock.getDt()) newOffsetZ = camera.getZ() - self.player.getZ() # check if the cam has reached the desired offset if newOffsetZ > self.camHeightAvg: # set the cam z position to exactly the desired offset camera.setZ(self.player.getZ() + self.camHeightAvg) camera.lookAt(self.camFloater) def __fightCam(self): """This function will check the min and max distance of the camera to the defined model and will correct the position if the cam is to close or to far away""" camera.setX(self.player, 0) camera.setY(self.player, self.fightCamDistance) camera.setZ(0.5) camera.lookAt(self.camFloater) # # FSM FUNCTIONS # def enterIdle(self): if self.mode == Player.NormalMode: self.player.loop("Idle") self.footstep.stop() elif self.mode == Player.FightMode: self.player.loop("Fight_Idle") self.footstep.stop() def enterRun(self): self.player.loop("Run") self.footstep.play() def enterRunReverse(self): self.player.loop("Run") self.footstep.play() def enterAction(self): if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying(): self.__exitAction() return self.isActionmove = True if self.mode == Player.NormalMode: self.__enterActivate() elif self.mode == Player.FightMode: self.__enterFightAttack() self.accept("ActionDone", self.__exitAction) def __exitAction(self): self.isActionmove = False for event in self.actionEvents: self.acceptOnce(event, self.request, ["Action"]) def __enterActivate(self): activateAnim = self.player.actorInterval("Activate", playRate=3) activateAnim.setDoneEvent("ActionDone") activateAnim.start() base.messenger.send("Player_Activate") self.footstep.stop() def enterDeath(self): self.footstep.stop() deathAnim = self.player.actorInterval("Death") deathComplete = None if self.health == 0: self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.gameOver)) else: self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.resetPlayerPos)) self.deathComplete.start() def enterJump(self): self.player.play("Jump") self.footstep.stop() def enterHit(self): self.player.setPlayRate(4, "Hit") self.player.play("Hit") self.footstep.stop() def __enterFightAttack(self): attackAnim = self.player.actorInterval("Fight_Attack", playRate=3) attackAnim.setDoneEvent("ActionDone") attackAnim.start() self.spearAttackSfx.play() for i in range(self.attackqueue.getNumEntries()): entry = self.attackqueue.getEntry(i) into = entry.getIntoNode() if "golemHitField" in into.getName(): if random.random() > 0.15: base.messenger.send("HitEnemy") self.footstep.stop() def enterFightLeft(self): self.player.loop("Fight_Left") self.footstep.play() def enterFightRight(self): self.player.loop("Fight_Right") self.footstep.play()
class CharGen(DirectObject): def __init__(self, common): self.common=common self.common['chargen']=self self.load() def load(self): self.font = loader.loadFont('Bitter-Bold.otf') self.currentLevel=0 self.common['pc_stat1']=50 self.common['pc_stat2']=50 self.common['pc_stat3']=50 #render.setShaderAuto() #base.disableMouse() #render.setAntialias(AntialiasAttrib.MMultisample) #base.setBackgroundColor(0, 0, 0) wp = base.win.getProperties() winX = wp.getXSize() winY = wp.getYSize() self.campmap=loader.loadModel("models/camp3") self.campmap.reparentTo(render) #music self.common['music']=MusicPlayer(self.common) self.common['music'].loop(0) #self.common['music']=base.loadMusic("music/LuridDeliusion.ogg") #self.common['music'].setLoop(True) #self.common['music'].play() self.node=render.attachNewNode("node") self.cameraNode = self.node.attachNewNode("cameraNode") self.cameraNode.setZ(-1) base.camera.setY(-8) base.camera.setZ(5) base.camera.lookAt((0,3,0)) base.camera.wrtReparentTo(self.cameraNode) self.pointer=self.cameraNode.attachNewNode("pointerNode") #light self.pLight = PointLight('plight') self.pLight.setColor(VBase4(1, .95, .9, 1)) self.pLight.setAttenuation(Point3(.5, 0, 0.1)) self.pLightNode = self.node.attachNewNode(self.pLight) self.pLightNode.setZ(1.0) render.setLight(self.pLightNode) self.sLight=Spotlight('sLight') self.sLight.setColor(VBase4(.4, .25, .25, 1)) if self.common['extra_ambient']: self.sLight.setColor(VBase4(.7, .5, .5, 1)) spot_lens = PerspectiveLens() spot_lens.setFov(40) self.sLight.setLens(spot_lens) self.Ambient = self.cameraNode.attachNewNode( self.sLight) self.Ambient.setPos(base.camera.getPos(render)) self.Ambient.lookAt((0,3,0)) render.setLight(self.Ambient) self.fire_node=self.node.attachNewNode("fireNode") self.fire=vfx(self.fire_node, texture='vfx/big_fire3.png',scale=.29, Z=.5, depthTest=True, depthWrite=True) self.fire.show() self.fire.loop(0.02) self.character1=Actor("models/pc/male", {"attack":"models/pc/male_attack2","idle":"models/pc/male_ready2", "block":"models/pc/male_block"}) self.character1.reparentTo(self.node) self.character1.setBlend(frameBlend = True) self.character1.setPos(1,2, 0) self.character1.setScale(.025) self.character1.setH(-25.0) self.character1.setBin("opaque", 10) self.character1.loop("idle") self.swingSound = base.loader.loadSfx("sfx/swing2.ogg") coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(1, 2, 1, 1)) coll_sphere.setTag("class", "1") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) if self.common['nude']: self.character2=Actor("models/pc/female_nude", {"attack":"models/pc/female_attack1","idle":"models/pc/female_idle"}) else: self.character2=Actor("models/pc/female", {"attack":"models/pc/female_attack1","idle":"models/pc/female_idle"}) #self.character2.setPlayRate(.4, "attack") self.character2.reparentTo(self.node) self.character2.setBlend(frameBlend = True) self.character2.setPos(-1,2, 0) self.character2.setScale(.026) self.character2.setH(25.0) #self.character2.setBin("opaque", 10) self.character2.loop("idle") self.char2_magic= loader.loadModel('vfx/vfx3') self.char2_magic.setPos(self.character2.getPos()) self.char2_magic.setH(self.character2.getH()) self.char2_magic.setP(-10.0) self.char2_magic.setZ(0.71) self.char2_magic.setScale(1,2,1) self.char2_magic.wrtReparentTo(self.character2) self.char2_magic.setY(-10) self.char2_magic.setDepthWrite(False) self.char2_magic.setDepthTest(False) self.char2_magic.setLightOff() self.char2_magic.hide() self.vfxU=-0.125 self.vfxV=0 self.magicSound = base.loader.loadSfx("sfx/thunder3.ogg") coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(-1, 2, 1, 1)) coll_sphere.setTag("class", "2") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) if self.common['nude']: self.character3=Actor("models/pc/female2_nude", {"attack":"models/pc/female2_arm","reset":"models/pc/female2_fire","idle":"models/pc/female2_idle"}) else: self.character3=Actor("models/pc/female2", {"attack":"models/pc/female2_arm","reset":"models/pc/female2_fire","idle":"models/pc/female2_idle"}) #self.character2.setPlayRate(.4, "attack") self.character3.reparentTo(self.node) self.character3.setBlend(frameBlend = True) self.character3.setPos(-1.8,0.9, 0) self.character3.setScale(.026) self.character3.setH(40.0) #self.character2.setBin("opaque", 10) self.character3.loop("idle") coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(-1.8,0.9, 0, 1)) coll_sphere.setTag("class", "3") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) self.arrow_bone=self.character3.exposeJoint(None, 'modelRoot', 'arrow_bone') self.arrow=loader.loadModel('models/arrow') self.arrow.reparentTo(self.arrow_bone) self.arrow.setP(-45) self.movingArrow=None self.arrowTime=0.0 self.drawSound = base.loader.loadSfx("sfx/draw_bow2.ogg") self.fireSound = base.loader.loadSfx("sfx/fire_arrow3.ogg") self.character4=Actor("models/pc/male2", {"attack":"models/pc/male2_aura","idle":"models/pc/male2_idle"}) #self.character2.setPlayRate(.4, "attack") self.character4.reparentTo(self.node) self.character4.setBlend(frameBlend = True) self.character4.setPos(1.8,0.9, 0) self.character4.setScale(.024) self.character4.setH(-60.0) #self.character2.setBin("opaque", 10) self.character4.loop("idle") self.FFSound = base.loader.loadSfx("sfx/teleport.ogg") #self.FFSound = base.loader.loadSfx("sfx/walk_new3.ogg") coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere')) coll_sphere.node().addSolid(CollisionSphere(1.8,0.9, 0, 1)) coll_sphere.setTag("class", "4") coll_sphere.node().setIntoCollideMask(BitMask32.bit(1)) #gui self.mp_logo=DirectFrame(frameSize=(-512, 0, 0, 128), frameColor=(1,1,1, 1), frameTexture='mp_logo.png', state=DGG.NORMAL, parent=pixel2d) self.mp_logo.setPos(256+winX/2, 0, -winY) self.mp_logo.setBin('fixed', 1) self.mp_logo.hide() self.mp_logo.setTransparency(TransparencyAttrib.MDual) self.mp_logo.bind(DGG.B1PRESS, self.open_www, ['http://www.matthewpablo.com/']) #self.mp_logo.bind(DGG.WITHIN, self.GUIOnEnter, ["MP"]) #self.mp_logo.bind(DGG.WITHOUT, self.GUIOnExit) self.title = DirectFrame(frameSize=(-512, 0, 0, 128), frameColor=(1,1,1, 1), frameTexture='select.png', parent=pixel2d) self.title.setPos(256+winX/2, 0, -128) self.title.setBin('fixed', 1) self.title.setTransparency(TransparencyAttrib.MDual) #self.title.hide() self.close=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/close.png', state=DGG.NORMAL, parent=pixel2d) self.close.setPos(winX, 0, -32) self.close.setBin('fixed', 1) self.close.bind(DGG.B1PRESS, self.exit) self.start=DirectFrame(frameSize=(-256, 0, 0, 32), frameTexture='icon/level_select.png', frameColor=(1, 1, 1, 1), parent=pixel2d) self.start.setPos(128+winX/2, 0, -164) self.start.setTransparency(TransparencyAttrib.MDual) #self.start.bind(DGG.B1PRESS, self.onStart) self.start.setBin('fixed', 1) #self.start.hide() self.start_main=DirectFrame(frameSize=(-192, 0, 0, 32), frameColor=(1,1,1, 0), text_font=self.font, text='Start in Level 1', text_pos = (-160, 12,0), text_scale = 16, text_fg=(0,0,0,1), text_align=TextNode.ALeft, textMayChange=1, state=DGG.NORMAL, parent=pixel2d) self.start_main.setPos(96+winX/2, 0, -164) self.start_main.setTransparency(TransparencyAttrib.MDual) self.start_main.bind(DGG.B1PRESS, self.onStart) self.start_main.bind(DGG.WITHIN, self.GUIOnEnter, ["4A"]) self.start_main.bind(DGG.WITHOUT, self.GUIOnExit) self.start_main.setBin('fixed', 1) self.start_main.wrtReparentTo(self.start) self.start_back=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1,0,0, 0), state=DGG.NORMAL, parent=pixel2d) self.start_back.setPos(128+winX/2, 0, -164) self.start_back.setTransparency(TransparencyAttrib.MDual) self.start_back.bind(DGG.B1PRESS, self.selectLevel, [1]) self.start_back.bind(DGG.WITHIN, self.GUIOnEnter, ["4B"]) self.start_back.bind(DGG.WITHOUT, self.GUIOnExit) self.start_back.setBin('fixed', 1) self.start_back.wrtReparentTo(self.start) self.start_next=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(0,1,0, 0), state=DGG.NORMAL, parent=pixel2d) self.start_next.setPos(-96+winX/2, 0, -164) self.start_next.setTransparency(TransparencyAttrib.MDual) self.start_next.bind(DGG.B1PRESS, self.selectLevel, [-1]) self.start_next.bind(DGG.WITHIN, self.GUIOnEnter, ["4C"]) self.start_next.bind(DGG.WITHOUT, self.GUIOnExit) self.start_next.setBin('fixed', 1) self.start_next.wrtReparentTo(self.start) self.start.hide() self.slider3 = DirectSlider(range=(0,100), value=50, pageSize=10, thumb_relief=DGG.FLAT, thumb_frameTexture='glass1.png', #thumb_frameColor=(1,1,1, 1), frameTexture='glass2.png', scale=96, #frameSize=(-100, 0, 0, 100), command=self.set_slider, extraArgs=["3"], parent=pixel2d) self.slider3.setPos(winX/2, 0, -16) self.slider3.setBin('fixed', 2) self.slider2 = DirectSlider(range=(0,100), value=50, pageSize=10, thumb_relief=DGG.FLAT, thumb_frameTexture='glass1.png', #thumb_frameColor=(1,1,1, 1), frameTexture='glass2.png', scale=96, #frameSize=(-100, 0, 0, 100), command=self.set_slider, extraArgs=["2"], parent=pixel2d) self.slider2.setPos(winX/2, 0, -64) self.slider2.setBin('fixed', 2) self.slider1 = DirectSlider(range=(0,100), value=50, pageSize=10, thumb_relief=DGG.FLAT, thumb_frameTexture='glass1.png', #thumb_frameColor=(1,1,1, 1), frameTexture='glass2.png', scale=96, #frameSize=(-100, 0, 0, 100), command=self.set_slider, extraArgs=["1"], parent=pixel2d) self.slider1.setPos(winX/2, 0, -112) self.slider1.setBin('fixed', 2) self.slider1.hide() self.slider2.hide() self.slider3.hide() self.cursor=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/cursor1.png', parent=pixel2d) self.cursor.setPos(32,0, -32) self.cursor.flattenLight() self.cursor.setBin('fixed', 10) self.cursor.setTransparency(TransparencyAttrib.MDual) self.button1A=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/armor.png', state=DGG.NORMAL, parent=pixel2d) self.button1A.setPos(128+winX/2, 0, -128) self.button1A.setBin('fixed', 1) self.button1B=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/armor.png', state=DGG.NORMAL, parent=pixel2d) self.button1B.setPos(-96+winX/2, 0, -128) self.button1B.setBin('fixed', 1) self.button2A=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/armor.png', state=DGG.NORMAL, parent=pixel2d) self.button2A.setPos(128+winX/2, 0, -79) self.button2A.setBin('fixed', 1) self.button2B=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/armor.png', state=DGG.NORMAL, parent=pixel2d) self.button2B.setPos(-96+winX/2, 0, -79) self.button2B.setBin('fixed', 1) self.button3A=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/armor.png', state=DGG.NORMAL, parent=pixel2d) self.button3A.setPos(128+winX/2, 0, -32) self.button3A.setBin('fixed', 1) self.button3B=DirectFrame(frameSize=(-32, 0, 0, 32), frameColor=(1, 1, 1, 1), frameTexture='icon/armor.png', state=DGG.NORMAL, parent=pixel2d) self.button3B.setPos(-96+winX/2, 0, -32) self.button3B.setBin('fixed', 1) self.button1A.hide() self.button1B.hide() self.button2A.hide() self.button2B.hide() self.button3A.hide() self.button3B.hide() self.button1A.bind(DGG.WITHIN, self.GUIOnEnter, ["1A"]) self.button1A.bind(DGG.WITHOUT, self.GUIOnExit) self.button2A.bind(DGG.WITHIN, self.GUIOnEnter, ["2A"]) self.button2A.bind(DGG.WITHOUT, self.GUIOnExit) self.button3A.bind(DGG.WITHIN, self.GUIOnEnter, ["3A"]) self.button3A.bind(DGG.WITHOUT, self.GUIOnExit) self.button1B.bind(DGG.WITHIN, self.GUIOnEnter, ["1B"]) self.button1B.bind(DGG.WITHOUT, self.GUIOnExit) self.button2B.bind(DGG.WITHIN, self.GUIOnEnter, ["2B"]) self.button2B.bind(DGG.WITHOUT, self.GUIOnExit) self.button3B.bind(DGG.WITHIN, self.GUIOnEnter, ["3B"]) self.button3B.bind(DGG.WITHOUT, self.GUIOnExit) #tooltip #self.font.setPixelsPerUnit(16) #self.font.setMinfilter(Texture.FTNearest ) #self.font.setMagfilter(Texture.FTNearest ) #self.font.setAnisotropicDegree(4) #self.font.setNativeAntialias(False) #self.font.setPageSize(1024,1024) self.Tooltip=DirectLabel(frameColor=(0, 0, 0, 0), text_font=self.font, text='Lorem ipsum dolor sit amet,\n consectetur adipisicing elit,\n sed do eiusmod tempor incididunt \nut labore et dolore magna aliqua.', #pos = (0, 0,-35), text_scale = 16, text_fg=(1,1,1,1), text_align=TextNode.ALeft , textMayChange=1, parent=pixel2d ) self.Tooltip.flattenLight() self.Tooltip.setBin('fixed', 300) self.Tooltip.hide() self.tooltip_text=[None, {"1A":"ARMOR:\nYou have more Hit Points\n", "1B":"REGENERATION:\nYou heal over time\n", "2A":"BLOCK:\nYour block is more effective\n", "2B":"SPEED:\nYour move faster\n", "3A":"DAMAGE:\nYou deal more damage\n", "3B":"CRITICAL HIT:\nChance for a critical hit\n"}, {"1A":"BLAST:\nBigger Magic Bolt explosion\n", "1B":"DAMAGE:\nMagic Bolt deals more damage\n", "2A":"LIGHTNING:\nMore damage to far targets\n", "2B":"THUNDER:\nMore damage to near targets\n", "3A":"RAPID CHARGE:\nExponential damage increase\n", "3B":"STATIC CHARGE:\nLinear damage increase\n"}, {"1A":"BARBS:\nOne hit counts as two\n", "1B":"PIERCE:\nArrows pass through targets\n", "2A":"BLEED:\nDamage over time\n", "2B":"CRIPPLE:\nSlow down enemies\n", "3A":"FINESSE:\nMore critical hits\n", "3B":"PROWESS:\nMore damage\n"}, {"1A":"BURNING DEATH:\nMagma deals more damage\n", "1B":"MAGMA FLOW:\nMore magma at once\n", "2A":"HEART OF FIRE:\nMagma lasts longer\n", "2B":"VOLCANIC ACTIVITY:\nMagma is bigger\n", "3A":"PHASESHIFT:\nYou can teleport more often\n", "3B":"WARP FIELD:\nFaster recovery after teleport\n"} ] #collisions #self.traverser=CollisionTraverser("playerTrav") #self.traverser.setRespectPrevTransform(True) #self.queue = CollisionHandlerQueue() self.MousePickerNode = CollisionNode('mouseRay') self.pickerNP = base.camera.attachNewNode(self.MousePickerNode) self.MousePickerNode.setFromCollideMask(BitMask32.bit(1)) self.MousePickerNode.setIntoCollideMask(BitMask32.allOff()) self.pickerRay = CollisionSegment() #Make our ray self.MousePickerNode.addSolid(self.pickerRay) #Add it to the collision node self.common['traverser'].addCollider(self.pickerNP, self.common['queue']) self.accept("mouse1", self.onClick) taskMgr.doMethodLater(0.2, self.flicker,'flicker') #taskMgr.add(self.camera_spin, "camera_spin") taskMgr.add(self.__getMousePos, "chargenMousePos") self.current_class=None self.camLoop=Sequence(LerpHprInterval(self.cameraNode, 10.0, VBase3(-20,0, 0), bakeInStart=0),LerpHprInterval(self.cameraNode, 10.0, VBase3(20,0, 0),bakeInStart=0)) self.camLoop.loop() self.accept( 'window-event', self.windowEventHandler) def selectLevel(self, next, event=None): self.currentLevel+=next if self.currentLevel<0: self.currentLevel=0 if self.currentLevel>self.common['max_level']: self.currentLevel=self.common['max_level'] self.start_main['text']="Start in Level "+str(self.currentLevel+1) def moveArrow(self, task): if self.movingArrow: self.arrowTime+=task.time if self.arrowTime>3.0: self.movingArrow.removeNode() self.arrowTime=0.0 return task.done dt = globalClock.getDt() self.movingArrow.setX(self.movingArrow, 400*dt) return task.again else: return task.done def fireArrow(self): self.movingArrow=loader.loadModel('models/arrow') self.movingArrow.reparentTo(self.arrow_bone) self.movingArrow.setP(-45) self.movingArrow.wrtReparentTo(render) self.arrow.hide() self.fireSound.play() taskMgr.add(self.moveArrow, "moveArrowTask") Sequence(Wait(0.5),Func(self.arrow.show)).start() def onStart(self, event=None): #unload stuff self.camLoop.pause() self.camLoop=None base.camera.reparentTo(render) self.campmap.removeNode() self.node.removeNode() self.fire.remove_loop() if taskMgr.hasTaskNamed('flicker'): taskMgr.remove('flicker') if taskMgr.hasTaskNamed('chargenMousePos'): taskMgr.remove('chargenMousePos') self.common['traverser'].removeCollider(self.pickerNP) self.pickerNP.removeNode() self.Ambient.removeNode() self.button1A.destroy() self.button1B.destroy() self.button2A.destroy() self.button2B.destroy() self.button3A.destroy() self.button3B.destroy() self.Tooltip.destroy() self.cursor.destroy() self.slider1.destroy() self.slider2.destroy() self.slider3.destroy() self.start.destroy() self.start_back.destroy() self.start_next.destroy() self.close.destroy() self.title.destroy() self.mp_logo.destroy() render.setLightOff() self.ignoreAll() #self.common['music'].stop() #self.common['spawner']=Spawner(self.common) #self.common['levelLoader']=LevelLoader(self.common) self.common['levelLoader'].load(self.currentLevel, PCLoad=False) #render.ls() if self.current_class=="1": self.common['PC']=PC1(self.common) #self.common['PC'].node.setPos(-12, 0, 0) elif self.current_class=="2": self.common['PC']=PC2(self.common) #self.common['PC'].node.setPos(-12, 0, 0) elif self.current_class=="3": self.common['PC']=PC3(self.common) #self.common['PC'].node.setPos(-12, 0, 0) elif self.current_class=="4": self.common['PC']=PC4(self.common) #self.common['PC'].node.setPos(-12, 0, 0) pos=(data.levels[self.currentLevel]["enter"][0], data.levels[self.currentLevel]["enter"][1], data.levels[self.currentLevel]["enter"][2]) self.common['PC'].node.setPos(pos) self.common['music'].loop(1, fadeIn=True) def open_www(self, url, event=None): webbrowser.open_new(url) def windowEventHandler( self, window=None ): #print "resize" if window is not None: # window is none if panda3d is not started wp = base.win.getProperties() X= wp.getXSize()/2 Y= wp.getYSize() self.slider3.setPos(X, 0, -16) self.slider2.setPos(X, 0, -64) self.slider1.setPos(X, 0, -112) self.button1A.setPos(128+X, 0, -128) self.button1B.setPos(-96+X, 0, -128) self.button2A.setPos(128+X, 0, -79) self.button2B.setPos(-96+X, 0, -79) self.button3A.setPos(128+X, 0, -32) self.button3B.setPos(-96+X, 0, -32) self.start.setPos(128+X, 0, -164) self.title.setPos(256+X, 0, -128) self.close.setPos(X*2, 0, -32) self.mp_logo.setPos(256+X, 0, -Y) def getSliderValue(self, option): value=0 if option[0]=="1": value=int(self.slider1['value']) elif option[0]=="2": value=int(self.slider2['value']) elif option[0]=="3": value=int(self.slider3['value']) if self.current_class=="2": if option=="1A": return "{0}% blast size".format(value+50) elif option=="1B": return "{0}% damage".format(75+(101-value)/2) elif option=="2A": return "{0}% damage to far targets".format(value*2) elif option=="2B": return "{0}% damage to near targets\n".format(2*(100-value)) elif option=="3A": return "{0}-{1} Lightning damage\n{2}-{3} Magic Bolt damage".format( int(round(value/100.0+8*(101-value)/100.0)), int(round(15*value/100.0+8*(101-value)/100)), 2*int(round(2*value/100.0+6*(101-value)/100.0)), 2*int(round(26*value/100.0+20*(101-value)/100)) ) elif option=="3B": return "{0}-{1} Lightning damage\n{2}-{3} Magic Bolt damage".format( int(round(value/100.0+8*(101-value)/100.0)), int(round(15*value/100.0+8*(101-value)/100)), 2*int(round(2*value/100.0+6*(101-value)/100.0)), 2*int(round(26*value/100.0+20*(101-value)/100)) ) elif self.current_class=="1": if option=="1A": return "{0} total HP".format(value+50) elif option=="1B": return "+{0}HP/second".format(round((101-value)/100.0, 1)) elif option=="2A": return "{0}% damage blocked".format(50+(value+1)/2) elif option=="2B": return "{0}% movement speed".format(75+(101-value)/2) elif option=="3A": return "{0}-{1} damage".format( int(round(1.0+(value+1.0)/100.0)), int(round(15.0*(1.0+(value+1.0)/50.0)))) elif option=="3B": return "{0}% chance for +{1} damage".format(5+(101-value)/2,5+(101-value)/5) elif self.current_class=="3": if option=="1A": return "{0}% chance to activate".format(int(value/2)) elif option=="1B": return "{0}%chance to pierce".format(int((100-value)/2)) elif option=="2A": return "{0}% of critical hits".format(int(value)) elif option=="2B": return "{0}% of critical hits".format(int(100-value)) elif option=="3A": return "{0}% chance for critical hit".format(25+ int(value/2)) elif option=="3B": return "{0}% damage".format(50+int(100-value)) elif self.current_class=="4": if option=="1A": return "{0}% damage".format(50+int(value)) elif option=="1B": v=1+int((100-value)/20) if v<2: return "Control 1 orb of magma" return "Control {0} orbs of magma".format(v) elif option=="2A": return "{0}% time".format(50+int(value)) elif option=="2B": return "{0}% size".format(50+int(100-value)) elif option=="3A": return "Teleport every {0} seconds".format(16.0*((100-value)/1000.0)+0.8) elif option=="3B": return "{0}% recovery time".format(50+int(value)) return "???" def GUIOnEnter(self, object, event=None): if object[0]=="4": if object[1]=="A": self.Tooltip['text']="Click to start!" elif object[1]=="B": self.Tooltip['text']="Next level" elif object[1]=="C": self.Tooltip['text']="Previous level" self.Tooltip['text_pos'] = (10, -40,0) self.Tooltip['text_align'] =TextNode.ACenter self.Tooltip.show() return if not self.current_class: return #print int(self.current_class) self.Tooltip['text']=self.tooltip_text[int(self.current_class)][object]+self.getSliderValue(object) if object[1]=="A": self.Tooltip['text_pos'] = (30, -10,0) self.Tooltip['text_align'] =TextNode.ALeft else: self.Tooltip['text_pos'] = (-20, -10,0) self.Tooltip['text_align'] =TextNode.ARight self.Tooltip.show() #print "in" def GUIOnExit(self, event=None): self.Tooltip.hide() #print "out" def start_lightning(self, time=0.03): taskMgr.doMethodLater(time, self.lightning,'vfx') self.magicSound.play() def lightning(self, task): self.char2_magic.show() self.vfxU=self.vfxU+0.5 if self.vfxU>=1.0: self.vfxU=0 self.vfxV=self.vfxV-0.125 if self.vfxV <=-1: self.char2_magic.hide() self.vfxU=0 self.vfxV=0 return task.done self.char2_magic.setTexOffset(TextureStage.getDefault(), self.vfxU, self.vfxV) return task.again def loopAnim(self, actor, anim): actor.loop(anim) def set_slider(self, id): #self.current_class=id #print id, if id=="1": self.common['pc_stat1']=int(self.slider1['value']) #print self.common['pc_stat1'] elif id=="2": self.common['pc_stat2']=int(self.slider2['value']) #print self.common['pc_stat2'] elif id=="3": self.common['pc_stat3']=int(self.slider3['value']) #print self.common['pc_stat3'] def onClick(self): self.common['traverser'].traverse(render) my_class=None for entry in self.common['queue'].getEntries(): if entry.getIntoNodePath().hasTag("class"): my_class=entry.getIntoNodePath().getTag("class") if my_class=="1": self.slider1['value']=50 self.slider2['value']=50 self.slider3['value']=50 self.current_class=my_class self.title.hide() self.start.show() self.button1A.show() self.button1B.show() self.button2A.show() self.button2B.show() self.button3A.show() self.button3B.show() self.button1A['frameTexture']='icon/armor.png' self.button1B['frameTexture']='icon/heart.png' self.button2A['frameTexture']='icon/shield2.png' self.button2B['frameTexture']='icon/move.png' self.button3A['frameTexture']='icon/power.png' self.button3B['frameTexture']='icon/critical.png' #self.skills.show() self.slider1.show() self.slider2.show() self.slider3.show() Sequence(self.character1.actorInterval("attack"),self.character1.actorInterval("block"), Func(self.loopAnim, self.character1, "idle")).start() self.swingSound.play() #self.character1.play("attack") self.character2.loop("idle") elif my_class=="2": self.slider1['value']=50 self.slider2['value']=50 self.slider3['value']=50 self.current_class=my_class self.title.hide() self.start.show() self.button1A.show() self.button1B.show() self.button2A.show() self.button2B.show() self.button3A.show() self.button3B.show() self.button1A['frameTexture']='icon/blast.png' self.button1B['frameTexture']='icon/damage.png' self.button2A['frameTexture']='icon/lightning.png' self.button2B['frameTexture']='icon/thunder.png' self.button3A['frameTexture']='icon/amp.png' self.button3B['frameTexture']='icon/volt.png' self.slider1.show() self.slider2.show() self.slider3.show() Sequence(self.character2.actorInterval("attack", playRate=0.8),Func(self.loopAnim, self.character2, "idle")).start() Sequence(Wait(0.3), Func(self.start_lightning, 0.05)).start() #self.character2.play("attack") self.character1.loop("idle") #RayVfx(self.character2, texture='vfx/lightning.png').start() elif my_class=="3": self.slider1['value']=50 self.slider2['value']=50 self.slider3['value']=50 self.current_class=my_class self.title.hide() self.start.show() self.button1A.show() self.button1B.show() self.button2A.show() self.button2B.show() self.button3A.show() self.button3B.show() self.button1A['frameTexture']='icon/barbs.png' self.button1B['frameTexture']='icon/pierce.png' self.button2A['frameTexture']='icon/bleed.png' self.button2B['frameTexture']='icon/cripple.png' self.button3A['frameTexture']='icon/finese.png' self.button3B['frameTexture']='icon/bow_damage.png' self.slider1.show() self.slider2.show() self.slider3.show() self.drawSound.play() self.character3.play("attack") Sequence(Wait(1.5),Func(self.fireArrow), Func(self.character3.play, "reset"),Wait(1.0),Func(self.loopAnim, self.character3, "idle")).start() elif my_class=="4": self.slider1['value']=50 self.slider2['value']=50 self.slider3['value']=50 self.current_class=my_class self.title.hide() self.start.show() self.button1A.show() self.button1B.show() self.button2A.show() self.button2B.show() self.button3A.show() self.button3B.show() self.button1A['frameTexture']='icon/hand_o_fate.png' self.button1B['frameTexture']='icon/magma_flow.png' self.button2A['frameTexture']='icon/heart_o_fire.png' self.button2B['frameTexture']='icon/vulcanic.png' self.button3A['frameTexture']='icon/warp.png' self.button3B['frameTexture']='icon/thorns.png' #self.skills.show() self.slider1.show() self.slider2.show() self.slider3.show() self.character4.loop("attack") aura=vfx(self.character4, texture='vfx/tele2.png',scale=.5, Z=.85, depthTest=False, depthWrite=False) aura.show() aura.start() self.FFSound.play() Sequence(Wait(2.2), Func(self.loopAnim, self.character4, "idle")).start() def exit(self, event=None): self.common['root'].save_and_exit() #sys.exit() def __getMousePos(self, task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) pos2d=Point3(mpos.getX() ,0, mpos.getY()) self.cursor.setPos(pixel2d.getRelativePoint(render2d, pos2d)) self.Tooltip.setPos(self.cursor.getPos()) return task.again def flicker(self, task): self.pLight.setAttenuation(Point3(1, 0, random.uniform(.1, 0.15))) self.pLightNode.setZ(random.uniform(.9, 1.1)) #self.pLight.setColor(VBase4(random.uniform(.9, 1.0), random.uniform(.9, 1.0), .9, 1)) return task.again def camera_spin(self, task): H=self.cameraNode.getH() #Z=self.cameraNode.getZ() #print H if H<=-20.0 or H>=20.0: if self.reverse_spin: self.reverse_spin=False else: self.reverse_spin=True if self.reverse_spin: self.cameraNode.setH(self.cameraNode, 4*globalClock.getDt()) #self.cameraNode.setZ(Z+0.1*globalClock.getDt()) else: self.cameraNode.setH(self.cameraNode, -4*globalClock.getDt()) #self.cameraNode.setZ(Z-0.1*globalClock.getDt()) return task.again #c=Camp() #run()
class Tricker(object): def __init__(self): ## tricker-model taken from tutorial files from # https://www.digitaltutors.com/tutorial/1478-Animating-an-Acrobatic-Fight-Scene-in-Maya self.actor = Actor( "tp/models/tricker-model", { "gainer": "tp/anims/tricker-gainer", "gainer_bad": "tp/anims/tricker-gainer-bad", "gswitch": "tp/anims/tricker-gswitch", "gswitch_bad": "tp/anims/tricker-gswitch-bad", "btwist": "tp/anims/tricker-btwist", "btwist_bad": "tp/anims/tricker-btwist", "cork": "tp/anims/tricker-cork", "cork_bad": "tp/anims/tricker-cork-bad", "doublecork": "tp/anims/tricker-dubcork", "doublecork_bad": "tp/anims/tricker-dubcork", "fall_swing": "tp/anims/tricker-fall-left", "initial_swing": "tp/anims/tricker-initial-swing", "end_swing": "tp/anims/tricker-end-swing", "fall_reversal": "tp/anims/tricker-fall-right", "raiz": "tp/anims/tricker-raiz", "raiz_bad": "tp/anims/tricker-raiz-bad", "fiveForty": "tp/anims/tricker-540", "fiveForty_bad": "tp/anims/tricker-540-bad" }) #saveDict contains all info to be saved to json self.saveDict = { 'name': '', 'level': 0, 'totalStam': 100, 'skills': { "gainer": 1, "gswitch": 1, "btwist": 1, "cork": 1, "doublecork": 1, "raiz": 1, "fiveForty": 1 } } self.updateAttributes() # trickMap is different - this shit maps trick names to their classes # in order to get class data just given an animation name self.trickMap = { 'gainer': self.gainer, 'gswitch': self.gswitch, 'btwist': self.btwist, 'cork': self.cork, 'doublecork': self.doublecork, 'raiz': self.raiz, 'fiveForty': self.fiveForty } # runtime traits, to be reset with reset function # NOTE: You MUST add any vals here to the reset function below self.prevTrick = None self.stamina = self.totalStam self.grade = '' self.timing = '' self.score = 0 self.comboLength = 0 self.comboEnded = False self.comboContinuing = False self.falling = False self.midTrick = False def comboHasEnded(self): return self.comboEnded def hasName(self): return self.name != '' def isFalling(self): return self.falling def isMidTrick(self): return self.midTrick def getName(self): if self.hasName(): return self.name else: return "NewPlayer" def getLevel(self): return str(self.saveDict['level']) def getTotalStam(self): return str(self.totalStam) def getSaveDict(self): return self.saveDict def getSkillDict(self): return self.skillDict def getComboLength(self): return str(int(self.comboLength)) def getScore(self): return str(int(self.score)) def getTiming(self): return self.timing def updateStamina(self, stamCost): self.stamina -= stamCost def updateComboLength(self): self.comboLength += 1 def updateScore(self, trick, goodPercentage, comboLength): b = trick.getDifficulty() * 100 score = b + (b * goodPercentage) + (b * (comboLength / 5)) self.score += score def getTimingBarPercentage(self): currAnim = self.actor.getCurrentAnim() if currAnim and 'fall' not in currAnim and 'initial' not in currAnim and 'end' not in currAnim: trick = self.trickMap[currAnim.split('_')[0]] sweetspot = trick.getSweetSpot() currFrame = self.actor.getCurrentFrame() dist = abs(sweetspot - currFrame) eMargin = trick.getDuration() * .2 / trick.getDifficulty() if dist > eMargin: gp = 0 else: gp = 1 - (dist / eMargin) return gp else: return 0 def getTrueStam(self): return self.stamina def stamPercentage(self): sp = self.stamina / self.totalStam if sp < 0: sp = 0 return sp def getGrade(self): return self.grade def increaseSkill(self, trick, grade): if grade == 0: b = 2 elif grade == 1: b = 1.66 elif grade == 2: b = 1.33 elif grade == 3: b = 1 elif grade == 4: b = 1 # This line makes the exp curve and prevents leveling over 100 exp = b - math.log(self.saveDict['skills'][str(trick)]) if exp < 0: exp = 0 self.saveDict['skills'][str(trick)] += exp self.updateAttributes() """ debug animation procedure: comment out: return under if self.comboEnded in self.tryTrick both moveInterval.start() in self.doTrickTask """ def tryTrick(self, trick, taskMgr): if self.midTrick: print("already received an input") return self.midTrick = True if self.comboEnded: print("combo ended - no more tricking 4 u") return if self.falling: print("can't trick once you've fallen boi") return if self.stamina <= 0: self.comboEnded = True print("no stamina to throw trick!! ending combo") return self.comboContinuing = True distance = (0, 0, 0) self.grade = 0 currAnim = self.actor.getCurrentAnim() goodPercentage = trick.getGoodPercentage(self.grade) if self.prevTrick: distance = self.prevTrick.getDistance() if currAnim and self.prevTrick: if (self.prevTrick.getExitTransition() != trick.getEntryTransition()): self.comboEnded = True print("invalid transition - ended combo") return distance = self.prevTrick.getDistance() currFrame = self.actor.getCurrentFrame(currAnim) numFrames = self.actor.getNumFrames(currAnim) framesLeft = numFrames - currFrame (self.grade, self.timing) = self.prevTrick.getGrade(currFrame) if self.grade == 4: self.falling = True print("Combo failed - falling") self.prevTrick = None stamCost = trick.getStamCost(self.grade) self.updateStamina(stamCost) goodPercentage = trick.getGoodPercentage(self.grade) # 0.06 is the time it takes for 2 frames - smooth blending delayTime = framesLeft / 30 - 0.09 taskMgr.doMethodLater( delayTime, self.doTrickTask, 'doTrick', extraArgs=[str(trick), goodPercentage, distance, taskMgr], appendTask=True) else: stamCost = trick.getStamCost(self.grade) self.updateStamina(stamCost) if trick.entryTransition == 'swing': self.actor.play('initial_swing') distance = (-2, 2, 0) taskMgr.doMethodLater( 21 / 30, self.doTrickTask, 'doTrick', extraArgs=[str(trick), goodPercentage, distance, taskMgr], appendTask=True) else: taskMgr.add( self.doTrickTask, 'doTrick', extraArgs=[str(trick), goodPercentage, distance, taskMgr], appendTask=True) if self.getTrueStam() < 0: self.falling = True return ("Ran out of stamina mid-trick - falling!") if not self.falling: self.updateScore(trick, goodPercentage, self.comboLength) self.updateComboLength() self.prevTrick = trick # this is tricking - you still learn from your falls! self.increaseSkill(trick, self.grade) def doTrickTask(self, animation, goodPercentage, distance, taskMgr, task): print("goodp:", goodPercentage) self.actor.setPos(self.actor, distance) badAnim = str(animation + "_bad") if not self.isFalling(): self.actor.enableBlend() self.actor.setControlEffect(badAnim, 1 - goodPercentage) self.actor.setControlEffect(animation, goodPercentage) self.actor.play(badAnim) self.actor.play(animation) self.actor.disableBlend() self.comboContinuing = False self.midTrick = False taskMgr.add(self.checkTrickStateTask, 'checkTrickState', extraArgs=[animation], appendTask=True) elif self.isFalling(): trick = self.trickMap[animation] fallDist = trick.getDistance() exitTrans = trick.getExitTransition() fallingAnim = "fall_" + exitTrans fallStartFrame = trick.getDuration() - trick.getSweetSpot() regFrames = self.actor.getNumFrames(animation) - fallStartFrame fallSeq = Sequence( self.actor.actorInterval(badAnim, endFrame=regFrames), Func(self.playFall, fallingAnim, fallDist, exitTrans)) fallSeq.start() # if moveInterval: moveInterval.start() return Task.done def playFall(self, fallingAnim, distance, exitTrans): # if fallingAnim == 'fall_swing': # self.actor.enableBlend() # self.actor.setControlEffect(badAnim, .5) # self.actor.setControlEffect(fallingAnim, .5) # self.actor.play(badAnim, fromFrame=startFrame) # self.actor.play(fallingAnim) # self.actor.disableBlend() # elif fallingAnim == 'fall_reversal': if exitTrans == 'swing': self.actor.setPos(self.actor, distance) self.actor.play(fallingAnim) def playSwingExit(self, distance): self.actor.setPos(self.actor, distance) self.actor.play('end_swing') def checkTrickStateTask(self, animation, task): # has to be -1 otherwise the currFrame never gets to the last frame. IDK why totalFrames = self.actor.getNumFrames(animation) - 1 currFrame = self.actor.getCurrentFrame(animation) if self.comboContinuing or self.falling: print("comboContinuing or falling") return Task.done self.comboContinuing = False if currFrame == totalFrames: self.comboEnded = True print("no input received - combo ended") trick = self.trickMap[animation] distance = trick.getDistance() if trick.getExitTransition() == 'swing': self.playSwingExit(distance) return Task.done return Task.cont def reset(self): self.prevTrick = None self.stamina = 100 self.grade = None self.timing = '' self.score = 0 self.comboLength = 0 self.comboEnded = False self.comboContinuing = False self.falling = False self.midTrick = False def setName(self, name): self.saveDict['name'] = name self.updateAttributes() def loadToSaveDict(self, indata): self.saveDict = indata self.updateAttributes() def updateAttributes(self): self.name = self.saveDict['name'] self.totalStam = self.saveDict['totalStam'] self.skillDict = self.saveDict['skills'] # set tricker's level based on proficiency in all skills numTricks = totalSP = 0 for trick in self.skillDict: numTricks += 1 totalSP += self.skillDict[trick] self.level = int(totalSP / numTricks) self.saveDict['level'] = self.level # Load tricks self.gainer = Gainer(self) self.gswitch = Gswitch(self) self.btwist = Btwist(self) self.cork = Cork(self) self.doublecork = DoubleCork(self) self.raiz = Raiz(self) self.fiveForty = FiveForty(self)
class World(DirectObject): def __init__(self): # Preliminary capabilities check. if not ape.base().win.getGsg().getSupportsBasicShaders(): self.t = addTitle( "Shadow Demo: Video driver reports that shaders are not supported." ) return if not ape.base().win.getGsg().getSupportsDepthTexture(): self.t = addTitle( "Shadow Demo: Video driver reports that depth textures are not supported." ) return self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation') self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle') self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot') self.inst_l = addInstructions(0.24, 'L : move light source far or close') self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results') self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map') self.inst_x = addInstructions( 0.42, 'Left/Right Arrow : switch camera angles') ape.base().setBackgroundColor(0, 0, 0.2, 1) ape.base().camLens.setNearFar(1.0, 10000) ape.base().camLens.setFov(75) ape.base().disableMouse() # Load the scene. floorTex = ape.loader().loadTexture('maps/envir-ground.jpg') cm = p3dc.CardMaker('') cm.setFrame(-2, 2, -2, 2) floor = ape.render().attachNewNode(p3dc.PandaNode("floor")) for y in range(12): for x in range(12): nn = floor.attachNewNode(cm.generate()) nn.setP(-90) nn.setPos((x - 6) * 4, (y - 6) * 4, 0) floor.setTexture(floorTex) floor.flattenStrong() self.pandaAxis = ape.render().attachNewNode('panda axis') self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'}) self.pandaModel.reparentTo(self.pandaAxis) self.pandaModel.setPos(9, 0, 0) self.pandaModel.setScale(0.01) self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8) self.pandaWalk.loop() self.pandaMovement = self.pandaAxis.hprInterval( 20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0)) self.pandaMovement.loop() self.teapot = ape.loader().loadModel('teapot') self.teapot.reparentTo(ape.render()) self.teapot.setPos(0, -20, 10) self.teapotMovement = self.teapot.hprInterval( 50, p3dc.LPoint3(0, 360, 360)) self.teapotMovement.loop() self.accept('escape', sys.exit) self.accept("arrow_left", self.incrementCameraPosition, [-1]) self.accept("arrow_right", self.incrementCameraPosition, [1]) self.accept("p", self.toggleInterval, [self.pandaMovement]) self.accept("t", self.toggleInterval, [self.teapotMovement]) self.accept("w", self.toggleInterval, [self.pandaWalk]) self.accept("v", ape.base().bufferViewer.toggleEnable) self.accept("u", self.toggleUpdateShadowMap) self.accept("l", self.incrementLightPosition, [1]) self.accept("o", ape.base().oobe) self.light = ape.render().attachNewNode(p3dc.Spotlight("Spot")) self.light.node().setScene(ape.render()) self.light.node().setShadowCaster(True) self.light.node().showFrustum() self.light.node().getLens().setFov(40) self.light.node().getLens().setNearFar(10, 100) ape.render().setLight(self.light) self.alight = ape.render().attachNewNode(p3dc.AmbientLight("Ambient")) self.alight.node().setColor(p3dc.LVector4(0.2, 0.2, 0.2, 1)) ape.render().setLight(self.alight) # Important! Enable the shader generator. ape.render().setShaderAuto() # default values self.cameraSelection = 0 self.lightSelection = 0 self.incrementCameraPosition(0) self.incrementLightPosition(0) def toggleInterval(self, ival): if ival.isPlaying(): ival.pause() else: ival.resume() def toggleUpdateShadowMap(self): buffer = self.light.node().getShadowBuffer(ape.base().win.gsg) buffer.active = not buffer.active def incrementCameraPosition(self, n): self.cameraSelection = (self.cameraSelection + n) % 6 if (self.cameraSelection == 0): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(30, -45, 26) ape.base().cam.lookAt(0, 0, 0) self.light.node().hideFrustum() if (self.cameraSelection == 1): ape.base().cam.reparentTo(self.pandaModel) ape.base().cam.setPos(7, -3, 9) ape.base().cam.lookAt(0, 0, 0) self.light.node().hideFrustum() if (self.cameraSelection == 2): ape.base().cam.reparentTo(self.pandaModel) ape.base().cam.setPos(-7, -3, 9) ape.base().cam.lookAt(0, 0, 0) self.light.node().hideFrustum() if (self.cameraSelection == 3): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(7, -23, 12) ape.base().cam.lookAt(self.teapot) self.light.node().hideFrustum() if (self.cameraSelection == 4): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(-7, -23, 12) ape.base().cam.lookAt(self.teapot) self.light.node().hideFrustum() if (self.cameraSelection == 5): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(1000, 0, 195) ape.base().cam.lookAt(0, 0, 0) self.light.node().showFrustum() def incrementLightPosition(self, n): self.lightSelection = (self.lightSelection + n) % 2 if (self.lightSelection == 0): self.light.setPos(0, -40, 25) self.light.lookAt(0, -10, 0) self.light.node().getLens().setNearFar(10, 100) if (self.lightSelection == 1): self.light.setPos(0, -600, 200) self.light.lookAt(0, -10, 0) self.light.node().getLens().setNearFar(10, 1000) def shaderSupported(self): return ape.base().win.getGsg().getSupportsBasicShaders() and \ ape.base().win.getGsg().getSupportsDepthTexture() and \ ape.base().win.getGsg().getSupportsShadowFilter()
class World(DirectObject): def __init__(self): # Preliminary capabilities check. if not ape.base().win.getGsg().getSupportsBasicShaders(): self.t = addTitle( "Shadow Demo: Video driver reports that shaders are not supported." ) return if not ape.base().win.getGsg().getSupportsDepthTexture(): self.t = addTitle( "Shadow Demo: Video driver reports that depth textures are not supported." ) return # creating the offscreen buffer. winprops = p3dc.WindowProperties(size=(512, 512)) props = p3dc.FrameBufferProperties() props.setRgbColor(1) props.setAlphaBits(1) props.setDepthBits(1) LBuffer = ape.base().graphicsEngine.makeOutput( ape.base().pipe, "offscreen buffer", -2, props, winprops, p3dc.GraphicsPipe.BFRefuseWindow, ape.base().win.getGsg(), ape.base().win) self.buffer = LBuffer if not LBuffer: self.t = addTitle( "Shadow Demo: Video driver cannot create an offscreen buffer.") return Ldepthmap = p3dc.Texture() LBuffer.addRenderTexture(Ldepthmap, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPDepthStencil) if ape.base().win.getGsg().getSupportsShadowFilter(): Ldepthmap.setMinfilter(p3dc.Texture.FTShadow) Ldepthmap.setMagfilter(p3dc.Texture.FTShadow) # Adding a color texture is totally unnecessary, but it helps with # debugging. Lcolormap = p3dc.Texture() LBuffer.addRenderTexture(Lcolormap, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPColor) self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation') self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle') self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot') self.inst_l = addInstructions(0.24, 'L : move light source far or close') self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results') self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map') self.inst_x = addInstructions( 0.42, 'Left/Right Arrow : switch camera angles') self.inst_a = addInstructions(0.48, 'Something about A/Z and push bias') ape.base().setBackgroundColor(0, 0, 0.2, 1) ape.base().camLens.setNearFar(1.0, 10000) ape.base().camLens.setFov(75) ape.base().disableMouse() # Load the scene. floorTex = ape.loader().loadTexture('maps/envir-ground.jpg') cm = p3dc.CardMaker('') cm.setFrame(-2, 2, -2, 2) floor = ape.render().attachNewNode(p3dc.PandaNode("floor")) for y in range(12): for x in range(12): nn = floor.attachNewNode(cm.generate()) nn.setP(-90) nn.setPos((x - 6) * 4, (y - 6) * 4, 0) floor.setTexture(floorTex) floor.flattenStrong() self.pandaAxis = ape.render().attachNewNode('panda axis') self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'}) self.pandaModel.reparentTo(self.pandaAxis) self.pandaModel.setPos(9, 0, 0) self.pandaModel.setShaderInput("scale", (0.01, 0.01, 0.01, 1.0)) self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8) self.pandaWalk.loop() self.pandaMovement = self.pandaAxis.hprInterval( 20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0)) self.pandaMovement.loop() self.teapot = ape.loader().loadModel('teapot') self.teapot.reparentTo(ape.render()) self.teapot.setPos(0, -20, 10) self.teapot.setShaderInput("texDisable", (1, 1, 1, 1)) self.teapotMovement = self.teapot.hprInterval( 50, p3dc.LPoint3(0, 360, 360)) self.teapotMovement.loop() self.accept('escape', sys.exit) self.accept("arrow_left", self.incrementCameraPosition, [-1]) self.accept("arrow_right", self.incrementCameraPosition, [1]) self.accept("p", self.toggleInterval, [self.pandaMovement]) self.accept("t", self.toggleInterval, [self.teapotMovement]) self.accept("w", self.toggleInterval, [self.pandaWalk]) self.accept("v", ape.base().bufferViewer.toggleEnable) self.accept("u", self.toggleUpdateShadowMap) self.accept("l", self.incrementLightPosition, [1]) self.accept("o", ape.base().oobe) self.accept('a', self.adjustPushBias, [1.1]) self.accept('z', self.adjustPushBias, [0.9]) self.LCam = ape.base().makeCamera(LBuffer) self.LCam.node().setScene(ape.render()) self.LCam.node().getLens().setFov(40) self.LCam.node().getLens().setNearFar(10, 100) # default values self.pushBias = 0.04 self.ambient = 0.2 self.cameraSelection = 0 self.lightSelection = 0 # setting up shader ape.render().setShaderInput('light', self.LCam) ape.render().setShaderInput('Ldepthmap', Ldepthmap) ape.render().setShaderInput('ambient', (self.ambient, 0, 0, 1.0)) ape.render().setShaderInput('texDisable', (0, 0, 0, 0)) ape.render().setShaderInput('scale', (1, 1, 1, 1)) # Put a shader on the Light camera. lci = p3dc.NodePath(p3dc.PandaNode("Light Camera Initializer")) lci.setShader(ape.loader().loadShader('shadows_caster.sha')) self.LCam.node().setInitialState(lci.getState()) # Put a shader on the Main camera. # Some video cards have special hardware for shadow maps. # If the card has that, use it. If not, use a different # shader that does not require hardware support. mci = p3dc.NodePath(p3dc.PandaNode("Main Camera Initializer")) if ape.base().win.getGsg().getSupportsShadowFilter(): mci.setShader(ape.loader().loadShader('shadows_shadow.sha')) else: mci.setShader( ape.loader().loadShader('shadows_shadow-nosupport.sha')) ape.base().cam.node().setInitialState(mci.getState()) self.incrementCameraPosition(0) self.incrementLightPosition(0) self.adjustPushBias(1.0) def toggleInterval(self, ival): if ival.isPlaying(): ival.pause() else: ival.resume() def toggleUpdateShadowMap(self): self.buffer.active = not self.buffer.active def incrementCameraPosition(self, n): self.cameraSelection = (self.cameraSelection + n) % 6 if (self.cameraSelection == 0): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(30, -45, 26) ape.base().cam.lookAt(0, 0, 0) self.LCam.node().hideFrustum() if (self.cameraSelection == 1): ape.base().cam.reparentTo(self.pandaModel) ape.base().cam.setPos(7, -3, 9) ape.base().cam.lookAt(0, 0, 0) self.LCam.node().hideFrustum() if (self.cameraSelection == 2): ape.base().cam.reparentTo(self.pandaModel) ape.base().cam.setPos(-7, -3, 9) ape.base().cam.lookAt(0, 0, 0) self.LCam.node().hideFrustum() if (self.cameraSelection == 3): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(7, -23, 12) ape.base().cam.lookAt(self.teapot) self.LCam.node().hideFrustum() if (self.cameraSelection == 4): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(-7, -23, 12) ape.base().cam.lookAt(self.teapot) self.LCam.node().hideFrustum() if (self.cameraSelection == 5): ape.base().cam.reparentTo(ape.render()) ape.base().cam.setPos(1000, 0, 195) ape.base().cam.lookAt(0, 0, 0) self.LCam.node().showFrustum() def incrementLightPosition(self, n): self.lightSelection = (self.lightSelection + n) % 2 if (self.lightSelection == 0): self.LCam.setPos(0, -40, 25) self.LCam.lookAt(0, -10, 0) self.LCam.node().getLens().setNearFar(10, 100) if (self.lightSelection == 1): self.LCam.setPos(0, -600, 200) self.LCam.lookAt(0, -10, 0) self.LCam.node().getLens().setNearFar(10, 1000) def shaderSupported(self): return ape.base().win.getGsg().getSupportsBasicShaders() and \ ape.base().win.getGsg().getSupportsDepthTexture() and \ ape.base().win.getGsg().getSupportsShadowFilter() def adjustPushBias(self, inc): self.pushBias *= inc self.inst_a.setText('A/Z: Increase/Decrease the Push-Bias [%F]' % self.pushBias) ape.render().setShaderInput('push', self.pushBias)
class SimpleWeapon: """Provides a simple weapon system - not very sophisticaed, but good enough to test shooting things.""" def __init__(self, manager, xml): self.gunView = render.attachNewNode('gun-view') self.ray = None self.reload(manager, xml) def destroy(self): self.gunView.removeNode() if self.ray != None: self.ray.destroy() def reload(self, manager, xml): # Get the path to load weapons from... basePath = manager.get('paths').getConfig().find('weapons').get('path') # Variables to manage the firing state (Used G36 as reference for defaults.)... bullet = xml.find('bullet') if bullet != None: self.bulletRate = float(bullet.get('rate', 1.0 / 12.5)) self.bulletSpeed = float(bullet.get('speed', 920.0)) self.bulletWeight = float(bullet.get('mass', 0.004)) else: self.bulletRate = 1.0 / 12.5 self.bulletSpeed = 920.0 self.bulletWeight = 0.004 # Determine the weapon meshes path... self.meshPath = posixpath.join(basePath, xml.find('egg').get('file')) # Get the camera interface, so we can zoom in when the player aims... self.camera = manager.get(xml.find('camera').get('plugin')) # Create our gun node - both the gun and the ray used for shooting track this - allows for gun jitter, kick back etc... parent = xml.find('parent') self.gunView.reparentTo( manager.get(parent.get('plugin')).getNode(parent.get('node'))) # Create a ray cast to detect what the player is looking at... and what will be shot... self.space = manager.get('ode').getSpace() if self.ray != None: self.ray.destroy() self.ray = OdeRayGeom(100.0) self.ray.setCategoryBits(BitMask32(0xfffffffe)) self.ray.setCollideBits(BitMask32(0xfffffffe)) # Get all the stuff we need to do the muzzle flash particle effect... flash = xml.find('muzzle_flash') self.flashManager = manager.get(flash.get('plugin')) self.flashEffect = flash.get('effect') self.flashBone = flash.get( 'bone') # Will be swapped out for the actual node latter. self.flashPos = csp.getPos(flash.get('pos')) # Get all the stuff we need to do the bullet hit sparks effect... sparks = xml.find('sparks') self.sparksManager = manager.get(sparks.get('plugin')) self.sparksEffect = sparks.get('effect') # Create a quaternion that rotates +ve z to +ve y - used to point it in the weapon direction rather than up... self.zToY = Quat() self.zToY.setFromAxisAngle(-90.0, Vec3(1.0, 0.0, 0.0)) # State for the animation... self.state = False # False==casual, True==aim. self.nextState = False # Firing state... self.firing = False # True if the trigger is being held. self.triggerTime = 0.0 # How long the trigger has been held for, so we know when to eject ammo. # For bullet holes bh = xml.find('bullet_holes') if bh != None: self.bulletHoles = manager.get(bh.get('plugin')) else: self.bulletHoles = None def postInit(self): for i in self.postReload(): yield i def postReload(self): # Load the actor... self.mesh = Actor(self.meshPath) yield # Shader generator makes it shiny, plus we need it in the right places in the render graph... self.mesh.setShaderAuto() self.mesh.reparentTo(self.gunView) self.mesh.hide() yield # Set its animation going... except we pause it until needed... self.nextAni() self.interval.pause() # Gun flash requires an exposed bone... self.flashBone = self.mesh.exposeJoint(None, "modelRoot", self.flashBone) yield def gunControl(self, task): # Update the gun direction ray to follow the players view... self.ray.setPosition(self.gunView.getPos(render)) self.ray.setQuaternion(self.zToY.multiply( self.gunView.getQuat(render))) # If the gun is firing update the trigger time, if a bullet is ejected do the maths... if self.firing: dt = globalClock.getDt() self.triggerTime += dt while self.triggerTime > self.bulletRate: self.triggerTime -= self.bulletRate hit, pos, norm = ray_cast.nearestHit(self.space, self.ray) # Create a muzzle flash effect... self.flashManager.doEffect(self.flashEffect, self.flashBone, True, self.flashPos) if hit: # Create an impact sparks effect... # Calculate the reflection direction... rd = self.ray.getDirection() sparkDir = (norm * (2.0 * norm.dot(rd))) - rd # Convert the reflection direction into a quaternion that will rotate +ve z to the required direction... try: ang = -math.acos(sparkDir[2]) except: print 'Angle problem', sparkDir ang = 0.0 axis = Vec3(0.0, 0.0, 1.0).cross(sparkDir) axis.normalize() sparkQuat = Quat() sparkQuat.setFromAxisAngleRad(ang, axis) # Set it going... self.sparksManager.doEffect(self.sparksEffect, render, False, pos, sparkQuat) # Make a bullet hole if hit.hasBody() and isinstance(hit.getBody().getData(), NodePath): self.bulletHoles.makeNew(pos, norm, hit.getBody().getData()) else: self.bulletHoles.makeNew(pos, norm, None) # Impart some energy on the object... if hit and hit.hasBody(): body = hit.getBody() # Calculate the force required to supply the energy the bullet contains to the body... force = self.bulletWeight * self.bulletSpeed / 0.05 # Get the direction of travel of the bullet, multiply by force... d = self.ray.getDirection() d *= force # If the object is asleep awaken it... if not body.isEnabled(): body.enable() # Add the force to the object... body.addForceAtPos(d, pos) return task.cont def start(self): # Make the gun visible... self.mesh.show() # Set the gun animation going... self.interval.finish() # Weapon task - this primarily makes it shoot... self.task = taskMgr.add(self.gunControl, 'GunControl') def stop(self): self.interval.pause() self.mesh.hide() taskMgr.remove(self.task) def nextAni(self): self.state = self.nextState if self.state: ani = random.choice( ('aim_wiggle_a', 'aim_wiggle_b', 'aim_wiggle_c')) else: ani = random.choice( ('casual_wiggle_a', 'casual_wiggle_b', 'casual_wiggle_c')) self.mesh.pose(ani, 0) self.interval = Sequence(self.mesh.actorInterval(ani), Func(self.nextAni)) self.interval.start() def setAiming(self, s): if self.nextState != s: self.interval.pause() self.nextState = s self.camera.setZoomed(s) def wib(): self.interval.finish() if s: ani = 'casual_aim' else: ani = 'aim_casual' transition = Sequence(self.mesh.actorInterval(ani), Func(wib)) transition.start() def setFiring(self, s): self.firing = s if self.firing: self.triggerTime = 0.0
class Golem(FSM, DirectObject): def __init__(self): FSM.__init__(self, "FSM-Golem") random.seed() self.golem = loader.loadModel("Golem") self.golem = Actor( "Golem", { "Idle": "Golem-Idle", "Walk": "Golem-Walk", "Attack": "Golem-Attack", "Destroyed": "Golem-Destroyed" }) self.golem.setBlend(frameBlend=True) golemViewSphere = CollisionSphere(0, 0, 0.5, 6) golemViewSphere.setTangible(False) golemViewColNP = self.golem.attachNewNode( CollisionNode('golemViewField')) golemViewColNP.node().addSolid(golemViewSphere) golemHitSphere = CollisionSphere(0, 0, 0.5, 1) golemHitColNP = self.golem.attachNewNode( CollisionNode('golemHitField')) golemHitColNP.node().addSolid(golemHitSphere) # a collision segment to check attacks self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1) self.golemAttackRay = self.golem.attachNewNode( CollisionNode("golemAttackCollision")) self.golemAttackRay.node().addSolid(self.attackCheckSegment) self.golemAttackRay.node().setIntoCollideMask(0) self.attackqueue = CollisionHandlerQueue() base.cTrav.addCollider(self.golemAttackRay, self.attackqueue) attackAnim = self.golem.actorInterval("Attack", playRate=2) self.AttackSeq = Parallel(attackAnim, Sequence(Wait(0.5), Func(self.ceckAttack))) self.lookatFloater = NodePath(PandaNode("golemTracker")) self.lookatFloater.setPos(self.golem, 0, 0, 3.4) self.lookatFloater.hide() self.lookatFloater.reparentTo(render) self.trackerObject = loader.loadModel("misc/Pointlight") self.trackerObject.setColor(0, 1, 0) self.trackerObject.setScale(0.25) self.trackerObject.reparentTo(self.lookatFloater) def start(self, startPos): self.golem.setPos(startPos.getPos()) self.golem.setHpr(startPos.getHpr()) self.golem.reparentTo(render) self.trackedEnemy = None self.health = 5 self.accept( "playerCollision-in-golemViewField", lambda extraArgs: base. messenger.send("golemSeesPlayer", [self.golem])) def stop(self): self.trackedEnemy = None taskMgr.remove("GolemAI_task") self.golem.hide() self.ignoreAll() def cleanup(self): self.stop() self.lookatFloater.removeNode() self.golem.cleanup() self.golem.removeNode() def activate(self, trackedEnemy): self.trackedEnemy = trackedEnemy taskMgr.add(self.aiTask, "GolemAI_task") self.lookatFloater.show() def aiTask(self, task): dt = globalClock.getDt() if self.AttackSeq.isPlaying(): return task.cont self.lookatFloater.setPos(self.golem, 0, 0, 3.4) self.lookatFloater.lookAt(self.trackedEnemy) self.lookatFloater.setH(self.lookatFloater.getH() + 180) self.lookatFloater.setP(0) self.lookatFloater.setR(0) self.golem.lookAt(self.trackedEnemy) self.golem.setH(self.golem.getH() + 180) distanceVec = self.golem.getPos() - self.trackedEnemy.getPos() enemyDist = distanceVec.length() if enemyDist < 2.0: # close enough for combat action = random.choice(["Attack", "Idle"]) if action == "Attack": self.request("Attack") else: if self.state != "Idle": self.request("Idle") else: self.golem.setY(self.golem, -0.5 * dt) if self.state != "Walk": self.request("Walk") return task.cont def hit(self): hitInterval = Sequence(Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15), Func(self.golem.setColorScale, 1, 0, 0, 0.75), Wait(0.15), Func(self.golem.clearColorScale), Wait(0.15)) self.health -= 1 if self.health == 4: self.trackerObject.setColor(0, 1, 0) hitInterval.start() elif self.health == 3: self.trackerObject.setColor(0.25, 0.75, 0) hitInterval.start() elif self.health == 2: self.trackerObject.setColor(0.5, .5, 0) hitInterval.start() elif self.health == 1: self.trackerObject.setColor(0.75, 0.25, 0) hitInterval.start() elif self.health == 0: self.trackerObject.setColor(0, 0, 0) self.request("Destroyed") def ceckAttack(self): for i in range(self.attackqueue.getNumEntries()): entry = self.attackqueue.getEntry(i) into = entry.getIntoNode() if "playerCollision" in into.getName(): if random.random() > .5: base.messenger.send("HitPlayer") def enterIdle(self): self.golem.loop("Idle") def enterWalk(self): self.golem.setPlayRate(2, "Walk") self.golem.loop("Walk") def enterAttack(self): self.AttackSeq.start() def enterDestroyed(self): self.ignoreAll() taskMgr.remove("GolemAI_task") self.AttackSeq.finish() self.golem.play("Destroyed") self.lookatFloater.hide() base.messenger.send("GolemDestroyed")