def loadPlanet(self): self.planet = loader.loadModel('planet.bam') self.planet.setPos(tupleToVec3(Game.PLANET_POSITION)) self.planet.setScale(20) self.planet.reparentTo(render) self.planetCollGeom = OdeSphereGeom(20)
def __init__(self, game, power = 50.0, range = 30): self.game = game self.POWER = power self.Active = False self.RANGE = range self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3) #self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.triggerGeom = OdeSphereGeom( range ) self.triggerGeom.setCategoryBits( BitMask32(0xffffffff) ) self.triggerGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) self.model = loader.loadModel('AbsorbingPylon.egg') self.model.setScale(1.5) self.model.reparentTo(self.visualNode) pow = self.getPower()*5 maxPow = self.game.MAX_PYLON_POWER if (pow > 0): self.offColor = Vec4(pow/maxPow, 0.0, 0.0, 0.0) self.onColor = Vec4(0.0, pow/maxPow, 0.0, 0.0) if (pow <= 0): self.offColor = Vec4(0.0, 0.0, -pow/maxPow, 0.0) self.onColor = Vec4(0.0, -pow/maxPow, 0.0, 0.0) self.setColor( self.offColor )
class Sphere(GameObject): def __init__(self, world, parent, color, pos, dir, radius, density, posParent=None): GameObject.__init__(self, world) self.node = parent.attachNewNode("") if posParent == None: self.node.setPos(*pos) else: self.node.setPos(posParent, *pos) self.node.setColor(*color) self.node.setScale(radius) self.node.lookAt(self.node, *dir) self.parent = parent self.color = color self.scale = radius self.model = loader.loadModel("models/smiley.egg") self.model.reparentTo(self.node) self.mass = OdeMass() self.mass.setSphere(density, radius) self.body = OdeBody(world.world) self.body.setMass(self.mass) self.body.setPosition(self.node.getPos()) self.body.setQuaternion(self.node.getQuat()) self.body.setData(self) self.geom = OdeSphereGeom(world.space, radius) self.geom.setBody(self.body) world.space.setSurfaceType(self.geom, world.surfaces["sphere"]) def onCollision(self, otherBody, entry): if otherBody.isEmpty(): # Collision on a wall geom = entry.getContactGeom(0) Ripple(self.parent, self.color, geom.getPos(), geom.getNormal() * -1, self.scale * 2.5)
def createCircularObstacle(self, pos, obstacleIndex): """Create one physics obstacle. Returns a nodePath""" self.notify.debug("create obstacleindex %s" % (obstacleIndex)) geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius) geom.setCollideBits(self.allTiresMask) # we only collide against tires geom.setCategoryBits(self.obstacleMask) self.space.setCollideId(geom, self.obstacleCollideId) #tireModel = loader.loadModel('phase_3/models/misc/sphere') tireModel = loader.loadModel( "phase_4/models/minigames/ice_game_tirestack") # assuming it has a radius of 1 tireHeight = 1 #tireModel.setScale(IceGameGlobals.TireRadius, IceGameGlobals.TireRadius, IceGameGlobals.TireRadius) #tireModel.setZ( 0 - IceGameGlobals.TireRadius + (tireHeight /2.0)) #tireModel.setZ(IceGameGlobals.TireRadius) tireModel.setPos(pos) #tireModel.setColor(0.5,0.5,0.5) tireModel.reparentTo(render) geom.setPosition(tireModel.getPos()) # the real assets are set at Z zero tireModel.setZ(0) return tireModel
def createBallGeom(self, modelNode, ballBody, space): ballGeom = OdeSphereGeom(space, 1) ballGeom.setCollideBits(BitMask32(0x2)) ballGeom.setCategoryBits(BitMask32(0x1)) ballGeom.setBody(ballBody) space.setSurfaceType(ballGeom, SurfaceType.BALL) return ballGeom
def createTire(self, tireIndex): if tireIndex < 0 or tireIndex >= len(self.tireMasks): self.notify.error('invalid tireIndex %s' % tireIndex) self.notify.debug('create tireindex %s' % tireIndex) zOffset = 0 body = OdeBody(self.world) mass = OdeMass() mass.setSphere(self.tireDensity, IceGameGlobals.TireRadius) body.setMass(mass) body.setPosition(IceGameGlobals.StartingPositions[tireIndex][0], IceGameGlobals.StartingPositions[tireIndex][1], IceGameGlobals.StartingPositions[tireIndex][2]) body.setAutoDisableDefaults() geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius) self.space.setSurfaceType(geom, self.tireSurfaceType) self.space.setCollideId(geom, self.tireCollideIds[tireIndex]) self.massList.append(mass) self.geomList.append(geom) geom.setCollideBits(self.allTiresMask | self.wallMask | self.floorMask | self.obstacleMask) geom.setCategoryBits(self.tireMasks[tireIndex]) geom.setBody(body) if self.notify.getDebug(): self.notify.debug('tire geom id') geom.write() self.notify.debug(' -') if self.canRender: testTire = render.attachNewNode('tire holder %d' % tireIndex) smileyModel = NodePath() if not smileyModel.isEmpty(): smileyModel.setScale(IceGameGlobals.TireRadius) smileyModel.reparentTo(testTire) smileyModel.setAlphaScale(0.5) smileyModel.setTransparency(1) testTire.setPos(IceGameGlobals.StartingPositions[tireIndex]) tireModel = loader.loadModel( 'phase_4/models/minigames/ice_game_tire') tireHeight = 1 tireModel.setZ(-(IceGameGlobals.TireRadius) + 0.01) tireModel.reparentTo(testTire) self.odePandaRelationList.append((testTire, body)) else: testTire = None self.bodyList.append((None, body)) return (testTire, body, geom)
def __init__(self, game, color): self.game = game self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('testipalikka.egg') model.reparentTo(self.visualNode) plight = PointLight('plight') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) plightNodePath = model.attachNewNode(plight) model.setLight(plightNodePath) self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) self.body.setGravityMode(False) #self.juttu = OdeUtil() self.collGeom = OdeSphereGeom( self.game.physicsSpace, 2) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) )
def __init__(self, game, color): #self.POWER = 100 self.game = game self.thrust = False self.thrustLeft = False self.thrustRight = False self.thrustBack = False self.rotation = 0 self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) #odespheregeom(... , size of hitbox sphere) self.collGeom = OdeSphereGeom( self.game.physicsSpace, 5) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('lautanen2.egg') model.reparentTo(self.visualNode) plight = PointLight('plight') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) plightNodePath = model.attachNewNode(plight) model.setLight(plightNodePath)
def loadPlanet(self): self.planet = loader.loadModel('planet.bam') self.planet.setPos( tupleToVec3(Game.PLANET_POSITION) ) self.planet.setScale(20) self.planet.reparentTo(render) self.planetCollGeom = OdeSphereGeom(20)
def __init__(self, world, parent, color, pos, dir, radius, density, posParent=None): GameObject.__init__(self, world) self.node = parent.attachNewNode("") if posParent == None: self.node.setPos(*pos) else: self.node.setPos(posParent, *pos) self.node.setColor(*color) self.node.setScale(radius) self.node.lookAt(self.node, *dir) self.parent = parent self.color = color self.scale = radius self.model = loader.loadModel("models/smiley.egg") self.model.reparentTo(self.node) self.mass = OdeMass() self.mass.setSphere(density, radius) self.body = OdeBody(world.world) self.body.setMass(self.mass) self.body.setPosition(self.node.getPos()) self.body.setQuaternion(self.node.getQuat()) self.body.setData(self) self.geom = OdeSphereGeom(world.space, radius) self.geom.setBody(self.body) world.space.setSurfaceType(self.geom, world.surfaces["sphere"])
def __init__(self, game, color, value = 1, drain = 20): self.game = game self.VALUE = value self.DRAIN = drain #self.idnumber = id self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('Ball2.egg') model.setScale(2.5) model.reparentTo(self.visualNode) plight = PointLight('plight') plight.setPoint( Point3(0, 0, 3) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.05, 0.01, 0.01) ) self.plightNodePath = model.attachNewNode(plight) model.setLight(self.plightNodePath) self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) self.body.setGravityMode(True) #self.body.setGravityMode(False) #self.juttu = OdeUtil() self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3.5) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) )
def createCircularObstacle(self, pos, obstacleIndex): self.notify.debug('create obstacleindex %s' % obstacleIndex) geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius) geom.setCollideBits(self.allTiresMask) geom.setCategoryBits(self.obstacleMask) self.space.setCollideId(geom, self.obstacleCollideId) tireModel = loader.loadModel('phase_4/models/minigames/ice_game_tirestack') tireHeight = 1 tireModel.setPos(pos) tireModel.reparentTo(render) geom.setPosition(tireModel.getPos()) tireModel.setZ(0) return tireModel
def createTire(self, tireIndex): if tireIndex < 0 or tireIndex >= len(self.tireMasks): self.notify.error("invalid tireIndex %s" % tireIndex) self.notify.debug("create tireindex %s" % tireIndex) zOffset = 0 body = OdeBody(self.world) mass = OdeMass() mass.setSphere(self.tireDensity, IceGameGlobals.TireRadius) body.setMass(mass) body.setPosition( IceGameGlobals.StartingPositions[tireIndex][0], IceGameGlobals.StartingPositions[tireIndex][1], IceGameGlobals.StartingPositions[tireIndex][2], ) body.setAutoDisableDefaults() geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius) self.space.setSurfaceType(geom, self.tireSurfaceType) self.space.setCollideId(geom, self.tireCollideIds[tireIndex]) self.massList.append(mass) self.geomList.append(geom) geom.setCollideBits(self.allTiresMask | self.wallMask | self.floorMask | self.obstacleMask) geom.setCategoryBits(self.tireMasks[tireIndex]) geom.setBody(body) if self.notify.getDebug(): self.notify.debug("tire geom id") geom.write() self.notify.debug(" -") if self.canRender: testTire = render.attachNewNode("tire holder %d" % tireIndex) smileyModel = NodePath() if not smileyModel.isEmpty(): smileyModel.setScale(IceGameGlobals.TireRadius) smileyModel.reparentTo(testTire) smileyModel.setAlphaScale(0.5) smileyModel.setTransparency(1) testTire.setPos(IceGameGlobals.StartingPositions[tireIndex]) tireModel = loader.loadModel("phase_4/models/minigames/ice_game_tire") tireHeight = 1 tireModel.setZ(-IceGameGlobals.TireRadius + 0.01) tireModel.reparentTo(testTire) self.odePandaRelationList.append((testTire, body)) else: testTire = None self.bodyList.append((None, body)) return (testTire, body, geom)
def __init__( self, name=NAME_DEFAULT, pos=POS_DEFAULT, heading=HEADING_DEFAULT, vel=VEL_DEFAULT, acc=ACC_DEFAULT # player controlled acceleration. Can be 0.0 - 1.0 ): """@param name string""" self.name = name self.pos = pos self.vel = vel self.acc = acc self.heading = heading self.rotateLeft = False self.rotateRight = False self.visualNode = self.createVisualNode(self.pos) self.bullets = [] self.collisionHandler = colHandler self.collisions = [] self.collisionSphere = OdeSphereGeom(4) self.collisionSphere.setCategoryBits(BitMask32(0xffffffff)) self.collisionSphere.setCollideBits(BitMask32(0xffffffff)) self.collisionSphere.setPosition(pos[0], pos[1], 0) self.forces = [] self.mass = 1.0 self.health = Ship.HEALTH self.isAlive = True self.shootingSound = loader.loadSfx('anti_tank_gun_single_shot.mp3') self.destroySound = loader.loadSfx('large_explosion.mp3') self.bulletHitSound = loader.loadSfx( 'explosion_loud_internal_explosion_very_reverberant.mp3') self.collisionSound = loader.loadSfx('car_door_close.mp3') self.bulletParent = NodePath("Bullet Parent") self.bulletParent.reparentTo(render) self.bulletAmbientLight = AmbientLight('Bullet Light') self.bulletAmbientLight.setColor(Vec4(.0, .1, .2, .0)) lightnode = render.attachNewNode(self.bulletAmbientLight) self.bulletParent.setLight(lightnode)
def initPlanet(self, parent, tex, pos, radius, mass, lvel, avel): planet = loader.loadModel(self.main.modeld + "planet") planet.reparentTo(parent) planet_tex = loader.loadTexture(tex) planet.setTexture(planet_tex) planet.setPos(pos) planet.setScale(radius) body = OdeBody(self.main.physicsWorld) M = OdeMass() M.setSphereTotal(mass, radius) body.setMass(M) body.setPosition(planet.getPos(parent)) body.setQuaternion(planet.getQuat(parent)) body.setLinearVel(lvel) body.setAngularVel(avel) geom = OdeSphereGeom(self.main.space, radius) geom.setBody(body) self.main.getPlist().append(planet) self.main.getBlist().append(body) self.main.getGlist().append(geom)
def shoot(self): # TODO: add proper unit tests! angle = self.heading * math.pi / 180.0 headingX = math.cos(angle) headingY = math.sin(angle) offset = Vec3(headingX, headingY, 0) * Ship.BULLET_OFFSET shipPos = self.getPos() bulletPos = (offset[0] + shipPos[0], offset[1] + shipPos[1], offset[2]) bulletVisual = loader.loadModel("bullet.bam") bulletVisual.setPos(tupleToVec3(bulletPos)) bulletVisual.setHpr(tupleToVec3((self.heading + 90, 180))) bulletVisual.setScale(1.5) bulletVisual.reparentTo(self.bulletParent) # Create physics for bullet collisionSphere = OdeSphereGeom(1.5) collisionSphere.setCategoryBits(BitMask32(0xffffffff)) collisionSphere.setCollideBits(BitMask32(0xffffffff)) collisionSphere.setPosition(bulletPos[0], bulletPos[1], bulletPos[2]) shipVel = self.getVel() bullet = { 'vel': (headingX * Ship.BULLET_SPEED + shipVel[0] / Ship.BULLET_SHIP_SPEED_CORRELATION, headingY * Ship.BULLET_SPEED + shipVel[1] / Ship.BULLET_SHIP_SPEED_CORRELATION), 'visual': bulletVisual, 'physical': collisionSphere, 'isAlive': True, 'timeToLive': Ship.BULLET_MAX_LIFE_TIME } self.bullets.append(bullet) self.shootingSound.play()
def __init__(self, game, color): self.POWER = 200 self.game = game self.SHIP_TYPE = "RAKETTI" self.Ball_offset = 10.0 # self.hasBall = False self.thrust = False self.thrustLeft = False self.thrustRight = False self.thrustBack = False self.rotation = 0 self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) #self.body.setGravityMode(False) #odespheregeom(... , size of hitbox sphere) self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('spaceship.egg') model.setH(180) model.setY(15) model.reparentTo(self.visualNode) self.visualNode.setScale(0.4) plight = PointLight('plight') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) plightNodePath = model.attachNewNode(plight) model.setLight(plightNodePath)
def __init__(self, game, power = 10): self.game = game self.POWER = power self.Active = False self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3) #self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) self.model = loader.loadModel('AbsorbingPylon.egg') self.model.setScale(2) self.model.reparentTo(self.visualNode) #TODO: trigger geom #self.effectGeom = OdeSphereGeom( ) if (self.getPower() > 0): self.setColor( Vec4(1.0, 0.0, 0.0, 0.0) ) if (self.getPower() <= 0): self.setColor( Vec4(0.0, 0.0, 1.0, 0.0) )
class Ship: NAME_DEFAULT = "unnamed" POS_DEFAULT = (0, 30) VEL_DEFAULT = (0, 0) ACC_DEFAULT = 0.0 # 0.0 - 1.0 HEADING_DEFAULT = -90.0 ACC_COEFFICIENT = 35.0 # This is how much acceleration affects speed ROTATION_SPEED = 200 MODEL_ROTATION_OFFSET = (0.0, 0.0, -5.0) HEALTH = 10.0 BULLET_OFFSET = 5.0 # This is how far ahead the bullet spawns at BULLET_SPEED = 200 BULLET_SHIP_SPEED_CORRELATION = 40.0 BULLET_MAX_LIFE_TIME = 100 BULLET_DAMAGE = 1.0 PLANET_DAMAGE = 0.5 SPEED_MAX = 50.0 def __init__( self, name=NAME_DEFAULT, pos=POS_DEFAULT, heading=HEADING_DEFAULT, vel=VEL_DEFAULT, acc=ACC_DEFAULT # player controlled acceleration. Can be 0.0 - 1.0 ): """@param name string""" self.name = name self.pos = pos self.vel = vel self.acc = acc self.heading = heading self.rotateLeft = False self.rotateRight = False self.visualNode = self.createVisualNode(self.pos) self.bullets = [] self.collisionHandler = colHandler self.collisions = [] self.collisionSphere = OdeSphereGeom(4) self.collisionSphere.setCategoryBits(BitMask32(0xffffffff)) self.collisionSphere.setCollideBits(BitMask32(0xffffffff)) self.collisionSphere.setPosition(pos[0], pos[1], 0) self.forces = [] self.mass = 1.0 self.health = Ship.HEALTH self.isAlive = True self.shootingSound = loader.loadSfx('anti_tank_gun_single_shot.mp3') self.destroySound = loader.loadSfx('large_explosion.mp3') self.bulletHitSound = loader.loadSfx( 'explosion_loud_internal_explosion_very_reverberant.mp3') self.collisionSound = loader.loadSfx('car_door_close.mp3') self.bulletParent = NodePath("Bullet Parent") self.bulletParent.reparentTo(render) self.bulletAmbientLight = AmbientLight('Bullet Light') self.bulletAmbientLight.setColor(Vec4(.0, .1, .2, .0)) lightnode = render.attachNewNode(self.bulletAmbientLight) self.bulletParent.setLight(lightnode) def createVisualNode(self, pos=(0, 0)): # modelNode is the actualy ship model modelNode = loader.loadModel("indicator.bam") # visualNode is the node we operate on to move and rotate the ship visualNode = NodePath('Ship: ' + self.name) visualNode.setPos(tupleToVec3(pos)) visualNode.setHpr(Vec3(0, -90, 90)) # TODO: add scale parameter to this or some other aggregator class visualNode.setScale(1) # Reparent the actual modelNode to the visualNode modelNode.reparentTo(visualNode) # Offset the model node relative to the parent modelNode.setPos(tripleToVec3(Ship.MODEL_ROTATION_OFFSET)) visualNode.reparentTo(render) return visualNode def applyForce(self, force): self.forces.append(force) def setCollisionHandler(self, handler): self.collisionHandler = handler def addCollision(self, col): self.collisions.append(col) self.collisionSound.play() def getCollisions(self): return self.collisions def getVisualNode(self): return self.visualNode def getMass(self): return self.mass def isVisible(self): result = False visualNode = self.getVisualNode() # To be visible the ship has to be not hidden and has to have render as # the master parent (aka getTop). result = (not visualNode.isHidden()) and (visualNode.getTop() == render) return result def setPos(self, pos): self.pos = pos def getPos(self): return self.pos def setVel(self, vel): self.vel = vel self.momentum = vel def getVel(self): return self.vel def getAcc(self): return self.acc def getHeading(self): return self.heading def shoot(self): # TODO: add proper unit tests! angle = self.heading * math.pi / 180.0 headingX = math.cos(angle) headingY = math.sin(angle) offset = Vec3(headingX, headingY, 0) * Ship.BULLET_OFFSET shipPos = self.getPos() bulletPos = (offset[0] + shipPos[0], offset[1] + shipPos[1], offset[2]) bulletVisual = loader.loadModel("bullet.bam") bulletVisual.setPos(tupleToVec3(bulletPos)) bulletVisual.setHpr(tupleToVec3((self.heading + 90, 180))) bulletVisual.setScale(1.5) bulletVisual.reparentTo(self.bulletParent) # Create physics for bullet collisionSphere = OdeSphereGeom(1.5) collisionSphere.setCategoryBits(BitMask32(0xffffffff)) collisionSphere.setCollideBits(BitMask32(0xffffffff)) collisionSphere.setPosition(bulletPos[0], bulletPos[1], bulletPos[2]) shipVel = self.getVel() bullet = { 'vel': (headingX * Ship.BULLET_SPEED + shipVel[0] / Ship.BULLET_SHIP_SPEED_CORRELATION, headingY * Ship.BULLET_SPEED + shipVel[1] / Ship.BULLET_SHIP_SPEED_CORRELATION), 'visual': bulletVisual, 'physical': collisionSphere, 'isAlive': True, 'timeToLive': Ship.BULLET_MAX_LIFE_TIME } self.bullets.append(bullet) self.shootingSound.play() def bulletHit(self): self.health -= Ship.BULLET_DAMAGE if self.health <= 0: self.destroy() self.bulletHitSound.play() def planetHit(self): self.health -= Ship.PLANET_DAMAGE if self.health <= 0.0: self.destroy() self.bulletHitSound.play() def destroyBullet(self, bullet): bullet['visual'].removeNode() #bullet['physical'].destroy() bullet['physical'].disable() # If the "bullet['physical'].destroy()" line is giving errors use the # following one instead: #bullet['physical'].disable() self.bullets.remove(bullet) bullet = None def destroy(self): self.isAlive = False self.visualNode.hide() self.destroySound.play() def thrustOn(self): self.acc = 1.0 def thrustOff(self): self.acc = 0.0 def rotateLeftOn(self): self.rotateLeft = True def rotateLeftOff(self): self.rotateLeft = False def isRotatingLeft(self): return self.rotateLeft def rotateRightOn(self): self.rotateRight = True def rotateRightOff(self): self.rotateRight = False def isRotatingRight(self): return self.rotateRight def update(self, deltaTime): """@param deltaTime float, how many seconds have passed since last tick""" # TODO: refactor the updating code into different methods # Update the bullets # TODO: Add test for this in testUpdate! for bullet in self.bullets: bullet['timeToLive'] -= 1 if bullet['timeToLive'] <= 0: bullet['isAlive'] = False if not bullet['isAlive']: self.destroyBullet(bullet) continue pos = bullet['visual'].getPos() bulletPos = Vec3(bullet['vel'][0] * deltaTime + pos[0], bullet['vel'][1] * deltaTime + pos[1], 0) bullet['visual'].setPos(bulletPos) bullet['physical'].setPosition(bulletPos) # If the ship is not alive anymore, we don't move it if not self.isAlive: return # update the heading. Must be done before position updating! if self.rotateLeft: self.heading = self.heading + Ship.ROTATION_SPEED * deltaTime elif self.rotateRight: self.heading = self.heading - Ship.ROTATION_SPEED * deltaTime for c in self.collisions: self.collisionHandler(self, c) # update position gainedSpeedScalar = self.acc * deltaTime * Ship.ACC_COEFFICIENT # convert degrees to radians angle = self.heading * math.pi / 180.0 #correction = math.pi / 2 deltaVelX = gainedSpeedScalar * math.cos(angle) deltaVelY = gainedSpeedScalar * math.sin(angle) for f in self.forces: deltaVelX += f[0] deltaVelY += f[1] self.forces = [] self.vel = (self.vel[0] + deltaVelX, self.vel[1] + deltaVelY) # Limit the ship's speed to Ship.SPEED_MAX self.limitVelocity() deltaPosX = deltaTime * self.vel[0] deltaPosY = deltaTime * self.vel[1] newPosX = self.pos[0] + deltaPosX newPosY = self.pos[1] + deltaPosY self.pos = (newPosX, newPosY) # Rotate the visual representation of the ship self.visualNode.setH(self.heading) # Move the actual visual representation self.visualNode.setPos(tupleToVec3(self.pos)) self.collisionSphere.setPosition(self.pos[0], self.pos[1], 0) def limitVelocity(self): shipVel = self.getVel() newVelScalar = tupleLength(shipVel) if newVelScalar > Ship.SPEED_MAX: newVelScale = Ship.SPEED_MAX / newVelScalar newVel = scaleTuple(shipVel, newVelScale) self.setVel(newVel)
# This 'balls' list contains tuples of nodepaths with their ode geoms for i in range(15): # Setup the geometry ballNP = ball.copyTo(render) ballNP.setPos(randint(-7, 7), randint(-7, 7), 10 + random() * 5.0) ballNP.setColor(random(), random(), random(), 1) ballNP.setHpr(randint(-45, 45), randint(-45, 45), randint(-45, 45)) # Create the body and set the mass ballBody = OdeBody(world) M = OdeMass() M.setSphere(50, 1) ballBody.setMass(M) ballBody.setPosition(ballNP.getPos(render)) ballBody.setQuaternion(ballNP.getQuat(render)) # Create a ballGeom ballGeom = OdeSphereGeom(space, 1) ballGeom.setCollideBits(BitMask32(0x00000001)) ballGeom.setCategoryBits(BitMask32(0x00000001)) ballGeom.setBody(ballBody) # Create the sound ballSound = loader.loadSfx("audio/sfx/GUI_rollover.wav") balls.append((ballNP, ballGeom, ballSound)) # Add a plane to collide with cm = CardMaker("ground") cm.setFrame(-20, 20, -20, 20) cm.setUvRange((0, 1), (1, 0)) ground = render.attachNewNode(cm.generate()) ground.setPos(0, 0, 0); ground.lookAt(0, 0, -1) groundGeom = OdePlaneGeom(space, (0, 0, 1, 0)) groundGeom.setCollideBits(BitMask32(0x00000001))
class Pallo(Collectible): # COLLECTIBLE_TYPE = 'PointBall' # VALUE = 1 # DRAIN = 20 def __init__(self, game, color, value = 1, drain = 20): self.game = game self.VALUE = value self.DRAIN = drain #self.idnumber = id self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('Ball2.egg') model.setScale(2.5) model.reparentTo(self.visualNode) plight = PointLight('plight') plight.setPoint( Point3(0, 0, 3) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.05, 0.01, 0.01) ) self.plightNodePath = model.attachNewNode(plight) model.setLight(self.plightNodePath) self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) self.body.setGravityMode(True) #self.body.setGravityMode(False) #self.juttu = OdeUtil() self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3.5) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) def getValue(self): return self.VALUE def hitShips(self, shipList): for ship in shipList: if OdeUtil.areConnected(ship.body, self.body) and not ship.hasBall(): self.PowerUpEffect(ship) def PowerUpEffect(self, ship): # ship.mass.add(self.mass) ship.addPower(-(self.DRAIN)) ship.gotBall(self) self.hideObject() ship.visualNode.setLight(self.plightNodePath) #print player print ship.SHIP_TYPE + " lost " + str(self.DRAIN) + " power!!" def Restore(self, ship): # ship.mass.add(self.mass) ship.addPower(self.DRAIN) self.showObject() ship.visualNode.clearLight(self.plightNodePath) #self.setPos( Vec3(random.randrange(30), random.randrange(40), 0)) #ship.dropBall() #print player print ship.getShipType() + " regained 20 power!!"
class Game: STATE_INITIALIZING = "Initializing" STATE_RUNNING = "Running" SHIPS_MAX_X_DISTANCE = 330.0 SHIPS_MAX_Y_DISTANCE = 250.0 NAME_SHIP_ONE = "Ship 1" NAME_SHIP_TWO = "Ship 2" NAME_PLAYER_ONE = "Player 1" NAME_PLAYER_TWO = "Player 2" START_POS_SHIP_ONE = (100, 100) START_POS_SHIP_TWO = (-100, -100) START_HEADING_SHIP_ONE = -135.0 START_HEADING_SHIP_TWO = 45.0 PLAYER_ONE_FORWARD_KEY = "arrow_up" PLAYER_ONE_ROTATE_LEFT_KEY = "arrow_left" PLAYER_ONE_ROTATE_RIGHT_KEY = "arrow_right" PLAYER_ONE_SHOOT = "rcontrol" PLAYER_TWO_FORWARD_KEY = "w" PLAYER_TWO_ROTATE_LEFT_KEY = "a" PLAYER_TWO_ROTATE_RIGHT_KEY = "d" PLAYER_TWO_SHOOT = "lcontrol" HUD_TEXT_SCALE = 0.05 HUD_PLAYER_ONE_X = -1.25 HUD_PLAYER_TWO_X = 1.05 HUD_Y_FIRST_LINE = 0.85 HUD_Y_SECOND_LINE = 0.75 HUD_Y_THIRD_LINE = 0.65 CAMERA_POS_DEFAULT = (0.0, 0.0, 250.0) CAMERA_HPR_DEFAULT = (0.0, -90.0, 0.0) CAMERA_DISTANCE_COEFFICIENT = 3.0 CAMERA_DISTANCE_MAX = 450.0 CAMERA_DISTANCE_MIN = 150.0 CAMERA_MODE_GAME = "Game" CAMERA_MODE_FPS_ONE = "Fps 1" CAMERA_MODE_FPS_TWO = "Fps 2" CAMERA_MODE_STILL = "Still" CAMERA_FPS_OFFSET_HEIGHT = 2.0 CAMERA_FPS_OFFSET_BACK = 15.0 WINNER_TEXT = "has won the round" PLANET_POSITION = (0, 0) PLANET_CAMERA_DISTANCE_MAX = 400.0 MATCH_MAX_POINTS = 5 GRAVITY_DISTANCE = 100.0 GRAVITY = 2000.0 def __init__(self): # Disable Panda's base camera mover base.disableMouse() base.setBackgroundColor(0,0,0,0) self.state = Game.STATE_INITIALIZING # contains a list of the ships in game self.ships = None self.players = None self.bullets = None self.stars = None self.planet = None self.time = 0.0 self.isListening = False getModelPath().prependDirectory( Filename('./media/') ) self.physWorld = OdeWorld() self.physWorld.setGravity(0, 0, 0) self.physWorld.initSurfaceTable(1) self.physWorld.setSurfaceEntry( 0, 0, 1.0, # u .35, # elasticity .01, # minimum threshold for physical movement .01, # .00000001, # softening .01, # .01) # dampening self.physSpace = OdeHashSpace() self.winnerText = None self.gameFrames = 0 self.lastWarp = 0 self.cameraMode = Game.CAMERA_MODE_GAME self.lastCameraPos = None self.pause = False def start(self): self.resetCamera() self.loadPlanet() self.loadShips() self.loadPlayers() self.loadStars() self.loadHUD() light = DirectionalLight('light') light.setDirection( Vec3(-1, .1, -.5) ) light.setColor( Vec4(.7, .6, .6, 0) ) light.setSpecularColor( Vec4(.3, .5, .7, 0) ) lightnode = render.attachNewNode(light) render.setLight(lightnode) render.setShaderAuto() render.setShaderInput('light', lightnode) render.setAntialias(AntialiasAttrib.MAuto) # TODO: it might be necessary here to check that the task # does not already exist in the task manager because the # unit tests at the moment call the start method # continuously. taskMgr.add(self.tick, "gameloop") self.time = self.getTime() self.registerListeners() self.state = Game.STATE_RUNNING # Load music self.music = loader.loadSfx('MVi - Ilwrath Are Watching.mp3') self.music.setLoop(True) self.music.setVolume(0.5) self.music.play() def loadHUD(self): self.winnerText = OnscreenText( text= "Insert Winner Text Here", style=1, fg=(1,1,1,1), pos=(-0.25, 0), align=TextNode.ALeft, scale = .07 ) self.winnerText.hide() self.scoreTextPlayerOne = OnscreenText( text= "Player 1:", style=1, fg=(1,1,1,1), pos=(Game.HUD_PLAYER_ONE_X, Game.HUD_Y_FIRST_LINE), align=TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.scorePlayerOne = OnscreenText( text= "Score: 0", style=1, fg=(1,1,1,1), pos=(Game.HUD_PLAYER_ONE_X, Game.HUD_Y_SECOND_LINE), align=TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.healthPlayerOne = OnscreenText( text= "Health: " + str(Ship.HEALTH), style=1, fg=(1,1,1,1), pos=(Game.HUD_PLAYER_ONE_X, Game.HUD_Y_THIRD_LINE), align=TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.scoreTextPlayerTwo = OnscreenText( text= "Player 2:", style=1, fg=(1,1,1,1), pos=(Game.HUD_PLAYER_TWO_X, Game.HUD_Y_FIRST_LINE), align=TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.scorePlayerTwo = OnscreenText( text= "Score: 0", style=1, fg=(1,1,1,1), pos=(Game.HUD_PLAYER_TWO_X, Game.HUD_Y_SECOND_LINE), align=TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.healthPlayerTwo = OnscreenText( text= "Health: " + str(Ship.HEALTH), style=1, fg=(1,1,1,1), pos=(Game.HUD_PLAYER_TWO_X, Game.HUD_Y_THIRD_LINE), align=TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) def generateRandomPos( self ): return ( random.random() * Game.SHIPS_MAX_X_DISTANCE - Game.SHIPS_MAX_X_DISTANCE / 2., random.random() * Game.SHIPS_MAX_Y_DISTANCE - Game.SHIPS_MAX_Y_DISTANCE / 2. ) def generateRandomStartPos( self, offlimits = [] ): pos = self.generateRandomPos() while not self.checkIfStartPosValid( pos, offlimits ): pos = self.generateRandomPos() return pos def checkIfStartPosValid( self, pos, offlimits ): for o in offlimits: if tupleDistanceSquared( pos, o[0] ) < o[1]**2: return False return True def getBullets(self): ships = self.getShips() shipOne = ships[0] shipTwo = ships[1] bullets = [shipOne.bullets, shipTwo.bullets] return bullets def resetCamera(self): self.setCameraPos(Game.CAMERA_POS_DEFAULT) self.setCameraHpr(Game.CAMERA_HPR_DEFAULT) pos = Game.CAMERA_POS_DEFAULT self.lastCameraPos = ( pos[0], pos[1] ) def setCameraPos(self, pos): base.camera.setPos( tripleToVec3(pos) ) def getCameraPos(self): return vec3ToTriple( base.camera.getPos() ) def setCameraHpr(self, hpr): base.camera.setHpr( tripleToVec3(hpr) ) def getCameraHpr(self): return vec3ToTriple( base.camera.getHpr() ) def getTime(self): return globalClock.getFrameTime() def getDeltaTime(self): return globalClock.getDt() def run(self): """Call this to run the game. Untested because this method won't return.""" taskMgr.run() def loadShips(self): shipOne = Ship( Game.NAME_SHIP_ONE, Game.START_POS_SHIP_ONE, Game.START_HEADING_SHIP_ONE ) shipTwo = Ship( Game.NAME_SHIP_TWO, Game.START_POS_SHIP_TWO, Game.START_HEADING_SHIP_TWO ) offlimits = [ ( vec3ToTuple( self.planet.getPos() ), Game.GRAVITY_DISTANCE ) ] shipOne.setPos( self.generateRandomStartPos( offlimits ) ) shipOne.heading = random.random()*360 shipTwo.heading = random.random()*360 offlimits.append( ( shipOne.getPos(), 150 ) ) shipTwo.setPos( self.generateRandomStartPos( offlimits ) ) self.ships = [] self.ships.append(shipOne) self.ships.append(shipTwo) def loadPlayers(self): playerOne = Player(Game.NAME_PLAYER_ONE) playerTwo = Player(Game.NAME_PLAYER_TWO) self.players = [] self.players.append(playerOne) self.players.append(playerTwo) def loadStars(self): ambientlight = AmbientLight('alight') ambientlight.setColor( Vec4(1, 1, 1, 0) ) lightnode = render.attachNewNode(ambientlight) self.stars = loader.loadModel("stars.bam") self.stars.setLight(lightnode) self.stars.setScale(1000) self.stars.setPos(0,0,0) self.stars.reparentTo(render) self.starsRotation = self.stars.getQuat() def loadPlanet(self): self.planet = loader.loadModel('planet.bam') self.planet.setPos( tupleToVec3(Game.PLANET_POSITION) ) self.planet.setScale(20) self.planet.reparentTo(render) self.planetCollGeom = OdeSphereGeom(20) #self.planetCollGeom.setCategoryBits( BitMask32(0xffffffff) ) #self.planetCollGeom.setCollideBits( BitMask32(0xffffffff) ) def updateCamera(self): ships = self.getShips() shipOne = ships[0] shipOnePos = shipOne.getPos() shipTwo = ships[1] shipTwoPos = shipTwo.getPos() # Calculate the distance between the ships distance = tupleDistance(shipOnePos, shipTwoPos) cameraDistance = distance * Game.CAMERA_DISTANCE_COEFFICIENT if cameraDistance > Game.CAMERA_DISTANCE_MAX: cameraDistance = Game.CAMERA_DISTANCE_MAX if cameraDistance < Game.CAMERA_DISTANCE_MIN: cameraDistance = Game.CAMERA_DISTANCE_MIN # Calculate the middle point in space between the ship's positions middle = tupleMiddle(shipOnePos, shipTwoPos) cameraPos = self.getCameraPos() self.lastCameraPos = cameraPos newCameraPos = (middle[0], middle[1], cameraDistance) self.setCameraPos(newCameraPos) self.updateStars(newCameraPos) def updateStars(self, newCameraPos): # TODO: Add unit tests! self.stars.setPos(newCameraPos) cameraDeltaPos = tupleSegment( self.lastCameraPos, vec3ToTuple( newCameraPos ) ) xRotation = Quat() xRotation.setFromAxisAngle( cameraDeltaPos[0] * .1, Vec3( 0, 1, 0 ) ) yRotation = Quat() yRotation.setFromAxisAngle( -cameraDeltaPos[1] * .1, Vec3( 1, 0, 0 ) ) newRotation = xRotation.multiply( yRotation ) self.starsRotation *= newRotation self.stars.setQuat( self.starsRotation ) # With Euler angles: #self.stars.setHpr(0, -newCameraPos[1] * 0.1, newCameraPos[0] * 0.1 ) def applyGravity(self, ship, deltaTime): distance = tupleDistance( ship.getPos(), vec3ToTuple( self.planet.getPos() ) ) if distance > Game.GRAVITY_DISTANCE: return gravity = Game.GRAVITY/distance gravityVector = tupleNormalize( tupleSegment( ship.getPos(), vec3ToTuple( self.planet.getPos() ) ) ) gravityVector = scaleTuple( gravityVector, gravity * deltaTime) ship.applyForce( gravityVector ) def tick(self, task): if not self.pause: ships = self.getShips() # Check if the ships' positions need to be warped xDistance = abs(ships[0].getPos()[0] - ships[1].getPos()[0] ) if xDistance >= Game.SHIPS_MAX_X_DISTANCE: #and self.gameFrames - self.lastWarp > 10: self.warpShips('x') #self.lastWarp = self.gameFrames yDistance = abs(ships[0].getPos()[1] - ships[1].getPos()[1] ) if yDistance >= Game.SHIPS_MAX_Y_DISTANCE: self.warpShips('y') # Check if the planet's position needs to be warped planetXDistance = abs( self.getCameraPos()[0] - self.planet.getPos()[0] ) if planetXDistance >= Game.PLANET_CAMERA_DISTANCE_MAX: self.warpPlanet('x') planetYDistance = abs( self.getCameraPos()[1] - self.planet.getPos()[1] ) if planetYDistance >= Game.PLANET_CAMERA_DISTANCE_MAX: self.warpPlanet('y') # Check collisions col = OdeUtil.collide(ships[0].collisionSphere, ships[1].collisionSphere, 1) if not col.isEmpty(): ships[0].addCollision( point3ToTuple( col.getContactPoint(0) ) ) ships[1].addCollision( point3ToTuple( col.getContactPoint(0) ) ) colPlanet1 = OdeUtil.collide(ships[0].collisionSphere, self.planetCollGeom, 1) colPlanet2 = OdeUtil.collide(ships[1].collisionSphere, self.planetCollGeom, 1) if not colPlanet1.isEmpty(): ships[0].addCollision( point3ToTuple( colPlanet1.getContactPoint(0) ) ) ships[0].planetHit() if not colPlanet2.isEmpty(): ships[1].addCollision( point3ToTuple( colPlanet2.getContactPoint(0) ) ) ships[1].planetHit() # Bullet collisions ship one for bullet in ships[0].bullets: colBulletShip1 = OdeUtil.collide( bullet['physical'], ships[1].collisionSphere, 1 ) if not colBulletShip1.isEmpty(): ships[0].destroyBullet(bullet) ships[1].bulletHit() colBulletPlanet = OdeUtil.collide( bullet['physical'], self.planetCollGeom, 1 ) if not colBulletPlanet.isEmpty(): ships[0].destroyBullet(bullet) # Bullet collisions ship two for bullet in ships[1].bullets: colBulletShip2 = OdeUtil.collide( bullet['physical'], ships[0].collisionSphere, 1 ) if not colBulletShip2.isEmpty(): ships[1].destroyBullet(bullet) ships[0].bulletHit() colBulletPlanet = OdeUtil.collide( bullet['physical'], self.planetCollGeom, 1 ) if not colBulletPlanet.isEmpty(): ships[1].destroyBullet(bullet) for ship in ships: self.applyGravity( ship, self.getDeltaTime() ) ship.update( self.getDeltaTime() ) if not ships[0].isAlive: self.showWinnerText(self.players[1]) self.players[1].score += 1 self.restartGame() if not ships[1].isAlive: self.showWinnerText(self.players[0]) self.players[0].score += 1 self.restartGame() if self.cameraMode == Game.CAMERA_MODE_GAME: self.updateCamera() if self.gameFrames >= 125: self.winnerText.hide() self.gameFrames += 1 # Update health points in the HUD # TODO: These should be optimized so that they get updated only when they # change. self.healthPlayerOne.setText( "Health: " + str(self.ships[0].health) ) self.healthPlayerTwo.setText( "Health: " + str(self.ships[1].health) ) return task.cont def distanceToPlanetSquared(self, pos): return tupleDistanceSquared( pos, vec3ToTuple( self.planet.getPos() ) ) def warpShips(self, warpAxis): shipOne = self.ships[0] shipTwo = self.ships[1] shipOnePos = shipOne.getPos() shipTwoPos = shipTwo.getPos() furtherShip = None closerShip = None if shipOnePos == tupleFurthestDistance( vec3ToTuple( self.planet.getPos() ), [shipOnePos, shipTwoPos] ): furtherShip = shipOne closerShip = shipTwo else: closerShip = shipOne furtherShip = shipTwo furtherToCloser = tupleSegment( furtherShip.getPos(), closerShip.getPos() ) if warpAxis == 'x': furtherShip.setPos( ( furtherShip.getPos()[0] + furtherToCloser[0]*2, furtherShip.getPos()[1] ) ) elif warpAxis == 'y': furtherShip.setPos( ( furtherShip.getPos()[0], furtherShip.getPos()[1] + furtherToCloser[1]*2 ) ) def warpPlanet(self, warpAxis): planetPos = vec3ToTuple( self.planet.getPos() ) planetToCamera = tupleSegment( planetPos, self.getCameraPos() ) if warpAxis == 'x': self.planet.setPos( planetPos[0] + planetToCamera[0]*2, planetPos[1], 0 ) self.planetCollGeom.setPosition( planetPos[0] + planetToCamera[0]*2, planetPos[1], 0 ) elif warpAxis == 'y': self.planet.setPos( planetPos[0], planetPos[1] + planetToCamera[1]*2, 0 ) self.planetCollGeom.setPosition( planetPos[0], planetPos[1] + planetToCamera[1]*2, 0 ) def restartGame(self): self.planet.setPos( Vec3() ) self.planetCollGeom.setPosition( Vec3() ) offlimits = [ ( vec3ToTuple( self.planet.getPos() ), 102 ) ] # Reset ship one self.ships[0].setPos( self.generateRandomStartPos( offlimits ) ) self.ships[0].heading = random.random()*360 self.ships[0].setVel( Ship.VEL_DEFAULT ) self.ships[0].isAlive = True self.ships[0].health = Ship.HEALTH self.ships[0].visualNode.show() for bullet in self.ships[0].bullets: bullet['isAlive'] = False offlimits.append( ( self.ships[0].getPos(), 128 ) ) # Reset ship two self.ships[1].setPos( self.generateRandomStartPos( offlimits ) ) self.ships[1].heading = random.random()*360 self.ships[1].setVel( Ship.VEL_DEFAULT ) self.ships[1].isAlive = True self.ships[1].health = Ship.HEALTH self.ships[1].visualNode.show() for bullet in self.ships[1].bullets: bullet['isAlive'] = False for s in self.ships: s.update( 1/60. ) self.gameFrames = 0 playerOneScore = self.players[0].score playerTwoScore = self.players[1].score if playerOneScore >= Game.MATCH_MAX_POINTS: self.showGameWinnerText(self.players[0]) self.players[0].score = 0 self.players[1].score = 0 if playerTwoScore >= Game.MATCH_MAX_POINTS: self.showGameWinnerText(self.players[1]) self.players[0].score = 0 self.players[1].score = 0 playerOneScore = self.players[0].score playerTwoScore = self.players[1].score self.scorePlayerOne.setText( 'Score: ' + str(playerOneScore) ) self.scorePlayerTwo.setText( 'Score: ' + str(playerTwoScore) ) def showWinnerText(self, player): self.winnerText.setText( player.name + " " + Game.WINNER_TEXT ) self.winnerText.show() def showGameWinnerText(self, player): self.winnerText.setText( player.name + " wins the match!" ) self.winnerText.show() def registerListeners(self): playerOne = self.getPlayers()[0] playerTwo = self.getPlayers()[1] shipOne = self.getShips()[0] shipTwo = self.getShips()[1] # Player one events playerOneMoveForwardOn = createNamedEvent( playerOne.name, Event.PLAYER_MOVE_FORWARD_ON ) playerOneMoveForwardOff = createNamedEvent( playerOne.name, Event.PLAYER_MOVE_FORWARD_OFF ) playerOneRotateLeftOn = createNamedEvent( playerOne.name, Event.PLAYER_ROTATE_LEFT_ON ) playerOneRotateLeftOff = createNamedEvent( playerOne.name, Event.PLAYER_ROTATE_LEFT_OFF ) playerOneRotateRightOn = createNamedEvent( playerOne.name, Event.PLAYER_ROTATE_RIGHT_ON ) playerOneRotateRightOff = createNamedEvent( playerOne.name, Event.PLAYER_ROTATE_RIGHT_OFF ) playerOneShoot = createNamedEvent( playerOne.name, Event.PLAYER_SHOOT ) base.accept(playerOneMoveForwardOn, shipOne.thrustOn) base.accept(playerOneMoveForwardOff, shipOne.thrustOff) base.accept(playerOneRotateLeftOn, shipOne.rotateLeftOn) base.accept(playerOneRotateLeftOff, shipOne.rotateLeftOff) base.accept(playerOneRotateRightOn, shipOne.rotateRightOn) base.accept(playerOneRotateRightOff, shipOne.rotateRightOff) base.accept(playerOneShoot, shipOne.shoot) # Player two events playerTwoMoveForwardOn = createNamedEvent( playerTwo.name, Event.PLAYER_MOVE_FORWARD_ON ) playerTwoMoveForwardOff = createNamedEvent( playerTwo.name, Event.PLAYER_MOVE_FORWARD_OFF ) playerTwoRotateLeftOn = createNamedEvent( playerTwo.name, Event.PLAYER_ROTATE_LEFT_ON ) playerTwoRotateLeftOff = createNamedEvent( playerTwo.name, Event.PLAYER_ROTATE_LEFT_OFF ) playerTwoRotateRightOn = createNamedEvent( playerTwo.name, Event.PLAYER_ROTATE_RIGHT_ON ) playerTwoRotateRightOff = createNamedEvent( playerTwo.name, Event.PLAYER_ROTATE_RIGHT_OFF ) playerTwoShoot = createNamedEvent( playerTwo.name, Event.PLAYER_SHOOT ) base.accept(playerTwoMoveForwardOn, shipTwo.thrustOn) base.accept(playerTwoMoveForwardOff, shipTwo.thrustOff) base.accept(playerTwoRotateLeftOn, shipTwo.rotateLeftOn) base.accept(playerTwoRotateLeftOff, shipTwo.rotateLeftOff) base.accept(playerTwoRotateRightOn, shipTwo.rotateRightOn) base.accept(playerTwoRotateRightOff, shipTwo.rotateRightOff) base.accept(playerTwoShoot, shipTwo.shoot) # Player one key mapping base.accept(Game.PLAYER_ONE_FORWARD_KEY, playerOne.moveForwardOn) base.accept("control-" + Game.PLAYER_ONE_FORWARD_KEY, playerOne.moveForwardOn) base.accept(Game.PLAYER_ONE_FORWARD_KEY + "-up", playerOne.moveForwardOff) base.accept(Game.PLAYER_ONE_ROTATE_LEFT_KEY, playerOne.rotateLeftOn) base.accept("control-" + Game.PLAYER_ONE_ROTATE_LEFT_KEY, playerOne.rotateLeftOn) base.accept(Game.PLAYER_ONE_ROTATE_LEFT_KEY + "-up", playerOne.rotateLeftOff) base.accept(Game.PLAYER_ONE_ROTATE_RIGHT_KEY, playerOne.rotateRightOn) base.accept("control-" + Game.PLAYER_ONE_ROTATE_RIGHT_KEY, playerOne.rotateRightOn) base.accept(Game.PLAYER_ONE_ROTATE_RIGHT_KEY + "-up", playerOne.rotateRightOff) base.accept(Game.PLAYER_ONE_SHOOT, playerOne.shoot) # Player two key mapping base.accept(Game.PLAYER_TWO_FORWARD_KEY, playerTwo.moveForwardOn) base.accept("control-" + Game.PLAYER_TWO_FORWARD_KEY, playerTwo.moveForwardOn) base.accept(Game.PLAYER_TWO_FORWARD_KEY + "-up", playerTwo.moveForwardOff) base.accept(Game.PLAYER_TWO_ROTATE_LEFT_KEY, playerTwo.rotateLeftOn) base.accept("control-" + Game.PLAYER_TWO_ROTATE_LEFT_KEY, playerTwo.rotateLeftOn) base.accept(Game.PLAYER_TWO_ROTATE_LEFT_KEY + "-up", playerTwo.rotateLeftOff) base.accept(Game.PLAYER_TWO_ROTATE_RIGHT_KEY, playerTwo.rotateRightOn) base.accept("control-" + Game.PLAYER_TWO_ROTATE_RIGHT_KEY, playerTwo.rotateRightOn) base.accept(Game.PLAYER_TWO_ROTATE_RIGHT_KEY + "-up", playerTwo.rotateRightOff) base.accept(Game.PLAYER_TWO_SHOOT, playerTwo.shoot) # Game specific key mapping base.accept("escape", sys.exit) base.accept( "f1", self.switchCameraMode, [Game.CAMERA_MODE_FPS_ONE] ) base.accept( "f2", self.switchCameraMode, [Game.CAMERA_MODE_FPS_TWO] ) base.accept( "f3", self.switchCameraMode, [Game.CAMERA_MODE_GAME] ) base.accept( "f4", self.switchCameraMode, [Game.CAMERA_MODE_STILL] ) base.accept( "p", self.togglePause ) # The game is now listening to all the necessary events self.isListening = True def togglePause(self): self.pause = not self.pause def windowExists(self): return base.isMainWindowOpen() def getShips(self): return self.ships def getPlayers(self): return self.players def switchCameraMode(self, cameraMode): self.cameraMode = cameraMode if cameraMode == Game.CAMERA_MODE_FPS_ONE: angle = self.ships[0].heading * math.pi / 180.0 headingX = math.cos(angle) headingY = math.sin(angle) offset = Vec3( headingX, headingY, 0 ) pos = self.ships[0].visualNode.getChildren()[0].getPos() base.camera.setPos( pos[0] + offset[0], pos[1] + offset[1] - Game.CAMERA_FPS_OFFSET_HEIGHT, pos[2] - Game.CAMERA_FPS_OFFSET_BACK ) hpr = self.ships[0].visualNode.getChildren()[0].getHpr() base.camera.setHpr( hpr[0], hpr[1] + 90, hpr[2] ) base.camera.reparentTo(self.ships[0].visualNode) if cameraMode == Game.CAMERA_MODE_FPS_TWO: angle = self.ships[1].heading * math.pi / 180.0 headingX = math.cos(angle) headingY = math.sin(angle) offset = Vec3( headingX, headingY, 0 ) pos = self.ships[1].visualNode.getChildren()[0].getPos() base.camera.setPos( pos[0] + offset[0], pos[1] + offset[1] - Game.CAMERA_FPS_OFFSET_HEIGHT, pos[2] - Game.CAMERA_FPS_OFFSET_BACK ) hpr = self.ships[1].visualNode.getChildren()[0].getHpr() base.camera.setHpr( hpr[0], hpr[1] + 90, hpr[2] ) base.camera.reparentTo(self.ships[1].visualNode) if cameraMode == Game.CAMERA_MODE_GAME: base.camera.setHpr(Game.CAMERA_HPR_DEFAULT) base.camera.reparentTo(render) if cameraMode == Game.CAMERA_MODE_STILL: base.camera.reparentTo(render)
class Game: STATE_INITIALIZING = "Initializing" STATE_RUNNING = "Running" SHIPS_MAX_X_DISTANCE = 330.0 SHIPS_MAX_Y_DISTANCE = 250.0 NAME_SHIP_ONE = "Ship 1" NAME_SHIP_TWO = "Ship 2" NAME_PLAYER_ONE = "Player 1" NAME_PLAYER_TWO = "Player 2" START_POS_SHIP_ONE = (100, 100) START_POS_SHIP_TWO = (-100, -100) START_HEADING_SHIP_ONE = -135.0 START_HEADING_SHIP_TWO = 45.0 PLAYER_ONE_FORWARD_KEY = "arrow_up" PLAYER_ONE_ROTATE_LEFT_KEY = "arrow_left" PLAYER_ONE_ROTATE_RIGHT_KEY = "arrow_right" PLAYER_ONE_SHOOT = "rcontrol" PLAYER_TWO_FORWARD_KEY = "w" PLAYER_TWO_ROTATE_LEFT_KEY = "a" PLAYER_TWO_ROTATE_RIGHT_KEY = "d" PLAYER_TWO_SHOOT = "lcontrol" HUD_TEXT_SCALE = 0.05 HUD_PLAYER_ONE_X = -1.25 HUD_PLAYER_TWO_X = 1.05 HUD_Y_FIRST_LINE = 0.85 HUD_Y_SECOND_LINE = 0.75 HUD_Y_THIRD_LINE = 0.65 CAMERA_POS_DEFAULT = (0.0, 0.0, 250.0) CAMERA_HPR_DEFAULT = (0.0, -90.0, 0.0) CAMERA_DISTANCE_COEFFICIENT = 3.0 CAMERA_DISTANCE_MAX = 450.0 CAMERA_DISTANCE_MIN = 150.0 CAMERA_MODE_GAME = "Game" CAMERA_MODE_FPS_ONE = "Fps 1" CAMERA_MODE_FPS_TWO = "Fps 2" CAMERA_MODE_STILL = "Still" CAMERA_FPS_OFFSET_HEIGHT = 2.0 CAMERA_FPS_OFFSET_BACK = 15.0 WINNER_TEXT = "has won the round" PLANET_POSITION = (0, 0) PLANET_CAMERA_DISTANCE_MAX = 400.0 MATCH_MAX_POINTS = 5 GRAVITY_DISTANCE = 100.0 GRAVITY = 2000.0 def __init__(self): # Disable Panda's base camera mover base.disableMouse() base.setBackgroundColor(0, 0, 0, 0) self.state = Game.STATE_INITIALIZING # contains a list of the ships in game self.ships = None self.players = None self.bullets = None self.stars = None self.planet = None self.time = 0.0 self.isListening = False getModelPath().prependDirectory(Filename('./media/')) self.physWorld = OdeWorld() self.physWorld.setGravity(0, 0, 0) self.physWorld.initSurfaceTable(1) self.physWorld.setSurfaceEntry( 0, 0, 1.0, # u .35, # elasticity .01, # minimum threshold for physical movement .01, # .00000001, # softening .01, # .01) # dampening self.physSpace = OdeHashSpace() self.winnerText = None self.gameFrames = 0 self.lastWarp = 0 self.cameraMode = Game.CAMERA_MODE_GAME self.lastCameraPos = None self.pause = False def start(self): self.resetCamera() self.loadPlanet() self.loadShips() self.loadPlayers() self.loadStars() self.loadHUD() light = DirectionalLight('light') light.setDirection(Vec3(-1, .1, -.5)) light.setColor(Vec4(.7, .6, .6, 0)) light.setSpecularColor(Vec4(.3, .5, .7, 0)) lightnode = render.attachNewNode(light) render.setLight(lightnode) render.setShaderAuto() render.setShaderInput('light', lightnode) render.setAntialias(AntialiasAttrib.MAuto) # TODO: it might be necessary here to check that the task # does not already exist in the task manager because the # unit tests at the moment call the start method # continuously. taskMgr.add(self.tick, "gameloop") self.time = self.getTime() self.registerListeners() self.state = Game.STATE_RUNNING # Load music self.music = loader.loadSfx('MVi - Ilwrath Are Watching.mp3') self.music.setLoop(True) self.music.setVolume(0.5) self.music.play() def loadHUD(self): self.winnerText = OnscreenText(text="Insert Winner Text Here", style=1, fg=(1, 1, 1, 1), pos=(-0.25, 0), align=TextNode.ALeft, scale=.07) self.winnerText.hide() self.scoreTextPlayerOne = OnscreenText(text="Player 1:", style=1, fg=(1, 1, 1, 1), pos=(Game.HUD_PLAYER_ONE_X, Game.HUD_Y_FIRST_LINE), align=TextNode.ALeft, scale=Game.HUD_TEXT_SCALE) self.scorePlayerOne = OnscreenText(text="Score: 0", style=1, fg=(1, 1, 1, 1), pos=(Game.HUD_PLAYER_ONE_X, Game.HUD_Y_SECOND_LINE), align=TextNode.ALeft, scale=Game.HUD_TEXT_SCALE) self.healthPlayerOne = OnscreenText(text="Health: " + str(Ship.HEALTH), style=1, fg=(1, 1, 1, 1), pos=(Game.HUD_PLAYER_ONE_X, Game.HUD_Y_THIRD_LINE), align=TextNode.ALeft, scale=Game.HUD_TEXT_SCALE) self.scoreTextPlayerTwo = OnscreenText(text="Player 2:", style=1, fg=(1, 1, 1, 1), pos=(Game.HUD_PLAYER_TWO_X, Game.HUD_Y_FIRST_LINE), align=TextNode.ALeft, scale=Game.HUD_TEXT_SCALE) self.scorePlayerTwo = OnscreenText(text="Score: 0", style=1, fg=(1, 1, 1, 1), pos=(Game.HUD_PLAYER_TWO_X, Game.HUD_Y_SECOND_LINE), align=TextNode.ALeft, scale=Game.HUD_TEXT_SCALE) self.healthPlayerTwo = OnscreenText(text="Health: " + str(Ship.HEALTH), style=1, fg=(1, 1, 1, 1), pos=(Game.HUD_PLAYER_TWO_X, Game.HUD_Y_THIRD_LINE), align=TextNode.ALeft, scale=Game.HUD_TEXT_SCALE) def generateRandomPos(self): return (random.random() * Game.SHIPS_MAX_X_DISTANCE - Game.SHIPS_MAX_X_DISTANCE / 2., random.random() * Game.SHIPS_MAX_Y_DISTANCE - Game.SHIPS_MAX_Y_DISTANCE / 2.) def generateRandomStartPos(self, offlimits=[]): pos = self.generateRandomPos() while not self.checkIfStartPosValid(pos, offlimits): pos = self.generateRandomPos() return pos def checkIfStartPosValid(self, pos, offlimits): for o in offlimits: if tupleDistanceSquared(pos, o[0]) < o[1]**2: return False return True def getBullets(self): ships = self.getShips() shipOne = ships[0] shipTwo = ships[1] bullets = [shipOne.bullets, shipTwo.bullets] return bullets def resetCamera(self): self.setCameraPos(Game.CAMERA_POS_DEFAULT) self.setCameraHpr(Game.CAMERA_HPR_DEFAULT) pos = Game.CAMERA_POS_DEFAULT self.lastCameraPos = (pos[0], pos[1]) def setCameraPos(self, pos): base.camera.setPos(tripleToVec3(pos)) def getCameraPos(self): return vec3ToTriple(base.camera.getPos()) def setCameraHpr(self, hpr): base.camera.setHpr(tripleToVec3(hpr)) def getCameraHpr(self): return vec3ToTriple(base.camera.getHpr()) def getTime(self): return globalClock.getFrameTime() def getDeltaTime(self): return globalClock.getDt() def run(self): """Call this to run the game. Untested because this method won't return.""" taskMgr.run() def loadShips(self): shipOne = Ship(Game.NAME_SHIP_ONE, Game.START_POS_SHIP_ONE, Game.START_HEADING_SHIP_ONE) shipTwo = Ship(Game.NAME_SHIP_TWO, Game.START_POS_SHIP_TWO, Game.START_HEADING_SHIP_TWO) offlimits = [(vec3ToTuple(self.planet.getPos()), Game.GRAVITY_DISTANCE) ] shipOne.setPos(self.generateRandomStartPos(offlimits)) shipOne.heading = random.random() * 360 shipTwo.heading = random.random() * 360 offlimits.append((shipOne.getPos(), 150)) shipTwo.setPos(self.generateRandomStartPos(offlimits)) self.ships = [] self.ships.append(shipOne) self.ships.append(shipTwo) def loadPlayers(self): playerOne = Player(Game.NAME_PLAYER_ONE) playerTwo = Player(Game.NAME_PLAYER_TWO) self.players = [] self.players.append(playerOne) self.players.append(playerTwo) def loadStars(self): ambientlight = AmbientLight('alight') ambientlight.setColor(Vec4(1, 1, 1, 0)) lightnode = render.attachNewNode(ambientlight) self.stars = loader.loadModel("stars.bam") self.stars.setLight(lightnode) self.stars.setScale(1000) self.stars.setPos(0, 0, 0) self.stars.reparentTo(render) self.starsRotation = self.stars.getQuat() def loadPlanet(self): self.planet = loader.loadModel('planet.bam') self.planet.setPos(tupleToVec3(Game.PLANET_POSITION)) self.planet.setScale(20) self.planet.reparentTo(render) self.planetCollGeom = OdeSphereGeom(20) #self.planetCollGeom.setCategoryBits( BitMask32(0xffffffff) ) #self.planetCollGeom.setCollideBits( BitMask32(0xffffffff) ) def updateCamera(self): ships = self.getShips() shipOne = ships[0] shipOnePos = shipOne.getPos() shipTwo = ships[1] shipTwoPos = shipTwo.getPos() # Calculate the distance between the ships distance = tupleDistance(shipOnePos, shipTwoPos) cameraDistance = distance * Game.CAMERA_DISTANCE_COEFFICIENT if cameraDistance > Game.CAMERA_DISTANCE_MAX: cameraDistance = Game.CAMERA_DISTANCE_MAX if cameraDistance < Game.CAMERA_DISTANCE_MIN: cameraDistance = Game.CAMERA_DISTANCE_MIN # Calculate the middle point in space between the ship's positions middle = tupleMiddle(shipOnePos, shipTwoPos) cameraPos = self.getCameraPos() self.lastCameraPos = cameraPos newCameraPos = (middle[0], middle[1], cameraDistance) self.setCameraPos(newCameraPos) self.updateStars(newCameraPos) def updateStars(self, newCameraPos): # TODO: Add unit tests! self.stars.setPos(newCameraPos) cameraDeltaPos = tupleSegment(self.lastCameraPos, vec3ToTuple(newCameraPos)) xRotation = Quat() xRotation.setFromAxisAngle(cameraDeltaPos[0] * .1, Vec3(0, 1, 0)) yRotation = Quat() yRotation.setFromAxisAngle(-cameraDeltaPos[1] * .1, Vec3(1, 0, 0)) newRotation = xRotation.multiply(yRotation) self.starsRotation *= newRotation self.stars.setQuat(self.starsRotation) # With Euler angles: #self.stars.setHpr(0, -newCameraPos[1] * 0.1, newCameraPos[0] * 0.1 ) def applyGravity(self, ship, deltaTime): distance = tupleDistance(ship.getPos(), vec3ToTuple(self.planet.getPos())) if distance > Game.GRAVITY_DISTANCE: return gravity = Game.GRAVITY / distance gravityVector = tupleNormalize( tupleSegment(ship.getPos(), vec3ToTuple(self.planet.getPos()))) gravityVector = scaleTuple(gravityVector, gravity * deltaTime) ship.applyForce(gravityVector) def tick(self, task): if not self.pause: ships = self.getShips() # Check if the ships' positions need to be warped xDistance = abs(ships[0].getPos()[0] - ships[1].getPos()[0]) if xDistance >= Game.SHIPS_MAX_X_DISTANCE: #and self.gameFrames - self.lastWarp > 10: self.warpShips('x') #self.lastWarp = self.gameFrames yDistance = abs(ships[0].getPos()[1] - ships[1].getPos()[1]) if yDistance >= Game.SHIPS_MAX_Y_DISTANCE: self.warpShips('y') # Check if the planet's position needs to be warped planetXDistance = abs(self.getCameraPos()[0] - self.planet.getPos()[0]) if planetXDistance >= Game.PLANET_CAMERA_DISTANCE_MAX: self.warpPlanet('x') planetYDistance = abs(self.getCameraPos()[1] - self.planet.getPos()[1]) if planetYDistance >= Game.PLANET_CAMERA_DISTANCE_MAX: self.warpPlanet('y') # Check collisions col = OdeUtil.collide(ships[0].collisionSphere, ships[1].collisionSphere, 1) if not col.isEmpty(): ships[0].addCollision(point3ToTuple(col.getContactPoint(0))) ships[1].addCollision(point3ToTuple(col.getContactPoint(0))) colPlanet1 = OdeUtil.collide(ships[0].collisionSphere, self.planetCollGeom, 1) colPlanet2 = OdeUtil.collide(ships[1].collisionSphere, self.planetCollGeom, 1) if not colPlanet1.isEmpty(): ships[0].addCollision( point3ToTuple(colPlanet1.getContactPoint(0))) ships[0].planetHit() if not colPlanet2.isEmpty(): ships[1].addCollision( point3ToTuple(colPlanet2.getContactPoint(0))) ships[1].planetHit() # Bullet collisions ship one for bullet in ships[0].bullets: colBulletShip1 = OdeUtil.collide(bullet['physical'], ships[1].collisionSphere, 1) if not colBulletShip1.isEmpty(): ships[0].destroyBullet(bullet) ships[1].bulletHit() colBulletPlanet = OdeUtil.collide(bullet['physical'], self.planetCollGeom, 1) if not colBulletPlanet.isEmpty(): ships[0].destroyBullet(bullet) # Bullet collisions ship two for bullet in ships[1].bullets: colBulletShip2 = OdeUtil.collide(bullet['physical'], ships[0].collisionSphere, 1) if not colBulletShip2.isEmpty(): ships[1].destroyBullet(bullet) ships[0].bulletHit() colBulletPlanet = OdeUtil.collide(bullet['physical'], self.planetCollGeom, 1) if not colBulletPlanet.isEmpty(): ships[1].destroyBullet(bullet) for ship in ships: self.applyGravity(ship, self.getDeltaTime()) ship.update(self.getDeltaTime()) if not ships[0].isAlive: self.showWinnerText(self.players[1]) self.players[1].score += 1 self.restartGame() if not ships[1].isAlive: self.showWinnerText(self.players[0]) self.players[0].score += 1 self.restartGame() if self.cameraMode == Game.CAMERA_MODE_GAME: self.updateCamera() if self.gameFrames >= 125: self.winnerText.hide() self.gameFrames += 1 # Update health points in the HUD # TODO: These should be optimized so that they get updated only when they # change. self.healthPlayerOne.setText("Health: " + str(self.ships[0].health)) self.healthPlayerTwo.setText("Health: " + str(self.ships[1].health)) return task.cont def distanceToPlanetSquared(self, pos): return tupleDistanceSquared(pos, vec3ToTuple(self.planet.getPos())) def warpShips(self, warpAxis): shipOne = self.ships[0] shipTwo = self.ships[1] shipOnePos = shipOne.getPos() shipTwoPos = shipTwo.getPos() furtherShip = None closerShip = None if shipOnePos == tupleFurthestDistance( vec3ToTuple(self.planet.getPos()), [shipOnePos, shipTwoPos]): furtherShip = shipOne closerShip = shipTwo else: closerShip = shipOne furtherShip = shipTwo furtherToCloser = tupleSegment(furtherShip.getPos(), closerShip.getPos()) if warpAxis == 'x': furtherShip.setPos( (furtherShip.getPos()[0] + furtherToCloser[0] * 2, furtherShip.getPos()[1])) elif warpAxis == 'y': furtherShip.setPos( (furtherShip.getPos()[0], furtherShip.getPos()[1] + furtherToCloser[1] * 2)) def warpPlanet(self, warpAxis): planetPos = vec3ToTuple(self.planet.getPos()) planetToCamera = tupleSegment(planetPos, self.getCameraPos()) if warpAxis == 'x': self.planet.setPos(planetPos[0] + planetToCamera[0] * 2, planetPos[1], 0) self.planetCollGeom.setPosition( planetPos[0] + planetToCamera[0] * 2, planetPos[1], 0) elif warpAxis == 'y': self.planet.setPos(planetPos[0], planetPos[1] + planetToCamera[1] * 2, 0) self.planetCollGeom.setPosition( planetPos[0], planetPos[1] + planetToCamera[1] * 2, 0) def restartGame(self): self.planet.setPos(Vec3()) self.planetCollGeom.setPosition(Vec3()) offlimits = [(vec3ToTuple(self.planet.getPos()), 102)] # Reset ship one self.ships[0].setPos(self.generateRandomStartPos(offlimits)) self.ships[0].heading = random.random() * 360 self.ships[0].setVel(Ship.VEL_DEFAULT) self.ships[0].isAlive = True self.ships[0].health = Ship.HEALTH self.ships[0].visualNode.show() for bullet in self.ships[0].bullets: bullet['isAlive'] = False offlimits.append((self.ships[0].getPos(), 128)) # Reset ship two self.ships[1].setPos(self.generateRandomStartPos(offlimits)) self.ships[1].heading = random.random() * 360 self.ships[1].setVel(Ship.VEL_DEFAULT) self.ships[1].isAlive = True self.ships[1].health = Ship.HEALTH self.ships[1].visualNode.show() for bullet in self.ships[1].bullets: bullet['isAlive'] = False for s in self.ships: s.update(1 / 60.) self.gameFrames = 0 playerOneScore = self.players[0].score playerTwoScore = self.players[1].score if playerOneScore >= Game.MATCH_MAX_POINTS: self.showGameWinnerText(self.players[0]) self.players[0].score = 0 self.players[1].score = 0 if playerTwoScore >= Game.MATCH_MAX_POINTS: self.showGameWinnerText(self.players[1]) self.players[0].score = 0 self.players[1].score = 0 playerOneScore = self.players[0].score playerTwoScore = self.players[1].score self.scorePlayerOne.setText('Score: ' + str(playerOneScore)) self.scorePlayerTwo.setText('Score: ' + str(playerTwoScore)) def showWinnerText(self, player): self.winnerText.setText(player.name + " " + Game.WINNER_TEXT) self.winnerText.show() def showGameWinnerText(self, player): self.winnerText.setText(player.name + " wins the match!") self.winnerText.show() def registerListeners(self): playerOne = self.getPlayers()[0] playerTwo = self.getPlayers()[1] shipOne = self.getShips()[0] shipTwo = self.getShips()[1] # Player one events playerOneMoveForwardOn = createNamedEvent(playerOne.name, Event.PLAYER_MOVE_FORWARD_ON) playerOneMoveForwardOff = createNamedEvent( playerOne.name, Event.PLAYER_MOVE_FORWARD_OFF) playerOneRotateLeftOn = createNamedEvent(playerOne.name, Event.PLAYER_ROTATE_LEFT_ON) playerOneRotateLeftOff = createNamedEvent(playerOne.name, Event.PLAYER_ROTATE_LEFT_OFF) playerOneRotateRightOn = createNamedEvent(playerOne.name, Event.PLAYER_ROTATE_RIGHT_ON) playerOneRotateRightOff = createNamedEvent( playerOne.name, Event.PLAYER_ROTATE_RIGHT_OFF) playerOneShoot = createNamedEvent(playerOne.name, Event.PLAYER_SHOOT) base.accept(playerOneMoveForwardOn, shipOne.thrustOn) base.accept(playerOneMoveForwardOff, shipOne.thrustOff) base.accept(playerOneRotateLeftOn, shipOne.rotateLeftOn) base.accept(playerOneRotateLeftOff, shipOne.rotateLeftOff) base.accept(playerOneRotateRightOn, shipOne.rotateRightOn) base.accept(playerOneRotateRightOff, shipOne.rotateRightOff) base.accept(playerOneShoot, shipOne.shoot) # Player two events playerTwoMoveForwardOn = createNamedEvent(playerTwo.name, Event.PLAYER_MOVE_FORWARD_ON) playerTwoMoveForwardOff = createNamedEvent( playerTwo.name, Event.PLAYER_MOVE_FORWARD_OFF) playerTwoRotateLeftOn = createNamedEvent(playerTwo.name, Event.PLAYER_ROTATE_LEFT_ON) playerTwoRotateLeftOff = createNamedEvent(playerTwo.name, Event.PLAYER_ROTATE_LEFT_OFF) playerTwoRotateRightOn = createNamedEvent(playerTwo.name, Event.PLAYER_ROTATE_RIGHT_ON) playerTwoRotateRightOff = createNamedEvent( playerTwo.name, Event.PLAYER_ROTATE_RIGHT_OFF) playerTwoShoot = createNamedEvent(playerTwo.name, Event.PLAYER_SHOOT) base.accept(playerTwoMoveForwardOn, shipTwo.thrustOn) base.accept(playerTwoMoveForwardOff, shipTwo.thrustOff) base.accept(playerTwoRotateLeftOn, shipTwo.rotateLeftOn) base.accept(playerTwoRotateLeftOff, shipTwo.rotateLeftOff) base.accept(playerTwoRotateRightOn, shipTwo.rotateRightOn) base.accept(playerTwoRotateRightOff, shipTwo.rotateRightOff) base.accept(playerTwoShoot, shipTwo.shoot) # Player one key mapping base.accept(Game.PLAYER_ONE_FORWARD_KEY, playerOne.moveForwardOn) base.accept("control-" + Game.PLAYER_ONE_FORWARD_KEY, playerOne.moveForwardOn) base.accept(Game.PLAYER_ONE_FORWARD_KEY + "-up", playerOne.moveForwardOff) base.accept(Game.PLAYER_ONE_ROTATE_LEFT_KEY, playerOne.rotateLeftOn) base.accept("control-" + Game.PLAYER_ONE_ROTATE_LEFT_KEY, playerOne.rotateLeftOn) base.accept(Game.PLAYER_ONE_ROTATE_LEFT_KEY + "-up", playerOne.rotateLeftOff) base.accept(Game.PLAYER_ONE_ROTATE_RIGHT_KEY, playerOne.rotateRightOn) base.accept("control-" + Game.PLAYER_ONE_ROTATE_RIGHT_KEY, playerOne.rotateRightOn) base.accept(Game.PLAYER_ONE_ROTATE_RIGHT_KEY + "-up", playerOne.rotateRightOff) base.accept(Game.PLAYER_ONE_SHOOT, playerOne.shoot) # Player two key mapping base.accept(Game.PLAYER_TWO_FORWARD_KEY, playerTwo.moveForwardOn) base.accept("control-" + Game.PLAYER_TWO_FORWARD_KEY, playerTwo.moveForwardOn) base.accept(Game.PLAYER_TWO_FORWARD_KEY + "-up", playerTwo.moveForwardOff) base.accept(Game.PLAYER_TWO_ROTATE_LEFT_KEY, playerTwo.rotateLeftOn) base.accept("control-" + Game.PLAYER_TWO_ROTATE_LEFT_KEY, playerTwo.rotateLeftOn) base.accept(Game.PLAYER_TWO_ROTATE_LEFT_KEY + "-up", playerTwo.rotateLeftOff) base.accept(Game.PLAYER_TWO_ROTATE_RIGHT_KEY, playerTwo.rotateRightOn) base.accept("control-" + Game.PLAYER_TWO_ROTATE_RIGHT_KEY, playerTwo.rotateRightOn) base.accept(Game.PLAYER_TWO_ROTATE_RIGHT_KEY + "-up", playerTwo.rotateRightOff) base.accept(Game.PLAYER_TWO_SHOOT, playerTwo.shoot) # Game specific key mapping base.accept("escape", sys.exit) base.accept("f1", self.switchCameraMode, [Game.CAMERA_MODE_FPS_ONE]) base.accept("f2", self.switchCameraMode, [Game.CAMERA_MODE_FPS_TWO]) base.accept("f3", self.switchCameraMode, [Game.CAMERA_MODE_GAME]) base.accept("f4", self.switchCameraMode, [Game.CAMERA_MODE_STILL]) base.accept("p", self.togglePause) # The game is now listening to all the necessary events self.isListening = True def togglePause(self): self.pause = not self.pause def windowExists(self): return base.isMainWindowOpen() def getShips(self): return self.ships def getPlayers(self): return self.players def switchCameraMode(self, cameraMode): self.cameraMode = cameraMode if cameraMode == Game.CAMERA_MODE_FPS_ONE: angle = self.ships[0].heading * math.pi / 180.0 headingX = math.cos(angle) headingY = math.sin(angle) offset = Vec3(headingX, headingY, 0) pos = self.ships[0].visualNode.getChildren()[0].getPos() base.camera.setPos( pos[0] + offset[0], pos[1] + offset[1] - Game.CAMERA_FPS_OFFSET_HEIGHT, pos[2] - Game.CAMERA_FPS_OFFSET_BACK) hpr = self.ships[0].visualNode.getChildren()[0].getHpr() base.camera.setHpr(hpr[0], hpr[1] + 90, hpr[2]) base.camera.reparentTo(self.ships[0].visualNode) if cameraMode == Game.CAMERA_MODE_FPS_TWO: angle = self.ships[1].heading * math.pi / 180.0 headingX = math.cos(angle) headingY = math.sin(angle) offset = Vec3(headingX, headingY, 0) pos = self.ships[1].visualNode.getChildren()[0].getPos() base.camera.setPos( pos[0] + offset[0], pos[1] + offset[1] - Game.CAMERA_FPS_OFFSET_HEIGHT, pos[2] - Game.CAMERA_FPS_OFFSET_BACK) hpr = self.ships[1].visualNode.getChildren()[0].getHpr() base.camera.setHpr(hpr[0], hpr[1] + 90, hpr[2]) base.camera.reparentTo(self.ships[1].visualNode) if cameraMode == Game.CAMERA_MODE_GAME: base.camera.setHpr(Game.CAMERA_HPR_DEFAULT) base.camera.reparentTo(render) if cameraMode == Game.CAMERA_MODE_STILL: base.camera.reparentTo(render)
def createTire(self, tireIndex): """Create one physics tire. Returns a (nodePath, OdeBody, OdeGeom) tuple""" if (tireIndex < 0) or (tireIndex >= len(self.tireMasks)): self.notify.error('invalid tireIndex %s' % tireIndex) self.notify.debug("create tireindex %s" % (tireIndex)) zOffset = 0 # for now the tires are spheres body = OdeBody(self.world) mass = OdeMass() mass.setSphere(self.tireDensity, IceGameGlobals.TireRadius) body.setMass(mass) body.setPosition(IceGameGlobals.StartingPositions[tireIndex][0], IceGameGlobals.StartingPositions[tireIndex][1], IceGameGlobals.StartingPositions[tireIndex][2]) #body.setAutoDisableFlag(1) #body.setAutoDisableLinearThreshold(1.01 * MetersToFeet) # skipping AutoDisableAngularThreshold as that is radians per second #body.setAutoDisableAngularThreshold(0.1) body.setAutoDisableDefaults() geom = OdeSphereGeom(self.space, IceGameGlobals.TireRadius) self.space.setSurfaceType(geom, self.tireSurfaceType) self.space.setCollideId(geom, self.tireCollideIds[tireIndex]) self.massList.append(mass) self.geomList.append(geom) # a tire collides against other tires, the wall and the floor geom.setCollideBits(self.allTiresMask | self.wallMask | self.floorMask | self.obstacleMask) geom.setCategoryBits(self.tireMasks[tireIndex]) geom.setBody(body) if self.notify.getDebug(): self.notify.debug('tire geom id') geom.write() self.notify.debug(' -') if self.canRender: testTire = render.attachNewNode("tire holder %d" % tireIndex) smileyModel = NodePath( ) # loader.loadModel('models/misc/smiley') # smiley! if not smileyModel.isEmpty(): smileyModel.setScale(IceGameGlobals.TireRadius) smileyModel.reparentTo(testTire) smileyModel.setAlphaScale(0.5) smileyModel.setTransparency(1) testTire.setPos(IceGameGlobals.StartingPositions[tireIndex]) #debugAxis = loader.loadModel('models/misc/xyzAxis') if 0: #not debugAxis.isEmpty(): debugAxis.reparentTo(testTire) debugAxis.setScale(IceGameGlobals.TireRadius / 10.0) debugAxis2 = loader.loadModel('models/misc/xyzAxis') debugAxis2.reparentTo(testTire) debugAxis2.setScale(-IceGameGlobals.TireRadius / 10.0) # lets create a black tire #tireModel = loader.loadModel('phase_3/models/misc/sphere') tireModel = loader.loadModel( "phase_4/models/minigames/ice_game_tire") # assuming it has a radius of 1 tireHeight = 1 #tireModel.setScale(IceGameGlobals.TireRadius, IceGameGlobals.TireRadius, 1) #tireModel.setZ( 0 - IceGameGlobals.TireRadius + (tireHeight /2.0)) #tireModel.setColor(0,0,0) tireModel.setZ(-IceGameGlobals.TireRadius + 0.01) tireModel.reparentTo(testTire) #tireModel.setAlphaScale(0.5) #tireModel.setTransparency(1) self.odePandaRelationList.append((testTire, body)) else: testTire = None self.bodyList.append((None, body)) return testTire, body, geom
class Pylon(StaticObject): def __init__(self, game, power = 50.0, range = 30): self.game = game self.POWER = power self.Active = False self.RANGE = range self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3) #self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.triggerGeom = OdeSphereGeom( range ) self.triggerGeom.setCategoryBits( BitMask32(0xffffffff) ) self.triggerGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) self.model = loader.loadModel('AbsorbingPylon.egg') self.model.setScale(1.5) self.model.reparentTo(self.visualNode) pow = self.getPower()*5 maxPow = self.game.MAX_PYLON_POWER if (pow > 0): self.offColor = Vec4(pow/maxPow, 0.0, 0.0, 0.0) self.onColor = Vec4(0.0, pow/maxPow, 0.0, 0.0) if (pow <= 0): self.offColor = Vec4(0.0, 0.0, -pow/maxPow, 0.0) self.onColor = Vec4(0.0, -pow/maxPow, 0.0, 0.0) self.setColor( self.offColor ) def setPos(self, pos): self.visualNode.setPos( pos ) self.collGeom.setPosition( pos ) self.triggerGeom.setPosition( pos ) def addToPylonList(self, pylonList): pylonList.append(self) def getPower(self): return self.POWER def getRange(self): return self.RANGE def setColor(self, color): plight = PointLight('plight4') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) self.plight = plight self.plightNodePath = self.model.attachNewNode(self.plight) self.model.setLight(self.plightNodePath) def setActive(self, active, ship): if active == self.Active: return if active: self.whoActivated = ship self.plight.setColor(self.onColor) self.Active = active else: if ship == self.whoActivated: self.plight.setColor(self.offColor) self.Active = active def isActive(self): return self.Active #checks when ship gets inside the trigger zone of this pylon def insideTrigger(self, ship): if OdeUtil.collide(self.triggerGeom, ship.collGeom): # self.setActiveOn() #print str(ship.getShipType()) self.setActive(True, ship) self.usingTheForce( ship ) # print "moo" else: #self.setActiveOff() #print "muu" self.setActive(False, ship) #applies force to ship relative to the position of the pylon #while ship is inside trigger zone def usingTheForce(self, ship): #if (self.isActive()): #algoritmi ei toimi viela optimaalisesti pylonpos = self.getPos() shippos = ship.getPos() relativepos = [ (shippos[0] - pylonpos[0]) , (shippos[1] - pylonpos[1]) ] # if (shippos[0] - pylonpos[0]) < 0: # relativepos = [] ship.body.addForce( relativepos[0] * self.POWER, relativepos[1] * self.POWER, 0 ) # #checks if collision happens with one ship # #quite useless, but leaving it anyway # def checkCollision(self, ship): # if OdeUtil.collide(ship.collGeom, self.collGeom) and ship.hasBall(): # #ship.Ball.Restore(ship) # ship.dropBall( z = 300 ) # print str(ship.getShipType()) + " lost its balls! ONOES!!" #checks if collision happens with a ship in the list of ships #also checks if ship is inside the range of the pylon's power def checkCollisionList(self, shipList): for ship in shipList: self.insideTrigger( ship ) #self.usingTheForce( ship ) if OdeUtil.collide(ship.collGeom, self.collGeom) and ship.hasBall(): #ship.Ball.Restore(ship) self.game.collision2Sfx.play() pos = ship.getPos() ship.dropBall(x = pos[0], y = pos[1], z = 30, linX = ( (0-pos[0])/7 ), linY = ( (0-pos[1])/7 ), linZ = 2) print str(ship.getShipType()) + " lost its balls! NOOOO!"
class Ship_1(Ship): POWER = 100 SHIP_TYPE = "UFO" def __init__(self, game, color): #self.POWER = 100 self.game = game self.thrust = False self.thrustLeft = False self.thrustRight = False self.thrustBack = False self.rotation = 0 self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) #odespheregeom(... , size of hitbox sphere) self.collGeom = OdeSphereGeom( self.game.physicsSpace, 5) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('lautanen2.egg') model.reparentTo(self.visualNode) plight = PointLight('plight') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) plightNodePath = model.attachNewNode(plight) model.setLight(plightNodePath) # setMoreKeys in ship class = BAD IDEA #def setMoreKeys(self): # base.accept('arrow_down', self.thrustBackOn) # base.accept('arrow_down-up', self.thrustBackOff) def applyForces(self): if self.thrust: heading = self.getHeading() self.body.addForce( -math.sin( math.radians(heading) ) * self.POWER, math.cos( math.radians(heading) ) * self.POWER, 0 ) if self.thrustLeft: heading = self.getHeading() self.body.addForce( -math.sin( math.radians(heading) + math.pi/2 ) * self.POWER, math.cos( math.radians(heading) + math.pi/2 ) * self.POWER, 0 ) if self.thrustRight: heading = self.getHeading() self.body.addForce( -math.sin( math.radians(heading) - math.pi/2 ) * self.POWER, math.cos( math.radians(heading) - math.pi/2 ) * self.POWER, 0 ) if self.thrustBack: heading = self.getHeading() self.body.addForce( -math.sin( math.radians(heading) + math.pi ) * self.POWER, math.cos( math.radians(heading) + math.pi ) * self.POWER, 0 )
class Ship_2(Ship): ROTATING_SPEED = 1 MAX_ROTATE_SPEED = 3.0 SHIP_TYPE = "RAKETTI" def __init__(self, game, color): self.POWER = 100 self.game = game self.thrust = False self.thrustLeft = False self.thrustRight = False self.thrustBack = False self.rotation = 0 self.body = OdeBody(game.physicsWorld) self.mass = OdeMass() self.mass.setBox(10,1,1,1) self.body.setMass(self.mass) #odespheregeom(... , size of hitbox sphere) self.collGeom = OdeSphereGeom( self.game.physicsSpace, 2) self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) model = loader.loadModel('testipalikka.egg') model.reparentTo(self.visualNode) plight = PointLight('plight') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) plightNodePath = model.attachNewNode(plight) model.setLight(plightNodePath) def rotating(self): if self.thrustLeft: self.setRotation(self.ROTATING_SPEED) if self.thrustRight: self.setRotation(-(self.ROTATING_SPEED)) if not self.thrustRight and not self.thrustLeft: self.setRotation(0) def applyForces(self): if self.thrust: heading = self.getHeading() #addForce (x, y, z) self.body.addForce( -math.sin( math.radians(heading) ) * self.POWER, math.cos( math.radians(heading) ) * self.POWER, 0 ) # uncomment for backwards thrust (eli siis pakki) # if self.thrustBack: # heading = self.getHeading() # self.body.addForce( # math.sin( math.radians(heading) ) * self.POWER, # -math.cos( math.radians(heading) ) * self.POWER, # 0 # ) self.rotating()
class Pylon(StaticObject): def __init__(self, game, power = 10): self.game = game self.POWER = power self.Active = False self.collGeom = OdeSphereGeom( self.game.physicsSpace, 3) #self.collGeom.setBody(self.body) self.collGeom.setCategoryBits( BitMask32(0xffffffff) ) self.collGeom.setCollideBits( BitMask32(0xffffffff) ) self.visualNode = NodePath('Visual node') self.visualNode.reparentTo(render) self.model = loader.loadModel('AbsorbingPylon.egg') self.model.setScale(2) self.model.reparentTo(self.visualNode) #TODO: trigger geom #self.effectGeom = OdeSphereGeom( ) if (self.getPower() > 0): self.setColor( Vec4(1.0, 0.0, 0.0, 0.0) ) if (self.getPower() <= 0): self.setColor( Vec4(0.0, 0.0, 1.0, 0.0) ) def addToPylonList(self, pylonList): pylonList.append(self) def getPower(self): return self.POWER def setColor(self, color): plight = PointLight('plight') plight.setPoint( Point3(0.6, 0, 5) ) plight.setColor( color ) plight.setAttenuation( Vec3(0.5, 0.01, 0.01) ) plightNodePath = self.model.attachNewNode(plight) self.model.setLight(plightNodePath) def setActiveOn(self): self.Active = True def setActiveOff(self): self.Active = False def isActive(self): return self.Active #checks when ship gets inside the trigger zone of this pylon def insideTrigger(self, ship): pass # if OdeUtil.collide(ship.collGeom, self.effectGeom) # self.setActiveOn() #applies force to ship relative to the position of the pylon #while ship is inside trigger zone def usingTheForce(self, ship): if (self.isActive()): pass #checks if collision happens with one ship #quite useless, but leaving it anyway def checkCollision(self, ship): if OdeUtil.collide(ship.collGeom, self.collGeom) and ship.hasBall(): #ship.Ball.Restore(ship) ship.dropBall( z = 300 ) print str(ship.getShipType()) + " lost its balls! ONOES!!" #checks if collision happens with a ship in the list of ships def checkCollisionList(self, shipList): for ship in shipList: if OdeUtil.collide(ship.collGeom, self.collGeom) and ship.hasBall(): #ship.Ball.Restore(ship) ship.dropBall() print str(ship.getShipType()) + " lost its balls! NOOOO!"