class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) self.level = StatusWithText(self, 100, 580, 'Level: %d', 1) self.level_wait = 0 # StatusWithText encap self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) self.score_wait = 0 self.bomb_power = StatusWithText(self, 700, 20, 'Power: %d%%', BOMB_FULL_POWER) self.bomb_wait = 0 self.elements.append(self.ship) self.enemies = [] self.bullets = [] # strategy pattern self.enemy_creation_strategies = [ (0.2, StarEnemyGenerationStrategy()), (1.0, EdgeEnemyGenerationStrategy()) ] # CoR pattern self.init_key_handlers() # canvas configure self.canvas.configure(bg="darkgray") for item in [self.level, self.score, self.bomb_power]: self.canvas.itemconfigure(item.label_text.canvas_object_id, fill="white") def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) ### START: bomb improvement ### def bomb(self): if self.bomb_power.value == BOMB_FULL_POWER: self.bomb_power.value = 0 self.create_bomb() self.process_bomb_destruction() def create_bomb(self): self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS ) self.after(200, lambda: self.canvas.delete(self.bomb_canvas_id)) def process_bomb_destruction(self): for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True ### END: bomb improvement ### def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: self.score.value += 1 self.score_wait = 0 def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power.value != BOMB_FULL_POWER): self.bomb_power.value += 1 self.bomb_wait = 0 def update_level(self): self.level_wait += 1 if self.level_wait >= LEVEL_WAIT: self.level.value += 1 self.level_wait = 0 # add more enemies if self.level.value % 20 == 0: self.enemy_creation_strategies.append((0.2, StarEnemyGenerationStrategy())) self.enemy_creation_strategies.append((1.0, EdgeEnemyGenerationStrategy())) def create_enemies(self): p = random() for prob, strategy in self.enemy_creation_strategies: if p < prob: enemies = strategy.generate(self, self.ship) break for e in enemies: self.add_enemy(e) def pre_update(self): # raise more enemies creation chance by level if random() < 0.05 * self.level.value: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() # ship edge collision def process_ship_edge_collision(self): w, h = CANVAS_WIDTH, CANVAS_HEIGHT x, y = self.ship.x, self.ship.y if not (0 <= x <= w and 0 <= y <= h): self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() self.process_ship_enemy_collision() self.process_ship_edge_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power() self.update_level() # CoR pattern def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler(self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler
class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) self.score_wait = 0 self.level = 1 self.level_text = Text(self, '', 100, 580) self.update_level_text() self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) self.bomb_power = BOMB_FULL_POWER self.bomb_wait = 0 self.bomb_power_text = Text(self, '', 700, 20) self.update_bomb_power_text() self.elements.append(self.ship) self.power_up = [] self.enemies = [] self.bullets = [] self.enemy_creation_strategies = [ StarEnemyGenerationStrategy(), EdgeEnemyGenerationStrategy(), GhostEnemyGenerationStrategy() ] self.init_key_handlers() def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler(self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler def create_enemies(self): p = random() for i in range(len(self.enemy_creation_strategies)): if p < 0.2: enemies = self.enemy_creation_strategies[0].generate( self, self.ship) break elif p < 0.5: enemies = self.enemy_creation_strategies[1].generate( self, self.ship) else: enemies = self.enemy_creation_strategies[2].generate( self, self.ship) for e in enemies: self.add_enemy(e) def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def powerup(self): self.create_power_up() self.after_function(15000, self.canvas.delete(self.bomb_canvas_id)) def create_power_up(self): pass def bomb(self): if self.bomb_power == BOMB_FULL_POWER: self.bomb_power = 0 self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) self.after(200, lambda: self.canvas.delete(self.bomb_canvas_id)) for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True def create_bomb(self): self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) def enemy_distroyed_by_bomb(self): for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True # def update_score_text(self): # self.score_text.set_text('Score: %d' % self.score) def update_bomb_power_text(self): self.bomb_power_text.set_text('Power: %d%%' % self.bomb_power) def update_level_text(self): self.level_text.set_text('Level: %d' % self.level) def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: # self.score += 1 self.score.value += 1 self.score_wait = 0 # self.update_score_text() def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power != BOMB_FULL_POWER): self.bomb_power += 1 self.bomb_wait = 0 self.update_bomb_power_text() # def create_enemy_star(self): # enemies = [] # # x = randint(100, CANVAS_WIDTH - 100) # y = randint(100, CANVAS_HEIGHT - 100) # # while vector_len(x - self.ship.x, y - self.ship.y) < 200: # x = randint(100, CANVAS_WIDTH - 100) # y = randint(100, CANVAS_HEIGHT - 100) # # for d in range(18): # dx, dy = direction_to_dxdy(d * 20) # enemy = Enemy(self, x, y, dx * ENEMY_BASE_SPEED, dy * ENEMY_BASE_SPEED) # enemies.append(enemy) # # return enemies # def create_enemy_from_edges(self): # x, y = random_edge_position() # vx, vy = normalize_vector(self.ship.x - x, self.ship.y - y) # # vx *= ENEMY_BASE_SPEED # vy *= ENEMY_BASE_SPEED # # enemy = Enemy(self, x, y, vx, vy) # return [enemy] def pre_update(self): if random() < 0.1: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() # self.process_ship_enemy_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power()
class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) self.level = 1 self.level_text = Text(self, '', 100, 580) self.update_level_text() self.score_wait = 0 self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) self.bomb_power = BOMB_FULL_POWER self.bomb_wait = 0 self.bomb_power_text = Text(self, '', 700, 20) self.update_bomb_power_text() self.elements.append(self.ship) self.enemies = [] self.bullets = [] self.enemy_creation_strategies = [(0.2, StarEnemyGenerationStrategy()), (1.0, EdgeEnemyGenerationStrategy())] self.init_key_handlers() def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def bomb(self): if self.bomb_power == BOMB_FULL_POWER: self.bomb_power = 0 self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) self.after(200, lambda: self.canvas.delete(self.bomb_canvas_id)) for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True self.update_bomb_power_text() def update_bomb_power_text(self): self.bomb_power_text.set_text('Power: %d%%' % self.bomb_power) def update_level_text(self): self.level_text.set_text('Level: %d' % self.level) def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: self.score.value += 1 self.score_wait = 0 def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power != BOMB_FULL_POWER): self.bomb_power += 1 self.bomb_wait = 0 self.update_bomb_power_text() def create_enemies(self): p = random() for prob, strategy in self.enemy_creation_strategies: if p < prob: enemies = strategy.generate(self, self.ship) break for e in enemies: self.add_enemy(e) def pre_update(self): if random() < 0.1: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() self.process_ship_enemy_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power() def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler(self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler
class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) self.level = StatusWithText(self, 100, 580, 'Level: %d', 0) self.score_wait = 0 self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) self.bomb_wait = 0 self.bomb_power = StatusWithText(self, 700, 20, 'Power: %d%%', 0) self.elements.append(self.ship) self.enemy_creation_strategies = [(0.2, StarEnemyGenerationStrategy()), (1.0, EdgeEnemyGenerationStrategy())] self.init_key_handlers() self.enemies = [] self.bullets = [] def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def bomb(self): if self.bomb_power.value == BOMB_FULL_POWER: self.bomb_power.value = 0 self.bomb_circle self.after(200, lambda: self.canvas.delete(self.bomb_canvas_id)) self.enemy_destroying def bomb_circle(self): self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) def enemy_destroying(self): for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: self.score_wait = 0 self.score.value += 1 def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power.value != BOMB_FULL_POWER): self.bomb_power.value += 1 self.bomb_wait = 0 def create_enemy_star(self): enemies = [] x = randint(100, CANVAS_WIDTH - 100) y = randint(100, CANVAS_HEIGHT - 100) while vector_len(x - self.ship.x, y - self.ship.y) < 200: x = randint(100, CANVAS_WIDTH - 100) y = randint(100, CANVAS_HEIGHT - 100) for d in range(18): dx, dy = direction_to_dxdy(d * 20) enemy = Enemy(self, x, y, dx * ENEMY_BASE_SPEED, dy * ENEMY_BASE_SPEED) enemies.append(enemy) return enemies def create_enemy_from_edges(self): x, y = random_edge_position() vx, vy = normalize_vector(self.ship.x - x, self.ship.y - y) vx *= ENEMY_BASE_SPEED vy *= ENEMY_BASE_SPEED enemy = Enemy(self, x, y, vx, vy) return [enemy] def create_enemies(self): p = random() for prob, strategy in self.enemy_creation_strategies: if p < prob: enemies = strategy.generate(self, self.ship) break for e in enemies: self.add_enemy(e) def pre_update(self): if random() < 0.1: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() self.process_ship_enemy_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power() def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler(self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler
class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) # self.level = 1 # self.level_text = Text(self, '', 100, 580) self.level = StatusWithText(self, 100, 580, 'Level: %d', 1) # self.update_level_text() self.score_wait = 0 # self.score = 0 # self.score_wait = 0 # self.score_text = Text(self, '', 100, 20) # self.update_score_text() self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) # self.bomb_power = BOMB_FULL_POWER self.bomb_wait = 0 # self.bomb_power_text = Text(self, '', 700, 20) self.bomb_power = StatusWithText(self, 700, 20, 'Power: %d', BOMB_FULL_POWER) # self.update_bomb_power_text() self.elements.append(self.ship) self.enemies = [] self.bullets = [] self.enemy_creation_strategies = [(0.2, StarEnemyGenerationStrategy()), (1.0, EdgeEnemyGenerationStrategy())] self.init_key_handlers() def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler(self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def bomb(self): if self.bomb_power.value == BOMB_FULL_POWER: self.bomb_power.value = 0 self.bomb_canvas_id = self.create_bomb() self.after(200, lambda: self.canvas.delete(self.bomb_canvas_id)) # for e in self.enemies: # if self.ship.distance_to(e) <= BOMB_RADIUS: # e.to_be_deleted = True self.destroy_enemie(len(self.enemies)) self.update_bomb_power_text() def create_bomb(self): self.canvas.create_oval(self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) def destroy_enemie(self, enemie_amount): if enemie_amount == 0: return if self.ship.distance_to(self.enemies[enemie_amount]) <= BOMB_RADIUS: self.enemies[enemie_amount].to_be_deleted = True self.destroy_enemie(enemie_amount - 1) # def update_score_text(self): # self.score_text.set_text('Score: %d' % self.score) def update_bomb_power_text(self): self.bomb_power_text.set_text('Power: %d%%' % self.bomb_power) def update_level_text(self): self.level_text.set_text('Level: %d' % self.level) def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: # self.score += 1 self.score.value += 1 self.score_wait = 0 # self.update_score_text() self.level.value = self.score.value // 10 + 1 def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power.value != BOMB_FULL_POWER): self.bomb_power.value += 1 self.bomb_wait = 0 # self.update_bomb_power_text() def create_enemy_star(self): enemies = [] x = randint(100, CANVAS_WIDTH - 100) y = randint(100, CANVAS_HEIGHT - 100) while vector_len(x - self.ship.x, y - self.ship.y) < 200: x = randint(100, CANVAS_WIDTH - 100) y = randint(100, CANVAS_HEIGHT - 100) for d in range(18): dx, dy = direction_to_dxdy(d * 20) enemy = Enemy(self, x, y, dx * ENEMY_BASE_SPEED, dy * ENEMY_BASE_SPEED) enemies.append(enemy) return enemies def create_enemy_from_edges(self): x, y = random_edge_position() vx, vy = normalize_vector(self.ship.x - x, self.ship.y - y) vx *= ENEMY_BASE_SPEED vy *= ENEMY_BASE_SPEED enemy = Enemy(self, x, y, vx, vy) return [enemy] def create_enemies(self): # if random() < 0.2: # enemies = self.create_enemy_star() # else: # enemies = self.create_enemy_from_edges() p = random() for prob, strategy in self.enemy_creation_strategies: if p < prob: enemies = strategy.generate(self, self.ship) break for e in enemies: self.add_enemy(e) def pre_update(self): if random() < 0.1: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() self.end_game() self.init_game() def process_collisions(self): self.process_bullet_enemy_collisions() # -- comment out this line to prevent ship collision self.process_ship_enemy_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power() # def on_key_pressed(self, event): # if event.keysym == 'Left': # self.ship.start_turn('LEFT') # elif event.keysym == 'Right': # self.ship.start_turn('RIGHT') # elif event.char == ' ': # self.ship.fire() # elif event.char.upper() == 'Z': # self.bomb() # def on_key_released(self, event): # if event.keysym == 'Left': # self.ship.stop_turn('LEFT') # elif event.keysym == 'Right': # self.ship.stop_turn('RIGHT') def end_game(self): for enemie in self.enemies: enemie.to_be_deleted = True self.enemies.clear() for b in self.bullets: b.to_be_deleted = True self.bullets.clear() for e in self.elements: e.to_be_deleted = True self.elements.clear() self.level.to_be_deleted = True self.score.to_be_deleted = True self.bomb_power.to_be_deleted = True
class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) # Debugging: Avoid death # This is a bad practice. GameApp should not access argument. # TODO: Refactor this self.is_debugging = len(sys.argv) >= 2 self.level = StatusWithText(self, 100, 580, 'Level: %d', 1) self.level_wait = 0 self.score_wait = 0 self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) self.bomb_power = StatusWithText(self, 700, 20, 'Power: %d%%', BOMB_FULL_POWER) self.bomb_canvas_id = None self.bomb_wait = 0 self.elements.append(self.ship) self.init_key_handlers() self.enemies = [] self.bullets = [] def create_strategies(self): return [ # Formula 0.2 + level/100 # Ex. Level 1 = 0.2 + 1/100 == 0.21 # Note: Floating point error is not taken in account (min(0.2 + (self.level.value / 100), 0.3), StarEnemyGenerationStrategy()), (1.0, EdgeEnemyGenerationStrategy()) ] def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler(self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def create_bomb(self): self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) def destroy_bomb(self): self.canvas.delete(self.bomb_canvas_id) def destroy_enemies_in_bomb(self): for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True def bomb(self): if self.bomb_power.value == BOMB_FULL_POWER: self.bomb_power.value = 0 self.create_bomb() self.after(200, self.destroy_bomb) self.destroy_enemies_in_bomb() def update_level(self): self.level_wait += 1 if self.level_wait >= LEVEL_WAIT: self.level.value += 1 self.level_wait = 0 def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: self.score.value += 1 self.score_wait = 0 def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power.value != BOMB_FULL_POWER): self.bomb_power.value += 1 self.bomb_wait = 0 def create_enemies(self): p = random() enemies = [] for prob, strategy in self.create_strategies(): if p < prob: enemies = strategy.generate(self, self.ship) break for e in enemies: self.add_enemy(e) def pre_update(self): if random() < 0.1: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() self.process_ship_enemy_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): if not self.is_debugging: self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power() if self.score.value % 20 == 0: self.update_level()
class SpaceGame(GameApp): def init_game(self): self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) self.level = 1 self.level_text = Text(self, '', 100, 580) self.update_level_text() self.score = 0 self.score_wait = 0 self.score_text = Text(self, '', 100, 20) self.update_score_text() self.bomb_power = BOMB_FULL_POWER self.bomb_wait = 0 self.bomb_power_text = Text(self, '', 700, 20) self.update_bomb_power_text() self.elements.append(self.ship) self.enemies = [] self.bullets = [] def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def bomb(self): if self.bomb_power == BOMB_FULL_POWER: self.bomb_power = 0 self.bomb_canvas_id = self.canvas.create_oval( self.ship.x - BOMB_RADIUS, self.ship.y - BOMB_RADIUS, self.ship.x + BOMB_RADIUS, self.ship.y + BOMB_RADIUS) self.after(200, lambda: self.canvas.delete(self.bomb_canvas_id)) for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: e.to_be_deleted = True self.update_bomb_power_text() def update_score_text(self): self.score_text.set_text('Score: %d' % self.score) def update_bomb_power_text(self): self.bomb_power_text.set_text('Power: %d%%' % self.bomb_power) def update_level_text(self): self.level_text.set_text('Level: %d' % self.level) def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: self.score += 1 self.score_wait = 0 self.update_score_text() def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power != BOMB_FULL_POWER): self.bomb_power += 1 self.bomb_wait = 0 self.update_bomb_power_text() def create_enemy_star(self): enemies = [] x = randint(100, CANVAS_WIDTH - 100) y = randint(100, CANVAS_HEIGHT - 100) while vector_len(x - self.ship.x, y - self.ship.y) < 200: x = randint(100, CANVAS_WIDTH - 100) y = randint(100, CANVAS_HEIGHT - 100) for d in range(18): dx, dy = direction_to_dxdy(d * 20) enemy = Enemy(self, x, y, dx * ENEMY_BASE_SPEED, dy * ENEMY_BASE_SPEED) enemies.append(enemy) return enemies def create_enemy_from_edges(self): x, y = random_edge_position() vx, vy = normalize_vector(self.ship.x - x, self.ship.y - y) vx *= ENEMY_BASE_SPEED vy *= ENEMY_BASE_SPEED enemy = Enemy(self, x, y, vx, vy) return [enemy] def create_enemies(self): if random() < 0.2: enemies = self.create_enemy_star() else: enemies = self.create_enemy_from_edges() for e in enemies: self.add_enemy(e) def pre_update(self): if random() < 0.1: self.create_enemies() def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() self.process_ship_enemy_collision() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power() def on_key_pressed(self, event): if event.keysym == 'Left': self.ship.start_turn('LEFT') elif event.keysym == 'Right': self.ship.start_turn('RIGHT') elif event.char == ' ': self.ship.fire() elif event.char.upper() == 'Z': self.bomb() def on_key_released(self, event): if event.keysym == 'Left': self.ship.stop_turn('LEFT') elif event.keysym == 'Right': self.ship.stop_turn('RIGHT')
class SpaceGame(GameApp): def init_game(self): self.background = Sprite( self, "images/background.png", CANVAS_WIDTH//2, CANVAS_HEIGHT//2) self.ship = Ship(self, CANVAS_WIDTH // 2, CANVAS_HEIGHT // 2) self.level = StatusWithText( self, 100, CANVAS_WIDTH-CANVAS_WIDTH*0.3, 'level: %d', 1) self.score_wait = 0 self.score = StatusWithText(self, 100, 20, 'Score: %d', 0) self.enemy_creation_strategies = [ [0.09, TieFighterEnemyGeration()], [0.03, StarEnemyGenerationStrategy()], [0.8, EdgeEnemyGenerationStrategy()] ] self.bomb_power = StatusWithText( self, CANVAS_WIDTH-100, 20, 'power: %d', BOMB_FULL_POWER) self.bomb_wait = 0 self.bomb_power_text = Text(self, '', 700, 20) self.health = StatusWithText( self, 700, CANVAS_WIDTH-CANVAS_WIDTH*0.3, 'health: %d', 4) self.elements.append(self.ship) self.boss = None self.turbo_power() self.enemies = [] self.bullets = [] self.init_key_handlers() def init_key_handlers(self): key_pressed_handler = ShipMovementKeyPressedHandler(self, self.ship) key_pressed_handler = BombKeyPressedHandler( self, self.ship, key_pressed_handler) self.key_pressed_handler = key_pressed_handler key_released_handler = ShipMovementKeyReleasedHandler(self, self.ship) self.key_released_handler = key_released_handler def deathstar_fire(self, delay=0): if self.boss.in_screen: self.boss.start_fire_dir_ship(self.ship.x, self.ship.y) if delay <= 200: self.after(100, lambda: self.deathstar_fire(delay+1)) else: delay = 0 self.after(5000, lambda: self.deathstar_fire(delay)) def level_stage(self): if self.score.value >= 400 and self.boss == None: self.boss = DeathStar(self) self.boss.come_in() self.deathstar_fire() if self.score.value >= 300: self.level.value = 5 self.enemy_creation_strategies[0][0] = 1 self.enemy_creation_strategies[1][0] = 0 self.enemy_creation_strategies[2][0] = 0 elif self.score.value >= 200: self.level.value = 4 self.enemy_creation_strategies[1][0] = 0.05 elif self.score.value >= 100: self.level.value = 3 self.enemy_creation_strategies[0][0] = 0.15 elif self.score.value >= 10: self.level.value = 2 self.enemy_creation_strategies[2][0] = 1 def create_enemies(self): p = random() for prob, strategy in self.enemy_creation_strategies: if p < prob: enemies = strategy.generate(self, self.ship) for e in enemies: self.add_enemy(e) def add_enemy(self, enemy): self.enemies.append(enemy) def add_bullet(self, bullet): if self.bomb_power.value > 0: self.bomb_power.value -= 1 self.bullets.append(bullet) def bullet_count(self): return len(self.bullets) def animate_bomb(self, i): if len(self.bomb_list) > 0: self.canvas.delete(self.bomb_list[-1]) if i == 10: return bomb = 0+BOMB_RADIUS*(i*0.1) self.bomb_list.append(self.canvas.create_oval( self.ship.x - bomb, self.ship.y - bomb, self.ship.x + bomb, self.ship.y + bomb, fill="#CCFFFF")) self.after(50, lambda: self.animate_bomb(i+1)) def bomb(self): if self.bomb_power.value == BOMB_FULL_POWER: self.bomb_power.value = 0 self.bomb_list = [] self.animate_bomb(0) for e in self.enemies: if self.ship.distance_to(e) <= BOMB_RADIUS: if isinstance(e, TieFighter): explode = Explode(self, e.x, e.y, 200) explode.update() else: explode = Explode(self, e.x, e.y, 50) explode.update() self.score.value += 1 e.to_be_deleted = True def update_level_text(self): self.level.value += 1 def update_score(self): self.score_wait += 1 if self.score_wait >= SCORE_WAIT: self.score.value += 1 self.score_wait = 0 def update_health(self): self.health_wait += 1 def update_bomb_power(self): self.bomb_wait += 1 if (self.bomb_wait >= BOMB_WAIT) and (self.bomb_power.value != BOMB_FULL_POWER): self.bomb_wait = 0 self.bomb_power.value += 1 def pre_update(self): if random() < 0.1: self.create_enemies() def turbo_power(self): if self.bomb_power.value < 10: self.ship.turbo = False if self.ship.turbo == True and self.bomb_power.value > 0: self.bomb_power.value -= 1 self.after(50, self.turbo_power) def process_bullet_enemy_collisions(self): for b in self.bullets: for e in self.enemies: if b.is_colliding_with_enemy(e): if isinstance(e, TieFighter): explode = Explode(self, e.x, e.y, 200) explode.update() else: explode = Explode(self, e.x, e.y, 50) explode.update() self.score.value += 1 b.to_be_deleted = True e.to_be_deleted = True def process_ship_enemy_collision(self): for e in self.enemies: if self.ship.is_colliding_with_enemy(e): self.health.value -= 1 self.ship_got_hit(50) e.to_be_deleted = True if self.health.value == 0 or isinstance(e, TieFighter): self.health.value = 0 self.ship_got_hit(200) self.ship.delete() self.stop_animation() def process_collisions(self): self.process_bullet_enemy_collisions() self.process_ship_enemy_collision() def ship_got_hit(self, size): explode = Explode(self, self.ship.x, self.ship.y, size) explode.update() def update_and_filter_deleted(self, elements): new_list = [] for e in elements: e.update() e.render() if e.to_be_deleted: e.delete() else: new_list.append(e) return new_list def post_update(self): self.process_collisions() self.level_stage() self.bullets = self.update_and_filter_deleted(self.bullets) self.enemies = self.update_and_filter_deleted(self.enemies) self.update_score() self.update_bomb_power()