class Player(Mob): def __init__(self): (max_health, health_states, radius, body, MAX_VEL, ACC, gun_type, bg_radius, superpower) = PLAYER_PARAMS[(0, 0)] Mob.__init__(self, name='Player', x=c.SCR_W2, y=c.SCR_H2, health=0, health_states=health_states, bubbles=0, radius=radius, body=body, gun_type=gun_type) self.pos = np.array([self.x, self.y], dtype=float) self.MAX_VEL = MAX_VEL self.vel_x, self.vel_y = 0, 0 self.ACC = ACC self.acc_x, self.acc_y = 0, 0 self.MU = c.MU self.mu_x, self.mu_y = 0, 0 self.moving_left = False self.moving_right = False self.moving_up = False self.moving_down = False self.superpower = superpower_factory(superpower) self.is_shooting = False self.bullets = [] self.homing_bullets = [] self.shurikens = [] self.is_max_tank = False self.max_health = max_health self.bg_radius = bg_radius self.armor_on = [False] self.invisible = [False] self.state = (0, 0) self.states_history = [(0, 0)] def handler(self, e_type, key): if key == pg.K_a: self.moving_left = True if e_type == pg.KEYDOWN else False elif key == pg.K_d: self.moving_right = True if e_type == pg.KEYDOWN else False elif key == pg.K_w: self.moving_up = True if e_type == pg.KEYDOWN else False elif key == pg.K_s: self.moving_down = True if e_type == pg.KEYDOWN else False elif key == 1: self.is_shooting = False if e_type == pg.MOUSEBUTTONUP else True elif key == pg.K_SPACE: self.superpower.on = True if e_type == pg.KEYDOWN else False def move(self, dx, dy): self.pos += np.array([dx, dy]) def stop(self): self.vel_x = 0 self.vel_y = 0 def is_ready_to_upgrade(self): return not self.is_max_tank and self.health >= self.max_health def get_mouse_pos(self): """ :return: Mouse position relative to the center of the room """ pos = pg.mouse.get_pos() mouse_pos = self.pos + np.array((pos[0] - c.SCR_W2, pos[1] - c.SCR_H2)) return mouse_pos def rotate_body(self, dt): if self.moving_left == self.moving_right: if self.moving_up and not self.moving_down: dest_angle = 0.5 * pi elif not self.moving_up and self.moving_down: dest_angle = -0.5 * pi else: dest_angle = None elif self.moving_left and not self.moving_right: if self.moving_up and not self.moving_down: dest_angle = 0.75 * pi elif not self.moving_up and self.moving_down: dest_angle = -0.75 * pi else: dest_angle = pi else: if self.moving_up and not self.moving_down: dest_angle = 0.25 * pi elif not self.moving_up and self.moving_down: dest_angle = -0.25 * pi else: dest_angle = 0 if dest_angle is not None: self.body.rotate(dest_angle, dt) def update_body(self, dt): mouse_pos = self.get_mouse_pos() self.rotate_body(dt) self.body.update(*self.pos, dt, mouse_pos) def setup(self, max_health, health_states, radius, body, MAX_VEL, ACC, gun_type, bg_radius, superpower): self.gun = guns_factory(gun_type) self.superpower = superpower_factory(superpower) self.max_health = max_health self.health = 0 self.health_states = health_states self.radius = radius self.body = Body(body) self.bg_radius = bg_radius self.MAX_VEL = MAX_VEL self.ACC = ACC self.armor_on = [False] self.invisible = [False] def collide_bullet(self, x, y): radius = self.bg_radius if self.armor_on[0] else self.radius return circle_collidepoint(*self.pos, radius, x, y) def collide_bubble(self, x, y): return circle_collidepoint(*self.pos, self.radius // 2, x, y) def in_latest_state(self): return self.state == self.states_history[-1] def handle_injure(self, damage): if not self.armor_on[0]: super().handle_injure(damage) def make_body_frozen(self): for i in range(-6, 0): self.body.circles[i].is_visible = True def make_body_unfrozen(self): for i in range(-6, 0): self.body.circles[i].is_visible = False def make_frozen(self): self.frost_time = 0 if not self.is_frozen: self.is_frozen = True self.MAX_VEL *= 0.2 self.ACC *= 0.2 self.make_body_frozen() def make_unfrozen(self): if self.is_frozen: self.is_frozen = False self.frost_time = 0 self.MAX_VEL *= 5 self.ACC *= 5 self.make_body_unfrozen() def set_transportation_vel(self, alpha, max_vel): self.vel_x = max_vel * cos(alpha) self.vel_y = -max_vel * sin(alpha) def clear_bullets(self): """ Method is called when player is transported to the next room. Deletes all player's bullets except orbiting shurikens. """ self.bullets = [] self.homing_bullets = [] needless_shurikens = [] index = 0 for shuriken in self.shurikens: if not shuriken.is_orbiting: needless_shurikens.append(index) index += 1 needless_shurikens.reverse() for index in needless_shurikens: self.shurikens.pop(index) def upgrade(self, new_state, state=None): self.shurikens = [] if new_state: self.states_history.append(state) self.state = state self.moving_left = False self.moving_right = False self.moving_up = False self.moving_down = False self.is_shooting = False else: self.state = self.states_history[self.state[0] + 1] self.setup(*PLAYER_PARAMS[self.state]) if new_state: self.is_shooting = False if self.state[0] == 5: self.is_max_tank = True if self.is_frozen: self.MAX_VEL *= 0.2 self.ACC *= 0.2 self.make_body_frozen() else: self.make_body_unfrozen() def downgrade(self): self.shurikens = [] if self.state[0] >= 1: self.is_max_tank = False self.state = self.states_history[self.state[0] - 1] self.setup(*PLAYER_PARAMS[self.state]) self.health = self.max_health - 1 self.change_body() if self.is_frozen: self.MAX_VEL *= 0.2 self.ACC *= 0.2 self.make_body_frozen() else: self.make_body_unfrozen() else: self.health = 0 def get_next_states(self): i, j = self.state[0], self.state[1] if self.state == (2, 3): return (i + 1, j), (i + 1, j + 1), (i + 1, j + 2) if i == 1 or self.state == (4, 0): return (i + 1, j), (i + 1, j + 1) elif self.state == (4, 5): return (i + 1, j - 1), (i + 1, j) elif self.state == (3, 5): return (i + 1, j - 2), (i + 1, j - 1), (i + 1, j) elif j == 0 or self.state == (0, 0): return (i + 1, j), (i + 1, j + 1), (i + 1, j + 2) return (i + 1, j - 1), (i + 1, j), (i + 1, j + 1) def delete_needless_bullets(self): """ Deletes bullets that hit a target (or are outside the room) from the list. """ needless_bullets = [] index = 0 for bullet in self.bullets: if bullet.is_outside() or bullet.hit_the_target: needless_bullets.append(index) index += 1 needless_bullets.reverse() for index in needless_bullets: self.bullets.pop(index) def delete_needless_homing_bullets(self, mobs, top_effects): """ Deletes homing bullets with health <= 0 (or if they hit a target) from the list. If there are no mobs in the room, deletes all homing bullets. Adds special effects in the places the needless homing bullets were. """ needless_bullets = [] index = 0 for bullet in self.homing_bullets: if not mobs or bullet.health <= 0 or bullet.hit_the_target: needless_bullets.append(index) if not bullet.hit_the_target: add_effect('RedHitCircle', top_effects, bullet.x, bullet.y) index += 1 needless_bullets.reverse() for index in needless_bullets: self.homing_bullets.pop(index) def delete_needless_shurikens(self): """ Deletes all shurikens that hit a target (or are outside the room and not orbiting) from the list. """ needless_shurikens = [] index = 0 for shuriken in self.shurikens: if not shuriken.is_orbiting and shuriken.is_outside( ) or shuriken.hit_the_target: needless_shurikens.append(index) index += 1 needless_shurikens.reverse() for index in needless_shurikens: self.shurikens.pop(index) def add_bullets(self, dt, sound_player, mobs): """ Adds new bullets generated by gun to the list. If there are new bullets, plays a "player_shot" sound. """ sound_player.reset() self.gun.update_time(dt) old_length = len(self.bullets) if self.is_shooting and not self.invisible[0]: target = self.get_mouse_pos() self.gun.append_bullets(*self.pos, target, self.bullets, self.body.body_angle) if self.gun.automatic and len(mobs): self.gun.append_bullets_auto(*self.pos, mobs, self.bullets, self.body.body_angle) if len(self.bullets) > old_length: sound_player.play_sound('player_bullet_shot') def update_bullets(self, dt, mobs, sound_player): self.add_bullets(dt, sound_player, mobs) fragments = [] for bullet in self.bullets: if bullet.frangible: params = [dt, fragments] else: params = [dt] bullet.update(*params) self.bullets.extend(fragments) self.delete_needless_bullets() def update_homing_bullets(self, dt, mobs, top_effects): target = (mobs[-1].x, mobs[-1].y) if len(mobs) else (0, 0) for bullet in self.homing_bullets: params = [dt, *target] bullet.update(*params) self.delete_needless_homing_bullets(mobs, top_effects) def update_shurikens(self, dt, mobs): for shuriken in self.shurikens: shuriken.update(dt, *self.pos, mobs) self.delete_needless_shurikens() def update_acc(self): if not self.moving_right ^ self.moving_left: self.acc_x = -copysign(1, self.vel_x) * self.MU if self.vel_x else 0 elif abs(self.vel_x) == self.MAX_VEL: self.acc_x = 0 else: self.acc_x = -self.ACC if self.moving_left else self.ACC if not self.moving_up ^ self.moving_down: self.acc_y = -copysign(1, self.vel_y) * self.MU if self.vel_y else 0 elif abs(self.vel_y) == self.MAX_VEL: self.acc_y = 0 else: self.acc_y = -self.ACC if self.moving_up else self.ACC def update_pos(self, dt): dx = self.vel_x * dt + self.acc_x * dt * dt / 2 dy = self.vel_y * dt + self.acc_y * dt * dt / 2 self.move(dx, dy) def update_vel(self, dt): self.vel_x += self.acc_x * dt if self.vel_x * (self.vel_x - self.acc_x * dt) < 0: self.vel_x = 0 elif abs(self.vel_x) > self.MAX_VEL: self.vel_x = copysign(1, self.vel_x) * self.MAX_VEL self.vel_y += self.acc_y * dt if self.vel_y * (self.vel_y - self.acc_y * dt) < 0: self.vel_y = 0 elif abs(self.vel_y) > self.MAX_VEL: self.vel_y = copysign(1, self.vel_y) * self.MAX_VEL def update_superpower(self, dt, mobs, top_effects, bottom_effects, camera, transportation=False): params = [] if self.superpower.id == 1: params = [dt, self.armor_on, top_effects] elif self.superpower.id in [2, 9]: params = [dt, self.pos, self.bullets] elif self.superpower.id in [3, 4]: params = [dt, self.pos, mobs, top_effects, bottom_effects, camera] elif self.superpower.id == 5: params = [dt, self.pos, top_effects, camera] elif self.superpower.id == 6: params = [dt, self.invisible, self.body] elif self.superpower.id in [7, 8]: params = [dt, self.pos, self.homing_bullets, self.health, 0] elif self.superpower.id == 10: params = [dt, self.pos, self.shurikens] elif self.superpower.id == 11: params = [ dt, self.pos, self.homing_bullets, self.health, self.body.body_angle ] elif self.superpower.id == 12: params = [ dt, *self.pos, self.body.body_angle, self.get_mouse_pos(), self.bullets ] elif self.superpower.id == 13: params = [dt, *self.pos, self.get_mouse_pos(), self.bullets] elif self.superpower.id == 14: params = [dt, *self.pos, self.bullets] if not transportation or self.superpower.id in [6, 10]: self.superpower.update(*params) def update(self, dt, mobs, top_effects, bottom_effects, camera, sound_player): self.update_acc() self.update_pos(dt) self.update_vel(dt) self.update_superpower(dt, mobs, top_effects, bottom_effects, camera) self.update_body(dt) self.update_bullets(dt, mobs, sound_player) self.update_homing_bullets(dt, mobs, top_effects) self.update_shurikens(dt, mobs) self.update_frozen_state(dt) def draw(self, surface, dx, dy): for bullet in self.bullets: if not bullet.vel: bullet.draw(surface, dx, dy) self.body.draw(surface, dx, dy) for bullet in self.bullets: if bullet.vel: bullet.draw(surface, dx, dy) for bullet in self.homing_bullets: bullet.draw(surface, dx, dy) for shuriken in self.shurikens: shuriken.draw(surface, dx, dy)
while 1: pygame.time.delay(20) for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if(pygame.mouse.get_pressed()[0] and last_ball_done): ball = Body( pygame.mouse.get_pos(),base_ball_size,screen ) balls.append(ball) last_ball_done = False if(pygame.mouse.get_pressed()[0]): ball.enlarge() if(not (pygame.mouse.get_pressed()[0] or last_ball_done)): ball.finish(pygame.mouse.get_pos()) last_ball_done = True screen.fill(black) collisions(balls) for ball in balls: print(ball.forces) if (ball.done): ball.move() ball.draw() pygame.display.flip()
class StatsWindow: def __init__(self): self.captions = [] self.tank_data = None self.tank_name = None self.tank_desc = None self.player_bodies = PLAYER_BODIES self.tank_body = None def set_captions(self, language): pg.font.init() font_1 = pg.font.SysFont('Arial', 35, True) font_2 = pg.font.SysFont('Arial', 28, True) if language == 'English': captions = eng.ENG_STATSWINDOW_CAPTIONS else: captions = rus.RUS_STATSWINDOW_CAPTIONS self.captions.append(font_1.render(captions[0], True, WHITE)) self.captions.append(font_2.render(captions[1], True, WHITE)) self.captions.append(font_2.render(captions[2], True, WHITE)) def set_tank_data(self, language): if language == 'English': self.tank_data = eng.ENG_UPGRADE_TEXT else: self.tank_data = rus.RUS_UPGRADE_TEXT def set_language(self, language): self.set_captions(language) self.set_tank_data(language) def setup_tank_name(self, player_state): pg.font.init() font = pg.font.SysFont('Arial', 26, True) self.tank_name = font.render(self.tank_data[player_state][0], True, WHITE) def setup_tank_desc(self, player_state): self.tank_desc = (TextBox(self.tank_data[player_state][3], c.FONT_2, 20, False, WHITE, (120, 205), False), TextBox(self.tank_data[player_state][1], 'Arial', 22, True, WHITE, (120, 410), False), TextBox(self.tank_data[player_state][2], 'Arial', 22, True, WHITE, (430, 410), False), TextBox(self.tank_data[player_state][4], c.FONT_2, 20, False, WHITE, (120, 463), False), TextBox(self.tank_data[player_state][5], c.FONT_2, 20, False, WHITE, (430, 463), False)) def setup(self, player_state): self.setup_tank_name(player_state) self.setup_tank_desc(player_state) self.tank_body = Body(self.player_bodies[player_state]) def update(self, dt): self.tank_body.update(595, 260, dt, (605, 260)) def draw_captions(self, screen): screen.blit(self.captions[0], (320, 110)) screen.blit(self.captions[1], (120, 370)) screen.blit(self.captions[2], (430, 370)) def draw_tank_name(self, screen): screen.blit(self.tank_name, (120, 170)) def draw_tank_desc(self, screen): for text in self.tank_desc: text.draw(screen) @staticmethod def draw_player_background(screen): pg.draw.circle(screen, WHITE, (595, 260), 93) pg.draw.circle(screen, PAUSEMENU_PLAYER_BG, (595, 260), 89) def draw(self, screen): self.draw_captions(screen) self.draw_tank_name(screen) self.draw_tank_desc(screen) self.draw_player_background(screen) self.tank_body.draw(screen)
class Bubble: def __init__(self, x, y, alpha, gravity_r=0, type_marker=0): self.x = x self.y = y self.radius = data.BUBBLE_RADIUS[type_marker] self.health = data.BUBBLE_HEALTH[type_marker] self.vel = uniform(0.7, 1.7) * data.BUBBLE_MAX_VEL self.max_vel = data.BUBBLE_MAX_VEL self.acc = data.BUBBLE_ACC self.alpha = alpha self.gravity_r = gravity_r self.in_player_gravity = False self.body = Body(data.BUBBLE_BODY[type_marker]) self.body.randomise_body_scale() def is_on_screen(self, dx, dy): if -self.radius <= self.x-dx <= c.SCR_W+self.radius and \ -self.radius <= self.y-dy <= c.SCR_H+self.radius: return True return False def is_outside(self): return not circle_collidepoint(c.SCR_W2, c.SCR_H2, c.ROOM_RADIUS, self.x, self.y) def check_player_pos(self, player_x, player_y): if hypot(self.x - player_x, self.y - player_y) <= self.gravity_r: self.in_player_gravity = True self.acc = data.BUBBLE_ACC else: self.in_player_gravity = False def maximize_vel(self): self.vel = 2 * data.BUBBLE_MAX_VEL def go_to_player(self, x, y, dt): self.alpha = calculate_angle(self.x, self.y, x, y) dr = self.vel * dt + self.acc * dt * dt / 2 dist = hypot(self.x - x, self.y - y) if dr > dist: self.x = x self.y = y else: self.x += dr * cos(self.alpha) self.y -= dr * sin(self.alpha) self.vel += self.acc * dt if self.vel >= self.max_vel: self.vel = self.max_vel self.acc = 0 def slow_down(self, dt): self.acc = -data.BUBBLE_ACC dr = self.vel * dt + self.acc * dt * dt / 2 self.x += dr * cos(self.alpha) self.y -= dr * sin(self.alpha) dv = self.acc * dt if self.vel * (self.vel + dv) < 0: self.vel = 0 self.acc = 0 else: self.vel += dv def move(self, dx, dy): self.x += dx self.y += dy self.body.move(dx, dy) def update(self, x, y, dt): if self.vel or self.is_on_screen(x - c.SCR_W2, y - c.SCR_H2): self.check_player_pos(x, y) if self.in_player_gravity: self.go_to_player(x, y, dt) elif self.vel: self.slow_down(dt) self.body.update(self.x, self.y, dt) def draw(self, surface, dx=0, dy=0): if self.is_on_screen(dx, dy): self.body.draw(surface, dx, dy)
class Room: def __init__(self): """ List of bullets is made separately from list of mobs, because when mob is dead and deleted, its bullets should continue existing. 'new_mobs' is a temporary list of mobs, which is created to draw the mobs of room player is being transported to. When player is transported, self.mobs = self.new_mobs.copy(). Text is a text surface of room, containing rules of the game. Screen rectangle is used to check if mob's rectangle collides with it. If yes, then a mob is drawn. Gravity radius is a radius of circle around player, in which bubbles gravitate to player. 'Bottom effects' are drawn below player, mobs, bubbles and bullets, other effects are 'Top effects'. """ self.bubbles = [] self.mobs = [] self.new_mobs = [] self.bullets = [] self.homing_bullets = [] self.bottom_effects = [] self.top_effects = [] self.text = None self.setup_text('') self.screen_rect = pg.Rect(0, 0, c.SCR_W, c.SCR_H) self.gravity_radius = 150 self.boss_skeleton = Body(BOSS_SKELETON_BODY) self.boss_skeleton.update(c.SCR_W2, c.SCR_H2, 0, (0, 0), 0.5 * pi) self.boss_position_marker = 0 def reset(self, new_game=False): """ Method is called when a new game is started or a new room is visited. Resets all room data. """ self.bubbles = [] self.bullets = [] self.homing_bullets = [] self.top_effects = [] self.bottom_effects = [] self.mobs = [] if new_game else self.new_mobs.copy() self.new_mobs = [] if new_game: self.boss_position_marker = 0 @staticmethod def encode_mobs(mobs): """ :param mobs: list of objects (mobs) :return: dictionary [mob_name] -> number of mobs """ mobs_dict = defaultdict(int) for mob in mobs: mobs_dict[mob.name] += 1 return mobs_dict @staticmethod def decode_mobs(mobs_dict): """ :param mobs_dict: dictionary [mob_name] -> number of mobs :return: list of objects (mobs) """ mobs = [] for mob_name in mobs_dict.keys(): for i in range(mobs_dict[mob_name]): mobs.append(m.mob_factory(mob_name)) return mobs def check_boss(self): if self.boss_position_marker in [1, 2]: self.boss_position_marker -= 1 for mob in self.new_mobs: if mob.name in ['BossLeg', 'BossHead', 'BossHand']: self.boss_position_marker = 2 break def setup_new_mobs(self, new_mobs): """ :param new_mobs: dictionary of new mobs, generated by Level Generator """ self.new_mobs = self.decode_mobs(new_mobs) self.check_boss() def setup_text(self, text): """ :param text: list of strings sets background room text, explaining the rules of the game """ self.text = TextBox(text, c.FONT_1, 47, True, WHITE, (400, 110)) def delete_needless_bullets(self): """ Method removes those bullets from list, that hit a target or are outside the room, and reduces the length of list to 100, if it is > 100. So the size of list becomes limited to avoid the situation of infinite filling the list. """ tmp_bullets = [] index = 0 for bullet in self.bullets: if bullet.is_outside() or bullet.hit_the_target: tmp_bullets.append(index) index += 1 tmp_bullets.reverse() for index in tmp_bullets: self.bullets.pop(index) while len(self.bullets) > 100: self.bullets.pop(0) def delete_dead_homing_bullets(self): """ Method deletes homing bullets with not positive health from list of homing bullets. """ dead_bullets = [] index = 0 for bullet in self.homing_bullets: if bullet.health <= 0 or bullet.hit_the_target: dead_bullets.append(index) index += 1 dead_bullets.reverse() for index in dead_bullets: self.homing_bullets.pop(index) def delete_needless_bubbles(self): """ removes those bubbles from list, which are outside the room, so that player can't eat them """ tmp_bubbles = [] for index in range(len(self.bubbles)): if self.bubbles[index].is_outside(): tmp_bubbles.append(index) tmp_bubbles.reverse() for index in tmp_bubbles: self.bubbles.pop(index) @staticmethod def delete_needless_effects(effects): """ removes those effects from the given list, which have stopped running """ tmp_effects = [] for index in range(len(effects)): if not effects[index].running: tmp_effects.append(index) tmp_effects.reverse() for index in tmp_effects: effects.pop(index) def delete_dead_mobs(self): """ Method deletes mobs with not positive health from list of mobs and replaces them with bubbles. """ dead_mobs = [] index = 0 for mob in self.mobs: if mob.health <= 0: dead_mobs.append(index) self.add_bubbles(mob.x, mob.y, mob.bubbles) index += 1 dead_mobs.reverse() for index in dead_mobs: self.mobs.pop(index) def update_bullets(self, dt): for bullet in self.bullets: bullet.update(dt) self.delete_needless_bullets() def update_homing_bullets(self, player_x, player_y, dt): for bullet in self.homing_bullets: bullet.update(dt, player_x, player_y) self.delete_dead_homing_bullets() def update_bubbles(self, x, y, dt): for bubble in self.bubbles: bubble.update(x, y, dt) self.delete_needless_bubbles() def update_effects(self, dt): for effect in self.top_effects: effect.update(dt) for effect in self.bottom_effects: effect.update(dt) self.delete_needless_effects(self.top_effects) self.delete_needless_effects(self.bottom_effects) def handle_bullet_explosion(self, x, y): """ Changes mobs' states according to their positions relative to the explosion, and adds appropriate effects. :param x: x-coord of bullet :param y: y-coord of bullet """ for mob in self.mobs: if hypot(x - mob.x, y - mob.y) <= 200: mob.health -= 20 mob.change_body() add_effect('BigHitLines', self.top_effects, mob.x, mob.y) add_effect('PowerfulExplosion', self.bottom_effects, x, y) add_effect('Flash', self.top_effects) def move_objects(self, offset): """ Method is called when the player is being transported to the next room. The objects of previous room become moved by the given offset to be drawn properly during player's transportation """ for bubble in self.bubbles: bubble.move(*offset) for mob in self.mobs: mob.move(*offset) for bullet in self.bullets: bullet.move(*offset) for bullet in self.homing_bullets: bullet.move(*offset) self.boss_skeleton.update(c.SCR_W2, c.SCR_H2, 0, (0, 0), 0.5 * pi) if self.boss_position_marker == 1: self.boss_skeleton.move(*offset) def setup_gravity(self, gravity_radius): """ Sets the new radius of player's gravitational field :param gravity_radius: radius of circle, in which the player's gravity exists """ if self.mobs: self.gravity_radius = gravity_radius for bubble in self.bubbles: bubble.gravity_r = gravity_radius def maximize_gravity(self): """ Method is called when all mobs in the room are dead. The radius of player's gravitational field is set equal to the diameter of room, so that every bubble starts gravitating to player regardless of his position in the room. Also speeds of bubbles are maximized to reach player faster. """ for bubble in self.bubbles: bubble.gravity_r = 2 * c.ROOM_RADIUS bubble.maximize_vel() def update_mobs(self, player_x, player_y, dt): generated_mobs = [] target = [player_x, player_y] for mob in self.mobs: mob.update(target, self.bullets, self.homing_bullets, generated_mobs, self.screen_rect, dt) self.mobs.extend(generated_mobs) self.delete_dead_mobs() def update_new_mobs(self, player_x, player_y, dt): """ Method updates positions and bodies of mobs of the room, player is being transported to. """ target = (player_x, player_y) for mob in self.new_mobs: mob.update_pos(dt) mob.gamma = mob.count_gamma() if mob.body_rect.colliderect(self.screen_rect): mob.update_body(dt, target) def set_screen_rect(self, pos): self.screen_rect.center = pos def game_is_over(self): return self.boss_position_marker == 2 and not self.mobs def update(self, player_pos, dt): self.set_screen_rect(player_pos) self.update_mobs(*player_pos, dt) self.update_bubbles(*player_pos, dt) self.update_bullets(dt) self.update_homing_bullets(*player_pos, dt) self.update_effects(dt) if not self.mobs: self.maximize_gravity() def add_bubbles(self, mob_x, mob_y, bubbles): """ :param mob_x: x coord of dead mob :param mob_y: y coord of dead mobs :param bubbles: list of the number of bubbles of 3 types: small, medium, big """ for type_marker in range(len(bubbles)): for i in range(bubbles[type_marker]): angle = uniform(0, 2 * pi) self.bubbles.append( Bubble(mob_x, mob_y, angle, self.gravity_radius, type_marker)) def draw_text(self, surface, dx, dy): self.text.draw(surface, dx, dy) def draw_bubbles(self, surface, dx, dy): for bubble in self.bubbles: bubble.draw(surface, dx, dy) def draw_mobs(self, surface, dx, dy): for mob in self.mobs: if mob.body_rect.colliderect(self.screen_rect): mob.body.draw(surface, dx, dy) def draw_new_mobs(self, surface, dx, dy): for mob in self.new_mobs: if mob.body_rect.colliderect(self.screen_rect): mob.body.draw(surface, dx, dy) def draw_boss_skeleton(self, surface, dx, dy): if self.boss_position_marker: self.boss_skeleton.draw(surface, dx, dy) def draw_bullets(self, surface, dx, dy): for bullet in self.bullets: bullet.draw(surface, dx, dy) for bullet in self.homing_bullets: bullet.draw(surface, dx, dy) def draw_top_effects(self, surface, dx, dy): for effect in self.top_effects: effect.draw(surface, dx, dy) def draw_bottom_effects(self, surface, dx, dy): for effect in self.bottom_effects: effect.draw(surface, dx, dy)