import os |
import random |
import pygame |
W, H = 288 , 512 |
FPS = 30 |
IMAGE_PATH = "./assets/sprites/" |
AUDIO_PATH = "./assets/audio/" |
pygame.init() |
pygame.mixer.init() |
SCREEN = pygame.display.set_mode((W, H)) |
pygame.display.set_caption( "Flappy Bird" ) |
CLOCK = pygame.time.Clock() |
IMAGE = {} |
for image in os.listdir(IMAGE_PATH): |
name, extension = os.path.splitext(image) |
path = os.path.join(IMAGE_PATH, image) |
IMAGE[name] = pygame.image.load(path) |
FLOOR_Y = H - IMAGE[ "floor" ].get_height() |
AUDIO = {} |
for audio in os.listdir(AUDIO_PATH): |
name, extension = os.path.splitext(audio) |
path = os.path.join(AUDIO_PATH, audio) |
AUDIO[name] = pygame.mixer.Sound(path) |
def main(): |
"""游戏主函数""" |
# 播放开始音效 |
AUDIO[ "start" ].play() |
IMAGE[ "bgpic" ] = IMAGE[random.choice([ "day" , "night" ])] |
color = random.choice([ "red" , "blue" , "yellow" ]) |
IMAGE[ "birds" ] = [IMAGE[color + "-up" ], IMAGE[color + "-mid" ], IMAGE[color + "-down" ]] |
pipe = IMAGE[random.choice([ "green-pipe" , "red-pipe" ])] |
IMAGE[ "pipes" ] = [pipe, pygame.transform.flip(pipe, False , True )] |
# 显示窗口 |
menu_window() |
result = game_window() |
end_window(result) |
def menu_window(): |
"""控制游戏菜单窗口函数""" |
floor_x = 0 |
floor_gap = W - IMAGE[ "floor" ].get_width() |
guide_x = (W - IMAGE[ "guide" ].get_width()) / 2 |
guide_y = (H - IMAGE[ "guide" ].get_height()) / 2 |
bird_x = W * 0.2 |
bird_y = (H - IMAGE[ "birds" ][ 0 ].get_width()) / 2 + 53 |
bird_y_val = 1 |
bird_y_range = [bird_y - 8 , bird_y + 8 ] |
idx = 0 |
repeat = 5 |
frames = [ 0 ] * repeat + [ 1 ] * repeat + [ 2 ] * repeat + [ 1 ] * repeat |
while True : |
for event in pygame.event.get(): |
if event. type = = pygame.QUIT: |
quit() |
if event. type = = pygame.KEYDOWN: |
if event.key = = pygame.K_ESCAPE: |
quit() |
if event.key = = pygame.K_SPACE: |
return |
floor_x - = 4 |
if floor_x < = floor_gap: |
floor_x = 0 |
bird_y + = bird_y_val |
if bird_y < bird_y_range[ 0 ] or bird_y > bird_y_range[ 1 ]: # 不让小鸟移出规定范围 |
bird_y_val * = - 1 |
idx + = 1 |
idx % = len (frames) |
SCREEN.blit(IMAGE[ "bgpic" ], ( 0 , 0 )) |
SCREEN.blit(IMAGE[ "floor" ], (floor_x, FLOOR_Y)) |
SCREEN.blit(IMAGE[ "guide" ], (guide_x, guide_y)) |
SCREEN.blit(IMAGE[ "birds" ][frames[idx]], (bird_x, bird_y)) |
pygame.display.update() |
CLOCK.tick(FPS) |
def game_window(): |
"""控制游戏进行函数""" |
AUDIO[ "flap" ].play() |
score = 0 |
floor_x = 0 |
floor_gap = W - IMAGE[ "floor" ].get_width() |
|
bird = Bird(W * 0.2 , H * 0.4 ) |
pipe_group = pygame.sprite.Group() |
distance = 150 |
n_pairs = 4 |
pipe_gap = 100 |
for i in range (n_pairs): |
pipe_y = random.randint( int (H * 0.3 ), int (H * 0.7 )) |
pipe_up = Pipe(W + i * distance, pipe_y) |
pipe_down = Pipe(W + i * distance, pipe_y - pipe_gap, False ) |
pipe_group.add(pipe_up) |
pipe_group.add(pipe_down) |
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_ESCAPE: |
quit() |
if event.key = = pygame.K_SPACE: |
AUDIO[ "flap" ].play() |
flap = True # 向上飞 |
floor_x - = 4 |
if floor_x < = floor_gap: # 不让地面移出屏幕 |
floor_x = 0 |
first_pipe_up = pipe_group.sprites()[ 0 ] |
first_pipe_down = pipe_group.sprites()[ 1 ] |
if first_pipe_up.rect.right < 0 : |
pipe_y = random.randint( int (H * 0.3 ), int (H * 0.75 )) |
new_pipe_up = Pipe(first_pipe_up.rect.x + n_pairs * distance, pipe_y) |
new_pipe_down = Pipe(first_pipe_down.rect.x + n_pairs * distance, pipe_y - pipe_gap, False ) |
pipe_group.add(new_pipe_up) |
pipe_group.add(new_pipe_down) |
first_pipe_up.kill() |
first_pipe_down.kill() |
# 更新角色状态 |
bird.update(flap) # 小鸟飞行动作切换 |
pipe_group.update() # 水管移动 |
# 碰撞检测 |
if bird.rect.y > FLOOR_Y or bird.rect.y < 0 or \ |
pygame.sprite.spritecollideany(bird, pipe_group): |
AUDIO[ "hit" ].play() |
AUDIO[ "die" ].play() |
bird.dying = True |
result = { "bird" : bird, "pipe_group" : pipe_group, "score" : score} |
return result |
if bird.rect.left + first_pipe_up.x_val < first_pipe_up.rect.centerx < bird.rect.left: |
AUDIO[ "score" ].play() |
score + = 1 |
SCREEN.blit(IMAGE[ "bgpic" ], ( 0 , 0 )) |
pipe_group.draw(SCREEN) |
SCREEN.blit(IMAGE[ "floor" ], (floor_x, FLOOR_Y)) |
show_score(score) |
SCREEN.blit(bird.image, bird.rect) |
pygame.display.update() |
CLOCK.tick(FPS) |
def end_window(result): |
"""控制游戏结束窗口函数""" |
gameover_x = (W - IMAGE[ "gameover" ].get_width()) / 2 |
gameover_y = (FLOOR_Y - IMAGE[ "gameover" ].get_height()) / 2 |
bird = result[ "bird" ] |
pipe_group = result[ "pipe_group" ] |
while True : |
if bird.dying: |
bird.go_die() |
else : |
for event in pygame.event.get(): |
if event. type = = pygame.QUIT: |
quit() |
if event. type = = pygame.KEYDOWN: |
if event.key = = pygame.K_ESCAPE: |
quit() |
if event.key = = pygame.K_SPACE: |
return |
SCREEN.blit(IMAGE[ "bgpic" ], ( 0 , 0 )) |
pipe_group.draw(SCREEN) |
SCREEN.blit(IMAGE[ "floor" ], ( 0 , FLOOR_Y)) |
SCREEN.blit(IMAGE[ "gameover" ], (gameover_x, gameover_y)) |
SCREEN.blit(bird.image, bird.rect) |
show_score(result[ "score" ]) |
pygame.display.update() |
CLOCK.tick(FPS) |
def show_score(score): |
"""显示得分""" |
score_str = str (score) |
n = len (score_str) |
w = IMAGE[ "0" ].get_width() * 1.1 |
x = (W - n * w) / 2 |
y = H * 0.1 |
for num in score_str: |
SCREEN.blit(IMAGE[num], (x, y)) |
x + = w |
class Bird: |
"""小鸟类""" |
def __init__( self , x, y): |
"""初始化小鸟信息""" |
self .dix = 0 |
self .frames = [ 0 ] * 5 + [ 1 ] * 5 + [ 2 ] * 5 + [ 1 ] * 5 |
self .images = IMAGE[ "birds" ] |
self .image = self .images[ self .frames[ self .dix]] |
self .rect = self .image.get_rect() |
self .rect.x = x |
self .rect.y = y |
self .y_val = - 10 |
self .max_y_val = 10 |
self .gravity = 1 |
self .rotate = 45 |
self .max_rotate = - 20 |
self .rotate_val = - 3 |
self .y_val_after_flap = - 10 |
self .rotate_after_flap = 45 |
self .dying = False |
def update( self , flap = False ): |
"""更新小鸟飞行状态""" |
if flap: |
self .y_val = self .y_val_after_flap |
self .rotate = self .rotate_after_flap |
self .y_val = min ( self .y_val + self .gravity, self .max_y_val) |
self .rect.y + = self .y_val |
self .rotate = max ( self .rotate + self .rotate_val, self .max_rotate) |
self .dix + = 1 |
self .dix % = len ( self .frames) |
self .image = self .images[ self .frames[ self .dix]] |
self .image = pygame.transform.rotate( self .image, self .rotate) |
def go_die( self ): |
"""判断失败后是否在地面之上""" |
if self .rect.y < FLOOR_Y: |
self .rect.y + = self .max_y_val |
self .rotate = - 90 |
self .image = self .images[ self .frames[ self .dix]] |
self .image = pygame.transform.rotate( self .image, self .rotate) |
else : |
self .dying = False |
class Pipe(pygame.sprite.Sprite): |
"""水管类""" |
def __init__( self , x, y, upwards = True ): |
"""初始化""" |
pygame.sprite.Sprite.__init__( self ) # 初始化精灵组 |
if upwards: |
self .image = IMAGE[ "pipes" ][ 0 ] |
self .rect = self .image.get_rect() |
self .rect.x = x |
self .rect.top = y |
else : |
self .image = IMAGE[ "pipes" ][ 1 ] |
self .rect = self .image.get_rect() |
self .rect.x = x |
self .rect.bottom = y |
self .x_val = - 4 |
def update( self ): |
"""更新水管移动""" |
self .rect.x + = self .x_val |
if __name__ = = '__main__' : |
main() |
初级程序员
by: 云代码会员 发表于:2021-11-11 17:35:03 顶(0) | 踩(0) 回复
dwdAWD
回复评论