Pygame — Flappy Bird из Clear Code — Как мне сохранить высокий балл для следующего открытия игры и ее отображения?

#python #python-3.x

#python #python-3.x

Вопрос:

Я изучаю Pygame уже 3 дня. Теперь я хочу сохранить и загрузить высокий балл и отобразить его.

Это было очень сложной задачей для других движков, которые я использовал — сохранение и загрузка, то есть — но с чистой решимостью мне удалось сделать это на одном из моих основных движков.

Подойдет любая помощь.

Код:

 import pygame, sys, random

def draw_floor():
    screen.blit(floor_surface,(floor_x_pos,900))
    screen.blit(floor_surface,(floor_x_pos   576,900))

def create_pipe():
    random_pipe_pos = random.choice(pipe_height)
    bottom_pipe = pipe_surface.get_rect(midtop = (584,random_pipe_pos))
    top_pipe = pipe_surface.get_rect(midbottom = (584,random_pipe_pos -300))
    return bottom_pipe,top_pipe

def move_pipes(pipes):
    for pipe in pipes:
        pipe.centerx -= 5
    visible_pipes = [pipe for pipe in pipes if pipe.right > -50]
    return visible_pipes

def draw_pipes(pipes):
    for pipe in pipes:
        if pipe.bottom >= 1024:
            screen.blit(pipe_surface,pipe)
        else:
            flip_pipe = pygame.transform.flip(pipe_surface,False,True)
            screen.blit(flip_pipe,pipe)

def check_collision(pipes):
    global can_score
    
    for pipe in pipes:
        if bird_rect.colliderect(pipe):
            hit_sound.play()
            can_score = True
            return False

        if bird_rect.top <= -100 or bird_rect.bottom >= 900:
            can_score = True
            hit_sound.play()
            return False

    return True

def rotate_bird(bird):
    new_bird = pygame.transform.rotozoom(bird,-bird_movement * 3,1)
    return new_bird

def bird_animation():
    new_bird = bird_frames[bird_index]
    new_bird_rect = new_bird.get_rect(center = (100,bird_rect.centery))
    return new_bird,new_bird_rect

def score_display(game_state):
    if game_state == 'main_game':
        score_surface = game_font.render(str(int(score)),True,(255,255,255))
        score_rect = score_surface.get_rect(center = (288,100))
        screen.blit(score_surface,score_rect)
    if game_state == 'game_over':
        score_surface = game_font.render(f'Score: {int(score)}',True,(255,255,255))
        score_rect = score_surface.get_rect(center = (288,100))
        screen.blit(score_surface,score_rect)

        high_score_surface = game_font.render(f'High score: {int(high_score)}',True,(255,255,255))
        high_score_rect = high_score_surface.get_rect(center = (288,850))
        screen.blit(high_score_surface,high_score_rect)

def update_score(score,high_score):
    if score > high_score:
        high_score = score
    return high_score

def pipe_score_check():
    global score, can_score
    
    if pipe_list:
        for pipe in pipe_list:
            if 95 < pipe.centerx < 105 and can_score:
                score  = 1
                point_sound.play()
                can_score = False
                if pipe.centerx < 0:
                    can_score = True
                    
# pygame.mixer.pre_init(frequency = 44100, size = 16, channels = 1, buffer = 512)
pygame.init()
screen = pygame.display.set_mode((576,1024))
clock = pygame.time.Clock()
game_font = pygame.font.Font('04B_19.ttf',40)

# Variables
gravity = 0.25
bird_movement = 0
game_active = True
score = 0
high_score = 0
can_score = True
# Loading images

bg_surface = pygame.image.load('assets/background-day.png').convert()
bg_surface = pygame.transform.scale2x(bg_surface)

floor_surface = pygame.image.load('assets/base.png').convert()
floor_surface = pygame.transform.scale2x(floor_surface)
floor_x_pos = 0

bird_downflap = pygame.transform.scale2x(pygame.image.load('assets/yellowbird-downflap.png').convert_alpha())
bird_midflap = pygame.transform.scale2x(pygame.image.load('assets/yellowbird-midflap.png').convert_alpha())
bird_upflap = pygame.transform.scale2x(pygame.image.load('assets/yellowbird-upflap.png').convert_alpha())
bird_frames = [bird_downflap,bird_midflap,bird_upflap]
bird_index = 0
bird_surface = bird_frames[bird_index]
bird_rect = bird_surface.get_rect(center = (100,512))

BIRDFLAP = pygame.USEREVENT   1
pygame.time.set_timer(BIRDFLAP,200)

# bird_surface = pygame.image.load('assets/yellowbird-midflap.png').convert_alpha()
# bird_surface = pygame.transform.scale2x(bird_surface)
# bird_rect = bird_surface.get_rect(center = (100,512))

pipe_surface = pygame.image.load('assets/pipe-green.png').convert()
pipe_surface = pygame.transform.scale2x(pipe_surface)

pipe_list = []

SPAWNPIPE = pygame.USEREVENT
pygame.time.set_timer(SPAWNPIPE,1500)
pipe_height = [400,600,800]

game_over_surface = pygame.transform.scale2x(pygame.image.load('assets/message.png').convert_alpha())
game_over_rect = game_over_surface.get_rect(center = (288,512))

flap_sound = pygame.mixer.Sound('sound/sfx_wing.wav')
hit_sound = pygame.mixer.Sound('sound/sfx_hit.wav')
point_sound = pygame.mixer.Sound('sound/sfx_point.wav')
countdown_sound_score = 100

# Event loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and game_active:
                bird_movement = 0
                bird_movement -= 12
                flap_sound.play()
            if event.key == pygame.K_SPACE and game_active == False:
                game_active = True
                pipe_list.clear()
                bird_rect.center = (100,512)
                bird_movement = 0
                score = 0
                
        if event.type == SPAWNPIPE:
            pipe_list.extend(create_pipe())

        if event.type == BIRDFLAP:
            if bird_index < 2:
                bird_index  = 1
            else:
                bird_index = 0

            bird_surface,bird_rect = bird_animation()

# Pasting background image
    screen.blit(bg_surface,(0,0))
    
    if game_active:
# Bird movement and pasting bird
        bird_movement  = gravity
        rotated_bird = rotate_bird(bird_surface)
        bird_rect.centery  = bird_movement
        screen.blit(rotated_bird,bird_rect)
        game_active = check_collision(pipe_list)

# Pipes
        pipe_list = move_pipes(pipe_list)
        draw_pipes(pipe_list)
# Score
        pipe_score_check()
        score_display('main_game')
    else:   
        screen.blit(game_over_surface,game_over_rect)
        high_score = update_score(score,high_score)
        score_display('game_over')
                      
# Floor movement and pasting floor image
    floor_x_pos -= 1
    draw_floor()
    if floor_x_pos <=-576:
        floor_x_pos = 0
    
    pygame.display.update()
    clock.tick(120)
 

Это мне очень поможет.

Спасибо,

Джош

Комментарии:

1. Вы изучали чтение и запись из файлов? Так вы сможете сохранять и извлекать данные между запусками программы. Возможно, у вас есть файл highscore.txt , который вы читаете при запуске программы и обновляете всякий раз, когда пользователь получает новый высокий балл?

Ответ №1:

Самым простым способом было бы иметь файл с вашим счетом. Вы запишете в нее результат перед закрытием игры или всякий раз, когда захотите сохранить результат. и прочитайте счет при открытии игры.

Вот пример функций чтения и записи для достижения этой цели:

 def write_score(score):
    with open("highscore.txt", 'w') as file:
        file.write(str(score))

def read_score():
    with open("highscore.txt", 'r') as file:
        return int(file.read())

 

(Я не тестировал код, но я почти уверен, что это сработает, если нет, я могу это исправить)

Комментарии:

1. Это будет работать нормально, хотя часто очень удобно использовать json библиотеку, которая может напрямую считывать и записывать словарь строк в дескриптор файла с json.load() помощью и json.dump() ( .dumps() и .loads() для строк соответственно, что может быть проще рассуждать) docs.python.org/3/library/json.html

2. Это (например) позволило бы пользователю легко читать и записывать коллекцию имен и их оценок в файл.

3. Да, я думаю, json будет лучше для этого.