Pygame制作简单的跑酷游戏

news2024/9/27 0:58:03

今天我们来看看如何使用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的官方文档,参与开源游戏项目,并在实践中不断总结经验。祝你在游戏开发的道路上取得成功!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++设计模式(代理模式)

1. 电话虫 在海贼中&#xff0c;有一种神奇的通信工具叫做电话虫&#xff08;Den Den Mushi&#xff09;&#xff0c;外形如蜗牛&#xff0c;身上带有斑点或条纹或通体纯色&#xff0c;壳顶上有对讲机或按键&#xff0c;不接通时会睡觉&#xff0c;接通时会惊醒&#xff0c;并发…

bpmn简单使用(制作流程图)

1、先下载依赖&#xff0c;下面是我下载的版本 "bpmn-io/properties-panel": "^3.23.0", "bpmn-js": "^17.9.1", "bpmn-js-properties-panel": "^5.6.1", "camunda-bpmn-moddle": "^7.0.1",…

【鸿蒙开发基础学习】HSP-应用程序包开发与使用

HSP - 应用程序包开发与使用 HSP HSP&#xff08;Harmony Shared Package&#xff09;是动态共享包&#xff0c;可以包含代码、C库、资源和配置文件&#xff0c;通过HSP可以实现代码和资源的共享。HSP不支持独立发布&#xff0c;而是跟随其宿主应用的APP包一起发布&#xff0…

【开端】web系统中返回状态码组织管理

一、绪论 http web系统接口返回状态码有很多中&#xff0c;包括行业内定的状态码 &#xff0c;比如200 表示成功&#xff0c;500表示服务器系统不可用&#xff0c;但是有包含很多业务上自定义的状态码。比如阿里&#xff0c;腾讯这些公司的产品会定义很多自己公司产品的状态码…

Spring全家桶(三):Spring AOP

Spring AOP面向切面编程 1.面向切面编程思维&#xff08;AOP&#xff09; 1.1.面向切面编程思想AOP AOP&#xff1a;Aspect Oriented Programming面向切面编程 AOP可以说是OOP&#xff08;Object Oriented Programming&#xff0c;面向对象编程&#xff09;的补充和完善。O…

宝塔+acme.sh 使用https请求

安装acme.sh curl https://get.acme.sh | sh -s emailmyexample.com [记得修改邮箱]安装后的路径 /root/.acme 设置别名 alias acme.sh~/.acme.sh/acme.sh 运行 source ~/.bashrc 或者打开~/.bashrc文件&#xff0c;输入要设置的alias命令&#xff0c;保存&#xff0c;然后运行…

mysql case when用法

目录 一&#xff1a;概述 二&#xff1a;使用场景 一&#xff1a;概述 CASE WHEN 是 SQL 中的一个条件表达式&#xff0c;用于在 SQL 查询中实现条件逻辑。它类似于编程语言中的 if-else 或 switch 语句。通过使用 CASE WHEN&#xff0c;你可以在执行查询时根据条件对结果进行…

全网最全的设计效率工具?设计师的最佳助手!

身为设计师的你&#xff0c;是不是下载的素材堆积如山&#xff0c;用时却得在文件夹里层层翻找。在PS&#xff0c;Figma等不同的设计软件里做好的效果样式和工程&#xff0c;想要整理和再次使用很麻烦。不过&#xff0c;现在有了千鹿设计助手&#xff0c;提供一系列适合设计师的…

系统编程-02进程间通信

目录 1、管道 2、消息队列 &#xff08;1&#xff09;ftock()--创建IPC的键值KEY &#xff08;2&#xff09;获取消息队列ID &#xff08;3&#xff09;发送和接收消息 &#xff08;4&#xff09;设置或者获取消息队列的相关属性 3、共享内存 &#xff08;1&#xff09…

14.Spring程序部署-Linux部署

文章目录 1. 打包项目2. linux中删除mariadb&#xff0c;下载mysql3. .yml配置文件4.xshell中部署项目1)首先先在Linux中创建一个新的文件夹2)进入刚创建的文件夹&#xff0c;并将刚打包好的.jar包文件拖进来3)进入Linux中的mysql&#xff0c;并建库建表4)启动程序5)Linux服务器…

使用Anaconda安装多个版本的Python并与Pycharm进行对接

1、参考链接 Anaconda安装使用教程解决多Python版本问题_anaconda安装多个python版本-CSDN博客 基于上面的一篇博客的提示&#xff0c;我做了尝试。并在Pycharm的对接上做了拓展。 2、首先安装Anaconda 这个比较简单&#xff0c;直接安装即可&#xff1a; 3、设置conda.exe的…

筑牢企业防线,打造高效员工行为管控体系!行为管控软件分享,老板的智慧之选!

商贾之道&#xff0c;在于治事有序&#xff0c;人心齐整。有言曰&#xff0c;防身立命&#xff0c;先固其本。企业之基&#xff0c;在于人心与秩序。 行为管控软件乃老板之智慧&#xff0c;企业之福音也&#xff01;本文将以安企神行为管控软件为例&#xff0c;探讨如何借助这…

人工智能在肿瘤免疫微环境领域的研究进展|顶刊速递·24-08-07

小罗碎碎念 2024-08-07 今天这期推文的主题是——人工智能在肿瘤免疫微环境领域的研究进展。 第三、五、六篇文献在06-02的推文中介绍过&#xff0c;但是考虑到知识体系的完整性&#xff0c;同时方便大家补充这一部分的临床知识&#xff0c;所以再次把这三篇文章收纳进来。 我…

进程状态(三)----- linux 中具体的进程状态(下)

目录 前言1. T && t 状态2. X 与 Z 状态3. 孤儿进程 前言 继上一篇文章 进程状态&#xff08;二&#xff09;----- linux 中具体的进程状态&#xff08;上&#xff09; 介绍了 linux 系统中具体的 R、S、D 状态&#xff0c;而这篇文章继续介绍 linux 系统中剩下的三种…

【hbz分享】-springboot启动时做了哪些事情

spring启动类启动时的流程 先调用SpringApplication完成一系列初始化操作 先把启动类保存起来&#xff0c;就是带有main函数的那个类&#xff0c;把这个保存起来保存应用类型&#xff0c;是Servlet还是Ractive通过getSpringFactoriesInstances(BootstrapRegistryInitializer.…

<数据集>战斗机识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;7903张 标注数量(xml文件个数)&#xff1a;7903 标注数量(txt文件个数)&#xff1a;7903 标注类别数&#xff1a;43 标注类别名称&#xff1a;[F16, Mig31, F35, F18, SR71, A10, A400M, AG600, J20, F4, C17, Tor…

C语言程序设计之基础易错题锦集2

C语言程序设计之基础易错题锦集2 自加自减代码2_0_1运行结果2_0_1代码2_0_2运行结果2_0_2 问题2_1解答2_1 问题2_2结果2_2 问题2_3结果2_3 问题2_4结果2_4 问题2_5结果2_5 问题2_6结果2_6 自加自减 代码2_0_1 #include<stdio.h>main(){int a,b,c,d;abcd10;printf("…

【枚举 图论】2242. 节点序列的最大得分

本文涉及知识点 枚举 图论知识汇总 LeetCode 2242. 节点序列的最大得分 给你一个 n 个节点的 无向图 &#xff0c;节点编号为 0 到 n - 1 。 给你一个下标从 0 开始的整数数组 scores &#xff0c;其中 scores[i] 是第 i 个节点的分数。同时给你一个二维整数数组 edges &…

区分虚拟网卡和物理网卡

枚举注册表网卡信息 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}读取没一项的Characteristics、NetCfgInstanceId信息Characteristics & NCF_PHYSICAL 即为物理网卡 Characteristics值 类型值说明NCF_VIRTUAL0x01…

STM32L051K8U6-HAL-LED闪烁设计

HAL三步法&#xff1a; 1、配置下载线 2、配置晶振 3、配置时钟 注意&#xff1a;中断优先级&#xff08;这里防止HAL_Delay卡死&#xff0c;详细请看 http://t.csdnimg.cn/NQhQV&#xff09; 4、 配置灯引脚属性为输出模式。并设置标签为LED 生成代码&#xff1a;编写while里…