class Eve(Character): #----- CLASS VARIABLES -----# HEIGHT = 21.00 WIDTH = 5.0 INITIAL_HEADING = 90 MAX_JUMP_HEIGHT = 200.0 JUMP_SPEED = 70 RUNNING_SPEED = 40.0 INITIAL_ROLL_SPEED = 200.0 ROLL_ANIM_RATE = 15 OMEGA = 60.0 #----- CONSTRUCTOR -----# def __init__(self,game,render,world,accept,health=100,damage=0): super(Eve,self).__init__('Eve',health,damage) #----- INSTANCE VARIABLES -----# self.state = {'normal': True, 'jumping' : False, 'rolling' : False} self.speed = Vec3(0, 0, 0) self.omega = 0.0 self.tiresCollected = 0 self.accept = accept self.ready = True #----- PRIVATE INSTANCE VARIABLES -----# self.__render = render self.__world = world self.__game = game #----- ACTOR SETUP -----# self.actorNP1 = Actor('models/eve/eve.egg', { 'run' : 'models/eve/eve-run.egg', 'walk' : 'models/eve/eve-walk.egg', 'jump' : 'models/eve/eve-jump.egg'}) self.actorNP2 = Actor('models/eve/eve-tireroll.egg', {'roll' : 'models/eve/eve-tireroll.egg'}) self.actorNP1.setPlayRate(2,'walk') #----- PREPARE SFX -----# self.jump = base.loader.loadSfx("sfx/jump.wav") self.jump.setVolume(.1) self.running = base.loader.loadSfx("sfx/walking.wav") self.running.setLoop(True) self.running.setPlayRate(1.55) self.running.setVolume(.08) self.land = base.loader.loadSfx("sfx/land.flac") self.land.setLoop(False) self.land.setVolume(.05) self.roll = base.loader.loadSfx("sfx/rolling.wav") self.roll.setLoop(True) self.roll.setVolume(.09) self.ouch = base.loader.loadSfx("sfx/ouch.wav") self.ouch.setLoop(False) self.ouch.setVolume(.75) self.ouch.setPlayRate(1.25) self.throw = base.loader.loadSfx("sfx/throw.wav") self.throw.setLoop(False) self.throw.setVolume(.75) self.blocked = base.loader.loadSfx("sfx/blocked.wav") self.blocked.setVolume(.05) #----- SETUP CONTROL FOR EVE -----# inputState.watchWithModifiers('forward', 'w') inputState.watchWithModifiers('turnLeft', 'a') inputState.watchWithModifiers('turnRight', 'd') inputState.watchWithModifiers('backwards', 's') def render_eve(self,pos): self.searchMode(pos,Eve.INITIAL_HEADING) # Changing jump animation play rate self.currentNode.setPlayRate(1,'jump') self.__game.taskMgr.add(self.process_contacts,'attacks') def disable_character_controls(self): self.accept('m', self.do_nothing) self.accept('space', self.do_nothing) self.accept('enter',self.do_nothing) def enable_character_controls(self): self.accept('m', self.toggle_modes) self.accept('space', self.doJump) self.accept('enter',self.attack) def do_nothing(self): pass #------ METHODS USED TO MODIFY JUMP ANIMATION ------# def firstPart(self): self.currentNode.play('jump', fromFrame=0) def stopInJump(self): self.currentNode.stop() def finishJump(self): self.currentNode.play('jump', fromFrame=11) self.land.play() #self.currentNode.play('jump', fromFrame=self.currentNode.getCurrentFrame('jump')) def doJump(self): if self.currentControllerNode.isOnGround() is True: if self.currentState() is 'normal': if self.speed.getY() > 0: self.running.stop() self.state['jumping'] = True self.jump.play() self.currentControllerNode.doJump() #sequence = Sequence(Func(self.firstPart),Wait(.3),Func(self.stopInJump),Wait(2.95),Func(self.finishJump)) sequence = Sequence(Func(self.firstPart),Wait(.3),Func(self.stopInJump),Wait(2.95)) sequence.start() def searchMode(self,location,heading): self.state['normal'] = True self.state['rolling'] = False (self.init_x,self.init_y,self.init_z) = location self.__capsule_shape = BulletCapsuleShape(Eve.WIDTH, Eve.HEIGHT - 2 * Eve.WIDTH, ZUp) # Create bullet character controller self.character1= BulletCharacterControllerNode(self.__capsule_shape,0.4,self.name) #self.character1.setMaxJumpHeight(Eve.MAX_JUMP_HEIGHT) self.character1.setJumpSpeed(Eve.JUMP_SPEED) self.character1.setGravity(70) self.characterNP1 = self.__render.attachNewNode(self.character1) self.characterNP1.setPos(self.init_x,self.init_y,self.init_z) self.characterNP1.setH(heading) self.characterNP1.setCollideMask(BitMask32.allOn()) self.__world.attachCharacter(self.character1) self.actorNP1.reparentTo(self.characterNP1) self.actorNP1.setScale(4.0) self.actorNP1.setH(180) self.actorNP1.setPos(0,0,-9) self.currentNode = self.actorNP1 self.currentNP = self.characterNP1 self.currentControllerNode = self.character1 # Create a cylindrical collision shape collisionShape = BulletCylinderShape(6.5,3,XUp) # Create a ghost node and attach to render self.ghostNode = BulletGhostNode('Weapon') self.ghostNode.addShape(collisionShape) self.weaponNP = self.__game.render.attachNewNode(self.ghostNode) self.weaponNP.setCollideMask(BitMask32.allOff()) self.weaponNP.setPos(self.init_x, self.init_y, self.init_z) self.__game.world.attachGhost(self.ghostNode) self.weapon = self.__game.loader.loadModel('models/environ/tire/tire.egg') self.weapon.setScale(4,4,4) self.weapon.setPos(-.5,0,0) self.weapon.reparentTo(self.weaponNP) self.weapon.hide() self.__game.taskMgr.add(self.update_weapon_pos,"weapon") def reset(self): self.characterNP1.setPos(self.init_x,self.init_y,self.init_z) def update_weapon_pos(self,task): self.weaponNP.setPos(self.characterNP1.getX(),self.characterNP1.getY(), self.characterNP1.getZ() + 5) self.weaponNP.setH(self.characterNP1.getH()) return task.cont def attack(self): if self.tiresCollected > 0 and self.ready is True: self.throw.play() self.weapon.show() xpos = 100 * cos((90 - self.characterNP1.getH()) * (pi / 180.0)) ypos = -100 * sin((90 - self.characterNP1.getH()) * (pi / 180.0)) trajectory = ProjectileInterval(self.weaponNP, startPos = self.weaponNP.getPos(), endPos = Point3(self.weaponNP.getX() - xpos,self.weaponNP.getY() - ypos, self.weaponNP.getZ()-10), duration = .5, gravityMult = 15) Sequence(Func(self.set_weapon_busy),trajectory,Func(self.weapon.hide),Func(self.set_weapon_ready)).start() self.tiresCollected -= 1 else: self.blocked.play() def set_weapon_ready(self): self.ready = True def set_weapon_busy(self): self.ready = False def process_contacts(self,task): for enemy in self.__game.e.enemies: self.check_impact(enemy) return task.cont def check_impact(self,enemy): result = self.__game.world.contactTestPair(self.ghostNode,enemy.np.node()) if len(result.getContacts()) > 0: if self.weapon.isHidden() is False: self.weapon.hide() if self.ready is False: enemy.take_damage(self.damage) def attackMode(self,location,heading): self.state['normal'] = False self.state['rolling'] = True (self.init_x,self.init_y,self.init_z) = location self.__cylinder_shape = BulletCylinderShape(Eve.WIDTH + 2, Eve.HEIGHT - 4, XUp) # Create bullet character controller self.character2= BulletCharacterControllerNode(self.__cylinder_shape,0.4,self.name) self.characterNP2 = self.__render.attachNewNode(self.character2) self.characterNP2.setPos(self.init_x,self.init_y,self.init_z-2) self.characterNP2.setH(heading) self.characterNP2.setCollideMask(BitMask32.allOn()) self.__world.attachCharacter(self.character2) self.character2.setGravity(70) self.actorNP2.reparentTo(self.characterNP2) self.actorNP2.setScale(4.0) self.actorNP2.setH(180) self.actorNP2.setPos(0,0,0) self.currentNode = self.actorNP2 self.currentNP = self.characterNP2 self.currentControllerNode = self.character2 # Set play rate of the rolling animation self.currentNode.setPlayRate(15,'roll') def is_attack_mode(self): return self.state['rolling'] def toggle_modes(self): if self.is_attack_mode() is False: loc = (self.characterNP1.getX(),self.characterNP1.getY(),self.characterNP1.getZ()) heading = self.characterNP1.getH() self.__world.removeCharacter(self.character1) self.character1.removeChild(0) self.attackMode(loc,heading) else: loc = (self.characterNP2.getX(),self.characterNP2.getY(),self.characterNP2.getZ()) heading = self.characterNP2.getH() self.__world.removeCharacter(self.character2) self.character2.removeChild(0) self.searchMode(loc,heading) def processEveInput(self): if self.currentControllerNode.isOnGround() is True: self.speed = Vec3(0, 0, 0) self.omega = 0.0 if inputState.isSet('forward'): if self.state['rolling'] == True: self.speed.setY( Eve.INITIAL_ROLL_SPEED) else: self.speed.setY( Eve.RUNNING_SPEED) self.currentNode.setP(15) if inputState.isSet('backwards'): if self.state['rolling'] == True: self.speed.setY( Eve.INITIAL_ROLL_SPEED - 300) else: self.speed.setY(-1 * Eve.RUNNING_SPEED - 10) if inputState.isSet('turnLeft'): self.omega = Eve.OMEGA if self.speed.getY() == 0: self.currentNode.setR(0) else: self.currentNode.setR(15) if inputState.isSet('turnRight'): self.omega = Eve.OMEGA * -1 if self.speed.getY() == 0: self.currentNode.setR(0) else: self.currentNode.setR(-15) self.currentControllerNode.setAngularMovement(self.omega) if self.currentControllerNode.isOnGround() is False: self.currentControllerNode.setAngularMovement(0.0) self.currentControllerNode.setLinearMovement(self.speed, True) self.currentNode.setR(0) if self.currentControllerNode.isOnGround() is True and self.currentNode.getCurrentAnim() == 'jump': self.currentNode.setR(0) self.currentControllerNode.setAngularMovement(0.0) self.currentControllerNode.setLinearMovement(0.0, True) if self.currentControllerNode.isOnGround() is True and self.currentNode.getCurrentAnim() != 'jump': self.currentControllerNode.setAngularMovement(self.omega) self.currentControllerNode.setLinearMovement(self.speed, True) def currentState(self): if self.state['rolling'] is True: return 'rolling' else: return 'normal' def updateEveAnim(self): self.processEveInput() if self.currentControllerNode.isOnGround() is True and self.currentNode.getCurrentAnim() != 'jump': if self.speed.getY() > 0: if self.omega == 0.0: self.currentNode.setR(0) if self.currentState() is 'rolling': if self.running.status() == self.running.PLAYING: self.running.stop() if self.roll.status() != self.roll.PLAYING: self.roll.play() if self.currentNode.getCurrentAnim() != 'roll': self.currentNode.loop('roll') elif self.currentState() is 'normal': if self.roll.status() == self.roll.PLAYING: self.roll.stop() if self.running.status() != self.running.PLAYING: self.running.play() if self.currentNode.getCurrentAnim() != 'run': self.currentNode.loop('run') elif self.speed.getY() < 0: if self.currentState() is 'rolling': if self.running.status() == self.running.PLAYING: self.running.stop() if self.roll.status() != self.roll.PLAYING: self.roll.play() if self.currentNode.getCurrentAnim() != 'roll': self.currentNode.loop('roll') elif self.currentState() is 'normal': if self.roll.status() == self.roll.PLAYING: self.roll.stop() if self.running.status() != self.running.PLAYING: self.running.play() if self.currentNode.getCurrentAnim() != 'walk': self.currentNode.loop('walk') else: if self.omega != 0: if self.currentState() is 'rolling': if self.currentNode.getCurrentAnim() != 'roll': self.currentNode.loop('roll') elif self.currentState() is 'normal': if self.currentNode.getCurrentAnim() != 'walk': self.actorNP1.setPlayRate(1,'walk') self.currentNode.loop('walk') else: self.currentNode.stop(self.currentNode.getCurrentAnim()) self.actorNP1.setPlayRate(2,'walk') self.currentNode.setP(0) self.currentNode.setR(0) if self.running.status() == self.running.PLAYING: self.running.stop() if self.roll.status() == self.roll.PLAYING: self.roll.stop() if self.state['rolling'] is True: frame = self.currentNode.getCurrentFrame('roll') if frame is None: frame = 0 else: frame = self.currentNode.getCurrentFrame('roll') self.currentNode.pose('roll',frame) elif self.state['normal'] is True: self.currentNode.pose('walk',5) elif self.currentControllerNode.isOnGround() is False and self.state['jumping'] is False: self.currentNode.pose('jump',7) def take_damage(self,damage): self.ouch.play() color_scale_interval1 = LerpColorScaleInterval(self.currentNode, .5, (1,0,0,.1), (1,0,0,0)) Sequence(color_scale_interval1,Wait(.005),Func(self.currentNode.clearColorScale)).start() self.health -= damage