Spaces:
Sleeping
Sleeping
| import sys, os | |
| sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..") | |
| import argparse | |
| from typing import Dict | |
| from game.pygame_base import PygameBase | |
| import logging | |
| import threading | |
| import time | |
| import pygame, random | |
| from utils.config import Config | |
| from utils.game_utils import capture | |
| from utils.dict_utils import get_with_warning | |
| from game.flappybird.settings import get_settings | |
| game_path = './game/flappybird/' | |
| # pygame.mixer.pre_init(frequency = 44100, size = 16, channels = 1, buffer = 512) | |
| # pygame.init() | |
| config = Config() | |
| class FlappyBirdGame(PygameBase): | |
| def __init__( | |
| self, | |
| output_dir, | |
| ): | |
| super(FlappyBirdGame, self).__init__(output_dir, "Flappy Bird") | |
| self.screen = pygame.display.set_mode((576,1024)) | |
| self.game_font = pygame.font.Font(os.path.join(game_path, '04B_19.ttf'), 40) | |
| self.bg_surface = pygame.image.load(game_path + 'assets/background-day.png').convert() | |
| self.bg_surface = pygame.transform.scale2x(self.bg_surface) | |
| self.floor_surface = pygame.image.load(game_path + 'assets/base.png').convert() | |
| self.floor_surface = pygame.transform.scale2x(self.floor_surface) | |
| self.bird_downflap = pygame.transform.scale2x(pygame.image.load(game_path + 'assets/bluebird-downflap.png').convert_alpha()) | |
| self.bird_midflap = pygame.transform.scale2x(pygame.image.load(game_path + 'assets/bluebird-midflap.png').convert_alpha()) | |
| self.bird_upflap = pygame.transform.scale2x(pygame.image.load(game_path + 'assets/bluebird-upflap.png').convert_alpha()) | |
| self.bird_frames = [self.bird_downflap,self.bird_midflap,self.bird_upflap] | |
| self.bird_index = 0 | |
| self.bird_surface = self.bird_frames[self.bird_index] | |
| bird_center = (100,512) | |
| self.bird_rect = self.bird_surface.get_rect(center = bird_center) | |
| self.floor_x_pos = 0 | |
| self.pipe_surface = pygame.image.load(game_path + 'assets/pipe-green.png') | |
| self.pipe_surface = pygame.transform.scale2x(self.pipe_surface) | |
| self.pipe_list = [] | |
| self.bird_movement = 0 | |
| self.create_pipe_count = 100 | |
| self.bird_flip_count = 0 | |
| def draw_floor(self): | |
| self.screen.blit(self.floor_surface,(self.floor_x_pos,900)) | |
| self.screen.blit(self.floor_surface,(self.floor_x_pos + 576,900)) | |
| def set_level_config(self, level_config: Dict): | |
| self.current_level = self.level_config.get("level", 1) | |
| self.settings = get_settings(self.current_level) | |
| self.jump_height = get_with_warning(self.settings, "jump_height", 7) | |
| self.gravity = get_with_warning(self.settings, "gravity", 0.25) | |
| self.move_speed = get_with_warning(self.settings, "move_speed", 5) | |
| self.pipe_gap = get_with_warning(self.settings, "pipe_gap", 500) | |
| self.pipe_frequency = get_with_warning(self.settings, "pipe_frequency", 100) | |
| self.rotate = get_with_warning(self.settings, "rotate", True) | |
| self.valid_actions = get_with_warning(self.settings, "valid_actions", ["UP", "KEEP"]) | |
| self.sample_frames = get_with_warning(self.settings, "sample_frame", 3) | |
| def create_pipe(self): | |
| if not self.pipe_list: | |
| random_pipe_pos = random.randint(self.pipe_gap + 50, 850) | |
| else: | |
| # 获取上一个管道的位置 | |
| last_pipe_pos = self.pipe_list[-2]['rect'].midtop[1] | |
| # 确保新管道与上一个管道的差距不会太大 | |
| print("last_pipe_pos:", last_pipe_pos) | |
| min_pipe_pos = max(self.pipe_gap + 50, last_pipe_pos - 300) | |
| max_pipe_pos = min(850, last_pipe_pos + 300) | |
| print("min_pipe_pos:", min_pipe_pos, ", max_pipe_pos:", max_pipe_pos) | |
| random_pipe_pos = random.randint(min_pipe_pos, max_pipe_pos) | |
| bottom_pipe = {'rect': self.pipe_surface.get_rect(midtop=(700, random_pipe_pos)), 'counted': False} | |
| top_pipe = {'rect': self.pipe_surface.get_rect(midbottom=(700, random_pipe_pos - self.pipe_gap)), 'counted': False} | |
| return bottom_pipe, top_pipe | |
| def move_pipes(self, pipes): | |
| for pipe in pipes: | |
| pipe['rect'].centerx -= self.move_speed | |
| return pipes | |
| def draw_pipes(self, pipes): | |
| for idx, pipe in enumerate(pipes): | |
| if idx % 2 == 0: | |
| self.screen.blit(self.pipe_surface, pipe['rect']) | |
| else: | |
| flip_pipe = pygame.transform.flip(self.pipe_surface, False, True) | |
| self.screen.blit(flip_pipe, pipe['rect']) | |
| def remove_pipes(self, pipes): | |
| while pipes[0]['rect'].centerx <= -600: | |
| pipes.pop(0) | |
| pipes.pop(0) | |
| return pipes | |
| def check_collision(self, pipes): | |
| for pipe in pipes: | |
| if self.bird_rect.colliderect(pipe['rect']): | |
| return False | |
| if self.bird_rect.top <= -100 or self.bird_rect.bottom >= 900: | |
| return False | |
| return True | |
| def rotate_bird(self, bird, movement): | |
| # new_bird = pygame.transform.rotozoom(bird,-self.bird_movement * 3,1) | |
| new_bird = pygame.transform.rotozoom(bird,-movement * 3,1) | |
| return new_bird | |
| def bird_animation(self): | |
| new_bird = self.bird_frames[self.bird_index] | |
| new_bird_rect = new_bird.get_rect(center = (100, self.bird_rect.centery)) | |
| return new_bird,new_bird_rect | |
| def score_display(self, game_state): | |
| if game_state == 'main_game': | |
| score_surface = self.game_font.render(str(int(self.score)),True,(255,255,255)) | |
| score_rect = score_surface.get_rect(center = (288,100)) | |
| self.screen.blit(score_surface,score_rect) | |
| def get_score(self): | |
| return { | |
| "score" : self.score, # win or lose | |
| "frames" : len(self.game_frames), | |
| "valid rate" : len(self.game_frames) / ( len(self.game_frames) + self.invalid_action_count ), | |
| } | |
| def step(self, action, dt=None): | |
| self.screen.blit(self.bg_surface,(0,0)) | |
| if action == "UP": | |
| self.bird_movement = -self.jump_height | |
| elif action == "DOWN": | |
| self.bird_movement = self.jump_height | |
| elif action == "KEEP": | |
| self.bird_movement = 0 | |
| self.create_pipe_count += 1 | |
| if self.create_pipe_count >= self.pipe_frequency: | |
| self.create_pipe_count = 0 | |
| pipe_pair = self.create_pipe() | |
| self.pipe_list.extend(pipe_pair) | |
| self.bird_flip_count += 1 | |
| if self.bird_flip_count >= 6: | |
| self.bird_flip_count = 0 | |
| if self.bird_index < 2: | |
| self.bird_index += 1 | |
| else: | |
| self.bird_index = 0 | |
| self.bird_surface, self.bird_rect = self.bird_animation() | |
| # Bird | |
| if self.rotate: | |
| rotated_bird = self.rotate_bird(self.bird_surface, self.bird_movement) | |
| else: | |
| rotated_bird = self.rotate_bird(self.bird_surface, 0) | |
| self.bird_rect.centery += self.bird_movement | |
| self.screen.blit(rotated_bird, self.bird_rect) | |
| game_active = self.check_collision(self.pipe_list) | |
| if not game_active: | |
| self.over = True | |
| return True, "Game over!" | |
| if self.gravity == 0: | |
| self.bird_movement = 0 | |
| else: | |
| self.bird_movement += self.gravity | |
| # Pipes | |
| self.pipe_list = self.move_pipes(self.pipe_list) | |
| self.pipe_list = self.remove_pipes(self.pipe_list) | |
| self.draw_pipes(self.pipe_list) | |
| for pipe in self.pipe_list: | |
| if pipe['rect'].centerx <= 100 and not pipe['counted']: | |
| self.score += 0.5 | |
| pipe['counted'] = True | |
| self.score_display('main_game') | |
| # screen.blit(game_over_surface,game_over_rect) | |
| # high_score = update_score(score,high_score) | |
| # score_display('game_over') | |
| # Floor | |
| self.floor_x_pos -= 1 | |
| self.draw_floor() | |
| if self.floor_x_pos <= -576: | |
| self.floor_x_pos = 0 | |
| pygame.display.update() | |
| return False, "Game continues." | |
| def human_mode_action(self, event): | |
| action = None | |
| if event.type == pygame.KEYDOWN: | |
| if event.key == pygame.K_UP or event.key == pygame.K_SPACE: | |
| action = "UP" | |
| elif event.key == pygame.K_DOWN: | |
| action = "DOWN" | |
| elif event.key == pygame.K_LCTRL: | |
| action = "KEEP" | |
| elif event.key == pygame.K_LEFT: | |
| action = "NONE" | |
| return action | |
| if __name__ == '__main__': | |
| print(os.path.dirname(os.path.abspath(__file__)) + "/..") | |
| parser = argparse.ArgumentParser() | |
| # parser.add_argument("--levelConfig", type=str, default="./config/level_config/flappybirdgame/level1.json", help="The path to the level config file.") | |
| parser.add_argument("--level", type=int, default=1, help="The level of the game.") | |
| args = parser.parse_args() | |
| level = args.level | |
| levelConfig = f"./config/level_config/flappybirdgame/level{level}.json" | |
| config.load_level_config(levelConfig) | |
| flappybird_game = FlappyBirdGame("") | |
| flappybird_game.run(None, human_mode=True) | |
| # python game/flappybird_game.py --level 4 | |