class GameScene(Scene): def _start(self): """ Init and start new game scene :return: None """ self.tileset = self.manager.get_image("tileset.png") self.main_theme_music = self.manager.get_music("main-theme.ogg") self.explosion_sound = self.manager.get_sound("boom.ogg") self.width, self.height = pygame.display.get_surface().get_size() self.track = Track() self.obstacle = Obstacle(self.track) self.player = Player(self.track) self.player.attach() self.explosion_sprite_size = 192 self.explosion_speed = 4 self.explosion = Animation(self.manager.get_image("explosion.png"), self.explosion_sprite_size, self.explosion_sprite_size, self.explosion_speed) self.is_explosion_started = False self.settings = Settings() self.font = pygame.font.SysFont("Monospace", 40, bold=False, italic=False) self.calculate_tile_size() self.make_threads() def make_threads(self): """ Start threads to change game state :return: None """ threading.Thread(target=self.update_track).start() threading.Thread(target=self.update_move).start() if self.settings['music']: self.main_theme_music.play() def update_track(self): """ Updating track for next game state :return: None """ while not self.is_end(): if not self.obstacle.wait: self.obstacle.attach() self.obstacle.wait = OBSTACLE_WAIT_FOR_NEXT if not self.obstacle.wait else self.obstacle.wait - 1 if self.player.is_dead: ScoreScene.save(self.player.score) self.is_explosion_started = True self.player.detach() self.explosion.start() if self.settings['music']: self.explosion_sound.play() break self.player.detach() self.track.move() self.player.attach() self.player.score += 1 if self.player.score % (SPEED_INCREASE_SCORE * self.track.level) == 0: self.track.speed += 1 if self.player.score % (LEVEL_INCREASE_SCORE * self.track.level) == 0: self.track.level += 1 self.player.lives_count = int(self.player.lives_count * PLAYER_LIVES_INCREASE) self.track.speed = self.track.level track_sleep_time = TRACK_MOVE_SLEEP_TIME / self.track.get_speed() time.sleep(track_sleep_time) def update_move(self): """ Update player move, handles player position on track :return: None """ while not self.is_end(): if self.player.is_dead: break self.player.move() time.sleep(PLAYER_MOVE_SLEEP_TIME) def _event(self, event): """ Make event handle :param event: any occurred event :return: None """ for e in event.get(): if e.type == pygame.KEYDOWN: if e.key == pygame.K_p: self.set_next_scene("pause") self.the_end() elif e.key == pygame.K_ESCAPE: ScoreScene.save(self.player.score) self.set_next_scene("menu") self.the_end() elif e.key == pygame.K_LEFT: self.player.direction = "left" self.player.move() elif e.key == pygame.K_RIGHT: self.player.direction = "right" self.player.move() elif e.key == pygame.K_UP: self.track.speed += 1 elif e.key == pygame.K_DOWN: self.track.speed -= 1 elif e.type == pygame.KEYUP: self.player.direction = None def _update(self, dt): """ Update scene by time :param dt: time interval pass from previous call :return: None """ if self.is_explosion_started: self.explosion.update(dt) if not self.explosion.is_start() and self.player.is_dead: self.set_next_scene("game_over") self.the_end() def _draw(self, dt): """ Redraw game by current status :param dt: time interval pass from previous call :return: None """ self.display.fill(BACKGROUND_COLOR) self.draw_field() self.draw_score() if self.explosion.is_start(): player_center = [ x - int(self.explosion_sprite_size / 2) for x in self.player.get_center(self.tile_size) ] self.display.blit(self.explosion.sprite, player_center, self.explosion.get_coords()) def the_end(self): self.main_theme_music.stop() super().the_end() def calculate_tile_size(self): field_width = self.width / 2 field_height = self.height tile_height = field_height / self.track.tiles_y tile_width = field_width / self.track.tiles_x self.tile_size = int( tile_width if tile_height > tile_width else tile_height) self.scaled_tile = pygame.transform.scale( self.tileset, (self.tile_size * TILES_COUNT, self.tile_size)) def draw_field(self): margin = 1 for x in range(self.track.tiles_x): for y in range(self.track.tiles_y): # Draw tile in (x,y) # get rect() area; select tile from tileset destination = Rect(x * self.tile_size, y * self.tile_size, self.tile_size, self.tile_size) src = Rect(self.track.tiles[x][y] * self.tile_size, 0, self.tile_size - margin, self.tile_size - margin) self.display.blit(self.scaled_tile, destination, src) def draw_score(self): x = self.width / 2 + self.tile_size y = self.tile_size self.display.blit( self.font.render("Счёт: " + str(self.player.score), True, (0, 0, 0)), (x, y)) self.display.blit( self.font.render("Скорость: " + str(self.track.speed), True, (0, 0, 0)), (x, y * 2)) self.display.blit( self.font.render("Жизней: " + str(self.player.lives_count), True, (0, 0, 0)), (x, y * 3)) self.display.blit( self.font.render("Уровень: " + str(self.track.level), True, (0, 0, 0)), (x, y * 4))