def automate(self): #control the enemy aircraft F = array([[0.8], [0], [0]]) #continuous thrust altitude = self.craft.get_altitude() if altitude < 100: avoid_crash = 150 / altitude #avoid ground collision else: avoid_crash = 0 stay_upright = expand_dims( cross(array([0, 1, 0]), self.model.theta[:, 1]), 1) * 0.3 #stay upright attack = ((self.craft.theta.T.dot( cross(self.model.theta[:, 0], mymath.unit(self.craft.pos - player.craft.pos).T).T) > 0) - 0.5).astype(float) * 0.5 #attack player tau = expand_dims( cross(array([0, avoid_crash, 0]), self.model.theta[:, 0]), 1) tau += stay_upright tau += attack self.craft.control(F, tau, self.max_a, self.max_alpha) #control the aircraft if self.model.theta[:, 0].T.dot( mymath.unit(player.craft.pos - self.craft.pos) ) > 0.9: #shoot if player is within 10 degrees of target reticle global bullets self.shoot()
def shoot(self, mode='bullet'): #shoot either a missile or bullet if mode == 'bullet': #shoot a bullet global bullets bullet = Bullet( copy(self.craft.pos + 140 * mymath.unit(self.craft.v)), copy( self.craft.theta.dot(array([[100], [0], [0]], dtype=float)))) bullets.append(bullet) elif mode == 'missile': #shoot a missile global missiles closest_aim = -1 #closest_aim tracks the distance from the target reticle to the enemy target = None for enemy in enemies + [ player ]: #find the aircraft which is the closest to the target reticle if enemy != self: aim = self.craft.theta[:, 0].dot( mymath.unit(enemy.craft.pos - self.craft.pos)) if closest_aim < aim and aim > 0.8: target = enemy closest_aim = aim missile = Missile(self.craft.pos + 60 * mymath.unit(self.craft.v), self.craft.v + 5 * mymath.unit(self.craft.v), target) missiles.append(missile)
def move(self): #move the missile global world if self.target != None: self.v += mymath.unit(self.target.craft.pos - self.pos) * 5 #thrust else: self.v += mymath.unit(self.v) * 5 self.v *= 0.9 #drag self.pos += self.v self.model.pos = self.pos side = cross(mymath.unit(self.v).T, array([[0, 1, 0] ])).T #a column vector for the side of the missile self.model.theta = hstack([ mymath.unit(self.v), -side, cross(mymath.unit(self.v).T, side.T).T ]) #rotate model if self.get_altitude() < 0: #hit ground v1 = ground_height(self.pos) v2 = ground_height(self.pos + array([[1], [0], [0]])) v3 = ground_height(self.pos + array([[0], [0], [1]])) normal = -expand_dims( mymath.unit( cross(array([1, v2 - v1, 0]), array([0, v3 - v1, 1]))), 1) self.hit(normal) if self.target == None and mymath.norm( player.craft.pos - self.pos ) > world.terrain.scale * world.terrain.distance: #despawn if too far global missiles try: missiles.remove(self) world.models.remove(self.model) except ValueError: pass
def shoot(self, mode='bullet'): #shoot if mode == 'bullet': global bullets bullet = Bullet( self.craft.pos + 140 * mymath.unit(self.craft.v), self.craft.theta.dot(array([[100], [0], [0]], dtype=float))) bullets.append(bullet) elif mode == 'missile': #enemy AI will not shoot missiles global missiles closest_aim = -1 #equivalent to the distance from the target reticle to the enemy target = None for enemy in enemies + [player]: if enemy != self: aim = self.craft.theta[0].dot( mymath.unit(enemy.craft.pos - self.craft.pos)) if closest_aim < aim and aim > 0.8: target = enemy closest_aim = aim missile = Missile(self.pos + 60 * mymath.unit(self.craft.v), self.craft.v + 5 * mymath.unit(self.craft.v), target) missiles.append(missile)
def move(self): #move bullet global world self.pos += self.v self.model.pos = self.pos if mymath.norm( player.craft.pos - self.pos ) > world.terrain.scale * world.terrain.distance: #despawn if too far try: bullets.remove(self) world.models.remove(self.model) except ValueError: pass elif self.get_altitude() < 0: #hit ground v1 = ground_height(self.pos) v2 = ground_height(self.pos + array([[1], [0], [0]])) v3 = ground_height(self.pos + array([[0], [0], [1]])) normal = -expand_dims( mymath.unit( cross(array([1, v2 - v1, 0]), array([0, v3 - v1, 1]))), 1) self.hit_ground(normal)
def update(self): #update the enemy self.craft.move() self.model.pos = self.craft.pos #move model self.model.theta = self.craft.theta #rotate model for obj in bullets + missiles: #test for bullet/missile collision closest_point = mymath.closestpoint(self.craft.pos, obj.pos, obj.pos - obj.v) if mymath.norm(self.craft.pos - closest_point) < 20: obj.pos = closest_point obj.hit(mymath.unit(closest_point - self.craft.pos)) if type(obj) == Bullet: self.craft.hp -= 1 elif type(obj) == Missile: self.craft.hp -= 20 if self.craft.hp <= 0: self.crash() if random.uniform() < 0.03 * (30 - self.craft.hp): #emit flames from damage global fragments fragments.append( Fragment('flames', self.craft.pos + (numpy.random.rand(3, 1) - 0.5) * 10, copy(self.craft.v / 2)))
def crashtest( self): #test for ground collision and bullet/missile collision h = ground_height(self.craft.pos) altitude = self.craft.pos[1][0] - h if altitude < 0: #test for ground collision self.crash() return True for obj in bullets + missiles: #test for bullet/missile collision closest_point = mymath.closestpoint(self.craft.pos, obj.pos, obj.pos - obj.v) if mymath.norm(self.craft.pos - closest_point) < 20: obj.pos = closest_point obj.hit(mymath.unit(obj.pos - self.craft.pos)) if type(obj) == Bullet: self.craft.hp -= 1 sounds['hit' + str(random.randint(1, 5))].play() elif type(obj) == Missile: self.craft.hp -= 20 sounds['explosion'].play() if self.craft.hp <= 0: self.crash() return True return False
def setup(window): #this runs once, at the beginning of a game global jet, helicopter, tester #this game only uses the jet jet = { 'linear drag': array([[0.01], [0.7], [0.3]]), 'angular drag': array([[0.15], [0.4], [0.6]]), 'linear accelleration': array([[0.2], [0.01], [0.04]]), 'angular accelleration': array([[0.015], [0.02], [0.1]]) } helicopter = { 'linear drag': array([[0.015], [0.04], [0.06]]), 'angular drag': array([[0.4], [0.7], [0.7]]), 'linear accelleration': array([[0], [0.1], [0.01]]), 'angular accelleration': array([[0.007], [0.1], [0.05]]) } tester = { 'linear drag': array([[0.01], [0.01], [0.01]]), 'angular drag': array([[0.4], [0.4], [0.4]]), 'linear accelleration': array([[0.2], [0.2], [0.2]]), 'angular accelleration': array([[0.007], [0.1], [0.1]]) } global world #the world contains all 3D graphics imformation except for the sky's colour. world = graphics.WorldModel() world.ambient = (0.1, 0.1, 0.4) #blue ambient light world.lights.append( graphics.Light(direction=mymath.unit(array([[3], [-1], [1]])), colour=(1, 1, 1))) #white angled sunlight terrain_scale = 300 #set up the terrain terrain_state = { 'detail': 4, 'max_dist': 8, 'smoothness': 2, 'max_height': 30, 'seed': random.randint(1, 1 << 15) } world.terrain = graphics.Terrain(graphics.Mountains, terrain_state, (0.9, 0.4, 0.2), terrain_scale, 6, world.ambient, world.lights) global background_colour, player background_colour = (120, 150, 255) #blue sky player = Player(jet) #create player global enemies, bullets, fragments, missiles #create lists containing other objects enemies = [] bullets = [] fragments = [] missiles = [] global F, tau, mousehold F = zeros([3, 1]) #supposed to go from -1 to 1 tau = zeros([3, 1]) #supposed to go from -1 to 1 mousehold = True #hold the mouse in the center global kills, framecounter, shooting, missiles_left kills = 0 #count the kills framecounter = 0 shooting = False missiles_left = 5 #the player is given 5 missiles global sounds #load all sounds sounds = { 'shooting': pygame.mixer.Sound(__file__[:-9] + '\\sounds\\shooting.wav'), 'explosion': pygame.mixer.Sound(__file__[:-9] + '\\sounds\\explosion.wav'), 'hit1': pygame.mixer.Sound(__file__[:-9] + '\\sounds\\hit1.wav'), 'hit2': pygame.mixer.Sound(__file__[:-9] + '\\sounds\\hit2.wav'), 'hit3': pygame.mixer.Sound(__file__[:-9] + '\\sounds\\hit3.wav'), 'hit4': pygame.mixer.Sound(__file__[:-9] + '\\sounds\\hit4.wav') }