Bootstrap

毕业设计 飞扬的小鸟小游戏设计与实现 (源码)


0 项目简介

🔥 Hi,各位同学好呀,这里是L学长!

🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品

python小游戏毕设 飞扬的小鸟小游戏设计与实现 (源码)

🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分)


1 游戏介绍

没错,《flappy bird》是一款由来自越南的独立游戏开发者Dong Nguyen所开发的作品,游戏于2013年5月24日上线,并在2014年2月突然暴红。

游戏规则:

游戏玩法非常简单,通过点击屏幕,使小鸟一直飞并穿过水管的空隙。虽然玩法简单,但是却具有一定的难度,因为要一直控制小鸟飞在适合的高度,以避开障碍。

这篇文章呢,就来分析这个游戏的原理,以及用python做一个简易版的FlappyBird。

2 实现效果

在这里插入图片描述

在这里插入图片描述

3 开发工具

3.1 环境配置

  • Python版本:3.6.4

  • 相关模块:

  • pygame模块;

  • 以及一些Python自带的模块。

3.2 Pygame介绍

简介

Pygame是一系列专门为编写电子游戏而设计的Python模块(modules)。Pygame在已经非常优秀的SDL库的基础上增加了许多功能。这让你能够用Python语言编写出丰富多彩的游戏程序。

Pygame可移植性高,几乎能在任何平台和操作系统上运行。

Pygame已经被下载过数百万次。

Pygame免费开源。它在LGPL许可证(Lesser General Public License,GNU宽通用公共许可证)下发行。使用Pygame,你可以创造出免费开源,可共享,或者商业化的游戏。详情请见LGPL许可证。

优点

  • 能够轻松使用多核CPU(multi core CPUs) :如今双核CPU很常用,8核CPU在桌面系统中也很便宜,而利用好多核系统,能让你在你的游戏中实现更多东西。特定的pygame函数能够释放令人生畏的python GIL(全局解释器锁),这几乎是你用C语言才能做的事。

  • 核心函数用最优化的C语言或汇编语言编写:C语言代码通常比Python代码运行速度快10-20倍。而汇编语言编写的代码(assembly code)比Python甚至快到100多倍。

  • 安装便捷:一般仅需包管理程序或二进制系统程序便能安装。

  • 真正地可移植:支持Linux (主要发行版), Windows (95, 98, ME, 2000, XP, Vista, 64-bit Windows,), Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX等操作系统.也能支持AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS and OS/2,但是还没有受到官方认可。你也可以在手持设备,游戏控制台, One Laptop Per Child (OLPC) computer项目的电脑等设备中使用pygame.

  • 用法简单:无论是小孩子还是大人都能学会用pygame来制作射击类游戏。

  • 很多Pygame游戏已发行:其中包括很多游戏大赛入围作品、非常受欢迎的开源可分享的游戏。

  • 由你来控制主循环:由你来调用pygame的函数,pygame的函数并不需要调用你的函数。当你同时还在使用其他库来编写各种各种的程序时,这能够为你提供极大的掌控权。

  • 不需要GUI就能使用所有函数:仅在命令行中,你就可以使用pygame的某些函数来处理图片,获取游戏杆输入,播放音乐……

  • 对bug反应迅速:很多bug在被上报的1小时内就能被我们修复。虽然有时候我们确实会卡在某一个bug上很久,但大多数时候我们都是很不错的bug修复者。如今bug的上报已经很少了,因为许多bug早已被我们修复。

  • 代码量少:pygame并没有数以万计的也许你永远用不到的冗杂代码。pygame的核心代码一直保持着简洁特点,其他附加物诸如GUI库等,都是在核心代码之外单独设计研发的。

  • 模块化:你可以单独使用pygame的某个模块。想要换着使用一个别的声音处理库?没问题。pygame的很多核心模块支持独立初始化与使用。

最小开发框架

import pygame,sys #sys是python的标准库,提供Python运行时环境变量的操控

pygame.init()  #内部各功能模块进行初始化创建及变量设置,默认调用
size = width,height = 800,600  #设置游戏窗口大小,分别是宽度和高度
screen = pygame.display.set_mode(size)  #初始化显示窗口
pygame.display.set_caption("小游戏程序")  #设置显示窗口的标题内容,是一个字符串类型
while True:  #无限循环,直到Python运行时退出结束
    for event in pygame.event.get():  #从Pygame的事件队列中取出事件,并从队列中删除该事件
        if event.type == pygame.QUIT:  #获得事件类型,并逐类响应
            sys.exit()   #用于退出结束游戏并退出          
    pygame.display.update()  #对显示窗口进行更新,默认窗口全部重绘

代码执行流程

在这里插入图片描述

4 具体实现

这里给大家介绍一下具体实现原理:

首先,我们来写个开始界面,让他看起来更像个游戏一些。效果大概是这样的:

在这里插入图片描述
原理也简单,关键点有三个:(1)下方深绿浅绿交替的地板不断往左移动来制造小鸟向前飞行的假象;(2)每过几帧切换一下小鸟的图片来实现小鸟翅膀扇动的效果:

在这里插入图片描述
(3)有规律地改变小鸟竖直方向上的位置来实现上下移动的效果。

具体而言,代码实现如下:

'''显示开始界面'''
def startGame(screen, sounds, bird_images, other_images, backgroud_image, cfg):
  base_pos = [0, cfg.SCREENHEIGHT*0.79]
  base_diff_bg = other_images['base'].get_width() - backgroud_image.get_width()
  msg_pos = [(cfg.SCREENWIDTH-other_images['message'].get_width())/2, cfg.SCREENHEIGHT*0.12]
  bird_idx = 0
  bird_idx_change_count = 0
  bird_idx_cycle = itertools.cycle([0, 1, 2, 1])
  bird_pos = [cfg.SCREENWIDTH*0.2, (cfg.SCREENHEIGHT-list(bird_images.values())[0].get_height())/2]
  bird_y_shift_count = 0
  bird_y_shift_max = 9
  shift = 1
  clock = pygame.time.Clock()
  while True:
    for event in pygame.event.get():
      if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
        pygame.quit()
        sys.exit()
      elif event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
          return {'bird_pos': bird_pos, 'base_pos': base_pos, 'bird_idx': bird_idx}
    sounds['wing'].play()
    bird_idx_change_count += 1
    if bird_idx_change_count % 5 == 0:
      bird_idx = next(bird_idx_cycle)
      bird_idx_change_count = 0
    base_pos[0] = -((-base_pos[0] + 4) % base_diff_bg)
    bird_y_shift_count += 1
    if bird_y_shift_count == bird_y_shift_max:
      bird_y_shift_max = 16
      shift = -1 * shift
      bird_y_shift_count = 0
    bird_pos[-1] = bird_pos[-1] + shift
    screen.blit(backgroud_image, (0, 0))
    screen.blit(list(bird_images.values())[bird_idx], bird_pos)
    screen.blit(other_images['message'], msg_pos)
    screen.blit(other_images['base'], base_pos)
    pygame.display.update()
    clock.tick(cfg.FPS)

点击空格键或者↑键进入主程序。对于主程序,在进行了必要的初始化工作之后,在游戏开始界面中实现的内容的基础上,主要还需要实现的内容有以下几个部分:

(1) 管道和深绿浅绿交替的地板不断往左移来实现小鸟向前飞行的效果;

(2) 按键检测,当玩家点击空格键或者↑键时,小鸟向上做加速度向下的均减速直线运动直至向上的速度衰减为0,否则小鸟做自由落体运动(实现时为了方便,可以认为在极短的时间段内小鸟的运动方式为匀速直线运动);

(3) 碰撞检测,当小鸟与管道/游戏边界碰撞到时,游戏失败并进入游戏结束界面。注意,为了碰撞检测更精确,我们使用:

pygame.sprite.collide_mask

来代替之前的:

pygame.sprite.collide_rect

(4) 进入游戏后,随机产生两对管道,并不断左移,当最左边的管道快要因为到达游戏界面的左边界而消失时,重新生成一对管道(注意不要重复生成);

(5) 当小鸟穿越一个上下管道之间的缺口时,游戏得分加一(注意不要重复记分)。

这里简单贴下主程序的源代码吧:

# 进入主游戏
score = 0
bird_pos, base_pos, bird_idx = list(game_start_info.values())
base_diff_bg = other_images['base'].get_width() - backgroud_image.get_width()
clock = pygame.time.Clock()
# --管道类
pipe_sprites = pygame.sprite.Group()
for i in range(2):
  pipe_pos = Pipe.randomPipe(cfg, pipe_images.get('top'))
  pipe_sprites.add(Pipe(image=pipe_images.get('top'), position=(cfg.SCREENWIDTH+200+i*cfg.SCREENWIDTH/2, pipe_pos.get('top')[-1])))
  pipe_sprites.add(Pipe(image=pipe_images.get('bottom'), position=(cfg.SCREENWIDTH+200+i*cfg.SCREENWIDTH/2, pipe_pos.get('bottom')[-1])))
# --bird类
bird = Bird(images=bird_images, idx=bird_idx, position=bird_pos)
# --是否增加pipe
is_add_pipe = True
# --游戏是否进行中
is_game_running = True
while is_game_running:
  for event in pygame.event.get():
    if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
      pygame.quit()
      sys.exit()
    elif event.type == pygame.KEYDOWN:
      if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
        bird.setFlapped()
        sounds['wing'].play()
  # --碰撞检测
  for pipe in pipe_sprites:
    if pygame.sprite.collide_mask(bird, pipe):
      sounds['hit'].play()
      is_game_running = False
  # --更新小鸟
  boundary_values = [0, base_pos[-1]]
  is_dead = bird.update(boundary_values, float(clock.tick(cfg.FPS))/1000.)
  if is_dead:
    sounds['hit'].play()
    is_game_running = False
  # --移动base实现小鸟往前飞的效果
  base_pos[0] = -((-base_pos[0] + 4) % base_diff_bg)
  # --移动pipe实现小鸟往前飞的效果
  flag = False
  for pipe in pipe_sprites:
    pipe.rect.left -= 4
    if pipe.rect.centerx < bird.rect.centerx and not pipe.used_for_score:
      pipe.used_for_score = True
      score += 0.5
      if '.5' in str(score):
        sounds['point'].play()
    if pipe.rect.left < 5 and pipe.rect.left > 0 and is_add_pipe:
      pipe_pos = Pipe.randomPipe(cfg, pipe_images.get('top'))
      pipe_sprites.add(Pipe(image=pipe_images.get('top'), position=pipe_pos.get('top')))
      pipe_sprites.add(Pipe(image=pipe_images.get('bottom'), position=pipe_pos.get('bottom')))
      is_add_pipe = False
    elif pipe.rect.right < 0:
      pipe_sprites.remove(pipe)
      flag = True
  if flag: is_add_pipe = True
  # --绑定必要的元素在屏幕上
  screen.blit(backgroud_image, (0, 0))
  pipe_sprites.draw(screen)
  screen.blit(other_images['base'], base_pos)
  showScore(screen, score, number_images)
  bird.draw(screen)
  pygame.display.update()
  clock.tick(cfg.FPS)

游戏结束后,进入游戏界面。没找到对应的游戏素材,所以只是让游戏界面静止了,然后小鸟做自由落体运行直到掉到地面上。代码实现如下:

'''游戏结束界面'''
def endGame(screen, sounds, showScore, score, number_images, bird, pipe_sprites, backgroud_image, other_images, base_pos, cfg):
  sounds['die'].play()
  clock = pygame.time.Clock()
  while True:
    for event in pygame.event.get():
      if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
        pygame.quit()
        sys.exit()
      elif event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE or event.key == pygame.K_UP:
          return
    boundary_values = [0, base_pos[-1]]
    bird.update(boundary_values, float(clock.tick(cfg.FPS))/1000.)
    screen.blit(backgroud_image, (0, 0))
    pipe_sprites.draw(screen)
    screen.blit(other_images['base'], base_pos)
    showScore(screen, score, number_images)
    bird.draw(screen)
    pygame.display.update()
    clock.tick(cfg.FPS)

再点击一下空格键或者↑键即可重新开始游戏。

5 最后

项目获取:https://gitee.com/sinonfin/system-sharing

;