当前位置: 首页 > 工具软件 > 1w-flappy > 使用案例 >

pygame小游戏--flappybird

汪永春
2023-12-01

游资资源加载及游戏对象定义

笔者已将代码和资源放在了gitee,请自行领取

加载资源

import pygame, os, random
from itertools import cycle

pygame.init()
images = {}
for image in os.listdir('../assets/sprites'):
    name, extension = os.path.splitext(image)
    path = os.path.join('../assets/sprites', image)
    images[name] = pygame.image.load(path)
color = random.choice(['red', 'yellow', 'blue'])
images['birds'] = [images[color + 'bird-upflap'], images[color + 'bird-midflap'],
                   images[color + 'bird-downflap']]

def return_audio():
    audios = {}
    audios['wing'] = pygame.mixer.Sound('../assets/audio/wing.wav')
    audios['point'] = pygame.mixer.Sound('../assets/audio/point.wav')
    audios['hit'] = pygame.mixer.Sound('../assets/audio/hit.wav')
    audios['die'] = pygame.mixer.Sound('../assets/audio/die.wav')
    return audios

def return_image():
    return images

小鸟类

class Bird(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.dying = False
        self.repeat = 2
        self.idx = 0
        self.frames = cycle([0, 0, 1, 1, 2, 2, 1, 1])
        self.images = images['birds']
        self.image = images['birds'][0]
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.y_vel = -10
        self.max_y_vel = 10  # 最大竖直速度
        self.gravity = 1  # 下落速度

        self.y_vel_after_flap = -10
        self.concussion_y = 1
        self.concussion_y_vel = 1
        self.bird_y_range = [self.rect.y - 8, self.rect.y + 8]

    def update(self):
        self.image = images['birds'][next(self.frames)]

    def move(self, flap=False):
        if flap:
            self.y_vel = self.y_vel_after_flap
            # self.rotate = self.rotate_after_flap
        self.y_vel = min(self.y_vel + self.gravity, self.max_y_vel)
        self.rect.y += self.y_vel

    def consussion(self):
        self.rect.y += self.concussion_y_vel
        if self.rect.y < self.bird_y_range[0] or self.rect.y > \
                self.bird_y_range[1]:
            self.concussion_y_vel *= -1

    def go_die(self, FLOOR_Y):
        if self.rect.y < FLOOR_Y:
            self.rect.y += self.max_y_vel
            self.image = self.images[self.frames[self.idx]]
        else:
            self.dying = False

    def is_die(self, FLOOR_Y):
        if self.rect.y > FLOOR_Y or self.rect.y < 0:
            self.dying = True
            return self.dying

管道类

class Pipe(pygame.sprite.Sprite):
    def __init__(self, x, y, upwards=True):
        super().__init__()
        if upwards:
            self.image = images['pipe-red']
            self.rect = self.image.get_rect()
            self.rect.x = x
            self.rect.top = y
        else:
            self.image = pygame.transform.flip(images['pipe-red'], False, True)
            self.rect = self.image.get_rect()
            self.rect.x = x
            self.rect.bottom = y
        self.x_vel = -4

    def update(self):
        self.rect.x += self.x_vel

管道移动类

用于生成管道

class GEN_PIPE:
    def __init__(self, n):
        self.n = n
        self.pipes = pygame.sprite.Group()
        self.gen_pipe()
        self.pipe_move()
        self.pipe_width=images['pipe-red'].get_width()

    def gen_pipe_y(self):
        return random.randint(int(H * 0.3), int(H * 0.7))

    def gen_distance(self):
        return random.randint(150, 180)

    def gen_pipe(self):
        for i in range(self.n):
            distance = self.gen_distance()
            # distance = 150
            pipe_y = self.gen_pipe_y()
            pipe_up = Pipe(W + i * distance, pipe_y, True)
            pipe_down = Pipe(W + i * distance, pipe_y - PIPE_GAP, False)
            self.pipes.add(pipe_up, pipe_down)

    def pipe_move(self):
        first_up = self.pipes.sprites()[0]
        first_down = self.pipes.sprites()[1]
        # distance = 150
        distance = self.gen_distance()
        if first_up.rect.right < 0:
            # distance = self.gen_distance()
            pipe_y = self.gen_pipe_y()
            new_pipe_up = Pipe(first_up.rect.x + self.n * distance, pipe_y, True)
            new_pipe_down = Pipe(first_up.rect.x + self.n * distance, pipe_y - PIPE_GAP, False)
            self.pipes.add(new_pipe_up)
            self.pipes.add(new_pipe_down)
            first_up.kill()
            first_down.kill()

游戏逻辑实现

游戏框架

import pygame
def main():
    while True:
        menu_window()# 开始界面
        game_window()# 游戏界面
        end_window()# 游戏结束界面
def menu_window():
	pass
def game_window():
	pass
def end_window():
	pass 

游戏参数

import random
from def_sprite import Bird, Pipe, return_image,return_audio
import pygame

images = return_image()
audios=return_audio()
W = 288
H = 500
FPS = 30
MAX_FLOOR_DISTANCE = images['base'].get_width() - W
PIPE_GAP = 100
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption('bird')
clock = pygame.time.Clock()
FLOOR_Y = H - return_image()['base'].get_height()  # 地板高度
floor_x = 0

开始界面

def menu_window():
    floor_gap = return_image()['base'].get_width() - W
    bird = Bird(W * 0.2, H * 0.5)
    # floor_x = 0
    guide_x = (W - return_image()['message'].get_width()) / 2
    guide_y = (FLOOR_Y - return_image()['message'].get_height()) / 2
    while True:
        # is_close()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            if event.type == pygame.KEYDOWN:
                # print('111')
                if event.key == pygame.K_SPACE:
                    return
        # floor_x -= 4
        # if floor_x <= -floor_gap:
        #     floor_x = 0
        # floor_move()
        bird.update()
        bird.consussion()

        screen.blit(images['background-day'], (0, 0))
        screen.blit(images['base'], (floor_move(), FLOOR_Y))
        screen.blit(images['message'], (guide_x, guide_y))
        screen.blit(bird.image, bird.rect)
        # 框架
        pygame.display.update()
        clock.tick(FPS)

游戏界面

def game_window():
    bird = Bird(W * 0.2, H * 0.4)
    # floor_x = 0
    score = 0
    ALL_PIPE = GEN_PIPE(4)
    while True:
        flap = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    flap = True
                    audios['wing'].play()

        # 地面移动
        # floor_x -= 4
        # if floor_x <= -MAX_FLOOR_DISTANCE:
        #     floor_x = 0
        bird.update()
        ALL_PIPE.pipe_move()
        ALL_PIPE.pipes.update()
        bird.move(flap)

        if bird.is_die(FLOOR_Y) or is_crash(bird, ALL_PIPE.pipes):
            audios['die'].play()
            return
        pipe_x=ALL_PIPE.pipes.sprites()[0].rect.x+ALL_PIPE.pipe_width
        if pipe_x<bird.rect.right<pipe_x+4:
            score+=1
            audios['point'].play()
        screen.blit(images['background-day'], (0, 0))
        ALL_PIPE.pipes.draw(screen)
        screen.blit(images['base'], (floor_move(), FLOOR_Y))
        show_score(score)
        screen.blit(bird.image, bird.rect)
        # 框架
        pygame.display.update()
        clock.tick(FPS)

游戏结束界面

def end_window():
    gameover_x = (W - images['gameover'].get_width()) / 2
    gameover_y = (H - images['gameover'].get_height()) / 2
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    return
        screen.blit(images['background-night'], (0, 0))

        screen.blit(images['base'], (0, FLOOR_Y))
        screen.blit(images['gameover'], (gameover_x, gameover_y))
        # 框架
        pygame.display.update()
        clock.tick(FPS)


def is_close():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()

其他

碰撞检测函数

def is_crash(sprite1, sprite2):
    aa = pygame.sprite.spritecollideany(sprite1, sprite2)
    return aa

地面移动

def floor_move():
    global floor_x
    floor_x -= 4
    if floor_x <= -MAX_FLOOR_DISTANCE:
        floor_x = 0
    return floor_x

分数显示


def show_score(score):
    score_str = str(score)
    n = len(score_str)
    width = images['0'].get_width() * 1.1
    init_x = (W - n * width) / 2
    init_y = H * 0.1
    for num in score_str:
        screen.blit(images[num], (init_x, init_y))
        init_x += width
 类似资料: