当前位置:   article > 正文

Pygame制作简单的跑酷游戏

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. 玩家控制

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

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

2. 障碍物生成

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

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

3. 碰撞检测

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

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

4. 背景滚动

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

  1. def update(self):
  2.     self.rect.left -= self.speed
  3.     if self.rect.left <= -WIDTH:
  4.         self.rect.left = WIDTH

完整代码

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

  1. import random
  2. import pygame
  3. WIDTH, HEIGHT = 500, 500
  4. ENEMY_BORN = pygame.USEREVENT + 1
  5. BORN_RATE = 3000
  6. class AudioManage:
  7. @staticmethod
  8. def playing_bg_music():
  9. pygame.mixer.music.load("./music/紧张.mp3")
  10. pygame.mixer.music.play(loops=True)
  11. pygame.mixer.music.set_volume(0.3)
  12. @staticmethod
  13. def ready_bg_music():
  14. pygame.mixer.music.load("./music/split.mp3")
  15. pygame.mixer.music.play(loops=True)
  16. pygame.mixer.music.set_volume(0.3)
  17. @staticmethod
  18. def end_bg_music():
  19. pygame.mixer.music.load("./music/沮丧.mp3")
  20. pygame.mixer.music.play(loops=True)
  21. pygame.mixer.music.set_volume(0.3)
  22. @staticmethod
  23. def set_sound_music(i):
  24. l0 = ["./music/汽车.mp3", "./music/直升机.mp3", "./music/飞机.mp3",
  25. "./music/降落伞.mp3", "./music/外星人.mp3", "./music/跳跃.mp3",
  26. "./music/失败.mp3"]
  27. pygame.mixer.Sound(l0[i]).play()
  28. class BaseSprite(pygame.sprite.Sprite):
  29. def __init__(self, image_name):
  30. super().__init__()
  31. self.image = pygame.image.load(image_name)
  32. self.rect = self.image.get_rect()
  33. class EnemySprite(BaseSprite):
  34. def __init__(self, image_name, em, speed=5):
  35. super().__init__(image_name)
  36. self.em = em
  37. self.image_name = image_name
  38. self.image = pygame.transform.flip(self.image, True, False)
  39. self.set_pos()
  40. self.speed = speed
  41. def set_pos(self):
  42. self.rect.left = WIDTH
  43. if self.image_name in ["./image/car1.png", "./image/car2.png", "./image/car3.png"]:
  44. AudioManage().set_sound_music(0)
  45. self.rect.bottom = 300
  46. elif self.image_name in ["./image/plan.png"]:
  47. AudioManage().set_sound_music(2)
  48. self.rect.bottom = 225
  49. elif self.image_name in ["./image/滑翔伞.png", "./image/直升机.png"]:
  50. if self.image_name == "./image/滑翔伞.png":
  51. AudioManage().set_sound_music(3)
  52. else:
  53. AudioManage().set_sound_music(1)
  54. self.rect.bottom = 150
  55. elif self.image_name in ["./image/外星人1.png", "./image/外星人2.png"]:
  56. AudioManage().set_sound_music(4)
  57. self.rect.bottom = 75
  58. def update(self):
  59. self.rect.left -= self.speed
  60. if self.rect.right < 0:
  61. self.kill()
  62. self.em.gm.ui.update_lab()
  63. class EnemyManage:
  64. def __init__(self, gm_):
  65. self.gm = gm_
  66. self.init_enemy()
  67. def init_enemy(self):
  68. self.enemy_group = pygame.sprite.Group()
  69. self.enemy = EnemySprite("./image/car1.png", self)
  70. self.enemy.add(self.enemy_group)
  71. def broth(self):
  72. em_img_name = random.choice(
  73. ["./image/car1.png", "./image/car2.png", "./image/car3.png", "./image/外星人1.png", "./image/外星人2.png",
  74. "./image/滑翔伞.png", "./image/直升机.png", "./image/plan.png"])
  75. self.enemy = EnemySprite(em_img_name, self)
  76. self.enemy.add(self.enemy_group)
  77. def clear(self):
  78. self.enemy_group.empty()
  79. def update(self):
  80. self.enemy_group.draw(self.gm.screen)
  81. self.enemy_group.update()
  82. class PlayerSprite(pygame.sprite.Sprite):
  83. def __init__(self, image_names):
  84. super().__init__()
  85. self.index = 0
  86. self.images = [pygame.image.load(image) for image in image_names]
  87. self.image = self.images[self.index]
  88. self.rect = self.image.get_rect()
  89. self.rect.bottom = 300
  90. self.rect.left = 100
  91. self.velocity_y = 0
  92. self.jump_count = 2
  93. def jump(self):
  94. if self.rect.bottom >= 300:
  95. self.jump_count = 2
  96. def is_jump(self):
  97. if self.jump_count > 0:
  98. AudioManage().set_sound_music(5)
  99. self.jump_count -= 1
  100. self.velocity_y = -12
  101. self.jump()
  102. def update(self):
  103. self.index += 1
  104. if self.index >= len(self.images) * 10:
  105. self.index = 0
  106. self.image = self.images[self.index // 10]
  107. self.velocity_y += 0.5
  108. self.rect.y += self.velocity_y
  109. self.jump()
  110. if self.rect.bottom > 300:
  111. self.rect.bottom = 300
  112. elif self.rect.top < 0:
  113. self.rect.top = 0
  114. class PlayerManage:
  115. def __init__(self, gm_):
  116. self.gm = gm_
  117. self.init_player()
  118. def init_player(self):
  119. self.player_group = pygame.sprite.Group()
  120. self.images = [f"./image/忍者{i}.png" for i in range(1, 3)]
  121. self.player = PlayerSprite(self.images)
  122. self.player.add(self.player_group)
  123. def broth(self):
  124. self.player = PlayerSprite([f"./image/忍者{i}.png" for i in range(1, 3)])
  125. self.player.add(self.player_group)
  126. def clear(self):
  127. self.player_group.empty()
  128. def update(self):
  129. if not self.player_group:
  130. self.broth()
  131. self.player.update()
  132. self.player_group.draw(self.gm.screen)
  133. class BGSprite(BaseSprite):
  134. def __init__(self, image_name, start_x, speed=3):
  135. super().__init__(image_name)
  136. self.rect.left = start_x
  137. self.speed = speed
  138. def update(self):
  139. self.rect.left -= self.speed
  140. if self.rect.left <= -WIDTH:
  141. self.rect.left = WIDTH
  142. class BGManage:
  143. def __init__(self, gm_):
  144. self.gm = gm_
  145. self.init_bg()
  146. def init_bg(self):
  147. self.bg_gaming_group = pygame.sprite.Group()
  148. self.bg1 = BGSprite("./image/load.png", 0)
  149. self.bg1.add(self.bg_gaming_group)
  150. self.bg2 = BGSprite("./image/load.png", WIDTH)
  151. self.bg2.add(self.bg_gaming_group)
  152. self.bg_ready_group = pygame.sprite.Group()
  153. self.bg3 = BGSprite("./image/background.png", 0)
  154. self.bg3.add(self.bg_ready_group)
  155. def update(self):
  156. if self.gm.game_state == "gaming":
  157. self.bg_gaming_group.draw(self.gm.screen)
  158. self.bg_gaming_group.update()
  159. else:
  160. self.bg_ready_group.draw(self.gm.screen)
  161. class UISprite(BaseSprite):
  162. def __init__(self, image_name, yes_no="yes", start_x=0, start_y=0):
  163. super().__init__(image_name)
  164. self.y_n = yes_no
  165. if self.y_n == "yes":
  166. self.rect.center = (WIDTH / 2, HEIGHT / 2)
  167. else:
  168. self.rect.left = start_x
  169. self.rect.top = start_y
  170. def is_collide(self):
  171. mouse_pos = pygame.mouse.get_pos()
  172. if self.rect.collidepoint(mouse_pos):
  173. return True
  174. class UIManage:
  175. def __init__(self, gm_ui):
  176. self.gm = gm_ui
  177. self.init_ready()
  178. self.init_end()
  179. self.font = pygame.font.Font("./font/幼圆.TTF", size=24)
  180. self.set_lab()
  181. def init_ready(self):
  182. self.ready_group = pygame.sprite.Group()
  183. self.ready_btn = UISprite("./image/ready.png")
  184. self.ready_btn.add(self.ready_group)
  185. def init_end(self):
  186. self.end_group = pygame.sprite.Group()
  187. self.end_btn = UISprite("./image/game_over.png")
  188. self.end_btn.add(self.end_group)
  189. self.con_btn = UISprite("./image/继续.png", "no", WIDTH - 180, HEIGHT - 88)
  190. self.con_btn.add(self.end_group)
  191. def set_lab(self):
  192. self.score_value = 0
  193. self.labile = self.font.render(f"score:{self.score_value}",
  194. True, "red")
  195. def update_lab(self):
  196. self.score_value += 1
  197. self.labile = self.font.render(f"score:{self.score_value}",
  198. True, "red")
  199. def check_collision(self):
  200. if self.gm.game_state == "ready":
  201. if self.ready_btn.is_collide():
  202. self.gm.game_state = "gaming"
  203. self.gm.set_time()
  204. AudioManage().playing_bg_music()
  205. elif self.gm.game_state == "end":
  206. if self.con_btn.is_collide():
  207. self.gm.game_state = "ready"
  208. AudioManage().ready_bg_music()
  209. def update(self):
  210. if self.gm.game_state == "ready":
  211. self.ready_group.draw(self.gm.screen)
  212. elif self.gm.game_state == "gaming":
  213. self.gm.screen.blit(self.labile, (200, 10))
  214. elif self.gm.game_state == "end":
  215. self.gm.screen.blit(self.labile, (210, 200))
  216. self.end_group.draw(self.gm.screen)
  217. class GameManage:
  218. def __init__(self):
  219. pygame.init()
  220. pygame.display.set_caption("小城跑酷")
  221. self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
  222. self.game_state = "ready"
  223. self.ui = UIManage(self)
  224. self.bg = BGManage(self)
  225. self.player = PlayerManage(self)
  226. self.enemy = EnemyManage(self)
  227. self.clock = pygame.time.Clock()
  228. AudioManage().ready_bg_music()
  229. def set_time(self):
  230. pygame.time.set_timer(ENEMY_BORN, BORN_RATE)
  231. def check_event(self):
  232. for event in pygame.event.get():
  233. if event.type == pygame.QUIT:
  234. pygame.quit()
  235. exit()
  236. if event.type == pygame.KEYUP:
  237. if event.key == pygame.K_UP or event.key == pygame.K_w:
  238. if self.game_state == "gaming":
  239. self.player.player.is_jump()
  240. if event.type == ENEMY_BORN:
  241. self.enemy.broth()
  242. if event.type == pygame.MOUSEBUTTONUP:
  243. if event.button == 1:
  244. self.ui.check_collision()
  245. def update_draw(self):
  246. self.bg.update()
  247. if self.game_state == "ready":
  248. self.ui.update()
  249. self.reset_score()
  250. elif self.game_state == "gaming":
  251. self.ui.update()
  252. self.player.update()
  253. self.enemy.update()
  254. elif self.game_state == "end":
  255. self.ui.update()
  256. pygame.display.flip()
  257. def check_collider(self):
  258. # pass
  259. r = pygame.sprite.groupcollide(self.enemy.enemy_group, self.player.player_group, False, False)
  260. if r:
  261. for players in r.values():
  262. for player in players:
  263. player.kill()
  264. self.game_state = "end"
  265. self.enemy.clear()
  266. pygame.time.set_timer(ENEMY_BORN, 0)
  267. AudioManage().set_sound_music(6)
  268. AudioManage().end_bg_music()
  269. def reset_score(self):
  270. self.ui.score_value = -1
  271. self.ui.update_lab()
  272. def run(self):
  273. while True:
  274. self.clock.tick(60)
  275. self.check_event()
  276. self.update_draw()
  277. self.check_collider()
  278. gm = GameManage()
  279. gm.run()

部分游戏截图:

总结

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

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

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/1005289
推荐阅读
相关标签
  

闽ICP备14008679号