def animate_female(self): female_stand = SpriteSheet('fe_stand.png') img1, img2 = [ female_stand.parse_sprite(f'fe-stand{v}.png') for v in range(1, 3) ] self.fe_stand_animation = [img1] * 5 + [img2] * 5 female_attack = SpriteSheet('fe_attack.png') attack_animation = [ female_attack.parse_sprite(f'fe-attack{v}.png') for v in range(1, 8) ] self.fe_attack_animation = attack_animation + [attack_animation[-1] ] * 3 female_attack = SpriteSheet('fe_attack2.png') img1, img2, img3 = [ female_attack.parse_sprite(f'fe-attack1{v}.png') for v in range(1, 4) ] self.fe_attack2_animation = [img1] + [img2] + [img3] * 6 + [img1] * 2 female_hurt = SpriteSheet('fe_hurt.png') img1, img2, img3, img4 = [ female_hurt.parse_sprite(f'fe-hurt{v}.png') for v in range(1, 5) ] self.fe_hurt_animation = [img1] + [img2] + [img3] + [img4] * 7 laser = SpriteSheet('hlaser.png') self.laser_animation = [ laser.parse_sprite(f'laser{v}.png') for v in range(1, 7) ]
def animate_dragon(self): dragon_stand = SpriteSheet('dr_stand.png') dr_stand = [ dragon_stand.parse_sprite(f'dr_stand{v}.png') for v in range(1, 5) ] dr_stand.extend(dr_stand) self.dr_stand_animation = dr_stand + [dr_stand[-2]] + [dr_stand[-1]] dragon_attack = SpriteSheet('dr_attack.png') attack_animation = [ dragon_attack.parse_sprite(f'dr_attack{v}.png') for v in range(1, 8) ] self.dr_attack_animation = attack_animation + [attack_animation[6]] + [ attack_animation[1] ] + [attack_animation[0]] dragon_hurt = SpriteSheet('dr_hurt.png') img1, img2, img3, img4 = [ dragon_hurt.parse_sprite(f'dr_hurt{v}.png') for v in range(1, 5) ] self.dr_hurt_animation = [img1] * 3 + [img2] * 2 + [img3] * 2 + [img4 ] * 3 dead = SpriteSheet('dr_dead.png') self.dr_dead_animation = [ dead.parse_sprite(f'dr_dead{v}.png') for v in range(1, 6) ]
class EyeLikeMob(pg.sprite.Sprite): """The eye-like alienship""" FRAMES = tuple(SpriteSheet(osp.join(SPRITESHEETS_FOLDER, "eyelike_mobsheet.png") ).get_image(((0, 31, 63, 95, 127, 175, 223, 270)[i], 0, (31, 32, 32, 32, 48, 48, 48, 48)[i], 80)) for i in range(8)) image = FRAMES[0] count = 0 duration = get_ticks() next_time = duration its_time = True radius = 50 def __init__(self, y): super(EyeLikeMob, self).__init__() self.frame_nbr = 0 self.rect = self.image.get_rect() self.rect.center = (WIDTH + 40, y) self.shield = 12 self.then = get_ticks() self.shoot_time = self.then self.switch = False EyeLikeMob.count += 1 def shoot(self, now): if now - self.shoot_time > 3500: self.shoot_time = now MobBullet(self.rect.center).add(game.all_sprites, game.mob_bullets) @classmethod def get(cls, now): if now - cls.next_time > 12000: cls.next_time = now if game.rand < 0.9: cls.count = 0 game.rand_pos = randrange(40, HEIGHT // 3) if now - cls.duration > 500 and cls.count < 12: cls.duration = now cls(game.rand_pos).add(game.all_sprites, game.mobs) def update(self): now = get_ticks() self.shoot(now) if now - self.then > 500: self.then = now self.frame_nbr += 1 if self.frame_nbr == 8: self.frame_nbr = 0 self.image = EyeLikeMob.FRAMES[self.frame_nbr] if self.rect.right < 0: self.kill() return self.rect.x -= game.dt / 3
class MobBullet(pg.sprite.Sprite): """The mob's bullets""" FRAMES = tuple(SpriteSheet(osp.join(SPRITESHEETS_FOLDER, "mobsheet.png") ).get_image_advanced( (x, 640, 32, 32), (16, 16)) for x in (0, 32, 64, 128)) image = FRAMES[0] MAX_SPEED = 6 radius = 5 def __init__(self, center): super(MobBullet, self).__init__() self.rect = self.image.get_rect() self.pos = vec(center) self.vel = (game.player.rect.center - self.pos).normalize() * MobBullet.MAX_SPEED self.acc = vec(0, 0) self.rect.center = center self.center = center self.frame_nbr = 0 self.shield = 5 self.then = get_ticks() def seek(self, target): desired = (target - self.pos).normalize() * MobBullet.MAX_SPEED steer = desired - self.vel if steer.length() > 0.4: steer.scale_to_length(0.4) return steer def update(self): now = get_ticks() if now - self.then < 20: return self.then = now self.frame_nbr += 1 if self.frame_nbr == 4: self.frame_nbr = 0 self.acc = vec(0, 0) self.vel += self.acc if self.vel.length() > MobBullet.MAX_SPEED: self.vel.scale_to_length(MobBullet.MAX_SPEED) self.pos += self.vel * game.dt / 10 if not (0 <= self.pos.x <= WIDTH and 0 <= self.pos.y <= HEIGHT): self.kill() self.image = MobBullet.FRAMES[self.frame_nbr] self.rect.center = self.pos
class Explosion(pg.sprite.Sprite): """A class for all types of explosions""" explosion_sheet = SpriteSheet(osp.join(SPRITESHEETS_FOLDER, "explsheet.png")) METADATA = { "x": tuple(j * 100 for i in range(8) for j in range(9)), "y": tuple(i * 100 for i in range(8) for j in range(9)), "width": 100, "height": 100 } def __init__(self, center, size): super(Explosion, self).__init__() self.image = self.explosion_sheet.get_image_advanced((0, 0, 100, 100), size) self.rect = self.image.get_rect() self.rect.center = center self.size = size self.frame_nbr = 0 self.then = get_ticks() def update(self): now = get_ticks() if now - self.then < 1: return self.then = now self.frame_nbr += 6 if self.frame_nbr == len(Explosion.METADATA["x"]): self.kill() return center = self.rect.center self.image = Explosion.explosion_sheet.get_image_advanced(( Explosion.METADATA["x"][self.frame_nbr], Explosion.METADATA["y"][self.frame_nbr], 100, 100 ), self.size) self.rect = self.image.get_rect() self.rect.center = center
class RedMob(pg.sprite.Sprite): """The elongted red alienship""" image = SpriteSheet(osp.join(IMAGES_FOLDER, "mobs", "redmob.png") ).get_image_advanced(size=(58, 100)) count = 0 duration = get_ticks() next_time = duration its_time = False MAX_SPEED = 10 radius = 40 def __init__(self, x, y): super(RedMob, self).__init__() self.rect = self.image.get_rect() self.pos = vec(x, y) self.vel = vec(0, RedMob.MAX_SPEED) self.acc = vec(0, 10) self.rect.center = self.pos self.shield = 10 self.right = True self.c = 0 now = get_ticks() self.shoot_time = now self.dtime = now self.then = now RedMob.count += 1 def shoot(self, now): if now - self.shoot_time > 3000: self.shoot_time = now MobBullet(self.rect.center).add(game.all_sprites, game.mob_bullets) @classmethod def get(cls, now): if now - cls.duration > 8000: cls.duration = now cls.its_time = True if now - cls.next_time > 200 and cls.its_time: cls.next_time = now cls(500, -200).add(game.all_sprites, game.mobs) if cls.count > 5: cls.count = 0 cls.its_time = False def update(self): now = get_ticks() self.shoot(now) if now - self.then > 300: self.then = now self.c = (self.c + 5) % 360 self.acc.x = cos(self.c) * RedMob.MAX_SPEED - 10 if self.rect.top > HEIGHT or self.rect.left > WIDTH or self.rect.right < 0: self.kill() return if now - self.dtime > 2000: self.dtime = now self.right = not self.right self.vel += self.acc if self.vel.length() > RedMob.MAX_SPEED: self.vel.scale_to_length(RedMob.MAX_SPEED) self.pos += self.vel * game.dt / 10 self.rect.center = self.pos
class GreyMob(pg.sprite.Sprite): """elongated grey alienship""" image = SpriteSheet(osp.join(IMAGES_FOLDER, "mobs", "greymob.png") ).get_image_advanced(size=(61, 92)) count = 0 duration = get_ticks() next_time = duration its_time = True MAX_SPEED = 10 APPROACH_RADIUS = 100 STEER_FORCE = 2 radius = 50 def __init__(self, x, y): super(GreyMob, self).__init__() self.rect = self.image.get_rect() self.x = x self.y = y + 200 self.pos = vec(x, y) self.vel = vec(0, GreyMob.MAX_SPEED) self.acc = vec(0, 0) self.rect.center = self.pos self.shield = 17 self.right = True now = get_ticks() self.shoot_time = now self.dtime = now GreyMob.count += 1 def shoot(self, now): if now - self.shoot_time > 3000: self.shoot_time = now MobBullet(self.rect.center).add(game.all_sprites, game.mob_bullets) def seek_with_approach(self, target): desired = target - self.pos dist = desired.length() desired.normalize_ip() if dist < GreyMob.APPROACH_RADIUS: desired *= dist / GreyMob.APPROACH_RADIUS * GreyMob.MAX_SPEED else: desired *= GreyMob.MAX_SPEED steer = desired - self.vel if steer.length() > GreyMob.STEER_FORCE: steer.scale_to_length(GreyMob.STEER_FORCE) return steer @classmethod def get(cls, now): if now - cls.duration > 10000: cls.duration = now cls.its_time = True if now - cls.next_time > 500 and cls.its_time: cls.next_time = now cls(200, -50).add(game.all_sprites, game.mobs) if cls.count > 5: cls.count = 0 cls.its_time = False def update(self): now = get_ticks() self.shoot(now) if not ((self.x, self.y) - self.pos).length() == 0: self.acc = self.seek_with_approach((self.x, self.y)) if now - self.dtime > 2000: self.dtime = now self.y += 400 if self.rect.top > HEIGHT or self.rect.left > WIDTH or self.rect.right < 0: self.kill() return if self.right: self.x += 100 self.right = False else: self.x -= 100 self.right = True self.vel += self.acc if self.vel.length() > GreyMob.MAX_SPEED: self.vel.scale_to_length(GreyMob.MAX_SPEED) self.pos += self.vel * game.dt / 10 self.rect.center = self.pos
class RoundMob(pg.sprite.Sprite): """The round alienship""" FRAMES = tuple(tuple(SpriteSheet(osp.join(SPRITESHEETS_FOLDER, "mobsheet.png") ).get_image( ((0, 95, 190, 285, 385, 480, 575)[i], y, (95, 95, 95, 100, 95, 95, 95)[i], 90)) for i in range(7)) for y in (45, 270, 496, 718)) next_time = get_ticks() MAX_SPEED = 10 STEER_FORCE = 0.2 APPROACH_RADIUS = 100 radius = 50 def __init__(self): super(RoundMob, self).__init__() start_pt = (-50, WIDTH + 50)[randrange(2)] self.ch = randrange(4) self.x = start_pt self.y = randrange(100, HEIGHT // 2) self.image = RoundMob.FRAMES[self.ch][0] self.rect = self.image.get_rect() self.pos = vec(start_pt, self.y) self.vel = vec(-RoundMob.MAX_SPEED, 0) self.acc = vec(0, 0) self.rect.center = self.pos self.frame_nbr = 0 self.shield = 300 self.then = get_ticks() self.shoot_time = self.then self.switch = start_pt == WIDTH + 50 def shoot(self, now): if now - self.shoot_time > 2500: self.shoot_time = now if randrange(2) == 0: MobMissile(self.rect.center).add(game.all_sprites, game.mobs) else: MobBullet(self.rect.center).add(game.all_sprites, game.mob_bullets) def seek_with_approach(self, target): desired = target - self.pos dist = desired.length() desired.normalize_ip() if dist < RoundMob.APPROACH_RADIUS: desired *= dist / RoundMob.APPROACH_RADIUS * RoundMob.MAX_SPEED else: desired *= RoundMob.MAX_SPEED steer = desired - self.vel if steer.length() > RoundMob.STEER_FORCE: steer.scale_to_length(RoundMob.STEER_FORCE) return steer @classmethod def get(cls, now): if now - cls.next_time > 6000: cls.next_time = now if game.rand > 0.6: cls().add(game.all_sprites, game.mobs) def update(self): now = get_ticks() self.shoot(now) if now - self.then > 500: self.then = now self.frame_nbr += 1 if self.frame_nbr == 7: self.frame_nbr = 0 self.image = RoundMob.FRAMES[self.ch][self.frame_nbr] if self.x < (WIDTH - 100) // 2: self.switch = False elif self.x > (WIDTH + 100) // 2: self.switch = True if self.switch: self.x -= game.dt / 10 else: self.x += game.dt / 10 if (vec(self.x, self.y) - self.pos).length(): self.acc = self.seek_with_approach((self.x, self.y)) self.vel += self.acc self.pos += self.vel self.rect.center = self.pos
pg.init() # set width and height relative to the device dimensions info = pg.display.Info() WIDTH, HEIGHT = info.current_w * 3 // 4, info.current_h * 4 // 5 # the game screen screen = pg.display.set_mode((WIDTH, HEIGHT), pg.constants.DOUBLEBUF) # disable alpha for speedier blits screen.set_alpha(None) # the game clock clock = pg.time.Clock() # set the title of the window pg.display.set_caption(CAPTION) # the ship spritesheet shipsheet = SpriteSheet(osp.join(SPRITESHEETS_FOLDER, "shipsheet.png")) # set the icon pg.display.set_icon(shipsheet.get_image((0, 192, 32, 50))) # restrict the allowed event for faster event handling pg.event.set_allowed(None) pg.event.set_allowed((pg.KEYDOWN, pg.KEYUP, pg.QUIT)) title_bar_rect = (0, 0, WIDTH, 30) mini_ship = shipsheet.get_image_advanced((0, 192, 32, 50), (20, 20)) mini_bomb = SpriteSheet(osp.join(IMAGES_FOLDER, "powerups", "bomb.png") ).get_image_advanced(size=(15, 25)) SOUNDS = {} for f in glob(osp.join(SOUNDS_FOLDER, "sound_tracks", "**")): sound = pg.mixer.Sound(f)
def __init__(self, screen): self.screen = screen self.status = SpriteSheet('heal_full.png') self.title = SpriteSheet('heroandfoe.png') self.animate_dragon() self.animate_female()