目录
上一篇文章我们学会了pygame的一些基本函数,可将用键盘和鼠标移动物体了,这篇文章学习了碰撞函数之后,就可以做小鸟躲柱子的经典游戏了
游戏做好的页面大致如下:
素材都是网上找的,我这个的素材会放在文章的最后
预备知识
1.pygame的碰撞检测函数
a.colliderect(b)
- 用于检测 a 与 b 的矩形是否有重叠的部分
- 若碰撞,则返回 True;否则返回 False
- 其中 a 和 b 都是Rect ,不然无法检测
2.图片的矩形裁剪
pygame.Rect(top,left,width,height)
- top 指矩形左上角距离原点的水平方向长度
- left 指矩形左上角距离原点的垂直方向长度
- width 指矩形的宽度
- height 指矩形的长度
3.时钟节拍
clock.tick()
- 控制帧率,数字越大,刷新越快
OK,有了之前的知识,加上以上知识,我们就可以开始了
分步解读代码
为了更好的封装和调用更新函数,我们将物体的类写在class类中
定义管道的类和方法
首先初始化管道,载入图片,定义管道的x坐标和两个y坐标;然后定义管道的更新函数,使每次向左移动2,如果已经溢出屏幕,就再放两个管道在初始化的位置,且用random函数使两根管道的位置是浮动的
class Pipes(object):
def __init__(self):
self.bar_up = pygame.image.load("C:/Users/leslie/Desktop/bar_down.png");
self.bar_down = pygame.image.load("C:/Users/leslie/Desktop/bar_up.png");
self.pipe_x = 400;
self.pipe_y1 = random.randint(-350,-300)
self.pipe_y2 = random.randint(400,500)
def update_pipe(self):
self.pipe_x -= 2
if self.pipe_x < -80:
global score
score += 1
self.pipe_x = 400
self.pipe_y1 = random.randint(-350,-100)
self.pipe_y2 = random.randint(430,550)
定义小鸟的类和方法
首先可以用列表封装小鸟的4种状态(平行,下降,起飞和死亡),然后将小鸟的图片裁剪成举行类,方便碰撞的检测,设置stutas为小鸟的状态为0,这个0对应着bird1的图片,平行飞行状态,再设置坐标,是否起飞,是否死亡,以及起飞和降落的速度。定义更新的函数,判断起飞或者是降落显示相应的位置。
class Bird():
def __init__(self):
self.birdsize=pygame.Rect(65,50,40,40)
self.birds=[pygame.image.load("C:/Users/leslie/Desktop/bird1.png"),
pygame.image.load("C:/Users/leslie/Desktop/bird2.png"),
pygame.image.load("C:/Users/leslie/Desktop/bird3.png"),
pygame.image.load("C:/Users/leslie/Desktop/dead.png")
]
self.stutas = 0
self.bird_x = 120
self.bird_y = 350
self.jump = False
self.jumpSpeed = 1
self.downing = 1
self.dead = False
def update_bird(self):
if self.jump:
self.bird_y -= self.jumpSpeed
else:
self.bird_y +=self.downing
self.birdsize[1] = self.bird_y
定义游戏开始的画布显示
将背景图片载入,画上两根柱子,判断小鸟的状态,再画上小鸟对应状态的图片,启用管道和小鸟的跟新函数来移动,再上面显示分数,最后更新画布
def map_view():
screen.blit(background, (0, 0))
screen.blit(Pipes.bar_up, (Pipes.pipe_x, Pipes.pipe_y1))
screen.blit(Pipes.bar_down, (Pipes.pipe_x, Pipes.pipe_y2))
Pipes.update_pipe()
if Bird.jump:
Bird.stutas=1
elif Bird.dead:
Bird.stutas=3
else:
Bird.stutas=2
screen.blit(Bird.birds[Bird.stutas],(Bird.bird_x,Bird.bird_y))
Bird.update_bird()
screen.blit(font.render('sorce:' + str(score), -1, 'blue'), (100, 50))
pygame.display.update()
定义碰撞检测的函数
将管道和小鸟都变成矩形才能用碰撞检测的函数,其中如果小鸟撞到柱子了或者是小鸟飞出边界了都算是游戏结束
def PZ_test():
up_bar = pygame.Rect(Pipes.pipe_x,Pipes.pipe_y1,Pipes.bar_up.get_width()-10 ,Pipes.bar_up.get_height())
down_bar = pygame.Rect(Pipes.pipe_x,Pipes.pipe_y2,Pipes.bar_down.get_width()-10,Pipes.bar_down.get_height())
if up_bar.colliderect(Bird.birdsize) or down_bar.colliderect(Bird.birdsize):
Bird.dead = True
return True
elif Bird.birdsize[1] > height or Bird.birdsize[1]<0:
Bird.dead = True
return True
else:
return False
定义游戏结束的画面
显示背景,显示字体,更新整个画布,这个我不熟,借鉴了其他人写的
def end_map():
screen.blit(background, (0, 0))
text1 = "Game Over"
text2 = "final score: " + str(score)
ft1_surf = font.render(text1, 1, 'green')
ft2_surf = font.render(text2, 1, 'red')
screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])
screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 200])
pygame.display.flip()
定义主函数
分别用键盘的上下键控制小鸟的飞行状态,设置时钟节拍控制游戏的快慢,检测小鸟的死亡状态,决定启用哪一个画布
if __name__ == '__main__':
pygame.init()
pygame.font.init()
pygame.display.set_caption("小鸟躲柱子")
size = width, height = 350, 600
screen = pygame.display.set_mode(size)
font = pygame.font.SysFont("ziti.ttf", 50)
clock = pygame.time.Clock()
Bird = Bird()
Pipes = Pipes()
score=0
while True:
clock.tick(80)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and Bird.dead==False:
if event.key == pygame.K_UP:
Bird.jump = True
if event.key == pygame.K_DOWN:
Bird.jump = False
background = pygame.image.load("C:/Users/leslie/Desktop/background.jpg")
if PZ_test():
end_map()
else:
map_view()
完整的代码
import pygame
import sys
import random
class Pipes(object):
def __init__(self):
self.bar_up = pygame.image.load("C:/Users/leslie/Desktop/bar_down.png");
self.bar_down = pygame.image.load("C:/Users/leslie/Desktop/bar_up.png");
self.pipe_x = 400;
self.pipe_y1 = random.randint(-350,-300)
self.pipe_y2 = random.randint(400,500)
def update_pipe(self):
self.pipe_x -= 2
if self.pipe_x < -80:
global score
score += 1
self.pipe_x = 400
self.pipe_y1 = random.randint(-350,-100)
self.pipe_y2 = random.randint(430,550)
class Bird():
def __init__(self):
self.birdsize=pygame.Rect(65,50,40,40)
self.birds=[pygame.image.load("C:/Users/leslie/Desktop/bird1.png"),
pygame.image.load("C:/Users/leslie/Desktop/bird2.png"),
pygame.image.load("C:/Users/leslie/Desktop/bird3.png"),
pygame.image.load("C:/Users/leslie/Desktop/dead.png")
]
self.stutas = 0
self.bird_x = 120
self.bird_y = 350
self.jump = False
self.jumpSpeed = 1
self.downing = 1
self.dead = False
def update_bird(self):
if self.jump:
self.bird_y -= self.jumpSpeed
else:
self.bird_y +=self.downing
self.birdsize[1] = self.bird_y
def map_view():
screen.fill('white')
screen.blit(background, (0, 0))
screen.blit(Pipes.bar_up, (Pipes.pipe_x, Pipes.pipe_y1))
screen.blit(Pipes.bar_down, (Pipes.pipe_x, Pipes.pipe_y2))
Pipes.update_pipe()
if Bird.jump:
Bird.stutas=1
elif Bird.dead:
Bird.stutas=3
else:
Bird.stutas=2
screen.blit(Bird.birds[Bird.stutas],(Bird.bird_x,Bird.bird_y))
Bird.update_bird()
screen.blit(font.render('sorce:' + str(score), -1, 'blue'), (100, 50))
pygame.display.update()
def PZ_test():
up_bar = pygame.Rect(Pipes.pipe_x,Pipes.pipe_y1,Pipes.bar_up.get_width()-10 ,Pipes.bar_up.get_height())
down_bar = pygame.Rect(Pipes.pipe_x,Pipes.pipe_y2,Pipes.bar_down.get_width()-10,Pipes.bar_down.get_height())
if up_bar.colliderect(Bird.birdsize) or down_bar.colliderect(Bird.birdsize):
Bird.dead = True
return True
elif Bird.birdsize[1] > height or Bird.birdsize[1]<0:
Bird.dead = True
return True
else:
return False
def end_map():
screen.blit(background, (0, 0))
text1 = "Game Over"
text2 = "final score: " + str(score)
ft1_surf = font.render(text1, 1, 'green')
ft2_surf = font.render(text2, 1, 'red')
screen.blit(ft1_surf, [screen.get_width() / 2 - ft1_surf.get_width() / 2, 100])
screen.blit(ft2_surf, [screen.get_width() / 2 - ft2_surf.get_width() / 2, 200])
pygame.display.flip()
if __name__ == '__main__':
pygame.init()
pygame.font.init()
pygame.display.set_caption("小鸟躲柱子")
size = width, height = 350, 600
screen = pygame.display.set_mode(size)
font = pygame.font.SysFont("ziti.ttf", 50)
clock = pygame.time.Clock()
Bird = Bird()
Pipes = Pipes()
score=0
while True:
clock.tick(80)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and Bird.dead==False:
if event.key == pygame.K_UP:
Bird.jump = True
if event.key == pygame.K_DOWN:
Bird.jump = False
background = pygame.image.load("C:/Users/leslie/Desktop/background.jpg")
if PZ_test():
end_map()
else:
map_view()