Pygame制作简单的跑酷游戏

今天我们来看看如何使用Pygame框架制作一个简单的跑酷游戏。这个游戏包含了基本的游戏元素,如玩家角色、障碍物、背景、音效等,可以作为入门Pygame游戏开发的一个不错的示例。

游戏概述

这是一个简单的横版跑酷游戏,玩家控制一个忍者角色,通过跳跃来躲避迎面而来的各种障碍物(汽车、飞机、外星人等)。游戏有三个状态:准备、游戏中和结束。

主要的游戏元素包括:

玩家角色(忍者)
障碍物(汽车、飞机等)  
滚动背景
音效和背景音乐
计分系统
游戏UI(开始、结束界面等)

代码结构

游戏的主要代码结构如下:
class AudioManage:  # 音频管理
class BaseSprite:   # 基础精灵类
class EnemySprite:  # 敌人精灵  
class EnemyManage:  # 敌人管理
class PlayerSprite: # 玩家精灵
class PlayerManage: # 玩家管理 
class BGSprite:     # 背景精灵
class BGManage:     # 背景管理
class UISprite:     # UI精灵
class UIManage:     # UI管理
class GameManage:   # 游戏主管理类

关键实现

1. 玩家控制

玩家通过上键控制忍者跳跃:

def is_jump(self):if self.jump_count > 0:AudioManage().set_sound_music(5)self.jump_count -= 1self.velocity_y = -12self.jump()

2. 障碍物生成

通过定时器事件定期生成新的障碍物:

pygame.time.set_timer(ENEMY_BORN, BORN_RATE)# 在事件循环中
if event.type == ENEMY_BORN:self.enemy.broth()

3. 碰撞检测

使用pygame的sprite collision检测玩家与障碍物的碰撞:
 

r = pygame.sprite.groupcollide(self.enemy.enemy_group, self.player.player_group, False, False)
if r:# 处理碰撞后的游戏结束逻辑

4. 背景滚动

通过不断移动两个背景图片实现无缝滚动:

def update(self):self.rect.left -= self.speedif self.rect.left <= -WIDTH:self.rect.left = WIDTH

完整代码

这里我把我的代码放在这里,给大家做个参考,里面还有很多不完善的地方,图片素材什么的也需要大家自行寻找,我的素材大多数都是使用 " 非常糟糕的城市 " 这个游戏的图片素材。

import randomimport pygameWIDTH, HEIGHT = 500, 500
ENEMY_BORN = pygame.USEREVENT + 1
BORN_RATE = 3000class AudioManage:@staticmethoddef playing_bg_music():pygame.mixer.music.load("./music/紧张.mp3")pygame.mixer.music.play(loops=True)pygame.mixer.music.set_volume(0.3)@staticmethoddef ready_bg_music():pygame.mixer.music.load("./music/split.mp3")pygame.mixer.music.play(loops=True)pygame.mixer.music.set_volume(0.3)@staticmethoddef end_bg_music():pygame.mixer.music.load("./music/沮丧.mp3")pygame.mixer.music.play(loops=True)pygame.mixer.music.set_volume(0.3)@staticmethoddef set_sound_music(i):l0 = ["./music/汽车.mp3", "./music/直升机.mp3", "./music/飞机.mp3","./music/降落伞.mp3", "./music/外星人.mp3", "./music/跳跃.mp3","./music/失败.mp3"]pygame.mixer.Sound(l0[i]).play()class BaseSprite(pygame.sprite.Sprite):def __init__(self, image_name):super().__init__()self.image = pygame.image.load(image_name)self.rect = self.image.get_rect()class EnemySprite(BaseSprite):def __init__(self, image_name, em, speed=5):super().__init__(image_name)self.em = emself.image_name = image_nameself.image = pygame.transform.flip(self.image, True, False)self.set_pos()self.speed = speeddef set_pos(self):self.rect.left = WIDTHif self.image_name in ["./image/car1.png", "./image/car2.png", "./image/car3.png"]:AudioManage().set_sound_music(0)self.rect.bottom = 300elif self.image_name in ["./image/plan.png"]:AudioManage().set_sound_music(2)self.rect.bottom = 225elif self.image_name in ["./image/滑翔伞.png", "./image/直升机.png"]:if self.image_name == "./image/滑翔伞.png":AudioManage().set_sound_music(3)else:AudioManage().set_sound_music(1)self.rect.bottom = 150elif self.image_name in ["./image/外星人1.png", "./image/外星人2.png"]:AudioManage().set_sound_music(4)self.rect.bottom = 75def update(self):self.rect.left -= self.speedif self.rect.right < 0:self.kill()self.em.gm.ui.update_lab()class EnemyManage:def __init__(self, gm_):self.gm = gm_self.init_enemy()def init_enemy(self):self.enemy_group = pygame.sprite.Group()self.enemy = EnemySprite("./image/car1.png", self)self.enemy.add(self.enemy_group)def broth(self):em_img_name = random.choice(["./image/car1.png", "./image/car2.png", "./image/car3.png", "./image/外星人1.png", "./image/外星人2.png","./image/滑翔伞.png", "./image/直升机.png", "./image/plan.png"])self.enemy = EnemySprite(em_img_name, self)self.enemy.add(self.enemy_group)def clear(self):self.enemy_group.empty()def update(self):self.enemy_group.draw(self.gm.screen)self.enemy_group.update()class PlayerSprite(pygame.sprite.Sprite):def __init__(self, image_names):super().__init__()self.index = 0self.images = [pygame.image.load(image) for image in image_names]self.image = self.images[self.index]self.rect = self.image.get_rect()self.rect.bottom = 300self.rect.left = 100self.velocity_y = 0self.jump_count = 2def jump(self):if self.rect.bottom >= 300:self.jump_count = 2def is_jump(self):if self.jump_count > 0:AudioManage().set_sound_music(5)self.jump_count -= 1self.velocity_y = -12self.jump()def update(self):self.index += 1if self.index >= len(self.images) * 10:self.index = 0self.image = self.images[self.index // 10]self.velocity_y += 0.5self.rect.y += self.velocity_yself.jump()if self.rect.bottom > 300:self.rect.bottom = 300elif self.rect.top < 0:self.rect.top = 0class PlayerManage:def __init__(self, gm_):self.gm = gm_self.init_player()def init_player(self):self.player_group = pygame.sprite.Group()self.images = [f"./image/忍者{i}.png" for i in range(1, 3)]self.player = PlayerSprite(self.images)self.player.add(self.player_group)def broth(self):self.player = PlayerSprite([f"./image/忍者{i}.png" for i in range(1, 3)])self.player.add(self.player_group)def clear(self):self.player_group.empty()def update(self):if not self.player_group:self.broth()self.player.update()self.player_group.draw(self.gm.screen)class BGSprite(BaseSprite):def __init__(self, image_name, start_x, speed=3):super().__init__(image_name)self.rect.left = start_xself.speed = speeddef update(self):self.rect.left -= self.speedif self.rect.left <= -WIDTH:self.rect.left = WIDTHclass BGManage:def __init__(self, gm_):self.gm = gm_self.init_bg()def init_bg(self):self.bg_gaming_group = pygame.sprite.Group()self.bg1 = BGSprite("./image/load.png", 0)self.bg1.add(self.bg_gaming_group)self.bg2 = BGSprite("./image/load.png", WIDTH)self.bg2.add(self.bg_gaming_group)self.bg_ready_group = pygame.sprite.Group()self.bg3 = BGSprite("./image/background.png", 0)self.bg3.add(self.bg_ready_group)def update(self):if self.gm.game_state == "gaming":self.bg_gaming_group.draw(self.gm.screen)self.bg_gaming_group.update()else:self.bg_ready_group.draw(self.gm.screen)class UISprite(BaseSprite):def __init__(self, image_name, yes_no="yes", start_x=0, start_y=0):super().__init__(image_name)self.y_n = yes_noif self.y_n == "yes":self.rect.center = (WIDTH / 2, HEIGHT / 2)else:self.rect.left = start_xself.rect.top = start_ydef is_collide(self):mouse_pos = pygame.mouse.get_pos()if self.rect.collidepoint(mouse_pos):return Trueclass UIManage:def __init__(self, gm_ui):self.gm = gm_uiself.init_ready()self.init_end()self.font = pygame.font.Font("./font/幼圆.TTF", size=24)self.set_lab()def init_ready(self):self.ready_group = pygame.sprite.Group()self.ready_btn = UISprite("./image/ready.png")self.ready_btn.add(self.ready_group)def init_end(self):self.end_group = pygame.sprite.Group()self.end_btn = UISprite("./image/game_over.png")self.end_btn.add(self.end_group)self.con_btn = UISprite("./image/继续.png", "no", WIDTH - 180, HEIGHT - 88)self.con_btn.add(self.end_group)def set_lab(self):self.score_value = 0self.labile = self.font.render(f"score:{self.score_value}",True, "red")def update_lab(self):self.score_value += 1self.labile = self.font.render(f"score:{self.score_value}",True, "red")def check_collision(self):if self.gm.game_state == "ready":if self.ready_btn.is_collide():self.gm.game_state = "gaming"self.gm.set_time()AudioManage().playing_bg_music()elif self.gm.game_state == "end":if self.con_btn.is_collide():self.gm.game_state = "ready"AudioManage().ready_bg_music()def update(self):if self.gm.game_state == "ready":self.ready_group.draw(self.gm.screen)elif self.gm.game_state == "gaming":self.gm.screen.blit(self.labile, (200, 10))elif self.gm.game_state == "end":self.gm.screen.blit(self.labile, (210, 200))self.end_group.draw(self.gm.screen)class GameManage:def __init__(self):pygame.init()pygame.display.set_caption("小城跑酷")self.screen = pygame.display.set_mode((WIDTH, HEIGHT))self.game_state = "ready"self.ui = UIManage(self)self.bg = BGManage(self)self.player = PlayerManage(self)self.enemy = EnemyManage(self)self.clock = pygame.time.Clock()AudioManage().ready_bg_music()def set_time(self):pygame.time.set_timer(ENEMY_BORN, BORN_RATE)def check_event(self):for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()exit()if event.type == pygame.KEYUP:if event.key == pygame.K_UP or event.key == pygame.K_w:if self.game_state == "gaming":self.player.player.is_jump()if event.type == ENEMY_BORN:self.enemy.broth()if event.type == pygame.MOUSEBUTTONUP:if event.button == 1:self.ui.check_collision()def update_draw(self):self.bg.update()if self.game_state == "ready":self.ui.update()self.reset_score()elif self.game_state == "gaming":self.ui.update()self.player.update()self.enemy.update()elif self.game_state == "end":self.ui.update()pygame.display.flip()def check_collider(self):# passr = pygame.sprite.groupcollide(self.enemy.enemy_group, self.player.player_group, False, False)if r:for players in r.values():for player in players:player.kill()self.game_state = "end"self.enemy.clear()pygame.time.set_timer(ENEMY_BORN, 0)AudioManage().set_sound_music(6)AudioManage().end_bg_music()def reset_score(self):self.ui.score_value = -1self.ui.update_lab()def run(self):while True:self.clock.tick(60)self.check_event()self.update_draw()self.check_collider()gm = GameManage()
gm.run()

部分游戏截图:

总结

这个简单的跑酷游戏涵盖了游戏开发的许多基本要素。通过这个项目,我们可以学习到:

- Pygame的基本使用
- 精灵(Sprite)的概念和应用
- 游戏循环的实现
- 用户输入处理
- 碰撞检测
- 音效和音乐的添加
- 简单的游戏UI实现

希望这个示例能帮助你更好地理解游戏开发的基本概念,并为你的Pygame学习之旅提供一个良好的起点。通过修改和扩展这个基础代码,你可以添加更多的游戏特性,如:

- 多种玩家角色
- 更复杂的障碍物模式
- 道具系统
- 关卡设计
- 更精美的图形和动画
- 存档和读档功能
- 多人游戏模式

记住,游戏开发是一个需要不断学习和实践的过程。从这个简单的项目开始,逐步提高你的技能,你将能够创造出更加复杂和有趣的游戏。

最后,建议你深入研究Pygame的官方文档,参与开源游戏项目,并在实践中不断总结经验。祝你在游戏开发的道路上取得成功!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/393495.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【研发日记】嵌入式处理器技能解锁(二)——TI C2000 DSP的SCI(串口)通信

文章目录 前言 背景介绍 SCI通信 Transmitter Receiver SCI中断 分析和应用 总结 参考资料 前言 见《【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法》 背景介绍 近期使用TI C2000 DSP做的一个嵌入式系统开发项目中&#xff0c;在使用它的SCI&…

Pytorch系列-张量的类型转换

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 张量转换为NumPy数组 使用Tensor.numpy()函数可以将张量转换为ndarray数组 # 1.将张量转换为numpy数组 data_tensortorch.tensor([2,3,4]) # 使用张量对象中的numpy函数进行转…

c++STL中list介绍,模拟实现和list与vector对比

目录 前言 &#xff1a; 1. list的介绍及使用 1.1list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list的迭代器失效 2. list的模拟实现 3. list与vector的对…

串行并行数据转换

前言 串行数据传输通常在数据传输距离较远时使用&#xff0c;而并行数据传输适用于短距离、高速数据交换。通过转换&#xff0c;可以根据实际需求选择合适的传输方式&#xff0c;以优化数据传输效率和速度。串行数据传输在长距离传输中可以减少信号的干扰和失真&#xff0c;因为…

springboot整合libreoffice(两种方式,使用本地和远程的libreoffice);docker中同时部署应用和libreoffice

一、 背景 因为项目中需要使用word转pdf功能&#xff0c;因为转换速度原因&#xff0c;最后选用了libreoffice&#xff0c;原因及部署请参考 linux ubuntu环境安装libreoffice&#xff0c;word转pdf 远程调用的话可选docker部署&#xff0c;请看2.3.1 二、springboot整合libr…

达梦数据库的系统视图v$mem_pool

达梦数据库的系统视图v$mem_pool 达梦数据库的V$MEM_POOL视图主要用于显示所有内存池的信息。通过查询这个视图&#xff0c;用户可以监控数据库中各个内存组件的使用状况&#xff0c;包括内存池的大小、使用情况等。这有助于用户判断内存池是否空闲或紧张&#xff0c;从而进行…

【机器人学】6-4.六自由度机器人运动学参数辨识-机器人精度验证【附MATLAB代码】

前言 前两个章节以及完成了机器人参数辨识。 【机器人学】6-1.六自由度机器人运动学参数辨识-辨识数学模型的建立 【机器人学】6-2.六自由度机器人运动学参数辨识-优化方法求解辨识参数 标定了工具端、基座以及机器人本身的DH参数。那么我们的机器人精度如何呢&#xff1f;机…

Unity射击游戏开发教程:(31)制造一定追踪行为的敌人

在本文中,我们将介绍如何在两种敌人行为之间切换。本文是前两篇文章的延续,分别介绍了敌人躲避玩家射击以及敌人不断旋转并向玩家射击的情况。我只是介绍如何在这两种行为之间进行转换。 这种新的敌人行为的目标: 当不开火时,敌人可以躲避玩家的射击。射击时,敌人无法躲避…

谷粒商城实战笔记-137-商城业务-首页-整合dev-tools渲染一级分类数据

文章目录 一&#xff0c;使用热加载工具spring-boot-devtools1&#xff0c;引入devtools依赖2&#xff0c;ctrlshiftf9 编译静态资源 二&#xff0c;thymeleaf原理三&#xff0c;渲染一级分类 一&#xff0c;使用热加载工具spring-boot-devtools 因为我们采用的前后端一体的开…

全国首例 腾讯《穿越火线》协助破获DMA外挂案

据腾讯游戏安全中心公告&#xff0c;腾讯旗下的游戏《穿越火线》协助警方破获了首例DMA外挂案件。DMA即Direct Memory Access&#xff08;直接内存访问&#xff09;&#xff0c;原本是一种读写数据的计算机技术。 DMA外挂则通过特殊的软硬件工具直接访问电脑内存&#xff0c;读…

MIMO技术入门(通俗易懂)

MIMO技术的思路 形象地形容就是&#xff0c;从原来的一个人在搬砖&#xff0c;转变成多个人在搬砖。 MIMO/SIMO/MISO示意图 MIMO用专业一点的词形容&#xff0c;就是发射端和接收端都有多个天线&#xff0c;这里的多天线并不是指有多个天线板&#xff0c;对于基站来说&#…

基于Raft算法的分布式KV数据库:六、常见问题及解答

CPPRaft系列-常见问题及解答 】 目前项目中还有很多地方可以优化&#xff0c;欢迎大家参与吼吼吼。 地址在&#xff1a; https://github.com/youngyangyang04/KVstorageBaseRaft-cpp 在前面的系列文章中&#xff0c;我对这个项目提出了很多问题&#xff0c;但是发现没有解答…

科普文:微服务之全文检索ElasticSearch忝删改查详细操作说明

一、Restful简介 RESTFul&#xff1a;Representational State Transfer&#xff0c;中文意思&#xff1a;表现层状态转化。变现层指的是资源的表现层&#xff0c;这里的资源是指网络上的信息&#xff0c;比如一张图片&#xff0c;一段文本&#xff0c;一步电影&#xff0c;那么…

Python | Leetcode Python题解之第326题3的幂

题目&#xff1a; 题解&#xff1a; class Solution:def isPowerOfThree(self, n: int) -> bool:return n > 0 and 1162261467 % n 0

[Git][分支设计规范]详细讲解

目录 0.概览1.master分支2.release分支3.develop分支4.feature分支5.hotfix分支 0.概览 以下是常用的分支和环境的搭配&#xff0c;可视情况而定不同的策略 分支名称适用环境master主分支生产环境release预发布分支预发布/测试环境develop开发分支开发环境feature需求开发分支本…

systemd-manage系统服务图形化管理工具使用教程

1. systemd-manage介绍 systemd-manage是一个开源的基于systemd服务管理的图形化工具&#xff0c;使用qt图形库进行开发&#xff0c;可以提供服务管理&#xff0c;用户会话&#xff0c;配置文件修改&#xff0c;日志查询&#xff0c;性能分析&#xff0c;进程管理等功能。图形…

AGV一体式ARM智能控制主机如何替代传统PLC、工控机等方案

工业自动化的不断发展&#xff0c;AGV&#xff08;自动导引车&#xff09;作为一种重要的物流搬运设备&#xff0c;在各个领域得到了广泛的应用。而 AGV 的控制主机是其核心部件之一&#xff0c;直接影响着 AGV 的性能和稳定性。传统的 AGV 控制主机通常采用 x86 工控机交换机i…

HTTPS协议讲解

HTTPS协议讲解 HTTPS是什么理解加密什么是加密为什么要加密 常见的加密方式对称加密非对称加密 数据摘要/数据指纹HTTPS的工作过程探究方案一&#xff0c;只使用对称加密方案二&#xff0c;只使用非对称加密方案三&#xff0c;双方都是用非对称加密方案四&#xff0c;非对称加密…

24/8/6算法笔记 不同核函数

import numpy as np from sklearn import datasets from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import matplotlib.pyplot as plt 加载数据 X,ydatasets.load_wine(return_X_y True) d…

运维工作中对反爬虫的一些思考

最近运维工作中单位的网站被攻击&#xff0c;我们的反爬虫系统已经比较严格了&#xff0c;突然有5个用户登录30多万次经我们查找发现&#xff0c;用户是正常登录&#xff0c;这一异常被我们的技术部门捕捉到第一时间响应&#xff0c;没想到常规架构已经不足以应付现在的技术了&…