def check_shoot(self): if self.frame % 200 > 150: self.direction = PVector(0, 0) if self.frame % 10 == 0: self.shoot() else: self.direction = PVector(0, -self.speed)
def __init__(self, player, angle, offset: PVector, bullet_level: int): super().__init__(player.bullets) self.player = player self.pos: PVector = player.pos + offset + player.direction.x * PVector( 3, 0) - PVector(3, 25) if player.id in {1, 2}: self.pos -= PVector(0, 10) else: if player.direction.x == 0: PlayerBullet.rotation = 0 else: PlayerBullet.rotation -= player.direction.x * 2 / player.weapon_level # Slowly rotate to the side if locust angle += PlayerBullet.rotation # print(adjusted_angle) self.direction = PVector(0, 0).project(radians(angle), PlayerBullet.speed) # print(self.direction) self.damage = 0 self.bullet_level = bullet_level self.orig_image: pygame.Surface = None self.init_image(player, angle) self.calc_damage(player)
def __init__(self, game, pos): super().__init__(game, pos) self.direction = PVector(0, -self.speed) self.image = GFX['e_secondlieutenant0'] self.rect = self.image.get_rect(center=tuple(self.pos)) self.hitbox.image = pygame.Surface((50, 180)) self.hitbox.rect = self.hitbox.image.get_rect(center=tuple(self.pos)) Exhaust(self, PVector(-10, 150), 3, False) Exhaust(self, PVector(0, 150), 3, False) Exhaust(self, PVector(10, 150), 3, False)
def startup(self, persist: dict): self.frame = 0 self.players.empty() self.enemies.empty() self.enemy_hitboxes.empty() self.enemy_bullets.empty() self.special_effects.empty() self.items.empty() self.boss = pygame.sprite.Sprite() self.done = False self.show_continue = False self.continue_time = 10 * 60 self.stage_transition = StageTransition(self.level_num) self.event_block = True self.stage_clear = True self.show_label_timer = 0 self.persist = persist self.controls = self.persist['controls'] # Guarantee will load self.coins = self.persist[ 'coins'] # no need to do try except because player had to insert coins to start # Player 1 if 'player_1' in self.persist: self.player_1 = self.persist['player_1'] if self.player_1.alive(): # If it's not just a base sprite # Reset position, hitbox and rect positions will be updated on next frame. self.player_1.pos = PVector(150, 700) self.player_1.game = self # Make sure it's spawning bullets, etc in the right game. self.players.add(self.player_1) # If the player just instantiated a character from select screen elif 'choice' in self.persist and self.persist['choice']['1p']: self.player_1 = Player(self, self.persist['choice']['1p'], PVector(150, 700)) else: # Just create a raw sprite for .alive() checking self.player_1 = pygame.sprite.Sprite() # Player 2 if 'player_2' in self.persist: self.player_2 = self.persist['player_2'] if self.player_2.alive(): # If it's not just a base sprite # Reset position, hitbox and rect positions will be updated on next frame. self.player_2.pos = PVector(150, 700) self.player_2.game = self # Make sure it's spawning bullets, etc in the right game. self.players.add(self.player_2) # If the player just instantiated a character from select screen elif 'choice' in self.persist and self.persist['choice']['2p']: self.player_2 = Player(self, self.persist['choice']['2p'], PVector(450, 700)) else: # Just create a raw sprite for .alive() checking self.player_2 = pygame.sprite.Sprite() self.set_music()
def check_death(self): if self.rect.top >= HEIGHT: self.kill() self.hitbox.kill() if self.health <= 0: EnemyExplosion(self.game, self) Coin(self.game, self.pos - PVector(10, 10)) Coin(self.game, self.pos + PVector(10, 10)) self.kill() self.hitbox.kill()
def __init__(self, game: Level, pos: PVector): super().__init__(game, pos) self.speed = Corporal0.speed self.health = 100 self.direction = PVector(0, Corporal0.speed) self.target = self.find_target_pos() self.image: pygame.Surface = pygame.transform.flip(GFX['e_corporal0'], False, True) self.rect: pygame.Rect = self.image.get_rect(center=tuple(self.pos)) # Pretty much the "main" portion of the ship excluding wings. self.hitbox.image: pygame.Surface = pygame.Surface((44, 50)) self.hitbox.rect: pygame.Rect = self.hitbox.image.get_rect(center=tuple(self.pos)) Exhaust(self, PVector(0, -90), 1, True)
def __init__(self, game, pos): super().__init__(game, pos) self.direction = PVector(0, self.speed) self.image = pygame.transform.flip(GFX['e_firstlieutenant0'], False, True) self.rect = self.image.get_rect(center=tuple(self.pos)) self.hitbox.image = pygame.Surface((80, 50)) self.hitbox.rect = self.hitbox.image.get_rect(center=tuple(self.pos)) self.circle_radius_delta = 0.5 self.initial_radius = 10 Exhaust(self, PVector(-24, -90), 1, True) Exhaust(self, PVector(24, -90), 1, True)
def __init__(self, game, pos): super().__init__(game, pos) self.direction = PVector(self.speed, 0) self.image = pygame.transform.flip(GFX['e_colonel0'], False, True) self.rect = self.image.get_rect(center=tuple(self.pos)) self.hitbox.image = pygame.Surface((128, 80)) self.hitbox.rect = self.hitbox.image.get_rect(center=tuple(self.pos)) Exhaust(self, PVector(-48, -63), 2, True) Exhaust(self, PVector(48, -63), 2, True) self.effect_img = cycle( [GFX['e_00{}{}'.format(x // 10, x % 10)] for x in range(1, 16)]) self.effect_image = next(self.effect_img) self.shooting = False self.weapon_of_choice = ColonelWeapon1
def determine_target(self): class default: #This is a default class that has all the variables needed to move the homing bullet upwards. class rect: center = (self.pos.x, -100) rect = rect @classmethod def alive(cls): return False self.target = min(self.game.enemy_hitboxes, key=lambda x: self.pos.dist_from(PVector.from_tuple(x.rect.center)), default=default) self.target_pos = PVector.from_tuple(self.target.rect.center)
def shoot(self): left_weapon = self.pos + PVector(-20, 40) right_weapon = self.pos + PVector(20, 40) if self.game.player_1.alive() and self.game.player_2.alive(): FirstLieutenantBullet(self.game, left_weapon, self.initial_radius, 0, self.game.player_1.pos.copy(), 15, self.circle_radius_delta) FirstLieutenantBullet(self.game, right_weapon, self.initial_radius, 0, self.game.player_2.pos.copy(), 15, self.circle_radius_delta) else: target = self.find_target_pos() FirstLieutenantBullet(self.game, left_weapon, self.initial_radius, 0, target, 15, self.circle_radius_delta) FirstLieutenantBullet(self.game, right_weapon, self.initial_radius, 0, target, 15, self.circle_radius_delta)
def __init__(self, game, weapon_level, pos): super().__init__(game.special_effects) i = game.frame % 50 + 1 # between 1 and 50 image = GFX[f'fire1_ {i//10}{i%10}'] # If number is less than 10, will have 0 at start size = (PVector.from_tuple(image.get_size()) / 10 * weapon_level).trunc() self.image = pygame.transform.scale(image, tuple(size)) self.rect = self.image.get_rect(center=tuple(pos))
def __init__(self, level_num): self.image = GFX[f'stage{level_num}'] self.particles = pygame.sprite.Group() for y in range(0, self.image.get_height(), 2): for x in range(0, self.image.get_width(), 2): if self.image.get_at((x, y))[3] != 0: # If there is non-transparent pixel at that location Particle(self, PVector(x + WIDTH // 2 - self.image.get_width() // 2, y + 200))
def player_choose_update(self): if self.player_1_choose: self.player_1_choose_time -= 1 if self.player_1_choose_time <= 0: self.player_1 = Player(self, self.choice['1p'], PVector(150, 700)) self.player_1_choose = False self.player_1_choose_time = 20 # Redundant since keyboard input also resets choose time if self.player_2_choose: self.player_2_choose_time -= 1 if self.player_2_choose_time <= 0: self.player_2 = Player(self, self.choice['2p'], PVector(450, 700)) self.player_2_choose = False self.player_2_choose_time = 20 # Redundant since keyboard input also resets choose time
def __init__(self, game, pos, size, angle, speed=5): super().__init__(game, pos) self.speed = speed self.images = cycle((pygame.transform.scale(x, (size, size)) for x in (GFX['e_bt3'], GFX['e_bt4']))) self.image = next(self.images) self.rect = self.image.get_rect(center=tuple(self.pos)) self.direction = PVector(0, 0).project(radians(angle), self.speed)
def __init__(self, offset, target, game, pos): # Offset is the offset from the angle to target. super().__init__(game, pos) self.angle = degrees(self.pos.angle_to(target)) + offset self.direction = PVector(0, 0).project(radians(self.angle), self.speed) self.image = pygame.transform.rotate(GFX['e_bt101'], self.angle - 90) self.rect = self.image.get_rect(center=tuple(self.pos))
def __init__(self, game, pos): super().__init__(game, pos) self.angle = randint(-110, -70) self.speed = randint(5, 10) self.image = pygame.transform.scale(GFX['ebt3'], (self.size, self.size)) self.rect = self.image.get_rect(center=tuple(self.pos)) self.direction = PVector(0, 0).project(radians(self.angle), self.speed)
def test_find_target_pos(self): class Player: def __init__(self, pos): self.pos = pos def alive(self): return True class Game: def __init__(self, pos1, pos2): self.player_1 = Player(pos1) self.player_2 = Player(pos2) self.enemies = [] self.enemy_hitboxes = [] g = Game(PVector(150, 700), PVector(450, 700)) e = Enemy(g, [600, 0]) assert e.find_target_pos() == g.player_2.pos
def check_death(self): if self.rect.top >= HEIGHT: self.kill() self.hitbox.kill() if self.health <= 0: EnemyExplosion(self.game, self) for i in range(3): Coin(self.game, self.pos + PVector(randint(-20, 20), randint(-20, 20))) self.kill() self.hitbox.kill()
def update_img(self): self.target = self.find_target_pos() angle = self.pos.angle_to(self.target) # radians self.bullet_pos = self.pos.project(angle, self.radius) rot_ang = degrees(angle) + 90 self.image = self.orig_image.copy() o_dim = PVector.from_tuple(self.turret_image.get_size()) rot_turret_image = pygame.transform.rotate(self.turret_image.copy(), rot_ang) n_dim = PVector.from_tuple(rot_turret_image.get_size()) top_left_adjust = (n_dim - o_dim) / 2 # explanation: when we rotate an image, new padding will be automatically added to fit the new dimensions. # Pygame blits images using top left. # This means the original "center" will be moved to somewhere that's not the center. # To be precise, it will be shifted (n.width-o.width)/2 pixels right, # since "extra" padding is added to the right and the left extra space. # It will also be shifted the same value down. Therefore we shift the center back. self.image.blit(rot_turret_image, tuple(-top_left_adjust)) self.image.blit(self.gun_image, (0, 0))
def update(self, *args): self.frame += 1 if self.frame > 90: self.kill() else: orig_image = GFX[f'explosion_100{self.frame//10}{self.frame%10}'] dimensions = PVector.from_tuple(orig_image.get_size()) self.image = pygame.transform.scale( orig_image, tuple((dimensions * self.ratio).trunc())) self.rect = self.image.get_rect(center=tuple(self.pos))
def __init__(self, game, pos): super().__init__(game, pos) self.direction = PVector(0, self.speed) self.image = pygame.transform.flip(GFX['e_captain0'], False, True) self.rect = self.image.get_rect(center=tuple(self.pos)) self.hitbox.image = pygame.Surface((60, 60)) self.hitbox.rect = self.hitbox.image.get_rect(center=tuple(self.pos)) self.effect_img = cycle( [GFX['e_00{}{}'.format(x // 10, x % 10)] for x in range(1, 16)]) self.effect_image = next(self.effect_img)
def __init__(self, transition, target_pos: PVector, ): super().__init__(transition.particles) self.target_pos = target_pos self.speed = PVector(randint(1, 10) * choice([-1, 1]), randint(1, 10) * choice([-1, 1])) self.pos = self.target_pos - self.speed * self.frames_to_group self.image = GFX['particle'] self.rect = self.image.get_rect(center=tuple(self.pos)) self.frame = 0
def __init__(self, game: Level, pos): super().__init__(game, pos) # print("spawned powerup") f = self.game.frame % 4 self.direction: PVector = PVector(copysign(1, f % 3 - 1), copysign(1, f // 2 - 1)) * self.speed # this results in (-1,-1) (1,-1) (1,1) (-1,1) * speed for 0-3, effectively "randomizing" the direction self.images = cycle([GFX[f'power{x}'] for x in range(1, 7)]) self.image: pygame.Surface = next(self.images) self.rect = self.image.get_rect(center=tuple(self.pos)) self.frame = 0
def check_death(self): if self.rect.bottom <= 0: self.kill() self.hitbox.kill() if self.health <= 0: EnemyExplosion(self.game, self) for _ in range(7): Coin(self.game, self.pos + PVector(randint(-25, 25), randint(-90, 90))) self.kill() self.hitbox.kill()
def move(self): if self.direction.x * self.direction.y in {-1, 1}: self.direction *= sqrt(0.5) # diagonal movement self.pos += self.direction * self.speed self.rect = self.image.get_rect(center=tuple(self.pos)) oob = self.rect.clamp(SCREENRECT) if oob != self.rect: # If we have to move the rectangle to keep it within screen boundaries # self.direction.x = 0 # Stop moving to the side self.rect = oob self.pos = PVector.from_tuple(oob.center)
def check_death(self): if self.rect.top >= 800: self.kill() self.hitbox.kill() if self.health <= 0: EnemyExplosion(self.game, self) for _ in range(9): Coin(self.game, self.pos + PVector(randint(-40, 40), randint(-25, 25))) self.kill() self.hitbox.kill()
def check_death(self): if self.frame >= 2000: Emerge2(self.game, self.pos) self.kill() self.hitbox.kill() if self.health <= 0: EnemyExplosion(self.game, self) for _ in range(9): Coin(self.game, self.pos + PVector(randint(-60, 60), randint(-40, 40))) self.kill() self.hitbox.kill()
def __init__(self, enemy, pos): SecondLieutenantBullet(enemy.game, pos + PVector(-43, 90), 180) SecondLieutenantBullet(enemy.game, pos + PVector(-43, 30), 180) SecondLieutenantBullet(enemy.game, pos + PVector(-43, -40), 180) SecondLieutenantBullet(enemy.game, pos + PVector(43, 90), 0) SecondLieutenantBullet(enemy.game, pos + PVector(43, 30), 0) SecondLieutenantBullet(enemy.game, pos + PVector(43, -40), 0)
def __init__(self, game, pos, angle, target): super().__init__(game, pos) self.circle_center = pos self.circle_radius = 0 self.target = target angle_to_target = self.circle_center.angle_to(self.target) self.direction = PVector(0, 0).project(angle_to_target, self.speed) self.angle = radians(angle) # In radians for math purposes self.pos = self.circle_center.project(self.angle, self.circle_radius) self.images = cycle([GFX['e_bt5'], GFX['e_bt6']]) self.image: pygame.Surface = next(self.images) self.rect: pygame.Rect = self.image.get_rect(center=tuple(self.pos))
def keep_exploding(self): self.explosion_frame += 1 if self.explosion_frame < 20: self.image = self.explosion_anim[self.explosion_frame // 2] self.rect = self.image.get_rect(center=tuple(self.pos)) elif 20 <= self.explosion_frame < self.explosion_time: self.image = GFX['name_blank'] # Transparent blank image else: self.explosion_frame = 0 self.lives -= 1 self.weapon_level = 1 Powerup(self.game, self.pos + PVector(0, -100)) if self.lives > 0: self.invincible = True self.explosion = False self.pos = PVector(150, 700) if self.id in {1, 3} else PVector( 450, 700) # Must be changed immediately otherwise Powerup will be collected next tick self.rect.center = tuple(self.pos) self.bomb_num = 3 else: self.kill()