import math, pyui, pygame from hoop.sim import SimObject from imprSim import ImprSimObject import constants, util, environment """ This class specifies the properties of Soldier objects """ class SoldierCategory: def __init__(self): self.mobile = 1 self.collide = 1 self.threshold = 0 self.life = 0 self.image = "spriteSrc/captain_jack.png" self.source = "spriteSrc/SourceSoldier.py" self.frictionConstantGround = 600 self.frictionConstantAir = 10 self.airControl = 0.4 self.motorForce = 120000 self.maxSpeed = self.motorForce/self.frictionConstantGround self.jumpSpeed = 210 self.health = 250 """ This class represents a soldier """ class Soldier(ImprSimObject): """ Creates a Soldier. """ def __init__(self, world, player): print 'Creating soldier' ImprSimObject.__init__(self, SoldierCategory()) self.gun = Gun(self) self.player = player self.world = world self.xForce = 0 self.yForce = 0 self.isGrounded = 0 self.testCollide = 0 self.mass = 80 self.health = self.category.health self.lastReload = 0 self.lastThrow = 0 self.removeCallback = self.onDeath self.radius = util.hypot(self.width, self.height) """ Updates this soldier. Will adjust velocity components according to the forces working on this soldier. """ def update(self, interval, world): if self.isGrounded: self.xForce -= self.category.frictionConstantGround*self.velocityX else: self.xForce -= self.category.frictionConstantAir*self.velocityX self.yForce -= self.category.frictionConstantAir*self.velocityY self.yForce -= constants.gravity*self.mass self.velocityX += self.xForce*interval/self.mass self.velocityY += self.yForce*interval/self.mass self.xForce = 0 self.yForce = 0 self.isAlive = ImprSimObject.update(self, interval, world) self.isGrounded = 0 self.testCollide = 1 world.grid.checkCollide(self, self.posX, self.posY-1, self.facing) #If this check invokes hit, this soldier will now be on the ground self.testCollide = 0 if (self.health < 0) and (constants.MODE == constants.MODE_SERVER): self.alive = 0 self.health = self.category.health return self.alive """ Updates a soldiers left going xForce based on the current motorForce """ def moveLeft(self): if self.isGrounded: self.xForce -= self.category.motorForce else: self.xForce -= self.category.motorForce * self.airControl() """ Updates a soldiers right going xForce based on the current motorForce """ def moveRight(self): if self.isGrounded: self.xForce += self.category.motorForce else: self.xForce += self.category.motorForce * self.airControl() """ When a player has been killed this method updates all relevent game info and plays the al importent "sound of death" """ def onDeath(self, world): print 'mein leben!' constants.SOUND_MEIN_LEBEN.play() self.health = self.category.health self.world.removeFromWorld(self.gun) self.world.addToWorld(Angel(self), self.posX, self.posY, 0) environment.Env.reportDeath(self) """ Used for adding bullets to the world based on a given reloadtimer. """ def fire(self): currentTime = pyui.readTimer() if currentTime - self.lastReload > self.gun.category.reloadTime: constants.SOUND_SHOOT.play() bullet = Bullet(self.gun.facing) self.world.addToWorld( bullet, self.posX+0.54*(self.radius+bullet.radius)*math.cos(self.gun.facing*math.pi/180), self.posY+0.54*(self.radius+bullet.radius)*math.sin(self.gun.facing*math.pi/180), 0) bullet.init() self.lastReload = currentTime """ The throw method generates a grenade object and adds it to the world. Also resets this Soldier's grenate reload timer. """ def throw(self): currentTime = pyui.readTimer() if currentTime - self.lastThrow > self.gun.category.throwTime: grenade = Grenade(self.gun.facing) self.world.addToWorld( grenade, self.posX+0.54*(self.radius+grenade.radius)*math.cos(self.gun.facing*math.pi/180), self.posY+0.54*(self.radius+grenade.radius)*math.sin(self.gun.facing*math.pi/180), 0) grenade.init() self.lastThrow = currentTime """ When a player is not grounded his onGround flag will be false. This enables the airControl degrading a players control """ def airControl(self): return self.category.airControl*(self.category.maxSpeed - abs(self.velocityX))/self.category.maxSpeed """ If this Soldier is located on the ground, this method will set the vertical velocity of this Soldier to jumpSpeed. """ def jump(self): if self.isGrounded: self.isGrounded = 0 self.velocityY = self.category.jumpSpeed """ This methods is called when hoop detects a collision involving this object. If this Soldier's testCollide flag is set to true, this method only updates whether or not this Soldier is situated on the ground. If thos Soldier collides with stationary object such as the edges of the world or a dirt type, either x-, y- or both components of the velocity is set to zero, depending on which directions the collision occurs in. """ def hit(self, other, newPosX, newPosY, newFacing): if self.testCollide: if isinstance(other, SimObject): if not other.category.mobile: #If it is immobile, we can stand on it self.isGrounded = 1 return 0 #We don't really collide elif other == 4: self.velocityY = 0 return 0 elif other == 3 or other == 1: self.velocityX = 0 return 0 elif isinstance(other, Dirt): (hitX, hitY) = self.findHitDirections(other, newPosX, newPosY, newFacing) #print 'dirt ',other.posX,' ',(self.hitX, self.hitY) if hitX: self.velocityX = 0 if hitY: self.velocityY = 0 return 1 """ This class contains static data for the Gun class """ class GunCategory: def __init__(self): self.mobile = 1 self.collide = 0 self.threshold = 0 self.life = 0 self.image = "spriteSrc/gun.png" self.source = "spriteSrc/SourceGun.py" self.reloadTime = 0.2 self.throwTime = 3 """ This object represents a gun. It will automatically follow the Soldier with whom it is associated. """ class Gun(SimObject): """ Creates a gun associated with argument Soldier """ def __init__(self, soldier): SimObject.__init__(self, GunCategory()) self.soldier = soldier """ Updates this Gun object by setting its (x,y) location and repainting. """ def update(self, interval, world): self.posX = self.soldier.posX self.posY = self.soldier.posY self.graphicsObject.setState(self.posX, self.posY, self.facing) return self.alive """ This class contains static data for the Bullet class """ class BulletCategory: def __init__(self): self.mobile = 1 self.collide = 1 self.threshold = 0 self.life = 0 self.image = "spriteSrc/normBullet.png" self.source = "spriteSrc/SourceBullet.py" self.frictionConstant = 0.2 self.mass = 2 """ This class represents a bullet, as may be fired by a soldier. """ class Bullet(SimObject): """ Initializes a Bullet to have a certain facing. Warning: adding this Bullet to the world will reset the facing. Use the init() method after adding to the world will properly set the facing and velocities of this Bullet. """ def __init__(self, facing): SimObject.__init__(self, BulletCategory()) self.speed = 700 self.angle = facing self.alive = 1 self.radius = util.hypot(self.width, self.height) """ Sets facing and velocity components. This is used to circumvent the hoop world overriding the settings when adding this Bullet to the world. """ def init(self): self.facing = self.angle self.velocityX = self.speed*math.cos(self.facing*math.pi/180) self.velocityY = self.speed*math.sin(self.facing*math.pi/180) """ Returns the amount of damage this bullet will deal if it hits now. Damage is proportional to mass times velocity squared. """ def damage(self): return self.category.mass * util.sumSquares(self.velocityX/100, self.velocityY/100) def hit(self, other, newPosX, newPosY, newFacing): if not isinstance(other, Bullet): self.alive = 0 if isinstance(other, Soldier): damage = self.damage() print 'Soldier hit for ',damage,' damage' other.health -= damage other.velocityX += self.velocityX*self.category.mass/other.mass other.velocityY += self.velocityY*self.category.mass/other.mass """ Updates this Bullet by applying gravitational forces. """ def update(self, interval, world): self.velocityX -= self.velocityX*self.category.frictionConstant*interval self.velocityY -= (self.velocityY*self.category.frictionConstant + constants.gravity)*interval return SimObject.update(self, interval, world) """ This class contains static data for the Grenade class """ class GrenadeCategory: def __init__(self): self.mobile = 1 self.collide = 1 self.threshold = 0 self.life = 1.8 self.image = "spriteSrc/grenade.png" self.source = "spriteSrc/SourceGrenade.py" self.frictionConstant = 0.2 self.mass = 8 """ Represents a Grenade which may be thrown by Soldiers. """ class Grenade(Bullet): def __init__(self, facing): SimObject.__init__(self, GrenadeCategory()) self.angle = facing self.radius = util.hypot(self.width, self.height) self.speed = 280 self.turnRate = 180 self.removeCallback = self.explode self.radius = util.hypot(self.width, self.height) def hit(self, other, newPosX, newPosY, newFacing): (hitX, hitY) = self.findHitDirections(other, newPosX, newPosY, newFacing) if hitX: self.velocityX = -self.velocityX*0.7 if hitY: self.velocityY = -self.velocityY*0.7 return 1 def explode(self, world): constants.SOUND_EXPLOSION.play() exp = Explosion() world.addToWorld(exp, self.posX, self.posY, 0) class ExplosionCategory: def __init__(self): self.mobile = 1 self.collide = 1 self.life = 0.8 self.threshold = 0 self.image = "spriteSrc/exp5.png" self.source = "spriteSrc/SourceExplosion.py" self.baseDamage = 550 self.rangeDamageFactor = 0.1 self.rangeBlowFactor = 10 class Explosion(SimObject): def __init__(self): SimObject.__init__(self, ExplosionCategory()) def damage(self, other): dx = other.posX-self.posX dy = other.posY-self.posY dist = util.hypot(dx, dy) other.velocityX += dx*self.category.rangeBlowFactor other.velocityY += dy*self.category.rangeBlowFactor return self.category.baseDamage/(1+dist*self.category.rangeDamageFactor) def hit(self, other, newPosX, newPosY, newFacing): if isinstance(other, Soldier): damage = self.damage(other) print 'Explosion damages for ',damage,' points' other.health -= damage return 0 class dirt1Category: def __init__(self): self.mobile = 0 self.collide = 1 self.life = 0 self.threshold = 0 self.image = "spriteSrc/texture1.png" self.source = "spriteSrc/SourceTexture1.py" class dirt2Category: def __init__(self): self.mobile = 0 self.collide = 1 self.life = 0 self.threshold = 0 self.image = "spriteSrc/texture2.png" self.source = "spriteSrc/SourceTexture2.py" class dirt3Category: def __init__(self): self.mobile = 0 self.collide = 1 self.life = 0 self.threshold = 0 self.image = "spriteSrc/texture3.png" self.source = "spriteSrc/SourceTexture3.py" class dirt4Category: def __init__(self): self.mobile = 0 self.collide = 1 self.life = 0 self.threshold = 0 self.image = "spriteSrc/texture4.png" self.source = "spriteSrc/SourceTexture4.py" class dirt5Category: def __init__(self): self.mobile = 0 self.collide = 1 self.life = 0 self.threshold = 0 self.image = "spriteSrc/texture5.png" self.source = "spriteSrc/SourceTexture5.py" class Dirt(SimObject): def __init__(self, dirtType): if dirtType == 1: SimObject.__init__(self, dirt1Category()) elif dirtType == 2: SimObject.__init__(self, dirt2Category()) elif dirtType == 3: SimObject.__init__(self, dirt3Category()) elif dirtType == 4: SimObject.__init__(self, dirt4Category()) elif dirtType == 5: SimObject.__init__(self, dirt5Category()) def hit(self, other, newPosX, newPosY, newFacing): return 0 class AngelCategory: def __init__(self): self.mobile = 1 self.collide = 0 self.life = 4 self.threshold = 0 self.image = "spriteSrc/angel.png" self.source = "spriteSrc/SourceAngel.py" class Angel(SimObject): def __init__(self, soldier): SimObject.__init__(self,AngelCategory()) self.soldier = soldier def update(self, interval, world): self.velocityY += constants.gravity*interval*0.3 SimObject.update(self,interval,world) if not self.alive: environment.Env.spawn(self.soldier) print 'spawn',(self.soldier.posX, self.soldier.posY) return self.alive