def setupPlayer(self, x, y, z): yetiHeight = 7 yetiRadius = 2 yetiShape = BulletCapsuleShape(yetiRadius, yetiHeight - 2 * yetiRadius, ZUp) modelPrefix = "../res/models/yeti_" self.yetiModel = Actor("../res/models/yeti.egg", {"idle":"../res/models/yeti_idle.egg", "walk":"../res/models/yeti_walking.egg"}) self.yetiModel.setH(90) self.yetiModel.setPos(0, 0, SNOW_HEIGHT) playerNode = BulletRigidBodyNode("Player") playerNode.setMass(MASS) playerNode.addShape(yetiShape) # Without this set to 0,0,0, the Yeti would wobble like a Weeble but not fall down. playerNode.setAngularFactor(Vec3(0,0,0)) # Without this disabled, things will weld together after a certain amount of time. It's really annoying. playerNode.setDeactivationEnabled(False) playerNP = self.worldNP.attachNewNode(playerNode) playerNP.setPos(x, y, z) playerNP.setH(270) self.yetiModel.reparentTo(playerNP) self.bulletWorld.attachRigidBody(playerNP.node()) # Hopefully Brandon will get those animation files to me so I can convert them. # self.setAnimation('idle') return playerNP
def _initAgents(self): # Load agents for agent in self.scene.scene.findAllMatches('**/agents/agent*'): transform = TransformState.makeIdentity() if self.agentMode == 'capsule': shape = BulletCapsuleShape( self.agentRadius, self.agentHeight - 2 * self.agentRadius) elif self.agentMode == 'sphere': shape = BulletCapsuleShape(self.agentRadius, 2 * self.agentRadius) # XXX: use BulletCharacterControllerNode class, which already handles local transform? node = BulletRigidBodyNode('physics') node.setMass(self.agentMass) node.setStatic(False) node.setFriction(self.defaultMaterialFriction) node.setRestitution(self.defaultMaterialRestitution) node.addShape(shape) self.bulletWorld.attach(node) # Constrain the agent to have fixed position on the Z-axis node.setLinearFactor(Vec3(1.0, 1.0, 0.0)) # Constrain the agent not to be affected by rotations node.setAngularFactor(Vec3(0.0, 0.0, 0.0)) node.setIntoCollideMask(BitMask32.allOn()) node.setDeactivationEnabled(True) # Enable continuous collision detection (CCD) node.setCcdMotionThreshold(1e-7) node.setCcdSweptSphereRadius(0.50) if node.isStatic(): agent.setTag('physics-mode', 'static') else: agent.setTag('physics-mode', 'dynamic') # Attach the physic-related node to the scene graph physicsNp = NodePath(node) physicsNp.setTransform(transform) # Reparent all child nodes below the new physic node for child in agent.getChildren(): child.reparentTo(physicsNp) physicsNp.reparentTo(agent) # NOTE: we need this to update the transform state of the internal bullet node physicsNp.node().setTransformDirty() # Validation assert np.allclose( mat4ToNumpyArray(physicsNp.getNetTransform().getMat()), mat4ToNumpyArray(agent.getNetTransform().getMat()), atol=1e-6)
class SMCollide: # ------------------------------------------------------------------------------------------------------------------------------------------------------------ # Creates a new collision-enabled gameObject. # Args: model - Model path # world - bulletWorld instance # worldNP - world's NodePath # pos - Point3 position # scale - int scale # hpr - Vec3(Heading, Pitch, Rotation) # ------------------------------------------------------------------------------------------------------------------------------------------------------------ def __init__(self, model, world, worldNP, pos, scale, hpr): self.worldNP = worldNP bulletWorld = world # Initialize the model. self.AIModel = loader.loadModel(model) self.AINode = BulletRigidBodyNode("AIChar") self.AIModel.setScale(scale) self.AIModel.flattenLight() # Combines all geom nodes into one geom node. # Build the triangle mesh shape and attach it with the transform. geom = self.AIModel.findAllMatches("**/+GeomNode").getPath(0).node().getGeom(0) mesh = BulletTriangleMesh() mesh.addGeom(geom) shape = BulletTriangleMeshShape(mesh, dynamic=False) self.AINode.addShape(shape, TransformState.makePosHprScale(Point3(0, 0, 0), hpr, scale)) self.AINode.setMass(0) bulletWorld.attachRigidBody(self.AINode) # Apply the same transforms on the model being rendered. self.AIModel.reparentTo(render) self.AIModel.setH(hpr.getX()) self.AIModel.setP(hpr.getY()) self.AIModel.setR(hpr.getZ()) self.AINode.setAngularFactor(Vec3(0, 0, 0)) # Attach it to the world. self.AIChar = self.worldNP.attachNewNode(self.AINode) self.AIModel.reparentTo(self.AIChar) self.AIChar.setPos(pos)
class SMCollide(): #------------------------------------------------------------------------------------------------------------------------------------------------------------ # Creates a new collision-enabled gameObject. # Args: model - Model path # world - bulletWorld instance # worldNP - world's NodePath # pos - Point3 position # scale - int scale # hpr - Vec3(Heading, Pitch, Rotation) #------------------------------------------------------------------------------------------------------------------------------------------------------------ def __init__(self, model, world, worldNP, pos, scale, hpr): self.worldNP = worldNP bulletWorld = world # Initialize the model. self.AIModel = loader.loadModel(model) self.AINode = BulletRigidBodyNode('AIChar') self.AIModel.setScale(scale) self.AIModel.flattenLight() # Combines all geom nodes into one geom node. # Build the triangle mesh shape and attach it with the transform. geom = self.AIModel.findAllMatches('**/+GeomNode').getPath(0).node().getGeom(0) mesh = BulletTriangleMesh() mesh.addGeom(geom) shape = BulletTriangleMeshShape(mesh, dynamic=False) self.AINode.addShape(shape, TransformState.makePosHprScale(Point3(0,0,0), hpr, scale)) self.AINode.setMass(0) bulletWorld.attachRigidBody(self.AINode) # Apply the same transforms on the model being rendered. self.AIModel.reparentTo(render) self.AIModel.setH(hpr.getX()) self.AIModel.setP(hpr.getY()) self.AIModel.setR(hpr.getZ()) self.AINode.setAngularFactor(Vec3(0,0,0)) # Attach it to the world. self.AIChar = self.worldNP.attachNewNode(self.AINode) self.AIModel.reparentTo(self.AIChar) self.AIChar.setPos(pos)
class Player(Entity): walkspeed = 50 damping = 0.9 topspeed = 15 leftMove = False rightMove = False jumpToggle = False crouchToggle = False def __init__(self, world): super(Player, self).__init__() self.obj = utilities.loadObject("player", depth=20) self.world = world self.health = 100 self.inventory = dict() self.depth = self.obj.getPos().y self.location = Point2(0,0) self.velocity = Vec3(0) self.pt = 0.0 self.shape = BulletBoxShape(Vec3(0.3, 1.0, 0.49)) self.bnode = BulletRigidBodyNode('Box') self.bnode.setMass(1.0) self.bnode.setAngularVelocity(Vec3(0)) self.bnode.setAngularFactor(Vec3(0)) self.bnode.addShape(self.shape) self.bnode.setLinearDamping(0.95) self.bnode.setLinearSleepThreshold(0) world.bw.attachRigidBody(self.bnode) self.bnode.setPythonTag("Entity", self) self.bnode.setIntoCollideMask(BitMask32.bit(0)) self.node = utilities.app.render.attachNewNode(self.bnode) self.node.setPos(self.obj.getPos()) self.obj.setPos(0,0,0) self.obj.setScale(1) self.obj.reparentTo(self.node) self.node.setPos(self.location.x, self.depth, self.location.y) def initialise(self): self.inventory["LightLaser"] = LightLaser(self.world, self) self.inventory["Blowtorch"] = Blowtorch(self.world, self) self.inventory["Grenade"] = Grenade(self.world, self) for i in self.inventory: self.inventory[i].initialise() self.currentItem = self.inventory["Blowtorch"] self.currentItem.equip() self.armNode = self.obj.attachNewNode("arm") self.armNode.setPos(0.20,0,0.08) self.arm = utilities.loadObject("arm", scaleX = 0.5,scaleY = 0.5, depth = -0.2) self.arm.reparentTo(self.armNode) def activate(self): self.currentItem.activate() def update(self, timer): self.velocity = self.bnode.getLinearVelocity() if (self.leftMove): self.bnode.applyCentralForce(Vec3(-Player.walkspeed,0,0)) if (self.rightMove): self.bnode.applyCentralForce(Vec3(Player.walkspeed,0,0)) if (self.jumpToggle): self.bnode.applyCentralForce(Vec3(0,0,Player.walkspeed)) if (self.crouchToggle): self.bnode.applyCentralForce(Vec3(0,0,-Player.walkspeed)) if (self.velocity.x < -self.topspeed): self.velocity.x = -self.topspeed if (self.velocity.x > self.topspeed): self.velocity.x = self.topspeed mouse = utilities.app.mousePos # extrude test near = Point3() far = Point3() utilities.app.camLens.extrude(mouse, near, far) camp = utilities.app.camera.getPos() near *= 20 # player depth if near.x != 0: angle = atan2(near.z + camp.z - self.node.getPos().z, near.x + camp.x - self.node.getPos().x) #angle = atan2(near.z, near.x) else: angle = 90 self.angle = angle # set current item to point at cursor self.currentItem.update(timer) # move the camera so the player is centred horizontally, # but keep the camera steady vertically utilities.app.camera.setPos(self.node.getPos().x, 0, self.node.getPos().z) #move arm into correct position. gunLength = 2.0 self.gunVector = Point2(cos(angle)*gunLength - self.armNode.getX()*5, sin(angle)*gunLength - self.armNode.getZ()*2) armAngle = atan2(self.gunVector.y, self.gunVector.x) self.arm.setHpr(self.armNode, 0, 0, -1 * degrees(armAngle)) def moveLeft(self, switch): self.leftMove = switch #self.bnode.applyCentralForce(Vec3(-500,0,0)) def moveRight(self, switch): self.rightMove = switch #self.bnode.applyCentralForce(Vec3(500,0,0)) def jump(self, switch): self.jumpToggle = switch def crouch(self, switch): self.crouchToggle = switch
class Flame(Entity): """ The thing that comes out the end of the thing you hold """ animspeed = 0.1 depth = 20 playerWidth = 3 speed = 30 maxlife = 10 damage = 30 def __init__(self, world, pos, hpr): super(Flame, self).__init__() self.shape = BulletBoxShape(Vec3(0.1, 0.05, 0.05)) self.bnode = BulletRigidBodyNode() self.bnode.setMass(0.00001) self.bnode.addShape(self.shape) self.np = utilities.app.render.attachNewNode(self.bnode) self.remove = False self.world = world self.anim = list() self.anim.append(utilities.loadObject("flame1", depth=0)) self.anim.append(utilities.loadObject("flame2", depth=0)) self.anim.append(utilities.loadObject("flame3", depth=0)) world.bw.attachRigidBody(self.bnode) self.curspr = 0 self.livetime = 0 self.delta = 0 self.pos = pos self.pos.y = Flame.depth self.hpr = hpr self.vel = Point2() self.vel.x = cos(world.player.angle) * Flame.speed self.vel.y = sin(world.player.angle) * Flame.speed tv = Vec3(self.vel.x, 0, self.vel.y) # this makes the shot miss the target if the player has any velocity tv += world.player.bnode.getLinearVelocity() self.bnode.setLinearVelocity(tv) tv.normalize() # initial position of RB and draw plane self.np.setHpr(hpr) self.np.setPos(pos + tv / 2) self.bnode.setAngularFactor(Vec3(0, 0, 0)) self.bnode.setLinearFactor(Vec3(1, 0, 1)) self.bnode.setGravity(Vec3(0, 0, 0)) #self.bnode.setCcdMotionThreshold(1e-7) #self.bnode.setCcdSweptSphereRadius(0.50) self.bnode.notifyCollisions(True) self.bnode.setIntoCollideMask(BitMask32.bit(1)) self.bnode.setPythonTag("Entity", self) self.noCollideFrames = 4 for a in self.anim: a.hide() a.reparentTo(self.np) a.setScale(0.25, 1, 0.25) a.setPos(0, -0.1, 0) self.obj = self.anim[self.curspr] self.obj.show() self.bnode.setPythonTag("entity", self) def update(self, timer): #animation self.delta += timer self.livetime += timer if self.remove: self.obj.hide() return if self.noCollideFrames == 0: self.bnode.setIntoCollideMask(BitMask32.allOn()) if self.noCollideFrames > -1: self.noCollideFrames -= 1 if self.delta > Flame.animspeed: self.delta = 0 self.obj.hide() self.curspr += 1 if self.curspr > len(self.anim) - 1: self.curspr = 0 self.obj = self.anim[self.curspr] self.obj.show() if self.livetime > Flame.maxlife: self.remove = True def hitby(self, index, projectile): return def destroy(self): self.remove = True self.obj.hide() for model in self.anim: model.remove() self.world.bw.removeRigidBody(self.bnode) def removeOnHit(self): self.remove = True
class Chunk(Entity): chunkmass = 5.0 def __init__(self, world, blocks, pos, hpr=Point3(0,0,0), diff = Vec3(0,0,0), angVel = Vec3(0,0,0), linVel = Vec3(0,0,0)): super(Chunk, self).__init__() self.mass = len(blocks)*Chunk.chunkmass self.world = world self.blocks = blocks self.bnode = BulletRigidBodyNode() self.bnode.setMass(self.mass) self.bnode.setAngularFactor(Vec3(0,1,0)) self.bnode.setLinearSleepThreshold(20) self.bnode.setAngularSleepThreshold(20) self.bnode.setAngularVelocity(angVel) self.bnode.setLinearVelocity(linVel) self.np = utilities.app.render.attachNewNode(self.bnode) self.np.setPos(pos.x,20,pos.y) self.np.setHpr(hpr) self.np.setPos(self.np, diff) self.bnode.setPythonTag("entity", self) self.inScope = False # culling not done yet # centre the blocks around the np and add their shapes in. self.minMax() cog = Point2((self.minX+self.maxX) / 2.0, (self.minY+self.maxY) / 2.0) for block in blocks: block.rebuild(self, cog) world.bw.attachRigidBody(self.bnode) self.hitlist = dict() def update(self, timer): for index in self.hitlist: # returns true if the wall is destroyed by the hit if self.blocks[index].hitby(self.hitlist[index]): self.blocks[index].destroy() self.rebuild(index) self.hitlist.clear() if self.playerDistance() > 40.0: self.bnode.setAngularSleepThreshold(1) self.bnode.setLinearSleepThreshold(1) else: self.bnode.setAngularSleepThreshold(0) self.bnode.setLinearSleepThreshold(0) def playerDistance(self): sp = self.np.getPos() pp = self.world.player.node.getPos() distance = hypot(sp.x - pp.x, sp.z - pp.z) return distance # remove an element and rebuild # TODO add another method for removing multiple # blocks in a single go def rebuild(self, index): deadblock = self.blocks[index] out = list() for block in self.blocks: for edge in block.edges: if edge == deadblock: block.edges.remove(edge) for block in deadblock.edges: chunk = list() self.searchBlock(block, chunk, deadblock) out.append(chunk) #out is a list of lists of populated blocks #remove duplicate chunks results = list() for chunk in out: chunk.sort(compareBlock) if not chunk in results and len(chunk) > 0: results.append(chunk) for result in results: self.minMax(result) #diff = Point2((self.minX+self.maxX) / 2.0, (self.minY+self.maxY) / 2.0) diff = Vec3((self.minX+self.maxX) / 2.0, 0, (self.minY+self.maxY) / 2.0) p = self.np.getPos() pos = Point2(p.x, p.z) h = self.np.getHpr() self.world.entities.append(Chunk(self.world, result, pos, h, diff, self.bnode.getAngularVelocity(), self.bnode.getLinearVelocity())) self.destroyNow() self.remove = True def searchBlock(self, block, lst, deleted): if block in lst: return else: lst.append(block) for newblock in block.edges: self.searchBlock(newblock, lst, deleted) def minMax(self, blocks=None): if blocks == None: blocks = self.blocks self.minX = blocks[0].pos.x self.minY = blocks[0].pos.y self.maxX = blocks[0].pos.x self.maxY = blocks[0].pos.y for point in blocks: self.minX = min(point.pos.x, self.minX) self.minY = min(point.pos.y, self.minY) self.maxX = max(point.pos.x, self.maxX) self.maxY = max(point.pos.y, self.maxY) # Need to clear the bulletrigidbody immediately # so that the phys object isn't present during next sim phase # which occurs before cleanup normally. Otherwise shit will # fly everywhere since two things are inside each other def destroyNow(self): self.world.bw.removeRigidBody(self.bnode) return # since this is handled earlier nothing happens def destroy(self): return def hitby(self, projectile, index): self.hitlist[index] = projectile
class Chunk(Entity): chunkmass = 5.0 def __init__(self, world, blocks, pos, hpr=Point3(0, 0, 0), diff=Vec3(0, 0, 0), angVel=Vec3(0, 0, 0), linVel=Vec3(0, 0, 0)): super(Chunk, self).__init__() self.mass = len(blocks) * Chunk.chunkmass self.world = world self.blocks = blocks self.bnode = BulletRigidBodyNode() self.bnode.setMass(self.mass) self.bnode.setAngularFactor(Vec3(0, 1, 0)) self.bnode.setLinearSleepThreshold(20) self.bnode.setAngularSleepThreshold(20) self.bnode.setAngularVelocity(angVel) self.bnode.setLinearVelocity(linVel) self.np = utilities.app.render.attachNewNode(self.bnode) self.np.setPos(pos.x, 20, pos.y) self.np.setHpr(hpr) self.np.setPos(self.np, diff) self.bnode.setPythonTag("entity", self) self.inScope = False # culling not done yet # centre the blocks around the np and add their shapes in. self.minMax() cog = Point2((self.minX + self.maxX) / 2.0, (self.minY + self.maxY) / 2.0) for block in blocks: block.rebuild(self, cog) world.bw.attachRigidBody(self.bnode) self.hitlist = dict() def update(self, timer): for index in self.hitlist: # returns true if the wall is destroyed by the hit if self.blocks[index].hitby(self.hitlist[index]): self.blocks[index].destroy() self.rebuild(index) self.hitlist.clear() if self.playerDistance() > 40.0: self.bnode.setAngularSleepThreshold(1) self.bnode.setLinearSleepThreshold(1) else: self.bnode.setAngularSleepThreshold(0) self.bnode.setLinearSleepThreshold(0) def playerDistance(self): sp = self.np.getPos() pp = self.world.player.node.getPos() distance = hypot(sp.x - pp.x, sp.z - pp.z) return distance # remove an element and rebuild # TODO add another method for removing multiple # blocks in a single go def rebuild(self, index): deadblock = self.blocks[index] out = list() for block in self.blocks: for edge in block.edges: if edge == deadblock: block.edges.remove(edge) for block in deadblock.edges: chunk = list() self.searchBlock(block, chunk, deadblock) out.append(chunk) #out is a list of lists of populated blocks #remove duplicate chunks results = list() for chunk in out: chunk.sort(compareBlock) if not chunk in results and len(chunk) > 0: results.append(chunk) for result in results: self.minMax(result) #diff = Point2((self.minX+self.maxX) / 2.0, (self.minY+self.maxY) / 2.0) diff = Vec3((self.minX + self.maxX) / 2.0, 0, (self.minY + self.maxY) / 2.0) p = self.np.getPos() pos = Point2(p.x, p.z) h = self.np.getHpr() self.world.entities.append( Chunk(self.world, result, pos, h, diff, self.bnode.getAngularVelocity(), self.bnode.getLinearVelocity())) self.destroyNow() self.remove = True def searchBlock(self, block, lst, deleted): if block in lst: return else: lst.append(block) for newblock in block.edges: self.searchBlock(newblock, lst, deleted) def minMax(self, blocks=None): if blocks == None: blocks = self.blocks self.minX = blocks[0].pos.x self.minY = blocks[0].pos.y self.maxX = blocks[0].pos.x self.maxY = blocks[0].pos.y for point in blocks: self.minX = min(point.pos.x, self.minX) self.minY = min(point.pos.y, self.minY) self.maxX = max(point.pos.x, self.maxX) self.maxY = max(point.pos.y, self.maxY) # Need to clear the bulletrigidbody immediately # so that the phys object isn't present during next sim phase # which occurs before cleanup normally. Otherwise shit will # fly everywhere since two things are inside each other def destroyNow(self): self.world.bw.removeRigidBody(self.bnode) return # since this is handled earlier nothing happens def destroy(self): return def hitby(self, projectile, index): self.hitlist[index] = projectile
class Catcher(Enemy): damage = 25 def __init__(self, location, player, cmap, world): super(Catcher, self).__init__(location) self.player = player self.cmap = cmap self.obj = utilities.loadObject("robot", depth=20) self.world = world self.health = 100 self.depth = self.obj.getPos().y self.location = location self.velocity = Vec3(0) self.shape = BulletBoxShape(Vec3(0.5, 1.0, 0.5)) self.bnode = BulletRigidBodyNode('Box') self.bnode.setMass(0.1) self.bnode.setAngularVelocity(Vec3(0)) self.bnode.setAngularFactor(Vec3(0)) self.bnode.addShape(self.shape) self.bnode.setLinearDamping(0.75) self.bnode.setLinearSleepThreshold(0) world.bw.attachRigidBody(self.bnode) self.bnode.setPythonTag("entity", self) self.bnode.setIntoCollideMask(BitMask32.bit(0)) self.node = utilities.app.render.attachNewNode(self.bnode) self.node.setPos(self.obj.getPos()) self.obj.setPos(0,0,0) self.obj.setScale(1) self.obj.reparentTo(self.node) self.node.setPos(self.location.x, self.depth, self.location.y) def update(self, time): self.location = Point2(self.node.getPos().x - self.player.location.x, self.node.getPos().z - self.player.location.y) if self.location.x > 20 or self.location.x < -20: return if self.location.y > 20 or self.location.y < -20: return path = findPath(Point2(self.location + Point2(20,20)), Point2(20,20), self.world.cmap) if len(path) > 1: move = path[1] - self.location self.bnode.applyCentralForce(Vec3(move.x-20,0,move.y-20)) def hitby(self, projectile, index): self.health -= projectile.damage if (self.health < 0): self.remove = True greyscale = 0.3 + (0.01 * self.health) self.obj.setColor(1, greyscale,greyscale,1) return False def removeOnHit(self): return def destroy(self): self.obj.hide() self.world.bw.removeRigidBody(self.bnode)
class EscapeFromJCMB(object, DirectObject): def __init__(self): print "Loading..." self.init_window() self.init_music() self.init_bullet() self.init_key() self.load_world() self.init_player() self.init_objects() render.prepareScene(base.win.getGsg()) print "Done" self.start_physics() def init_window(self): # Hide the mouse cursor props = WindowProperties() props.setCursorHidden(True) base.win.requestProperties(props) def init_music(self): music = base.loader.loadSfx("../data/snd/Bent_and_Broken.mp3") music.play() self.playferscream = base.loader.loadSfx("../data/snd/deadscrm.wav") def init_bullet(self): self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -9.81)) # debugNode = BulletDebugNode('Debug') # debugNode.showWireframe(True) # debugNode.showConstraints(True) # debugNode.showBoundingBoxes(False) # debugNode.showNormals(False) # debugNP = render.attachNewNode(debugNode) # debugNP.show() # self.world.setDebugNode(debugNP.node()) alight = AmbientLight('alight') alight.setColor(VBase4(0.05, 0.05, 0.05, 1)) alnp = render.attachNewNode(alight) render.setLight(alnp) def init_key(self): # Stores the state of the keys, 1 for pressed and 0 for unpressed self.key_state = { 'up': False, 'right': False, 'down': False, 'left': False } # Assign the key event handler self.accept('w', self.set_key_state, ['up', True]) self.accept('w-up', self.set_key_state, ['up', False]) self.accept('d', self.set_key_state, ['right', True]) self.accept('d-up', self.set_key_state, ['right', False]) self.accept('s', self.set_key_state, ['down', True]) self.accept('s-up', self.set_key_state, ['down', False]) self.accept('a', self.set_key_state, ['left', True]) self.accept('a-up', self.set_key_state, ['left', False]) # Stores the state of the mouse buttons, 1 for pressed and 0 for unpressed self.mouse_state = {'left_click': False, 'right_click': False} # Assign the mouse click event handler self.accept('mouse1', self.set_mouse_state, ['left_click', True]) self.accept('mouse1-up', self.set_mouse_state, ['left_click', False]) self.accept('mouse2', self.set_mouse_state, ['right_click', True]) self.accept('mouse2-up', self.set_mouse_state, ['right_click', False]) self.accept('z', self.print_pos) # Esc self.accept('escape', sys.exit) def set_key_state(self, key, state): self.key_state[key] = state def set_mouse_state(self, button, state): self.mouse_state[button] = state def print_pos(self): print self.playernp.getPos() def egg_to_BulletTriangleMeshShape(self, modelnp): mesh = BulletTriangleMesh() for collisionNP in modelnp.findAllMatches('**/+CollisionNode'): collisionNode = collisionNP.node() for collisionPolygon in collisionNode.getSolids(): tri_points = collisionPolygon.getPoints() mesh.addTriangle(tri_points[0], tri_points[1], tri_points[2]) shape = BulletTriangleMeshShape(mesh, dynamic=False) return shape def load_world(self): stairwell = loader.loadModel('../data/mod/jcmbstairs.egg') stairwell.reparentTo(render) stairwell_shape = self.egg_to_BulletTriangleMeshShape(stairwell) stairwellnode = BulletRigidBodyNode('stairwell') stairwellnode.addShape(stairwell_shape) self.world.attachRigidBody(stairwellnode) def init_player(self): # Stop the default mouse behaviour base.disableMouse() # Character has a capsule shape shape = BulletCapsuleShape(0.2, 1, ZUp) self.player = BulletRigidBodyNode('Player') self.player.setMass(80.0) self.player.addShape(shape) self.playernp = render.attachNewNode(self.player) self.playernp.setPos(0, 0, 1) self.world.attachRigidBody(self.player) self.player.setLinearSleepThreshold(0.0) self.player.setAngularFactor(0.0) self.player_speed = 3 self.player_is_grabbing = False # self.head = BulletRigidBodyNode('Player Head') # self.head.addShape(BulletSphereShape(0.2)) # self.head.setMass(10) # self.head.setInertia(Vec3(1,1,1)) # self.head.setAngularFactor(1.0) # self.head.setLinearFactor(0.0) # self.headnp = self.playernp.attachNewNode(self.head) # self.headnp.setPos(0,0,0) # self.headnp.setCollideMask(BitMask32.allOff()) # self.world.attachRigidBody(self.head) # Attach the camera to the player's head base.camera.reparentTo(self.playernp) # base.camera.setPos(0,0,.5) base.camLens.setFov(80) base.camLens.setNear(0.01) # Make the torch and attach it to our character torch = Spotlight('torch') torch.setColor(VBase4(1, 1, 1, 1)) lens = PerspectiveLens() lens.setFov(80) lens.setNearFar(20, 100) torch.setLens(lens) self.torchnp = base.camera.attachNewNode(torch) self.torchnp.setPos(0, 0, 0) # Allow the world to be illuminated by our torch render.setLight(self.torchnp) self.cs = None # Player's "hand" in the world hand_model = loader.loadModel('../data/mod/hand.egg') hand_model.setScale(1) hand_model.setBillboardPointEye() self.hand = BulletRigidBodyNode('Hand') self.hand.addShape(BulletSphereShape(0.1)) self.hand.setLinearSleepThreshold(0.0) self.hand.setLinearDamping(0.9999999) self.hand.setAngularFactor(0.0) self.hand.setMass(1.0) self.world.attachRigidBody(self.hand) self.handnp = render.attachNewNode(self.hand) self.handnp.setCollideMask(BitMask32.allOff()) # hand_model.reparentTo(self.handnp) # Create a text node to display object identification information and attach it to the player's "hand" self.hand_text = TextNode('Hand Text') self.hand_text.setText("Ch-ch-chek yoself befo yo rek yoself, bro.") self.hand_text.setAlign(TextNode.ACenter) self.hand_text.setTextColor(1, 1, 1, 1) self.hand_text.setShadow(0.05, 0.05) self.hand_text.setShadowColor(0, 0, 0, 1) self.hand_text_np = render.attachNewNode(self.hand_text) self.hand_text_np.setScale(0.03) self.hand_text_np.setBillboardPointEye() self.hand_text_np.hide() # Disable the depth testing for the hand and the text - we always want these things on top, with no clipping self.handnp.setDepthTest(False) self.hand_text_np.setDepthTest(False) # Add the player update task taskMgr.add(self.update, 'update_player_task') def init_objects(self): # Make Playfer Box shape = BulletBoxShape(Vec3(0.25, 0.25, 0.25)) node = BulletRigidBodyNode('Playfer Box') node.setMass(110.0) node.setFriction(1.0) node.addShape(shape) node.setAngularDamping(0.0) np = render.attachNewNode(node) np.setPos(-1.4, 1.7, -1.7) self.world.attachRigidBody(node) playferboxmodel = loader.loadModel('../data/mod/playferbox.egg') playferboxmodel.reparentTo(np) # Make Pendlepot shape = BulletBoxShape(Vec3(0.2, 0.15, 0.1)) node = BulletRigidBodyNode('Pendlepot') node.setMass(5.0) node.setFriction(1.0) node.addShape(shape) node.setAngularDamping(0.0) np = render.attachNewNode(node) np.setPos(-1.4, 1.7, -1.5) self.world.attachRigidBody(node) pendlepotmodel = loader.loadModel('../data/mod/pendlepot.egg') pendlepotmodel.reparentTo(np) def update(self, task): # Update camera orientation md = base.win.getPointer(0) mouse_x = md.getX() mouse_y = md.getY() centre_x = base.win.getXSize() / 2 centre_y = base.win.getYSize() / 2 if base.win.movePointer(0, centre_x, centre_y): new_H = base.camera.getH() + (centre_x - mouse_x) new_P = base.camera.getP() + (centre_y - mouse_y) if new_P < -90: new_P = -90 elif new_P > 90: new_P = 90 base.camera.setH(new_H) base.camera.setP(new_P) # Update player position speed = 3 self.player_is_moving = False if (self.key_state["up"] == True): self.player_is_moving = True dir = 0 if (self.key_state["down"] == True): self.player_is_moving = True dir = 180 if (self.key_state["left"] == True): self.player_is_moving = True dir = 90 if (self.key_state["right"] == True): self.player_is_moving = True dir = 270 self.player.clearForces() old_vel = self.player.getLinearVelocity() new_vel = Vec3(0, 0, 0) if self.player_is_moving == True: new_vel.setX(-speed * math.sin( (base.camera.getH() + dir) * 3.1415 / 180.0)) new_vel.setY(speed * math.cos( (base.camera.getH() + dir) * 3.1415 / 180.0)) timescale = 0.001 linear_force = (new_vel - old_vel) / (timescale) linear_force.setZ(0.0) self.player.applyCentralForce(linear_force) if self.player_is_grabbing == False: new_hand_pos = LPoint3f( render.getRelativePoint(base.camera, Vec3(0, 0.2, 0))) self.handnp.setPos(new_hand_pos) else: new_hand_pos = LPoint3f( render.getRelativePoint(base.camera, Vec3(0, 0.5, 0))) diff = new_hand_pos - self.handnp.getPos() self.hand.applyCentralForce(diff * 1000 - self.hand.getLinearVelocity() * 100) if diff.length() > .5: self.player.setLinearVelocity(Vec3(0, 0, 0)) # Identify what lies beneath the player's hand (unless player is holding something) if self.player_is_grabbing == False: ray_from = self.playernp.getPos() ray_to = LPoint3f( render.getRelativePoint(base.camera, Vec3(0, 1, 0))) result = self.world.rayTestClosest(ray_from, ray_to) if result.hasHit() == True: self.hand_text.setText(result.getNode().getName()) self.hand_text_np.setPos(result.getHitPos()) self.hand_text_np.show() # If player clicks, grab the object by the nearest point (as chosen by ray) if self.mouse_state["left_click"] == True: if result.getNode().getNumChildren() == 1: obj = NodePath(result.getNode().getChild(0)) if self.player_is_grabbing == False: self.player_is_grabbing = True # Find the position of contact in terms of the object's local coordinates. # Parent the player's hand to the grabbed object at that position. pos = obj.getRelativePoint(render, result.getHitPos()) self.grabbed_node = result.getNode() self.grabbed_node.setActive(True) print self.grabbed_node frameA = TransformState.makePosHpr( Vec3(0, 0, 0), Vec3(0, 0, 0)) frameB = TransformState.makePosHpr( Vec3(0, 0, 0), Vec3(0, 0, 0)) swing1 = 20 # degrees swing2 = 20 # degrees twist = 20 # degrees self.cs = BulletConeTwistConstraint( self.hand, result.getNode(), frameA, frameB) self.cs.setLimit(swing1, swing2, twist) self.world.attachConstraint(self.cs) # Stop the held object swinging all over the place result.getNode().setAngularDamping(0.7) else: self.hand_text_np.hide() self.player_is_grabbing = False if self.mouse_state["left_click"] == False: self.player_is_grabbing = False if self.cs != None: self.world.remove_constraint(self.cs) self.cs = None self.grabbed_node.setAngularDamping(0.0) if self.player_is_grabbing == True and self.mouse_state[ "right_click"] == True: self.world.remove_constraint(self.cs) self.cs = None self.grabbed_node.setAngularDamping(0.0) self.grabbed_node.setActive(True) self.grabbed_node.applyCentralImpulse(1000, 0, 0) if self.player_is_grabbing == True: self.hand_text_np.hide() return task.cont def update_physics(self, task): dt = globalClock.getDt() self.world.doPhysics(dt) return task.cont def start_physics(self): taskMgr.add(self.update_physics, 'update_physics')
class CharacterController(DynamicObject, FSM): def __init__(self, game): self.game = game FSM.__init__(self, "Player") # key states # dx direction left or right, dy direction forward or backward self.kh = self.game.kh self.dx = 0 self.dy = 0 self.jumping = 0 self.crouching = 0 # maximum speed when only walking self.groundSpeed = 5.0 # acceleration used when walking to rise to self.groundSpeed self.groundAccel = 100.0 # maximum speed in the air (air friction) self.airSpeed = 30.0 # player movement control when in the air self.airAccel = 10.0 # horizontal speed on jump start self.jumpSpeed = 5.5 self.turnSpeed = 5 self.moveSpeedVec = Vec3(0,0,0) self.platformSpeedVec = Vec3(0,0,0) h = 1.75 w = 0.4 self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp) self.node = BulletRigidBodyNode('Player') self.node.setMass(2) self.node.addShape(self.shape) self.node.setActive(True, True) self.node.setDeactivationEnabled(False, True) self.node.setFriction(200) #self.node.setGravity(10) #self.node.setFallSpeed(200) self.node.setCcdMotionThreshold(1e-7) self.node.setCcdSweptSphereRadius(0.5) self.node.setAngularFactor(Vec3(0,0,1)) self.np = self.game.render.attachNewNode(self.node) self.np.setPos(0, 0, 0) self.np.setH(0) #self.np.setCollideMask(BitMask32.allOn()) self.game.world.attachRigidBody(self.node) self.playerModel = None self.slice_able = False def setActor(self, modelPath, animDic={}, flip = False, pos = (0,0,0), scale = 1.0): self.playerModel = Actor(modelPath, animDic) self.playerModel.reparentTo(self.np) self.playerModel.setScale(scale) # 1ft = 0.3048m if flip: self.playerModel.setH(180) self.playerModel.setPos(pos) self.playerModel.setScale(scale) #------------------------------------------------------------------- # Speed def getSpeedVec(self): return self.node.getLinearVelocity() def setSpeedVec(self, speedVec): #print "setting speed to %s" % (speedVec) self.node.setLinearVelocity(speedVec) return speedVec def setPlatformSpeed(self, speedVec): self.platformSpeedVec = speedVec def getSpeed(self): return self.getSpeedVec().length() def setSpeed(self, speed): speedVec = self.getSpeedVec() speedVec.normalize() self.setSpeedVec(speedVec*speed) def getLocalSpeedVec(self): return self.np.getRelativeVector(self.getSpeed()) def getSpeedXY(self): vec = self.getSpeedVec() return Vec3(vec[0], vec[1], 0) def setSpeedXY(self, speedX, speedY): vec = self.getSpeedVec() z = self.getSpeedZ() self.setSpeedVec(Vec3(speedX, speedY, z)) def getSpeedH(self): return self.getSpeedXY().length() def getSpeedZ(self): return self.getSpeedVec()[2] def setSpeedZ(self, zSpeed): vec = self.getSpeedVec() speedVec = Vec3(vec[0], vec[1], zSpeed) return self.setSpeedVec(speedVec) def setLinearVelocity(self, speedVec): return self.setSpeedVec(speedVec) def setAngularVelocity(self, speed): self.node.setAngularVelocity(Vec3(0, 0, speed)) def getFriction(self): return self.node.getFriction() def setFriction(self, friction): return self.node.setFriction(friction) #------------------------------------------------------------------- # Acceleration def doJump(self): #self.setSpeedZ(self.getSpeedZ()+self.jumpSpeed) self.setSpeedZ(self.jumpSpeed) def setForce(self, force): self.node.applyCentralForce(force) #------------------------------------------------------------------- # contacts #------------------------------------------------------------------- # update def update(self, dt, dx=0, dy=0, jumping=0, crouching=0, dRot=0): #self.setR(0) #self.setP(0) self.jumping = jumping self.crouching = crouching self.dx = dx self.dy = dy #self.setAngularVelocity(dRot*self.turnSpeed) #self.setAngularVelocity(0) self.setH(self.game.camHandler.gameNp.getH()) speedVec = self.getSpeedVec() - self.platformSpeedVec speed = speedVec.length() localSpeedVec = self.np.getRelativeVector(self.game.render, speedVec) pushVec = self.game.render.getRelativeVector(self.np, Vec3(self.dx,self.dy,0)) if self.dx != 0 or self.dy != 0: pushVec.normalize() else: pushVec = Vec3(0,0,0) contacts = self.getContacts() contact = self.checkFeet() if self.jumping and contact in contacts: self.setFriction(0) self.doJump() if self.jumping: self.setForce(pushVec * self.airAccel) if speed > self.airSpeed: self.setSpeed(self.airSpeed) else: if contacts: self.setForce(pushVec * self.groundAccel) else: self.setForce(pushVec * self.airAccel) if self.dx == 0 and self.dy == 0: self.setFriction(100) else: self.setFriction(0) if speed > self.groundSpeed: if contacts: self.setSpeed(self.groundSpeed) '''
class CharacterController(DynamicObject, FSM): def __init__(self, game): self.game = game FSM.__init__(self, "Player") # key states # dx direction left or right, dy direction forward or backward self.kh = self.game.kh self.dx = 0 self.dy = 0 self.jumping = 0 self.crouching = 0 # maximum speed when only walking self.groundSpeed = 5.0 # acceleration used when walking to rise to self.groundSpeed self.groundAccel = 100.0 # maximum speed in the air (air friction) self.airSpeed = 30.0 # player movement control when in the air self.airAccel = 10.0 # horizontal speed on jump start self.jumpSpeed = 5.5 self.turnSpeed = 5 self.moveSpeedVec = Vec3(0, 0, 0) self.platformSpeedVec = Vec3(0, 0, 0) h = 1.75 w = 0.4 self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp) self.node = BulletRigidBodyNode('Player') self.node.setMass(2) self.node.addShape(self.shape) self.node.setActive(True, True) self.node.setDeactivationEnabled(False, True) self.node.setFriction(200) #self.node.setGravity(10) #self.node.setFallSpeed(200) self.node.setCcdMotionThreshold(1e-7) self.node.setCcdSweptSphereRadius(0.5) self.node.setAngularFactor(Vec3(0, 0, 1)) self.np = self.game.render.attachNewNode(self.node) self.np.setPos(0, 0, 0) self.np.setH(0) #self.np.setCollideMask(BitMask32.allOn()) self.game.world.attachRigidBody(self.node) self.playerModel = None self.slice_able = False def setActor(self, modelPath, animDic={}, flip=False, pos=(0, 0, 0), scale=1.0): self.playerModel = Actor(modelPath, animDic) self.playerModel.reparentTo(self.np) self.playerModel.setScale(scale) # 1ft = 0.3048m if flip: self.playerModel.setH(180) self.playerModel.setPos(pos) self.playerModel.setScale(scale) #------------------------------------------------------------------- # Speed def getSpeedVec(self): return self.node.getLinearVelocity() def setSpeedVec(self, speedVec): #print "setting speed to %s" % (speedVec) self.node.setLinearVelocity(speedVec) return speedVec def setPlatformSpeed(self, speedVec): self.platformSpeedVec = speedVec def getSpeed(self): return self.getSpeedVec().length() def setSpeed(self, speed): speedVec = self.getSpeedVec() speedVec.normalize() self.setSpeedVec(speedVec * speed) def getLocalSpeedVec(self): return self.np.getRelativeVector(self.getSpeed()) def getSpeedXY(self): vec = self.getSpeedVec() return Vec3(vec[0], vec[1], 0) def setSpeedXY(self, speedX, speedY): vec = self.getSpeedVec() z = self.getSpeedZ() self.setSpeedVec(Vec3(speedX, speedY, z)) def getSpeedH(self): return self.getSpeedXY().length() def getSpeedZ(self): return self.getSpeedVec()[2] def setSpeedZ(self, zSpeed): vec = self.getSpeedVec() speedVec = Vec3(vec[0], vec[1], zSpeed) return self.setSpeedVec(speedVec) def setLinearVelocity(self, speedVec): return self.setSpeedVec(speedVec) def setAngularVelocity(self, speed): self.node.setAngularVelocity(Vec3(0, 0, speed)) def getFriction(self): return self.node.getFriction() def setFriction(self, friction): return self.node.setFriction(friction) #------------------------------------------------------------------- # Acceleration def doJump(self): #self.setSpeedZ(self.getSpeedZ()+self.jumpSpeed) self.setSpeedZ(self.jumpSpeed) def setForce(self, force): self.node.applyCentralForce(force) #------------------------------------------------------------------- # contacts #------------------------------------------------------------------- # update def update(self, dt, dx=0, dy=0, jumping=0, crouching=0, dRot=0): #self.setR(0) #self.setP(0) self.jumping = jumping self.crouching = crouching self.dx = dx self.dy = dy #self.setAngularVelocity(dRot*self.turnSpeed) #self.setAngularVelocity(0) self.setH(self.game.camHandler.gameNp.getH()) speedVec = self.getSpeedVec() - self.platformSpeedVec speed = speedVec.length() localSpeedVec = self.np.getRelativeVector(self.game.render, speedVec) pushVec = self.game.render.getRelativeVector(self.np, Vec3(self.dx, self.dy, 0)) if self.dx != 0 or self.dy != 0: pushVec.normalize() else: pushVec = Vec3(0, 0, 0) contacts = self.getContacts() contact = self.checkFeet() if self.jumping and contact in contacts: self.setFriction(0) self.doJump() if self.jumping: self.setForce(pushVec * self.airAccel) if speed > self.airSpeed: self.setSpeed(self.airSpeed) else: if contacts: self.setForce(pushVec * self.groundAccel) else: self.setForce(pushVec * self.airAccel) if self.dx == 0 and self.dy == 0: self.setFriction(100) else: self.setFriction(0) if speed > self.groundSpeed: if contacts: self.setSpeed(self.groundSpeed) '''
class Player(object): #global playerNode #playerNode = NodePath('player') F_MOVE = 400.0 def __init__(self, btWorld): self._attachControls() self._initPhysics(btWorld) self._loadModel() taskMgr.add(self.mouseUpdate, 'player-task') taskMgr.add(self.moveUpdate, 'player-task') self._vforce = Vec3(0,0,0) #ItemHandling(self.playerNode) def _attachControls(self): #base.accept( "s" , self.__setattr__,["walk",self.STOP] ) base.accept("w", self.goForward) base.accept("w-up", self.nogoForward) base.accept("s", self.goBack) base.accept("s-up", self.nogoBack) base.accept("a", self.goLeft) base.accept("a-up", self.nogoLeft) base.accept("d", self.goRight) base.accept("d-up", self.nogoRight) base.accept("space", self.goUp) base.accept("space-up", self.nogoUp) def _loadModel(self): #self._model = loader.loadModel("../data/models/d1_sphere.egg") #self._model.reparentTo(self.playerNode) pl = base.cam.node().getLens() pl.setNear(0.2) base.cam.node().setLens(pl) def _initPhysics(self, world): rad = 1 shape = BulletSphereShape(rad) self._rb_node = BulletRigidBodyNode('Box') self._rb_node.setMass(80.0) self._rb_node.setFriction(1.8) self._rb_node.addShape(shape) self._rb_node.setAngularFactor(Vec3(0,0,0)) self._rb_node.setDeactivationEnabled(False, True) self.playerNode = render.attachNewNode(self._rb_node) self.playerNode.setPos(0, 0, 4) self.playerNode.setHpr(0,0,0) world.attachRigidBody(self._rb_node) self.camNode = self.playerNode.attachNewNode("cam node") base.camera.reparentTo(self.camNode) self.camNode.setPos(self.camNode, 0, 0, 1.75-rad) #self.camNode.setPos(self.camNode, 0, -5,0.5) #self.camNode.lookAt(Point3(0,0,0),Vec3(0,1,0)) def mouseUpdate(self,task): md = base.win.getPointer(0) dx = md.getX() - base.win.getXSize()/2.0 dy = md.getY() - base.win.getYSize()/2.0 yaw = dx/(base.win.getXSize()/2.0) * 90 self.camNode.setHpr(self.camNode, -yaw, 0, 0) #base.camera.setHpr(base.camera, yaw, pith, roll) base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2) return task.cont def moveUpdate(self,task): if (self._vforce.length() > 0): #self.rbNode.applyCentralForce(self._vforce) self._rb_node.applyCentralForce(self.playerNode.getRelativeVector(self.camNode, self._vforce)) else: pass return task.cont def goForward(self): self._vforce.setY( self.F_MOVE) def nogoForward(self): self._vforce.setY( 0) def goBack(self): self._vforce.setY(-self.F_MOVE) def nogoBack(self): self._vforce.setY( 0) def goLeft(self): self._vforce.setX(-self.F_MOVE) def nogoLeft(self): self._vforce.setX( 0) def goRight(self): self._vforce.setX( self.F_MOVE) def nogoRight(self): self._vforce.setX( 0) def goUp(self): self._vforce.setZ( self.F_MOVE*1.4) def nogoUp(self): self._vforce.setZ( 0) def getRBNode(self): return self._rb_node
class BulletNPC(DynamicObject): def __init__(self, name, game, pos): self.game = game self.name = name self.jumping = 0 self.crouching = 0 # maximum speed when only walking self.groundSpeed = 4.0 # acceleration used when walking to rise to self.groundSpeed self.groundAccel = 150.0 self.groundFriction = 0.0 # maximum speed in the air (air friction) self.airSpeed = 30.0 # player movement control when in the air self.airAccel = 10.0 # horizontal speed on jump start self.jumpSpeed = 5.5 self.turnSpeed = 5 self.moveSpeedVec = Vec3(0, 0, 0) self.platformSpeedVec = Vec3(0, 0, 0) h = 1.75 w = 0.4 self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp) self.node = BulletRigidBodyNode(self.name) self.node.setMass(1.0) self.node.addShape(self.shape) self.node.setActive(True, True) self.node.setDeactivationEnabled(False, True) self.node.setFriction(self.groundFriction) # self.node.setGravity(10) # self.node.setFallSpeed(200) self.node.setCcdMotionThreshold(1e-7) # do not use setCcdSweptSphereRadius # it messes up the bite contact test # self.node.setCcdSweptSphereRadius(0.5) self.node.setAngularFactor(Vec3(0, 0, 1)) self.np = self.game.render.attachNewNode(self.node) self.setPos(pos) self.setH(0) # self.np.setCollideMask(BitMask32.allOn()) self.game.world.attachRigidBody(self.node) self.playerModel = Actor( "models/monsters/ghoul2.egg", {"idle": "models/monsters/ghoul2-idle.egg", "walk": "models/monsters/ghoul2-walk.egg"}, ) self.playerModel.setScale(0.15) self.playerModel.setZ(0.15) self.playerModel.reparentTo(self.np) interval = Wait(random.uniform(0, 1)) i2 = Func(self.startWalkAnim) seq = Sequence() seq.append(interval) seq.append(i2) seq.start() self.growlTimer = 5.0 self.sound = None self.alive = True self.targetNp = NodePath(self.name) self.brainTimer = 0.0 self.brainDelay = 1.2 self.currentForce = Vec3(0, 0, 0) def startWalkAnim(self): self.playerModel.loop("walk") def stopWalkAnim(self): self.playerModel.loop("idle") def checkFront(self): p1 = Point3(self.getPos()) direction = self.game.playerNp.getPos() - self.getPos() direction.normalize() direction = direction * 2.0 p2 = Point3(self.getPos() + direction) result = self.game.world.rayTestClosest(p1, p2) # ts1 = TransformState.makePos(p1) # ts2 = TransformState.makePos(p2) # result = self.game.world.sweepTestClosest(self.shape, ts1, ts2, 0) if result.hasHit(): pos = result.getHitPos() n = result.getHitNormal() frac = result.getHitFraction() node = result.getNode() return node.getName() return None def checkRight(self): p1 = Point3(self.getPos()) direction = self.game.playerNp.getPos() - self.getPos() direction.normalize() right = direction.cross(Vec3(0, 0, 1)) right = right * 2.0 p2 = Point3(self.getPos() + right) result = self.game.world.rayTestClosest(p1, p2) if result.hasHit(): pos = result.getHitPos() n = result.getHitNormal() frac = result.getHitFraction() node = result.getNode() return node.getName() return None def checkLeft(self): p1 = Point3(self.getPos()) direction = self.game.playerNp.getPos() - self.getPos() direction.normalize() left = -direction.cross(Vec3(0, 0, 1)) left = left * 2.0 p2 = Point3(self.getPos() + left) result = self.game.world.rayTestClosest(p1, p2) if result.hasHit(): pos = result.getHitPos() n = result.getHitNormal() frac = result.getHitFraction() node = result.getNode() return node.getName() return None def updateDirection(self): direction = self.game.playerNp.getPos() - self.getPos() direction.setZ(0) direction.normalize() direction = direction * self.groundAccel right = direction.cross(Vec3(0, 0, 1)) left = -right inFront = self.checkFront() inRight = self.checkRight() inLeft = self.checkLeft() if inFront == "boxpack": if inRight == "boxpack": if inLeft == "boxPack": self.currentForce = -direction else: self.currentForce = left else: self.currentForce = right else: self.currentForce = direction def update(self, dt=0.0): if not self.alive: return self.brainTimer -= dt if self.brainTimer <= 0.0: self.updateDirection() self.brainTimer = self.brainDelay self.setForce(self.currentForce) self.capSpeedXY() speedVec = self.getSpeedVec() self.targetNp.setPos(self.getPos() + speedVec) self.lookAt(self.targetNp) # growl! self.growlTimer -= dt if self.growlTimer <= 0.0: if self.sound: self.game.soundDic3D[self.sound].stop() self.game.detachSound(self.sound) growlIndex = random.randint(1, len(self.game.zombieGrowlSounds)) soundName = "monster-" + str(growlIndex) self.sound = soundName self.game.attachSound(soundName, self.np) self.game.playSound3D(soundName) self.growlTimer = 1.0 + random.uniform(0.0, 1.0) # print "Growl from %s" % (self.name) # bite! # player is the only one checking for that now # res = self.getContacts() # if "player" in res: # print "%s took a bite on player at %s!" % (self.name, self.game.globalClock.getFrameTime()) # self.game.onDie() def destroy(self): self.alive = False self.game.world.removeRigidBody(self.node) self.stopWalkAnim() self.np.setTransparency(True) self.np.setColor(1, 1, 1, 1) self.setGlowOff() i1 = Wait(random.uniform(0, 1)) i2 = LerpColorInterval(self.np, 1.0, (1, 1, 1, 0)) i3 = Func(self.np.remove) seq = Sequence() seq.append(i1) seq.append(i2) seq.append(i3) seq.start()
class Player(Entity): walkspeed = 5 damping = 0.9 topspeed = 15 leftMove = False rightMove = False jumpToggle = False crouchToggle = False def __init__(self, world): super(Player, self).__init__() self.obj = utilities.loadObject("tdplayer", depth=20) self.world = world self.health = 100 self.inventory = list() self.depth = self.obj.getPos().y self.location = Point2(10,0) self.velocity = Vec3(0) self.shape = BulletBoxShape(Vec3(0.3, 1.0, 0.49)) self.bnode = BulletRigidBodyNode('Box') self.bnode.setMass(0.1) self.bnode.setAngularVelocity(Vec3(0)) self.bnode.setAngularFactor(Vec3(0)) self.bnode.addShape(self.shape) self.bnode.setLinearDamping(0.95) self.bnode.setLinearSleepThreshold(0) world.bw.attachRigidBody(self.bnode) self.bnode.setPythonTag("entity", self) self.bnode.setIntoCollideMask(BitMask32.bit(0)) self.node = utilities.app.render.attachNewNode(self.bnode) self.node.setPos(self.obj.getPos()) self.obj.setPos(0,0,0) self.obj.setScale(1) self.obj.reparentTo(self.node) self.node.setPos(self.location.x, self.depth, self.location.y) def initialise(self): self.inventory.append(LightLaser(self.world, self)) self.inventory.append(Blowtorch(self.world, self)) #self.inventory["Grenade"] = Grenade(self.world, self) for item in self.inventory: item.initialise() self.currentItemIndex = 1 self.currentItem = self.inventory[self.currentItemIndex] self.currentItem.equip() def activate(self): self.currentItem.activate() def update(self, timer): self.velocity = self.bnode.getLinearVelocity() if (self.leftMove): self.bnode.applyCentralForce(Vec3(-Player.walkspeed,0,0)) if (self.rightMove): self.bnode.applyCentralForce(Vec3(Player.walkspeed,0,0)) if (self.jumpToggle): self.bnode.applyCentralForce(Vec3(0,0,Player.walkspeed)) if (self.crouchToggle): self.bnode.applyCentralForce(Vec3(0,0,-Player.walkspeed)) if (self.velocity.x < -self.topspeed): self.velocity.x = -self.topspeed if (self.velocity.x > self.topspeed): self.velocity.x = self.topspeed mouse = utilities.app.mousePos # extrude test near = Point3() far = Point3() utilities.app.camLens.extrude(mouse, near, far) camp = utilities.app.camera.getPos() near *= 20 # player depth if near.x != 0: angle = atan2(near.z + camp.z - self.node.getPos().z, near.x + camp.x - self.node.getPos().x) #angle = atan2(near.z, near.x) else: angle = 90 self.angle = angle # set current item to point at cursor self.currentItem.update(timer) # move the camera so the player is centred horizontally, # but keep the camera steady vertically utilities.app.camera.setPos(self.node.getPos().x, 0, self.node.getPos().z) self.obj.setHpr(0, 0, -1 * degrees(angle)) self.location.x = self.node.getPos().x self.location.y = self.node.getPos().z def moveLeft(self, switch): self.leftMove = switch def moveRight(self, switch): self.rightMove = switch def jump(self, switch): self.jumpToggle = switch def crouch(self, switch): self.crouchToggle = switch def scrollItem(self, number): self.currentItem.unequip() self.currentItemIndex = self.currentItemIndex + number if self.currentItemIndex < 0: self.currentItemIndex = len(self.inventory) - 1 if self.currentItemIndex > len(self.inventory) - 1: self.currentItemIndex = 0 self.currentItem = self.inventory[self.currentItemIndex] self.currentItem.equip() def selectItem(self, number): if (number - 1 < len(self.inventory) and number - 1 >= 0): self.currentItem.unequip() self.currentItemIndex = number - 1 self.currentItem = self.inventory[self.currentItemIndex] self.currentItem.equip() def hitby(self, projectile, index): self.health -= projectile.damage if (self.health < 0): self.obj.setColor(1,0,0,1) return True greyscale = 0.3 + (0.01 * self.health) self.obj.setColor(greyscale, greyscale,greyscale,greyscale) return False
class Flame(Entity): """ The thing that comes out the end of the thing you hold """ animspeed = 0.1 depth = 20 playerWidth = 3 speed = 20 def __init__(self, world, pos, hpr): super(Flame, self).__init__() self.shape = BulletBoxShape(Vec3(0.1,0.05,0.05)) self.bnode = BulletRigidBodyNode() self.bnode.setMass(1.0) self.bnode.addShape(self.shape) self.np = utilities.app.render.attachNewNode(self.bnode) self.world =world self.anim = list() self.anim.append(utilities.loadObject("flame1", depth=0)) self.anim.append(utilities.loadObject("flame2", depth=0)) self.anim.append(utilities.loadObject("flame3", depth=0)) world.bw.attachRigidBody(self.bnode) self.curspr = 0 self.obj = self.anim[self.curspr] self.obj.show() self.livetime = 0 self.delta = 0 self.pos = pos self.pos.y = Flame.depth #self.pos.z -= 0.2 self.hpr = hpr self.vel = Point2() self.vel.x = cos(world.player.angle)*Flame.speed self.vel.y = sin(world.player.angle)*Flame.speed tv = Vec3(self.vel.x, 0, self.vel.y) # this makes the shot miss the target if the player has any velocity tv += world.player.bnode.getLinearVelocity() self.bnode.setLinearVelocity(tv) tv.normalize() # initial position of RB and draw plane self.np.setHpr(hpr) self.np.setPos(pos+tv/2) self.bnode.setAngularFactor(Vec3(0,0,0)) self.bnode.setLinearFactor(Vec3(1,0,1)) self.bnode.setGravity(Vec3(0,0,0)) self.bnode.setCcdMotionThreshold(1e-7) self.bnode.setCcdSweptSphereRadius(0.10) self.bnode.notifyCollisions(True) self.bnode.setIntoCollideMask(BitMask32.bit(1)) self.bnode.setPythonTag("Entity", self) self.noCollideFrames = 4 for a in self.anim: a.hide() a.reparentTo(self.np) a.setScale(0.25, 1, 0.25) a.setPos(0, -0.1,0) def update(self, timer): #animation self.delta += timer self.livetime += timer if self.noCollideFrames == 0: self.bnode.setIntoCollideMask(BitMask32.allOn()) if self.noCollideFrames > -1: self.noCollideFrames -= 1 if self.delta > Flame.animspeed: self.delta = 0 self.obj.hide() self.curspr += 1 if self.curspr > len(self.anim)-1: self.curspr = 0 self.obj = self.anim[self.curspr] self.obj.show()
class Catcher(Enemy): damage = 25 def __init__(self, location, player, cmap, world): super(Catcher, self).__init__(location) self.player = player self.cmap = cmap self.obj = utilities.loadObject("robot", depth=20) self.world = world self.health = 100 self.depth = self.obj.getPos().y self.location = location self.velocity = Vec3(0) self.shape = BulletBoxShape(Vec3(0.5, 1.0, 0.5)) self.bnode = BulletRigidBodyNode('Box') self.bnode.setMass(0.1) self.bnode.setAngularVelocity(Vec3(0)) self.bnode.setAngularFactor(Vec3(0)) self.bnode.addShape(self.shape) self.bnode.setLinearDamping(0.75) self.bnode.setLinearSleepThreshold(0) world.bw.attachRigidBody(self.bnode) self.bnode.setPythonTag("entity", self) self.bnode.setIntoCollideMask(BitMask32.bit(0)) self.node = utilities.app.render.attachNewNode(self.bnode) self.node.setPos(self.obj.getPos()) self.obj.setPos(0, 0, 0) self.obj.setScale(1) self.obj.reparentTo(self.node) self.node.setPos(self.location.x, self.depth, self.location.y) def update(self, time): self.location = Point2(self.node.getPos().x - self.player.location.x, self.node.getPos().z - self.player.location.y) if self.location.x > 20 or self.location.x < -20: return if self.location.y > 20 or self.location.y < -20: return path = findPath(Point2(self.location + Point2(20, 20)), Point2(20, 20), self.world.cmap) if len(path) > 1: move = path[1] - self.location self.bnode.applyCentralForce(Vec3(move.x - 20, 0, move.y - 20)) def hitby(self, projectile, index): self.health -= projectile.damage if (self.health < 0): self.remove = True greyscale = 0.3 + (0.01 * self.health) self.obj.setColor(1, greyscale, greyscale, 1) return False def removeOnHit(self): return def destroy(self): self.obj.hide() self.world.bw.removeRigidBody(self.bnode)
class SMAI(): #This constructs the nods tree needed for an AIChar object. #Takes in a model as a string, a speed double, a world object, a bullet physics world and n x, y and z positions def __init__(self, model, speed, world, worldNP, x, y, z): self.AISpeed = 80000 self.maxSpeed = speed self.AIX = x self.AIY = y self.AIZ = z self.worldNP = worldNP bulletWorld = world self.type = "" self.AIModel = loader.loadModel(model) self.AIModel.setScale(0.5) self.AIModel.reparentTo(render) AIShape = BulletBoxShape(Vec3(3, 3, 1)) self.AINode = BulletRigidBodyNode('AIChar') self.AINode.setMass(100) self.AINode.addShape(AIShape) self.AINode.setDeactivationEnabled(False) self.AINode.setAngularFactor(Vec3(0, 0, 0)) render.attachNewNode(self.AINode) self.AIChar = self.worldNP.attachNewNode(self.AINode) self.AIModel.reparentTo(self.AIChar) self.AIChar.setPos(x, y, z) bulletWorld.attachRigidBody(self.AIChar.node()) #This method needs to be called on your AIChar object to determine what type of AI you want. #Takes in a type string; either flee or seek and also a target object. def setBehavior(self, type, target): if (type == "flee"): self.type = type self.target = target print("Type set to flee") elif (type == "seek"): self.type = type self.target = target print("Type set to seek") else: print("Error @ Incorrect Type!") def moveTo(self, target): self.moveTo = True self.target = target def flee(self): h = 1 hx = 1 hy = 1 if (self.AIChar.getDistance(self.target) < 40.0): if (self.AINode.getLinearVelocity() > self.maxSpeed): if (self.AINode.getLinearVelocity() < 100): self.AIChar.setH(self.target.getH()) h = self.AIChar.getH() else: hx = sin(h * DEG_TO_RAD) * 10 hy = cos(h * DEG_TO_RAD) * 10 self.AINode.applyForce( Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT) # else: # self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT) def seek(self): if (self.AIChar.getDistance(self.target) > 20.0): if (self.AINode.getLinearVelocity() > self.maxSpeed): self.AIChar.lookAt(self.target) h = self.AIChar.getH() hx = sin(h * DEG_TO_RAD) * 10 hy = cos(h * DEG_TO_RAD) * 10 self.AINode.applyForce( Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT) def moveToRun(self): self.seek() # if(self.target.getX()+5 <= self.AIChar.getX() and self.target.getX()-5 >= self.AIChar.getX() and self.target.getY()+5 <= self.AIChar.getY() and self.target.getY()-5 >= self.AIChar.getY()): # print("It's stopped!") # self.AIChar.clearForces() # self.AIChar.setLinearVelocity(0) # else: # self.AINode.clearForces() # self.AIChar.lookAt(self.target) # self.AINode.setLinearVelocity(self.AISpeed) #Gets called on every AIChar in the world's update method to allow the AI to function at all. def AIUpdate(self): if (self.moveTo == True): self.moveToRun() if (self.type == "seek"): self.seek() elif (self.type == "flee"): self.flee() else: print("Error @ No AI Type")
class SMAI(): #This constructs the nods tree needed for an AIChar object. #Takes in a model as a string, a speed double, a world object, a bullet physics world and n x, y and z positions def __init__(self, model, speed, world, worldNP, x, y, z): self.AISpeed = 80000 self.maxSpeed = speed self.AIX = x self.AIY = y self.AIZ = z self.worldNP = worldNP bulletWorld = world self.type = "" self.AIModel = loader.loadModel(model) self.AIModel.setScale(0.5) self.AIModel.reparentTo(render) AIShape = BulletBoxShape(Vec3(3, 3, 1)) self.AINode = BulletRigidBodyNode('AIChar') self.AINode.setMass(100) self.AINode.addShape(AIShape) self.AINode.setDeactivationEnabled(False) self.AINode.setAngularFactor(Vec3(0,0,0)) render.attachNewNode(self.AINode) self.AIChar = self.worldNP.attachNewNode(self.AINode) self.AIModel.reparentTo(self.AIChar) self.AIChar.setPos(x, y, z) bulletWorld.attachRigidBody(self.AIChar.node()) #This method needs to be called on your AIChar object to determine what type of AI you want. #Takes in a type string; either flee or seek and also a target object. def setBehavior(self, type, target): if(type == "flee"): self.type = type self.target = target print("Type set to flee") elif(type == "seek"): self.type = type self.target = target print("Type set to seek") else: print("Error @ Incorrect Type!") def moveTo(self, target): self.moveTo = True self.target = target def flee(self): h = 1 hx = 1 hy = 1 if(self.AIChar.getDistance(self.target) < 40.0): if(self.AINode.getLinearVelocity() > self.maxSpeed): if(self.AINode.getLinearVelocity() < 100): self.AIChar.setH(self.target.getH()) h = self.AIChar.getH() else: hx = sin(h * DEG_TO_RAD) * 10 hy = cos(h * DEG_TO_RAD) * 10 self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT) # else: # self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT) def seek(self): if(self.AIChar.getDistance(self.target) > 20.0): if(self.AINode.getLinearVelocity() > self.maxSpeed): self.AIChar.lookAt(self.target) h = self.AIChar.getH() hx = sin(h * DEG_TO_RAD) * 10 hy = cos(h * DEG_TO_RAD) * 10 self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT) def moveToRun(self): self.seek() # if(self.target.getX()+5 <= self.AIChar.getX() and self.target.getX()-5 >= self.AIChar.getX() and self.target.getY()+5 <= self.AIChar.getY() and self.target.getY()-5 >= self.AIChar.getY()): # print("It's stopped!") # self.AIChar.clearForces() # self.AIChar.setLinearVelocity(0) # else: # self.AINode.clearForces() # self.AIChar.lookAt(self.target) # self.AINode.setLinearVelocity(self.AISpeed) #Gets called on every AIChar in the world's update method to allow the AI to function at all. def AIUpdate(self): if(self.moveTo == True): self.moveToRun() if(self.type == "seek"): self.seek() elif(self.type == "flee"): self.flee() else: print("Error @ No AI Type")
class Player(Entity): walkspeed = 5 damping = 0.9 topspeed = 15 leftMove = False rightMove = False jumpToggle = False crouchToggle = False def __init__(self, world): super(Player, self).__init__() self.obj = utilities.loadObject("tdplayer", depth=20) self.world = world self.health = 100 self.inventory = list() self.depth = self.obj.getPos().y self.location = Point2(10, 0) self.velocity = Vec3(0) self.shape = BulletBoxShape(Vec3(0.3, 1.0, 0.49)) self.bnode = BulletRigidBodyNode('Box') self.bnode.setMass(0.1) self.bnode.setAngularVelocity(Vec3(0)) self.bnode.setAngularFactor(Vec3(0)) self.bnode.addShape(self.shape) self.bnode.setLinearDamping(0.95) self.bnode.setLinearSleepThreshold(0) world.bw.attachRigidBody(self.bnode) self.bnode.setPythonTag("entity", self) self.bnode.setIntoCollideMask(BitMask32.bit(0)) self.node = utilities.app.render.attachNewNode(self.bnode) self.node.setPos(self.obj.getPos()) self.obj.setPos(0, 0, 0) self.obj.setScale(1) self.obj.reparentTo(self.node) self.node.setPos(self.location.x, self.depth, self.location.y) def initialise(self): self.inventory.append(LightLaser(self.world, self)) self.inventory.append(Blowtorch(self.world, self)) #self.inventory["Grenade"] = Grenade(self.world, self) for item in self.inventory: item.initialise() self.currentItemIndex = 1 self.currentItem = self.inventory[self.currentItemIndex] self.currentItem.equip() def activate(self): self.currentItem.activate() def update(self, timer): self.velocity = self.bnode.getLinearVelocity() if (self.leftMove): self.bnode.applyCentralForce(Vec3(-Player.walkspeed, 0, 0)) if (self.rightMove): self.bnode.applyCentralForce(Vec3(Player.walkspeed, 0, 0)) if (self.jumpToggle): self.bnode.applyCentralForce(Vec3(0, 0, Player.walkspeed)) if (self.crouchToggle): self.bnode.applyCentralForce(Vec3(0, 0, -Player.walkspeed)) if (self.velocity.x < -self.topspeed): self.velocity.x = -self.topspeed if (self.velocity.x > self.topspeed): self.velocity.x = self.topspeed mouse = utilities.app.mousePos # extrude test near = Point3() far = Point3() utilities.app.camLens.extrude(mouse, near, far) camp = utilities.app.camera.getPos() near *= 20 # player depth if near.x != 0: angle = atan2(near.z + camp.z - self.node.getPos().z, near.x + camp.x - self.node.getPos().x) #angle = atan2(near.z, near.x) else: angle = 90 self.angle = angle # set current item to point at cursor self.currentItem.update(timer) # move the camera so the player is centred horizontally, # but keep the camera steady vertically utilities.app.camera.setPos(self.node.getPos().x, 0, self.node.getPos().z) self.obj.setHpr(0, 0, -1 * degrees(angle)) self.location.x = self.node.getPos().x self.location.y = self.node.getPos().z def moveLeft(self, switch): self.leftMove = switch def moveRight(self, switch): self.rightMove = switch def jump(self, switch): self.jumpToggle = switch def crouch(self, switch): self.crouchToggle = switch def scrollItem(self, number): self.currentItem.unequip() self.currentItemIndex = self.currentItemIndex + number if self.currentItemIndex < 0: self.currentItemIndex = len(self.inventory) - 1 if self.currentItemIndex > len(self.inventory) - 1: self.currentItemIndex = 0 self.currentItem = self.inventory[self.currentItemIndex] self.currentItem.equip() def selectItem(self, number): if (number - 1 < len(self.inventory) and number - 1 >= 0): self.currentItem.unequip() self.currentItemIndex = number - 1 self.currentItem = self.inventory[self.currentItemIndex] self.currentItem.equip() def hitby(self, projectile, index): self.health -= projectile.damage if (self.health < 0): self.obj.setColor(1, 0, 0, 1) return True greyscale = 0.3 + (0.01 * self.health) self.obj.setColor(greyscale, greyscale, greyscale, greyscale) return False
class BulletNPC(DynamicObject): def __init__(self, name, game, pos): self.game = game self.name = name self.jumping = 0 self.crouching = 0 # maximum speed when only walking self.groundSpeed = 4.0 # acceleration used when walking to rise to self.groundSpeed self.groundAccel = 150.0 self.groundFriction = 0.0 # maximum speed in the air (air friction) self.airSpeed = 30.0 # player movement control when in the air self.airAccel = 10.0 # horizontal speed on jump start self.jumpSpeed = 5.5 self.turnSpeed = 5 self.moveSpeedVec = Vec3(0, 0, 0) self.platformSpeedVec = Vec3(0, 0, 0) h = 1.75 w = 0.4 self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp) self.node = BulletRigidBodyNode(self.name) self.node.setMass(1.0) self.node.addShape(self.shape) self.node.setActive(True, True) self.node.setDeactivationEnabled(False, True) self.node.setFriction(self.groundFriction) #self.node.setGravity(10) #self.node.setFallSpeed(200) self.node.setCcdMotionThreshold(1e-7) # do not use setCcdSweptSphereRadius # it messes up the bite contact test #self.node.setCcdSweptSphereRadius(0.5) self.node.setAngularFactor(Vec3(0, 0, 1)) self.np = self.game.render.attachNewNode(self.node) self.setPos(pos) self.setH(0) #self.np.setCollideMask(BitMask32.allOn()) self.game.world.attachRigidBody(self.node) self.playerModel = Actor( "models/monsters/ghoul2.egg", { "idle": "models/monsters/ghoul2-idle.egg", "walk": "models/monsters/ghoul2-walk.egg" }) self.playerModel.setScale(0.15) self.playerModel.setZ(0.15) self.playerModel.reparentTo(self.np) interval = Wait(random.uniform(0, 1)) i2 = Func(self.startWalkAnim) seq = Sequence() seq.append(interval) seq.append(i2) seq.start() self.growlTimer = 5.0 self.sound = None self.alive = True self.targetNp = NodePath(self.name) self.brainTimer = 0.0 self.brainDelay = 1.2 self.currentForce = Vec3(0, 0, 0) def startWalkAnim(self): self.playerModel.loop("walk") def stopWalkAnim(self): self.playerModel.loop("idle") def checkFront(self): p1 = Point3(self.getPos()) direction = self.game.playerNp.getPos() - self.getPos() direction.normalize() direction = direction * 2.0 p2 = Point3(self.getPos() + direction) result = self.game.world.rayTestClosest(p1, p2) #ts1 = TransformState.makePos(p1) #ts2 = TransformState.makePos(p2) #result = self.game.world.sweepTestClosest(self.shape, ts1, ts2, 0) if result.hasHit(): pos = result.getHitPos() n = result.getHitNormal() frac = result.getHitFraction() node = result.getNode() return node.getName() return None def checkRight(self): p1 = Point3(self.getPos()) direction = self.game.playerNp.getPos() - self.getPos() direction.normalize() right = direction.cross(Vec3(0, 0, 1)) right = right * 2.0 p2 = Point3(self.getPos() + right) result = self.game.world.rayTestClosest(p1, p2) if result.hasHit(): pos = result.getHitPos() n = result.getHitNormal() frac = result.getHitFraction() node = result.getNode() return node.getName() return None def checkLeft(self): p1 = Point3(self.getPos()) direction = self.game.playerNp.getPos() - self.getPos() direction.normalize() left = -direction.cross(Vec3(0, 0, 1)) left = left * 2.0 p2 = Point3(self.getPos() + left) result = self.game.world.rayTestClosest(p1, p2) if result.hasHit(): pos = result.getHitPos() n = result.getHitNormal() frac = result.getHitFraction() node = result.getNode() return node.getName() return None def updateDirection(self): direction = self.game.playerNp.getPos() - self.getPos() direction.setZ(0) direction.normalize() direction = direction * self.groundAccel right = direction.cross(Vec3(0, 0, 1)) left = -right inFront = self.checkFront() inRight = self.checkRight() inLeft = self.checkLeft() if inFront == "boxpack": if inRight == "boxpack": if inLeft == "boxPack": self.currentForce = -direction else: self.currentForce = left else: self.currentForce = right else: self.currentForce = direction def update(self, dt=0.0): if not self.alive: return self.brainTimer -= dt if self.brainTimer <= 0.0: self.updateDirection() self.brainTimer = self.brainDelay self.setForce(self.currentForce) self.capSpeedXY() speedVec = self.getSpeedVec() self.targetNp.setPos(self.getPos() + speedVec) self.lookAt(self.targetNp) # growl! self.growlTimer -= dt if self.growlTimer <= 0.0: if self.sound: self.game.soundDic3D[self.sound].stop() self.game.detachSound(self.sound) growlIndex = random.randint(1, len(self.game.zombieGrowlSounds)) soundName = "monster-" + str(growlIndex) self.sound = soundName self.game.attachSound(soundName, self.np) self.game.playSound3D(soundName) self.growlTimer = 1.0 + random.uniform(0.0, 1.0) #print "Growl from %s" % (self.name) # bite! # player is the only one checking for that now #res = self.getContacts() #if "player" in res: #print "%s took a bite on player at %s!" % (self.name, self.game.globalClock.getFrameTime()) #self.game.onDie() def destroy(self): self.alive = False self.game.world.removeRigidBody(self.node) self.stopWalkAnim() self.np.setTransparency(True) self.np.setColor(1, 1, 1, 1) self.setGlowOff() i1 = Wait(random.uniform(0, 1)) i2 = LerpColorInterval(self.np, 1.0, (1, 1, 1, 0)) i3 = Func(self.np.remove) seq = Sequence() seq.append(i1) seq.append(i2) seq.append(i3) seq.start()