You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

486 lines
19 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import pygame
import sys
from pygame.locals import *
import random
###小鸟类##
class Bird():
def __init__(self, pos_x, pos_y, speed): #初始化
self.images = [bird_0_image, bird_1_image, bird_2_image]
self.order = 0 #应该放第几张图片
self.number = 3 #做一个动画一共需要3张图
self.image = self.images[self.order]
self.rect = self.image.get_rect() #取出一个代表图片的矩形
self.rect.x = pos_x #矩形左上角的坐标
self.rect.y = pos_y
#小鸟图片并非充满整个rect做碰撞检测需要小鸟的精确位置记做self.base
self.base = pygame.Rect(self.rect.x + 6, self.rect.y + 13, 34, 24)
self.speed_y = speed
self.crash = 0 #坠落情况
self.score = 0 #分数
self.direct = 1
def draw(self, screen): #画在屏幕上
screen.blit(self.image, (self.rect.x, self.rect.y))
def flap(self): #扇翅膀动画
if self.order >= self.number - 1:
self.order = -1
self.order += 1
self.image = self.images[self.order]
def move_y(self): #动作规律以及积分情况
coin_sound = pygame.mixer.Sound("coin_sound.wav")
self.rect.y += self.speed_y
self.speed_y += gravity
self.base = pygame.Rect(self.rect.x + 6, self.rect.y + 13, 34, 24)
if self.rect.x == pipe_1.rect_up.x or self.rect.x == pipe_2.rect_up.x + 1:
coin_sound.play()
self.score = max(pipe_1.order, pipe_2.order) - 1
def up_and_down(self, pos_y):
if self.rect.y <= pos_y:
self.direct = 1
self.rect.y += self.direct
elif self.rect.y >= pos_y + 5 :
self.direct = -1
self.rect.y += self.direct
else:
self.rect.y += self.direct
def soar(self, speed): #点击小鸟飞起
self.speed_y = speed
def drop(self): #小鸟坠落
self.rect.y += self.speed_y
self.speed_y += gravity
def die(self): #小鸟死亡
self.rect.y = 365
self.image = self.images[0]
###柱子1###
class Pipe_1():
def __init__(self): #初始化
self.images = [pipe_up_image,pipe_down_image]
self.rand= random.randrange(50, 270, 20)
self.rect_up = self.images[0].get_rect() #上部分柱子
self.rect_down = self.images[1].get_rect() #下部分柱子
self.order = 1 #柱子编号
self.rect_up.x = 1.5 * screen_width #位置
self.rect_down.x = 1.5 * screen_width
self.rect_up.y = 400 - self.rand
self.rect_down.y = - self.rand - random.randrange(0, 100)
def imagein(self, a, b):
self.images = [a, b]
def draw(self, screen): #画在屏幕上
screen.blit(self.images[0], (self.rect_up.x, self.rect_up.y))
screen.blit(self.images[1], (self.rect_down.x, self.rect_down.y))
def move_x(self): #柱子动作规律
if self.rect_up.x > -pipe_width:
self.rect_up.x -= pipe_speed
self.rect_down.x -= pipe_speed
else:
self.reset()
def reset(self): #移出屏幕后重新进入屏幕
self.rand = random.randrange(50, 270, 20)
self.rect_up.x = screen_width
self.rect_down.x = screen_width
self.rect_up.y = 400 - self.rand
self.rect_down.y = -self.rand -random.randrange(0,100) ##柱子是320个像素点地面以上部分400个像素点两柱之间距离有点近- 20拉大20个像素的距离可根据喜好随意设置
self.order += 2
def collide(self, bird_rect): #判断与小鸟的碰撞
if self.rect_up.colliderect(bird_rect):
collide_pipe = 1
elif self.rect_down.colliderect(bird_rect):
collide_pipe= 1
else:
collide_pipe = 0
return collide_pipe
def halt(self):
pass
class Pipe_2():
def __init__(self):
self.images = [pipe_up_image,pipe_down_image]
self.rand= random.randrange(50, 270, 20)
self.rect_up = self.images[0].get_rect()
self.rect_down = self.images[1].get_rect()
self.order = 0
self.reset()
def imagein(self,a,b):
self.images=[a,b]
def draw(self, screen):
screen.blit(self.images[0], (self.rect_up.x, self.rect_up.y))
screen.blit(self.images[1], (self.rect_down.x, self.rect_down.y))
def move_x(self):
if pipe_1.rect_up.x < self.rect_up.x:
self.rect_up.x = pipe_1.rect_up.x + (screen_width + pipe_width)/2
self.rect_down.x = pipe_1.rect_down.x + (screen_width + pipe_width)/2
elif pipe_1.rect_up.x > self.rect_up.x and self.rect_up.x > -pipe_width:
self.rect_up.x -= pipe_speed
self.rect_down.x -= pipe_speed
else:
self.reset()
def reset(self):
self.rand = random.randrange(50, 270, 20)
self.rect_up.x = pipe_1.rect_up.x + (screen_width + pipe_width)/2
self.rect_down.x = pipe_1.rect_up.x + (screen_width + pipe_width)/2
self.rect_up.y = 400 - self.rand
self.rect_down.y = -self.rand - 20
self.order += 2
def collide(self, bird_rect):
if self.rect_up.colliderect(bird_rect):
collide_pipe = 1
elif self.rect_down.colliderect(bird_rect):
collide_pipe= 1
else:
collide_pipe = 0
return collide_pipe
def halt(self):
pass
###地面###
class Land():
def __init__(self): #初始化
self.image = land_image
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = 400
def draw(self, screen): #画在屏幕上
screen.blit(self.image, (self.rect.x, self.rect.y))
def move_x(self): #地面动作规律
if self.rect.x > -44:
self.rect.x -= pipe_speed
else:
self.rect.x = 0
def collide(self, bird_rect): #判断与小鸟碰撞
if self.rect.colliderect(bird_rect):
collide_land = 1
else:
collide_land = 0
return collide_land
def halt(self):
pass
###分数###
class Score():
def __init__(self):
self.images = [num_0_image, num_1_image, num_2_image, num_3_image,
num_4_image, num_5_image, num_6_image, num_7_image,
num_8_image, num_9_image]
self.hun_pos_3 = 108
self.dec_pos_3 = 132
self.dec_pos_2 = 120
self.uni_pos_3 = 156
self.uni_pos_2 = 144
self.uni_pos_1 = 132
def draw(self, screen, score): #画在屏幕上,为了保持分数在屏幕正中央,判断分数有几位,根据位数画图
if score < 10:
screen.blit(self.images[score], (self.uni_pos_1, 0))
if score >= 10 and score <100:
screen.blit(self.images[score % 10], (self.uni_pos_2, 0))
screen.blit(self.images[int(score/10)], (self.dec_pos_2, 0))
if score > 100:
screen.blit(self.images[score % 10], (self.uni_pos_3, 0))
screen.blit(self.images[int((score % 100)/10)], (self.dec_pos_3, 0))
screen.blit(self.images[int(score/100)], (self.hun_pos_3, 0))
gamename = "小鸟历险记"
screen_width = 288
screen_height = 512
#pipe_width = 52 # 固定柱子间距
pipe_width = random.randrange(22, 102, 10) # 随机柱子间距
pipe_height = 320
pipe_speed = 3
gravity = 1.2
soar_speed = -5
play_x = 120 #play界面下小鸟的位置
play_y = 190
ready_x = 60
ready_y = 210 #ready界面下小鸟的位置
game_over_x = 60
game_over_y = 365 #game over界面下小鸟的位置
###加载所有图片###
update = 30
bird_0_image = pygame.image.load("bird_0.png")
bird_1_image = pygame.image.load("bird_1.png")
bird_2_image = pygame.image.load("bird_2.png")
background_image = pygame.image.load("bg_day.png")
land_image = pygame.image.load("land.png")
pipe_up_image = pygame.image.load("pipe_up.png")
pipe_down_image = pygame.image.load("pipe_down.png")
num_0_image = pygame.image.load("num_0.png") #显示在屏幕中央的分数图片
num_1_image = pygame.image.load("num_1.png")
num_2_image = pygame.image.load("num_2.png")
num_3_image = pygame.image.load("num_3.png")
num_4_image = pygame.image.load("num_4.png")
num_5_image = pygame.image.load("num_5.png")
num_6_image = pygame.image.load("num_6.png")
num_7_image = pygame.image.load("num_7.png")
num_8_image = pygame.image.load("num_8.png")
num_9_image = pygame.image.load("num_9.png")
score_0_image = pygame.image.load("score_0.png") #显示在分数版上的分数图片
score_1_image = pygame.image.load("score_1.png")
score_2_image = pygame.image.load("score_2.png")
score_3_image = pygame.image.load("score_3.png")
score_4_image = pygame.image.load("score_4.png")
score_5_image = pygame.image.load("score_5.png")
score_6_image = pygame.image.load("score_6.png")
score_7_image = pygame.image.load("score_7.png")
score_8_image = pygame.image.load("score_8.png")
score_9_image = pygame.image.load("score_9.png")
medals_0_image = pygame.image.load('medals_0.png')
medals_1_image = pygame.image.load('medals_1.png')
medals_2_image = pygame.image.load('medals_2.png')
medals_3_image = pygame.image.load('medals_3.png')
pass
title_image = pygame.image.load("title.png")
button_play_image = pygame.image.load("button_play.png")
game_over_image = pygame.image.load("text_game_over.png")
score_panel_image = pygame.image.load("score_panel.png")
###全局变量初始化,由于小鸟在不同的游戏界面不一样,需要在函数内部设置局部变量
pipe_1 = Pipe_1()
pipe_2 = Pipe_2()
land = Land()
clock = pygame.time.Clock() #非常重要,控制游戏速度,每一帧的时间间隔
###最开始的play界面###
def play_page():
pygame.init()
screen = pygame.display.set_mode([screen_width, screen_height]) #设置屏幕
pygame.display.set_caption(gamename) #设置顶栏名称
bird = Bird(play_x, play_y, 0)
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
mouse_x, mouse_y = pygame.mouse.get_pos()
#判断是否在点击了play button点击之后退出该状态进入ready状态
if pygame.mouse.get_pressed()[0] and mouse_x >= 92 and mouse_x <= 196 and mouse_y >= 287 and mouse_y <= 345:
break
screen.blit(background_image, (0, 0))
screen.blit(title_image, (55, 98))
screen.blit(button_play_image, (86, 284))
bird.up_and_down(play_y)
bird.flap()
bird.draw(screen)
land.move_x()
land.draw(screen)
pygame.display.update()
global update
clock.tick(update)
###准备界面###
def ready_page():
pygame.init()
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption(gamename)
bird = Bird(ready_x, ready_y, 0)
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
#判断是否点击了鼠标,点击之后返回当前小鸟的位置和速度信息,使两界面之间的切换没有瑕疵
if pygame.mouse.get_pressed()[0]:
bird.soar(soar_speed)
return [bird.rect.x, bird.rect.y, bird.speed_y]
break
screen.blit(background_image, (0, 0))
bird.up_and_down(ready_y)
bird.flap()
bird.draw(screen)
land.move_x()
land.draw(screen)
pygame.display.update()
global update
clock.tick(update) #帧速最高不超过updatems/帧
###游戏界面,接收上一界面的信息,以保持画面不断帧###
def start_page(start_x, start_y, start_speed):
pygame.init()
collide_sound = pygame.mixer.Sound("collide_sound.wav") #加载碰撞声
pygame.mixer.music.load("bg_music.mp3") #加载并播放背景音乐,并且设置声音
pygame.mixer.music.set_volume(0.8)
pygame.mixer.music.play(-1)
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption(gamename)
bird = Bird(start_x, start_y, start_speed)
pipe_1.__init__() #初始化
pipe_2.__init__()
score = Score()
first_collide = 1
flag = 1 # 标志位
while True:
if bird.score >= 10 and bird.score<=20:
#b = 52 + bird.score*10
b = pipe_width + bird.score
new1 = pygame.transform.scale(pipe_up_image, (b, 320))
new2 = pygame.transform.scale(pipe_down_image, (b, 320))
pipe_1.imagein(new1, new2)
pipe_2.imagein(new1, new2)
global soar_speed
#if bird.score > 15 and (bird.score + 1) % 4 == 0 :
if bird.score > 20 and bird.score % 2 == 0 and flag ==1:
a = 52 + random.randrange(20,100)
new1 = pygame.transform.scale(pipe_up_image, (a, 320))
new2 = pygame.transform.scale(pipe_down_image, (a, 320))
if a >= 210:
new1 = pygame.transform.scale(pipe_up_image, (52, 320))
new2 = pygame.transform.scale(pipe_down_image, (52, 320))
pipe_1.imagein(new1, new2)
pipe_2.imagein(new1, new2)
if bird.score % 2 == 0:
flag = -1
else:
flag = 1
for event in pygame.event.get():
if event.type == QUIT:
exit()
screen.blit(background_image, (0, 0))
if pipe_1.collide(bird.base) == 0 and pipe_2.collide(bird.base) ==0 and land.collide(bird.rect) == 0: #正常飞行
if pygame.mouse.get_pressed()[0]:
bird.soar(soar_speed)
pipe_1.move_x()
pipe_1.draw(screen)
pipe_2.move_x()
pipe_2.draw(screen)
bird.move_y()
bird.flap()
bird.draw(screen)
land.move_x()
land.draw(screen)
score.draw(screen, bird.score)
elif (pipe_1.collide(bird.base) == 1 or pipe_2.collide(bird.base) ==1) and land.collide(bird.rect) == 0: #碰到柱子坠落
if first_collide == 1:
collide_sound.play()
pipe_1.halt()
pipe_1.draw(screen)
pipe_2.halt()
pipe_2.draw(screen)
bird.drop()
bird.flap()
bird.draw(screen)
land.halt()
land.draw(screen)
score.draw(screen, bird.score)
first_collide = 0
else: #坠落到地面时的状态
pipe_1.halt()
pipe_1.draw(screen)
pipe_2.halt()
pipe_2.draw(screen)
bird.die()
bird.draw(screen)
land.halt()
land.draw(screen)
score.draw(screen, bird.score)
pygame.display.update() #更新图像,否则显示不对
return bird.score #返回分数信息给game over界面
break #一旦碰到地面就进入game over界面
pygame.display.update()
clock.tick(30)
###game over界面接收上一界面的分数信息进行显示接收以往的最高成绩接收是否产生了新纪录###
def game_over_page(score, best):
pygame.init()
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption(gamename)
pygame.mixer.music.load("dead_sound.wav")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play()
bird = Bird(game_over_x, game_over_y, 0)
restart = 0
images = [score_0_image, score_1_image, score_2_image, score_3_image,
score_4_image, score_5_image, score_6_image, score_7_image,
score_8_image, score_9_image]
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
mouse_x, mouse_y = pygame.mouse.get_pos()
#判断是否点击开始按钮以重新开始
if pygame.mouse.get_pressed()[0] and mouse_x >= 92 and mouse_x <= 196 and mouse_y >= 337 and mouse_y <= 395:
restart = 1
return restart
break
screen.blit(background_image, (0, 0))
pipe_1.halt()
pipe_1.draw(screen)
pipe_2.halt()
pipe_2.draw(screen)
bird.die()
bird.draw(screen)
land.halt()
land.draw(screen)
screen.blit(game_over_image, (42, 98))
screen.blit(score_panel_image, (25, 183))
screen.blit(button_play_image, (86, 334))
#将分数按照位数进行分类,保证分数显示时的美观
if score < 10:
pass
elif score >= 10 and score < 50:
screen.blit(medals_3_image, (57, 226))
elif score >= 50 and score < 100:
screen.blit(medals_2_image, (57, 226))
elif score >= 100 and score < 500:
screen.blit(medals_1_image, (57, 226))
else:
screen.blit(medals_0_image, (57, 226))
if score < 10:
screen.blit(images[score], (215, 219))
if score >= 10 and score <100:
screen.blit(images[score%10], (215, 219))
screen.blit(images[int(score/10)], (202, 219))
if score > 100:
screen.blit(images[score%10], (215, 219))
screen.blit(images[int((score%100)/10)], (202, 219))
screen.blit(images[int(score/100)], (189, 219))
#最高成绩显示,同上
if best < 10:
screen.blit(images[best], (215, 261))
if best >= 10 and best <100:
screen.blit(images[best%10], (215, 261))
screen.blit(images[int(best/10)], (202, 261))
if best > 100:
screen.blit(images[best%10], (215, 261))
screen.blit(images[int((best%100)/10)], (202, 261))
screen.blit(images[int(best/100)], (189, 261))
pygame.display.update()
global update
clock.tick(update)
#游戏的总框架
def run():
play_page() #play界面
restart = 1 #先将restart置1否则无法开始游戏
best = 0
while restart: #判断是否重新开始游戏
[start_x, start_y, start_speed] = ready_page() #ready界面
score = start_page(start_x, start_y, start_speed) #start_page界面
if score > best:
best = score
restart = game_over_page(score, best) #game over界面
#开始游戏
if __name__ == "__main__":
run()