Pygame制作简单的跑酷游戏

avatar
作者
筋斗云
阅读量:0

今天我们来看看如何使用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 -= 1         self.velocity_y = -12     self.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.speed     if self.rect.left <= -WIDTH:         self.rect.left = WIDTH

完整代码

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

import random  import pygame  WIDTH, HEIGHT = 500, 500 ENEMY_BORN = pygame.USEREVENT + 1 BORN_RATE = 3000   class AudioManage:      @staticmethod     def playing_bg_music():         pygame.mixer.music.load("./music/紧张.mp3")         pygame.mixer.music.play(loops=True)         pygame.mixer.music.set_volume(0.3)      @staticmethod     def ready_bg_music():         pygame.mixer.music.load("./music/split.mp3")         pygame.mixer.music.play(loops=True)         pygame.mixer.music.set_volume(0.3)      @staticmethod     def end_bg_music():         pygame.mixer.music.load("./music/沮丧.mp3")         pygame.mixer.music.play(loops=True)         pygame.mixer.music.set_volume(0.3)      @staticmethod     def 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 = em         self.image_name = image_name         self.image = pygame.transform.flip(self.image, True, False)         self.set_pos()         self.speed = speed      def set_pos(self):         self.rect.left = WIDTH         if self.image_name in ["./image/car1.png", "./image/car2.png", "./image/car3.png"]:             AudioManage().set_sound_music(0)             self.rect.bottom = 300         elif self.image_name in ["./image/plan.png"]:             AudioManage().set_sound_music(2)             self.rect.bottom = 225         elif 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 = 150         elif self.image_name in ["./image/外星人1.png", "./image/外星人2.png"]:             AudioManage().set_sound_music(4)             self.rect.bottom = 75      def update(self):         self.rect.left -= self.speed         if 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 = 0         self.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 = 300         self.rect.left = 100         self.velocity_y = 0         self.jump_count = 2      def jump(self):         if self.rect.bottom >= 300:             self.jump_count = 2      def is_jump(self):         if self.jump_count > 0:             AudioManage().set_sound_music(5)             self.jump_count -= 1             self.velocity_y = -12         self.jump()      def update(self):         self.index += 1         if self.index >= len(self.images) * 10:             self.index = 0         self.image = self.images[self.index // 10]          self.velocity_y += 0.5         self.rect.y += self.velocity_y         self.jump()         if self.rect.bottom > 300:             self.rect.bottom = 300         elif self.rect.top < 0:             self.rect.top = 0    class 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_x         self.speed = speed      def update(self):         self.rect.left -= self.speed         if self.rect.left <= -WIDTH:             self.rect.left = WIDTH   class 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_no         if self.y_n == "yes":             self.rect.center = (WIDTH / 2, HEIGHT / 2)         else:             self.rect.left = start_x             self.rect.top = start_y      def is_collide(self):         mouse_pos = pygame.mouse.get_pos()         if self.rect.collidepoint(mouse_pos):             return True   class UIManage:     def __init__(self, gm_ui):         self.gm = gm_ui          self.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 = 0         self.labile = self.font.render(f"score:{self.score_value}",                                        True, "red")      def update_lab(self):         self.score_value += 1         self.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):         # pass         r = 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 = -1         self.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的官方文档,参与开源游戏项目,并在实践中不断总结经验。祝你在游戏开发的道路上取得成功!

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!