首页 > 编程语言 >【Python实战项目】用Python制作游戏—pygame超级玛丽!游戏开发

【Python实战项目】用Python制作游戏—pygame超级玛丽!游戏开发

时间:2024-07-13 14:57:49浏览次数:23  
标签:障碍物 游戏 Python self 玛丽 超级玛丽 窗体 pygame image

在这里插入图片描述


1、需求分析

具备功能
  • 播放与停止背景音乐
  • 随机生成管道与导弹障碍
  • 显示积分
  • 跳跃躲避障碍
  • 碰撞障碍

2、游戏功能结构

  • 玛丽冒险的功能结构主要分为三类,分别为音效、主窗体以及随机出现的障碍物。如下图
    在这里插入图片描述

3、游戏业务流程

  • 根据该游戏的需求分析以及功能结构
    在这里插入图片描述

##- 、游戏预览
在这里插入图片描述


5、开发必备

游戏开发运行环境
  • python3.7 以上
  • 开发工具 PyCharm
  • Python 内置模块:itertools、random
  • 第三方模块:pygame
文件夹组织结构
  • 玛丽冒险游戏的文件夹组织结构主要分为: audio(保存音效文件)和 image (保存图片)
    在这里插入图片描述

6、玛丽冒险游戏实现

6.1 游戏窗体的实现
  • 在实现游戏窗体时,首先需要定义窗体的宽度与高度,然后通过 ygame 模块中的 init0 方法,实现初始化功能,接下来需要创建循环,在循环中通过 pdate0 函数不断更新窗体,最后需要判断用户是否单击了关闭窗体的按钮,如果单击了“关闭”按钮,将关闭窗体,否则继续循环显示窗体
    在这里插入图片描述

通过 pygame 模块实现玛丽主窗体具体步骤如下
  • 创建文件夹,一个保存音频,一个图片,创建 marie.py 文件
  • 导入 pygame 库与 pygame 中的常用库,然后定义窗体宽度与高度
import pygame   
from pygame.locals import *   import sys      
# 设置游戏窗口的宽度和高度   
SCREENWIDTH = 822   SCREENHEIGHT = 199   
# 设置游戏帧率   
FPS = 60   
  • 创建 mainGame0 方法,在该方法中首先进行 pygame 的初始化工作,然后创建时间对象用于更新窗体中的画面,再创建窗体实例并设置窗体的标题文字,最后通过循环实现窗体的显示与刷新。
def mainGame():       
score = 0       
over = False       
global SCREEN, FPSCLOCK       
# 初始化pygame库       
pygame.init()       
# 初始化时钟对象       
FPSCLOCK = pygame.time.Clock()       
# 创建窗口对象       
SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))       
# 设置窗口标题      
pygame.display.set_caption("玛丽冒险")          
while True:           
# 处理游戏事件           
for event in pygame.event.get():               
if event.type == QUIT:                   
pygame.quit()                   
sys.exit()              
# 更新窗口内容           
pygame.display.update()              
# 控制帧率           
FPSCLOCK.tick(FPS)         
if __name__ == "__main__":       
mainGame()   

6.2地图加载

在这里插入图片描述


创建一个名称为 MyMap 的滚动地图类,然后在该类的初始化方法中加载背景图片和定义 X 与 Y 的坐标
class MyMap():       
def __init__(self, x, y):           
self.bg = pygame.image.load("image/bg.png").convert_alpha()           
self.x = x           
self.y = y   
  • 在 MyMap 类中创建 map _rolling0 方法,在该方法中根据地图背景图片的 X 坐标判断是否移出窗体,如果移出就给图片设置一个新的坐标点,否则按照每次 5 个像素的跨度向左移动
def map_rolling(self):           
if self.x < -790:               
self.x = 800           
else:               
self.x -= 5
  • 在 MyMap 类中创建 map update0 方法,在该方法中实现地图无限滚动的效果
def map_update(self):           
SCREEN.blit(self.bg,(self.x,self.y))
  • 在 mainGame0 方法中,设置标题文字代码的下面创建两个背景图片的对象
bg1 = MyMap(0,0)       
bg2 = MyMap(800,0)
  • 在 mainGame0 方法的循环中,实现无限循环滚动的地图
if over == False:                   
bg1.map_update()                   
bg1.map_rolling()                   
bg2.map_update()                   
bg2.map_rolling()

6.3玛丽的跳跃功能
  • 在实现玛丽的跳跃功能时,首先需要指定玛丽的固定坐标,也就是默认显示在地图上的固定位置,然后判断是否按下了键盘中的(空格)键,如果按下了就开启玛丽的跳跃开关,让玛丽以 5 个像素的距离向上移动。当玛丽到达窗体顶部的边缘时,再让玛丽以 5 个像素的距离向下移动,回到地面后关闭跳跃的开关。玛丽跳跃功能的业务流程如图
    在这里插入图片描述

  • 导入选代工具,创建一个名称为 Marie 的玛丽类,然后在该类的初始化方法中,首先定义玛丽跳跃时所需要的变量,然后加载玛丽跑动的三张图片,最后加载玛丽跳跃时的音效并设置玛丽默认显示的坐标位置

from itertools import cycle      
# 玛丽类   
class Marie():       
def __init__(self):           
# 初始化角色矩形对象           
self.rect = pygame.Rect(0, 0, 0, 0)           
# 角色跳跃状态,默认为False           
self.jumpState = False           
# 角色跳跃高度           
self.jumpHeight = 130           
# 角色最低y坐标           
self.lowest_y = 140           
# 角色已经跳跃的高度           
self.jumpValue = 0              
# 角色动作图片索引          
self.marieIndex = 0          
# 产生循环的角色动作图片索引值生成器           
self.marieIndexGen = cycle([0, 1, 2])              
# 角色动作图片元组           
self.adventure_img = (               
pygame.image.load("image/adventure1.png").convert_alpha(),               
pygame.image.load("image/adventure2.png").convert_alpha(),               
pygame.image.load("image/adventure3.png").convert_alpha(),           
)              
# 角色跳跃音频           
self.jump_audio = pygame.mixer.Sound("audio/jump.wav")           
# 设置角色矩形对象的大小为第一张动作图片的大小           
self.rect.size = self.adventure_img[0].get_size()              
# 角色初始位置           
self.x = 50           
self.y = self.lowest_y           
self.rect.topleft = (self.x, self.y)   
  • 在 Marie 类中创建 move 方法,在该方法中判断如果玛丽的跳跃开关开启时,再判断玛丽是否在地面上,如果满足这两个条件玛丽就以 5 个像素的距离向上移动。当玛丽到达窗体顶部时以 5 个像素的距离向下移动,当玛丽回到地面后关闭跳跃开关
# 玛丽移动       
def move(self):           
if self.jumpState:              
# 如果角色的y坐标大于等于最低y坐标,设置跳跃值为-5               
if self.rect.y >= self.lowest_y:                   
self.jumpValue = -5                  
# 如果角色的y坐标小于等于最低y坐标减去跳跃高度,设置跳跃值为5               
if self.rect.y <= self.lowest_y - self.jumpHeight:                   
self.jumpValue = 5                  
# 修改角色的y坐标               
self.rect.y += self.jumpValue                  
# 如果角色的y坐标大于等于最低y坐标,设置跳跃状态为False               
if self.rect.y >= self.lowest_y:                   
self.jumpState = False`
  • 在 Marie 类中创建 draw marie0 方法,在该方法中首先匹配玛丽跑步的动图,然后进行玛丽的绘制
#绘制玛丽       
def draw_marie(self):          
marieIndex = next(self.marieIndexGen)           
SCREEN.blit(self.adventure_img[marieIndex],(self.x,self.rect.y))`
  • 在 mainGame()方法中,创建地图对象的代码下面创建玛丽对象
marie = Marie()
  • 在 mainGame0 方法的 while 循环中,判断关闭窗体的下面判断是否按下了键盘中的 space>(空格)键,如果按下了就开启玛丽跳跃开关并播放跳跃音效
if event.type == KEYDOWN and event.key == K_SPACE:       
# 如果玛丽的y坐标大于等于最低y坐标,播放跳跃音频,调用跳跃方法       
if marie.rect.y >= marie.lowest_y:           
marie.jump_audio.play()           
marie.jump()   
  • 在 mainGame0 方法中,绘制地图的代码下面实现玛丽的移动与绘制功能
marie.move()                   
marie.draw_marie()

6.4随机出现障碍
  • 在实现障碍物的出现时,首先需要考虑到障碍物的大小以及障碍物不能相同,如果每次出现的障碍物都是相同的那么该游戏将失去了游戏的乐趣。所以需要加载两个大小不同的障碍物图片,然后随机抽选并显示,还需要通过计算来设置出现一个障碍并将障碍物显示在窗体当中的时间间隔
    在这里插入图片描述
  • 导入随机数,创建一个名称为 Obstacle 的障碍物类,在该类中定义一个分数,然后在初始化方法中加载障碍物图片、分数图片以及加分音效。创建 0 至 1 的随机数字,根据该数字抽选障碍物是管道还是飞行的导弹,最后根据图片的宽、高创建障碍物矩形的大小并设置障碍物的绘制坐标
class Obstacle():       
score = 1  
# 初始化分数变量为1       
move = 5  
# 设置移动速度为5       
obstacle_y = 150  
# 设置障碍物的y坐标为150          
def __init__(self):           
self.rect = pygame.Rect(0,0,0,0)  
# 创建用于碰撞检测的矩形对象           
self.missile = pygame.image.load("image/missile.png").convert_alpha()  
# 加载导弹图片           
self.pipe = pygame.image.load("image/pipe.png").convert_alpha()  
# 加载管道图片           
self.numbers = (  
# 加载数字图片               
pygame.image.load("image/0.png").convert_alpha(),               
pygame.image.load("image/1.png").convert_alpha(),               
pygame.image.load("image/2.png").convert_alpha(),               
pygame.image.load("image/3.png").convert_alpha(),               
pygame.image.load("image/4.png").convert_alpha(),               
pygame.image.load("image/5.png").convert_alpha(),               
pygame.image.load("image/6.png").convert_alpha(),               
pygame.image.load("image/7.png").convert_alpha(),               
pygame.image.load("image/8.png").convert_alpha(),               
pygame.image.load("image/9.png").convert_alpha(),           
)              
self.score_audio = pygame.mixer.Sound("audio/score.wav")  
# 加载得分音效              
r = random.randint(0,1)  
# 生成随机数0或1              
if r == 0:               
# 如果随机数为0,设置障碍物为导弹,移动速度为15,y坐标为100               
self.image = self.missile               
self.move = 15               
self.obstacle_y = 100           
else:               
# 如果随机数为1,设置障碍物为管道               
self.image = self.pipe              
# 设置障碍物的大小和位置           
self.rect.size = self.image.get_size()           
self.width, self.height = self.rect.size           
self.x = 800  
# 设置障碍物的初始位置为屏幕右侧           
self.y = self.obstacle_y           
self.rect.center = (self.x ,self.y)   
  • 在 Obstacle 类中首先创建 obstacle move0 方法,用于实现障碍物的移动,然后创建 drawobstacle()方法用于实现绘制障碍物
#障碍物移动       
def obstacle_move(self):           
self.rect.x -= self.move    
#绘制障碍物       
def draw_obstacle(self):           
SCREEN.blit(self.image,(self.rect.x, self.rect.y))
  • 在 mainGame()方法中,创建定义添加障碍物的时间与障碍物对象列表(玛丽对象的代码下面)
addObstackeTimer = 0       
list = []
  • 在 mainGame()方法中绘制计算障碍物出现的间隔时间(玛丽对象的代码下面)
if addObstackeTimer >= 100:  # 如果生成障碍物的计时器达到100       
r = random.randint(0, 50)  # 生成一个0到50之间的随机数       
if r > 15:  # 如果随机数大于15           
obstacle = Obstacle()  # 创建一个障碍物对象           
list.append(obstacle)  # 将障碍物对象添加到列表中   
addObstackeTimer = 0  # 重置生成障碍物的计时器为0   
  • 在 mainGame0 方法中计算循环遍历障碍物并进行障碍物的绘制(障碍物间隔时间代码的下面)
for i in range(len(list)):                   
list[i].obstacle_move()                   
list[i].draw_obstacle()`
  • 在 mainGame0 方法中更新整个窗体代码的上面,增加障碍物时间
addObstackeTimer += 10   

6.5背景音乐的播放与停止
  • 创建 Music Button 类,在该类中首先初始化背景音乐的音效文件与按钮图片,然后创建 isselect0 方法用于判断鼠标是否在按钮范围内
# 背景音乐按钮   
class Music_Button():       
is_open = True  
# 背景音乐是否开启的状态标志          
def __init__(self):           
# 加载开启和关闭按钮的图像资源           
self.open_img = pygame.image.load("image/btn_open.png").convert_alpha()           
self.close_img = pygame.image.load("image/btn_close.png").convert_alpha()           
# 加载背景音乐的音频文件           
self.bg_music = pygame.mixer.Sound("audio/bg_music.wav")          
def is_select(self):           
# 获取鼠标的位置           
point_x, point_y = pygame.mouse.get_pos()           
# 获取开启按钮图像的宽度和高度           
w, h = self.open_img.get_size()              
# 判断鼠标是否在按钮范围内           
in_x = point_x > 20 and point_x < 20 + w           
in_y = point_y > 20 and point_y < 20 + h              
return in_x and in_y   
  • mainGame 方法中障碍物对象列表代码的下面,创建背景音乐按钮对象,然后设置按钮默认图片,最后循环播放背景音乐。
muscic_button = Music_Button()       
btu_img = muscic_button.open_img       
muscic_button.bg_music.play(-1)
  • 在 mainGame0 方法的 while 循环中,获取单击事件代码的下面实现单击按钮控制背景音乐的播放与停止功能
if event.type == pygame.MOUSEBUTTONUP:       
# 判断是否为鼠标按键抬起事件       
if muscic_button.is_select():           
# 判断鼠标是否在背景音乐按钮范围内           
if muscic_button.is_open:               
# 如果背景音乐当前是开启状态               
btu_img = muscic_button.close_img               
muscic_button.is_open = False               
muscic_button.bg_music.stop()           
else:               
# 如果背景音乐当前是关闭状态               
btu_img = muscic_button.open_img               
muscic_button.is_open = True               
muscic_button.bg_music.play(-1)   
  • 在 mainGame()方法中添加障碍物时间代码的下面,绘制背景音乐按钮
SCREEN.blit(btu_img, (20, 20))   

####- 6.6碰撞与积分功能实现

  • 在实现碰撞与积分时,首先需要判断玛丽与障碍物的两个矩形图片是否发生了碰撞,如果发生了碰撞就证明该游戏已经结束,否则判断玛丽是否跃过了障碍物,确认越过后进行加分操作并将分数显示在窗体顶部右侧的位置。
    在这里插入图片描述
  • 在 Obstacle 类中,draw obstacle0 方法的下面创建 getScore0 方法用于获取分数并播放加分音效,然后创建 showScore() 方法用于在窗体顶部右侧的位置显示分数
def getSocre(self):       
"""       获取分数并重置分数为0       """       
# 获取当前的分数       
tmp = self.score       
# 如果分数为1,播放分数音效       
if tmp == 1:           
self.score_audio.play()       
# 将分数重置为0       
self.score = 0       
# 返回原来的分数       
return tmp         
# 显示分数   
def showScore(self, score):      
 """       在游戏界面上显示分数       """       
 # 将分数转换为一个数字列表       
 self.scoreDigits = [int(x) for x in list(str(score))]       
 # 计算所有数字图像的总宽度       
 totalWidth = 0       
 for digit in self.scoreDigits:           
 totalWidth += self.numbers[digit].get_width()          
 # 计算数字图像的起始横坐标      
 Xoffset = (SCREENWIDTH - (totalWidth + 30))          
 # 遍历分数的每个数字,将对应的数字图像绘制到屏幕上      
 for digit in self.scoreDigits:           
 # 绘制数字图像到屏幕上,并更新Xoffset的值           
 SCREEN.blit(self.numbers[digit], (Xoffset, SCREENHEIGHT * 0.1))           
 Xoffset += self.numbers[digit].get_width()   
  • 在 mainGame()方法的上面最外层创建 game over()方法,在该方法中首先需要加载与播放撞击的音效,然后获取窗体的宽度与高度,最后加载游戏结束的图片并将该图片显示在窗体的中间位置
def game_over():       
# 播放碰撞音效       
bump_audio = pygame.mixer.Sound("audio/bump.wav")      
bump_audio.play()          
# 获取屏幕的宽度和高度       
screen_w = pygame.display.Info().current_w       
screen_h = pygame.display.Info().current_h          
# 加载游戏结束图片       
over_img = pygame.image.load("image/gameover.png").convert_alpha()          
# 在屏幕上绘制游戏结束图片,位置居中显示在屏幕中央       
SCREEN.blit(over_img, ((screen_w - over_img.get_width()) / 2, (screen_h - over_img.get_height()) / 2))   
  • 在 mainGame()方法中,绘制障碍物代码的下面判断玛丽与障碍物是否发生碰撞,如果发生了碰撞则开启游戏结束的开关,并调用游戏结束的方法显示游戏结束的图片,否则判断玛丽是否跃过了障碍物,越过就进行分数的增加并显示当前得分
if pygame.sprite.collide_rect(marie, list[i]):       
# 玛丽与物品发生碰撞       
over = True  # 游戏结束标志设为True       
game_over()  # 显示游戏结束画面       
music_button.bg_music.stop() 
# 停止播放背景音乐   
else:       
if (list[i].rect.x + list[i].rect.width) < marie.rect.x:           
# 物品已完全移出玛丽的右侧,计入分数           
score += list[i].getSocre()   
list[i].showScore(score)   
  • 为了实现游戏结束后再次按下键盘上的(空格)键时,重新启动游戏。所以需要在 mainGame0 方法中开启玛丽跳的状态代码的下面判断游戏结束的开关是否开启,如果开启将重新调用 mainGame0)方法重新启动游戏
if over == True:    mainGame()   

7、结束

最后这里免费分享给大家一份Python全台学习资料,包含视频、源码。课件,希望能帮到那些不满现状,想提升自己却又没有方向的朋友,也可以和我一起来学习交流呀。
编程资料、学习路线图、源代码、软件安装包等!【点击这里】领取!

Python所有方向的学习路线图,清楚各个方向要学什么东西
100多节Python课程视频,涵盖必备基础、爬虫和数据分析
100多个Python实战案例,学习不再是只会理论
华为出品独家Python漫画教程,手机也能学习
历年互联网企业Python面试真题,复习时非常方便****
在这里插入图片描述
在这里插入图片描述

标签:障碍物,游戏,Python,self,玛丽,超级玛丽,窗体,pygame,image
From: https://blog.csdn.net/m0_75067840/article/details/140377542

相关文章

  • 用Python生成一个漂亮的圣诞节词云
    展示效果代码#-*-coding:UTF-8-*-importjiebaimportrefromstylecloudimportgen_stylecloudfromPILimportImageimportnumpyasnpwithopen('./圣诞素材/Christmas.txt',encoding="utf-8")asf:data=f.read()#文本预处理去除一些无用的字符......
  • 全栈物联网项目:结合 C/C++、Python、Node.js 和 React 开发智能温控系统(附代码示例)
    1.项目概述本文详细介绍了一个基于STM32微控制器和AWSIoT云平台的智能温控器项目。该项目旨在实现远程温度监控和控制,具有以下主要特点:使用STM32F103微控制器作为主控芯片,负责数据采集、处理和控制逻辑采用DHT22数字温湿度传感器,精确采集环境温湿度数据通过ESP8266WiF......
  • 全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则
    全网最适合入门的面向对象编程教程:16类和对象的Python实现-多态、方法重写与开闭原则摘要:本文主要介绍了Python中创建自定义类时子类如何实现对父类方法的重写、方法重写的定义和多态的基本概念,并对开闭原则进行介绍。原文链接:FreakStudio的博客往期推荐:学嵌入式的你,......
  • 【华为OD】D卷真题100分:阿里巴巴找黄金宝箱(III) python代码实现[思路+代码]
    【华为OD】2024年C、D卷真题集:最新的真题集题库C/C++/Java/python/JavaScript【华为OD】2024年C、D卷真题集:最新的真题集题库C/C++/Java/python/JavaScript-CSDN博客Java、JS、python、C、C++代码实现:【华为OD】D卷真题100分:阿里巴巴找黄金宝箱(III)Java代码实现[思路+代......
  • [python][whl]causal-conv1d的python模块在windows上whl文件下载
    【模块介绍】causal-conv1d,即因果一维卷积(Causal1DConvolution),是一种在深度学习特别是时序数据处理中广泛应用的卷积技术。它主要特点在于其“因果性”,即输出的每个元素仅依赖于输入序列中它之前的元素,而不考虑未来的输入。这种特性使得因果一维卷积在处理如语音处理、时间......
  • 【PyQt5连接Mysql】python连接成功记录(版本对应)-最新
    在做一个qt登陆注册界面时,不得不使用数据库的连接,但是一直连接失败,记录一下个人成功解决的方法,希望能帮到各位。我的版本为Qt5VersionNumberis:5.15.2,PyQt5Versionis:5.15.10,Mysql8.0。参考:①PyCharm+PyQt5(5.15.2)+mysql,PyQt5连接mysql,踩坑与解决办法②PyQt5连......
  • 可视化课设总结(星巴克网页爬取信息,百度地图网页版爬取信息,百度地图api,pyecharts库,pyth
    一、引言       本博客是本人是基于本人可视化课设所做的总结,其中有些过程的实现可能并不是最优的实现方法,有些实现效果也因为本人的实力有限,并不能达到预期的效果,所以也欢迎大家指点和改良。(刚考完期末回家,终于有时间把这个课设写个博客了,虽然这课设是明天截至的,我今......
  • python制作甘特图的基本知识(附Demo)
    目录前言1.matplotlib2.plotly前言甘特图是一种常见的项目管理工具,用于表示项目任务的时间进度直观地看到项目的各个任务在时间上的分布和进度常用的绘制甘特图的工具是matplotlib和plotly主要以Demo的形式展示1.matplotlib功能强大的绘图库,适合制作静态......
  • RC-u3 骰子游戏
    目录题目描述:输入格式:输出格式:输入样例:输出样例:样例说明:解题思路(DFS)完整代码(C++)题目描述:在某个游戏中有一个骰子游戏。在游戏中,你需要投掷5个标准六面骰子(骰子为一个正方体,6个面上分别有1、2、3、4、5、6中的一个数字,骰子的质量均匀),投出的点数根据组......
  • python 基础七 解析之 BeautifulSoup
    基本简介:安装以及创建:节点定位:节点信息:星巴克爬取:frombs4importBeautifulSoupimporturllib.requesturl='https://www.starbucks.com.cn/menu/'resp=urllib.request.urlopen(url)context=resp.read().decode('utf-8')soup=BeautifulSoup(conte......