python像素鸟游戏

   日期:2020-07-09     浏览:95    评论:0    
核心提示:该程序实现了像素鸟小游戏。该游戏的主要功能为:按下电脑键盘上面的 ↑ 键,让小鸟飞行,每越过一对管子,分数就加一。如果小鸟撞击了管子或者小鸟飞出游戏界面,那么游戏就会结束,同时显示你的分数和历史最高分.

目录

  • 1、引言
  • 2、系统结构
    • 2.1 总体结构
    • 2.2 局部结构
      • 2.2.1 main模块结构
      • 2.2.2 Bird模块结构
      • 2.2.3 Tubing模块结构
  • 3、代码实现
  • 4、实验
  • 5、总结和展望

1、引言

本次论文主要是基于对像素鸟游戏的研究。
像素鸟是一款风靡一时的小游戏,这款游戏架构简单,可以通过不同的编程语言去实现。近段时间学了python这门编程语言。于是突发奇想用python去实现这款游戏。
该程序主要实现的功能有:双击运行程序,播放背景音乐。出现游戏界面,通过不断按下键盘上面的 ↑ 键,使得小鸟飞行。每次按下 ↑ 键,就会播放小鸟翅膀挥舞的声音。通过小鸟的飞行,越过障碍物(管子),可以得到分数。每越过一个障碍物就可以得到一分。如果小鸟与障碍物发生碰撞,或者小鸟飞出游戏界面,那么就会播放gameover的声音,同时停止游戏,出现游戏结束界面。在游戏界面界面,你会看到历史最高分和你的分数,如果你的分数高于历史最高分,将会被记录在record.txt文件中。同时,在游戏结束界面有两个图片按钮,你可以通过点击鼠标左键来选择重新开始游戏或者是结束游戏。

2、系统结构

2.1 总体结构


本程序主要分成了3个模块,main模块是主函数模块,Bird模块是小鸟对象模块继承了(sprite),Tubing模块是管子对象模块也继承了(sprite)

2.2 局部结构

2.2.1 main模块结构


main模块中主要实现加载背景图片,加载游戏中需要的音乐。判断小鸟精灵和管子组精灵是否发生碰撞,实现小鸟按键飞行,播放音乐。绘制游戏结束后的界面以及按键事件、鼠标点击事件、与退出事件。

2.2.2 Bird模块结构


Bird模块主要实现关于小鸟对象的图片加载(__init__函数),小鸟显示的位置(__init__函数),小鸟的飞翔(fly函数),小鸟的下降(drop函数)

2.2.3 Tubing模块结构


Tubing模块主要实现了上面的管子(Tubing_up类)和下面的管子(Tubing_down类)的图片加载(__init__函数)、管子显示的位置(__init__函数)、管子的移动(move函数)

3、代码实现

先导入pygame模块,初始化pygame

import pygame
pygame.init()

创建游戏窗口,设置游戏窗口标题

bg_size = width,height = 903,495
view = pygame.display.set_mode(bg_size)
pygame.display.set_caption("像素鸟小游戏")

加载背景图片、背景音乐、绘制背景图片在游戏窗口上显示、播放背景音乐

import sys

#初始化pygame的扩音器
pygame.mixer.init()

#加载背景音乐
pygame.mixer.music.load("music/主界面BGM.mp3")

#加载背景图片
background = pygame.image.load("image/BGM.png").convert()

def main():

    #finish定义游戏是否结束(结束则为True)
    finish = False

    #开始循环播放背景音乐
    pygame.mixer.music.play(-1)
    while True:
        
        #如果点击了关闭事件就退出程序
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        #如果游戏还没结束
        if finish == False:

            #绘制背景图片
            view.blit(background,(0,0))

        #如果游戏已经结束,停止背景音乐的播放,绘制游戏结束后的界面
        if finish == True:
            pygame.mixer.music.stop()

        #更新界面
        pygame.display.flip()
        #延迟10毫秒
        pygame.time.delay(10)


if __name__ == "__main__":
    main()

新建一个模块实现小鸟对象

import pygame

#继承Sprite精灵类,方便用于碰撞检测
class Bird(pygame.sprite.Sprite):
        def __init__(self,bg_size):
                pygame.sprite.Sprite.__init__(self)

                #加载图片
                self.img1 = pygame.image.load("image/bird1.png").convert_alpha()
                self.img2 = pygame.image.load("image/bird2.png").convert_alpha()
                self.img3 = pygame.image.load("image/bird3.png").convert_alpha()

                #设置小鸟的初始位置为窗口1/4、高度1/2的位置
                self.width, self.height = bg_size[0], bg_size[1]
                self.rect = self.img1.get_rect()
                self.rect.left, self.rect.top = self.width // 4, self.height // 2

                #设置小鸟的初速度、加速度、路程、时间
                self.v = 20
                self.g = 2
                self.s = 0
                self.t = 0.2

        #小鸟向下飞行的方法
        def drop(self):
                self.v = self.v-self.g*self.t
                self.s = self.v*self.t - 0.5*self.g*self.t*self.t
                self.rect.top = self.rect.top-self.s

        #小鸟向上飞行的方法
        def fly(self):
                self.v = 10

在主函数里面绘制小鸟,并实现小鸟的下落和按键后小鸟飞翔,以及小鸟飞翔挥动翅膀的声音

import Bird

#加载小鸟挥动翅膀的声音、小鸟撞击的声音
wings_sound = pygame.mixer.Sound("music/翅膀声.wav")
crash_sound = pygame.mixer.Sound("music/me_down.wav")

def main():
    #设置小鸟飞行挥动翅膀图片的切换flag
    change = 1
    #创建一个小鸟对象
    bird = Bird.Bird(bg_size)

    while True:

        #如果游戏还没结束
        if finish == False:
            
            #如果小鸟飞行超过上边界或者超过下边界,就播放撞击音乐,把finish置为True,表示程序结束
            if bird.rect.top < 0 or bird.rect.bottom > width:
                crash_sound.play()
                finish = True

            #切换小鸟飞行图片,以达到小鸟挥动翅膀的效果
            if change % 3 == 0:
                view.blit(bird.img1,bird.rect)  #绘制小鸟图片
            elif change % 3 == 1:
                view.blit(bird.img2,bird.rect)
            else:
                view.blit(bird.img3,bird.rect)
                
            change = change +1

            #调用小鸟对象的下落方法
            bird.drop()

        #如果键盘上面的↑按键被按下,就调用小鸟对象的向上飞行的方法,同时播放小鸟挥动翅膀的声音
        key_pressed = pygame.key.get_pressed()
        if key_pressed[pygame.K_UP]:
            wings_sound.play()
            bird.fly()
        
        #更新界面
        pygame.display.flip()
        #延迟10毫秒
        pygame.time.delay(10)


if __name__ == "__main__":
    main()

新建一个Tubing模块实现管子对象

import pygame
import random

#检测Sprite精灵类,方便用于碰撞检测
class Tubing_down(pygame.sprite.Sprite):
    def __init__(self):
    	pygame.sprite.Sprite.__init__(self)

        #加载图片,设置下面管子的显示位置
    	self.pipe = pygame.image.load("image/管子.png").convert_alpha()
    	self.rect = self.pipe.get_rect()
    	self.rect.left = 903
    	self.rect.top = random.randint(120,495-40)

    #管子的移动方法
    def move(self):
    	self.rect.left = self.rect.left - 1


class Tubing_up(pygame.sprite.Sprite):
	def __init__(self,down_pipe):
                #加载图片,设置下面管子的显示位置,根据下面的管子来设置上面管子显示的位置,预留一些空间给小鸟飞行
		self.pipe = pygame.image.load("image/管子.png").convert_alpha()
		self.rect = self.pipe.get_rect()
		self.rect.left = 903
		self.rect.top = -(640-down_pipe.rect.top+120)

        #管子的移动方法
	def move(self):
		self.rect.left = self.rect.left - 1

在main模块里面实现管子的产生、绘制以及小鸟和管子发生碰撞的一系列事件

import Tubing 
from pygame.locals import *

#定义存放管子的数组,tubeUp_array代表存放上面的那条管子,tubeDown_array代表存放下面的那条管子
tubeUp_array = []
tubeDown_array = []

def main():
    #设置开始时间,用于每隔3秒就产生一对管子
    start_time = 0

    while True:

        #如果游戏还没结束
        if finish == False:

            #每3秒产生一对管子,一上一下,分别存放在ubeUp_array、tubeDown_array列表中
            end_time = pygame.time.get_ticks()
            if end_time - start_time >= 3000:
                tubeDown = Tubing.Tubing_down()
                tubeUp = Tubing.Tubing_up(tubeDown)
                tubeDown_array.append(tubeDown)
                tubeUp_array.append(tubeUp)
                start_time = end_time

            #判断小鸟精灵和管子精灵组有没有发生碰撞,如果发生了碰撞就播放碰撞音乐,同时将finish置为True
            Up_crash = pygame.sprite.spritecollide(bird, tubeUp_array, False)
            Down_crash = pygame.sprite.spritecollide(bird, tubeDown_array, False)
            if Up_crash or Down_crash:
                crash_sound.play()
                finish = True             

            #显示管子和移动管子
            for i in range(len(tubeDown_array)):
                view.blit(tubeDown_array[i].pipe,tubeDown_array[i].rect)
                view.blit(tubeUp_array[i].pipe,tubeUp_array[i].rect)
                tubeDown_array[i].move()
                tubeUp_array[i].move()

if __name__ == "__main__":
    main()

实现小鸟飞过一对管子就分数+1,同时把分数绘制显示出来

#设置分数显示的字体、
font = pygame.font.Font("font/font.ttf",35)

def main():
    #设置游戏的分数
score = 0

    while True:
        

        #如果游戏还没结束
        if finish == False:
            

            #小鸟每飞过一对管子分数就加1,显示管子和移动管子
            for i in range(len(tubeDown_array)):
                if bird.rect.right == tubeUp_array[i].rect.right:
                    score = score +1 
          
            #绘制分数
            font_view = font.render('score = %s' %str(score),True,(255,255,255))  
            view.blit(font_view,(10,5)) 

        
        #更新界面
        pygame.display.flip()
        #延迟10毫秒
        pygame.time.delay(10)


if __name__ == "__main__":
    main()

绘制游戏结束后的界面

from pygame.locals import *

#设置游戏结束之后显示最高分数等字的字体
gameover_font = pygame.font.Font("font/font.ttf", 48)

#加载游戏结束后重新开始按键图片、游戏结束后退出游戏按键图片
again_image = pygame.image.load("image/again.png").convert_alpha()
gameover_image = pygame.image.load("image/gameover.png").convert_alpha()

def main():

    #reader用于判断record.txt(存储最高分)的文件是否已经被打开(已经打开为True)
    reader = False

    #获取重新开始按键的方框、获取结束游戏按键的方框
    again_rect = again_image.get_rect()
    gameover_rect = gameover_image.get_rect()

    while True:
        
        #如果游戏已经结束,停止背景音乐的播放,绘制游戏结束后的界面
        if finish == True:

            #如果record.txt文件还未打开过,打开record.txt文件,将reader 置为 True
            if not reader:
                reader = True
                # 读取历史最高分
                with open("record.txt", "r") as f:
                    record_score = int(f.read())

                #判断当前分数是否高于历史最高分,如果是,则写入record.txt文件中,同时将record_score赋值为最高分
                if score > record_score:
                    with open("record.txt", "w") as f:
                        record_score = score
                        f.write(str(score))

            #绘制游戏结束后的历史最高分
            record_score_text = font.render("Best: %d" % record_score, True, (255,255,255))
            view.blit(record_score_text, (50, 50))

            #绘制游戏结束后的我的分数
            gameover_text1 = gameover_font.render("Your Score: ", True, (255,255,255))
            gameover_text1_rect = gameover_text1.get_rect()
            gameover_text1_rect.left, gameover_text1_rect.top = \
                (width - gameover_text1_rect.width) // 2, height // 3
            view.blit(gameover_text1, gameover_text1_rect)

            gameover_text2 = gameover_font.render(str(score), True, (255,255,255))
            gameover_text2_rect = gameover_text2.get_rect()
            gameover_text2_rect.left, gameover_text2_rect.top = \
                (width - gameover_text2_rect.width) // 2, \
                gameover_text1_rect.bottom + 10
            view.blit(gameover_text2, gameover_text2_rect)

            #绘制重新开始按钮
            again_rect.left, again_rect.top = \
                (width - again_rect.width) // 2, \
                gameover_text2_rect.bottom + 50
            view.blit(again_image, again_rect)

            #绘制结束游戏按钮
            gameover_rect.left, gameover_rect.top = \
                (width - again_rect.width) // 2, \
                again_rect.bottom + 6
            view.blit(gameover_image, gameover_rect)
            
            # 检测用户的鼠标操作
            # 如果用户按下鼠标左键
        if pygame.mouse.get_pressed()[0]:
            pos = pygame.mouse.get_pos()
            if again_rect.left < pos[0] < again_rect.right and \
                    again_rect.top < pos[1] < again_rect.bottom:
                tubeUp_array.clear()
                tubeDown_array.clear()
                main()
            elif gameover_rect.left < pos[0] < gameover_rect.right and \
                    gameover_rect.top < pos[1] < gameover_rect.bottom:
                pygame.quit()
                sys.exit()

        #更新界面
        pygame.display.flip()
        #延迟10毫秒
        pygame.time.delay(10)


if __name__ == "__main__":
    main()

main模块的总体集合代码如下

import pygame
import sys
import traceback
import Tubing 
import random
import Bird
from pygame.locals import *

#初始化pygame 初始化pygame的扩音器
pygame.init()
pygame.mixer.init()

#定义存放管子的数组,tubeUp_array代表存放上面的那条管子,tubeDown_array代表存放下面的那条管子
tubeUp_array = []
tubeDown_array = []

#定义窗口的大小,也是背景图片的大小
bg_size = width,height = 903,495

#加载背景音乐、小鸟挥动翅膀的声音、小鸟撞击的声音
pygame.mixer.music.load("music/主界面BGM.mp3")
wings_sound = pygame.mixer.Sound("music/翅膀声.wav")
crash_sound = pygame.mixer.Sound("music/me_down.wav")

#设置分数显示的字体、游戏结束之后显示最高分数等字的字体
font = pygame.font.Font("font/font.ttf",35)
gameover_font = pygame.font.Font("font/font.ttf", 48)

#设置游戏窗口的大小和标题
view = pygame.display.set_mode(bg_size)
pygame.display.set_caption("像素鸟小游戏")

#加载背景图片、游戏结束后重新开始按键图片、游戏结束后退出游戏按键图片
background = pygame.image.load("image/BGM.png").convert()
again_image = pygame.image.load("image/again.png").convert_alpha()
gameover_image = pygame.image.load("image/gameover.png").convert_alpha()

def main():
    #设置开始时间,用于每隔3秒就产生一对管子
    start_time = 0
    #设置游戏的分数
    score = 0
    #设置小鸟飞行挥动翅膀图片的切换flag
    change = 1

    #finish定义游戏是否结束(结束则为True),reader用于判断record.txt(存储最高分)的文件是否已经被打开(已经打开为True)
    finish = False
    reader = False

    #获取重新开始按键的方框、获取结束游戏按键的方框
    again_rect = again_image.get_rect()
    gameover_rect = gameover_image.get_rect()

    #创建一个小鸟对象
    bird = Bird.Bird(bg_size)

    #开始循环播放背景音乐
    pygame.mixer.music.play(-1)
    while True:
        
        #如果点击了关闭事件就退出程序
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        #如果游戏还没结束
        if finish == False:
            
            #如果小鸟飞行超过上边界或者超过下边界,就播放撞击音乐,把finish置为True,表示程序结束
            if bird.rect.top < 0 or bird.rect.bottom > width:
                crash_sound.play()
                finish = True

            #绘制背景图片
            view.blit(background,(0,0))

            #切换小鸟飞行图片,以达到小鸟挥动翅膀的效果
            if change % 3 == 0:
                view.blit(bird.img1,bird.rect)  #绘制小鸟图片
            elif change % 3 == 1:
                view.blit(bird.img2,bird.rect)
            else:
                view.blit(bird.img3,bird.rect)
                
            change = change +1

            #每3秒产生一对管子,一上一下,分别存放在ubeUp_array、tubeDown_array列表中
            end_time = pygame.time.get_ticks()
            if end_time - start_time >= 3000:
                tubeDown = Tubing.Tubing_down()
                tubeUp = Tubing.Tubing_up(tubeDown)
                tubeDown_array.append(tubeDown)
                tubeUp_array.append(tubeUp)
                start_time = end_time

            #判断小鸟精灵和管子精灵组有没有发生碰撞,如果发生了碰撞就播放碰撞音乐,同时将finish置为True
            Up_crash = pygame.sprite.spritecollide(bird, tubeUp_array, False)
            Down_crash = pygame.sprite.spritecollide(bird, tubeDown_array, False)
            if Up_crash or Down_crash:
                crash_sound.play()
                finish = True             

            #小鸟每飞过一对管子分数就加1,显示管子和移动管子
            for i in range(len(tubeDown_array)):
                if bird.rect.right == tubeUp_array[i].rect.right:
                    score = score +1 
                view.blit(tubeDown_array[i].pipe,tubeDown_array[i].rect)
                view.blit(tubeUp_array[i].pipe,tubeUp_array[i].rect)
                tubeDown_array[i].move()
                tubeUp_array[i].move()
          
            #绘制分数
            font_view = font.render('score = %s' %str(score),True,(255,255,255))  
            view.blit(font_view,(10,5)) 

            #调用小鸟对象的下落方法
            bird.drop()

        #如果游戏已经结束,停止背景音乐的播放,绘制游戏结束后的界面
        if finish == True:
            pygame.mixer.music.stop()

            #如果record.txt文件还未打开过,打开record.txt文件,将reader 置为 True
            if not reader:
                reader = True
                # 读取历史最高分
                with open("record.txt", "r") as f:
                    record_score = int(f.read())

                #判断当前分数是否高于历史最高分,如果是,则写入record.txt文件中,同时将record_score赋值为最高分
                if score > record_score:
                    with open("record.txt", "w") as f:
                        record_score = score
                        f.write(str(score))

            #绘制游戏结束后的历史最高分
            record_score_text = font.render("Best: %d" % record_score, True, (255,255,255))
            view.blit(record_score_text, (50, 50))

            #绘制游戏结束后的我的分数
            gameover_text1 = gameover_font.render("Your Score: ", True, (255,255,255))
            gameover_text1_rect = gameover_text1.get_rect()
            gameover_text1_rect.left, gameover_text1_rect.top = \
                (width - gameover_text1_rect.width) // 2, height // 3
            view.blit(gameover_text1, gameover_text1_rect)

            gameover_text2 = gameover_font.render(str(score), True, (255,255,255))
            gameover_text2_rect = gameover_text2.get_rect()
            gameover_text2_rect.left, gameover_text2_rect.top = \
                (width - gameover_text2_rect.width) // 2, \
                gameover_text1_rect.bottom + 10
            view.blit(gameover_text2, gameover_text2_rect)

            #绘制重新开始按钮
            again_rect.left, again_rect.top = \
                (width - again_rect.width) // 2, \
                gameover_text2_rect.bottom + 50
            view.blit(again_image, again_rect)

            #绘制结束游戏按钮
            gameover_rect.left, gameover_rect.top = \
                (width - again_rect.width) // 2, \
                again_rect.bottom + 6
            view.blit(gameover_image, gameover_rect)
            # 检测用户的鼠标操作
            # 如果用户按下鼠标左键
        if pygame.mouse.get_pressed()[0]:
            pos = pygame.mouse.get_pos()
            if again_rect.left < pos[0] < again_rect.right and \
                    again_rect.top < pos[1] < again_rect.bottom:
                tubeUp_array.clear()
                tubeDown_array.clear()
                main()
            elif gameover_rect.left < pos[0] < gameover_rect.right and \
                    gameover_rect.top < pos[1] < gameover_rect.bottom:
                pygame.quit()
                sys.exit()

        #如果键盘上面的↑按键被按下,就调用小鸟对象的向上飞行的方法,同时播放小鸟挥动翅膀的声音
        key_pressed = pygame.key.get_pressed()
        if key_pressed[pygame.K_UP]:
            wings_sound.play()
            bird.fly()
        
        #更新界面
        pygame.display.flip()
        #延迟10毫秒
        pygame.time.delay(10)


if __name__ == "__main__":
    main()

4、实验

实验运行结果如下:

5、总结和展望

不足之处:
1、没有实现小鸟向上飞行的时候,头朝上。往下坠落的时候,头往下
参考文献:
[1] 小甲鱼的飞机大战视频

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服