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 | |