(十八)C++自制植物大战僵尸游戏的游戏暂停实现

news2024/12/23 10:10:24

植物大战僵尸游戏开发教程专栏地址icon-default.png?t=N7T8http://t.csdnimg.cn/uzrnw


游戏暂停

当玩家遇到突发事件,可以通过暂停功能暂停游戏,以便及时处理问题。在激烈的游戏中,玩家可能需要暂停游戏来进行策略调整。此外,长时间的游戏对战可能会让玩家感到疲劳,暂停功能可以让玩家短暂休息,调整状态,以便更好地进行后续的游戏。

代码文件位置

实现功能的代码在Class\Scenes\GameScene文件夹中。具体位置如下图所示 。


PauseQuitLayer.h 

这段代码定义了一个枚举类 PauseQuitLayer_Button,用于表示暂停退出图层中的按钮。

枚举类中定义了以下几个枚举值:

cpp

复制

enum class PauseQuitLayer_Button
{
    查看图鉴 = 0,
    重新开始,
    退出游戏,
    按键说明,
    返回游戏
};

每个枚举值都代表了暂停退出图层中的一个按钮,并具有与之对应的整数值。这些枚举值的含义如下:

  • 查看图鉴:表示一个按钮,用于查看游戏中的图鉴。
  • 重新开始:表示一个按钮,用于重新开始游戏。
  • 退出游戏:表示一个按钮,用于退出游戏。
  • 按键说明:表示一个按钮,用于显示按键说明。
  • 返回游戏:表示一个按钮,用于返回游戏继续进行。

使用这个枚举类可以方便地标识和操作暂停退出图层中的不同按钮,提高代码的可读性和维护性。


 

class GSPauseQuitLayer :public OptionsMenu
{
public:
	CREATE_FUNC(GSPauseQuitLayer);
	static Layer* addLayer();
	static void pauseLayer();
	static void resumeLayer();
	static int getPauseNumbers();
	
CC_CONSTRUCTOR_ACCESS:
	GSPauseQuitLayer();
	~GSPauseQuitLayer();
	virtual bool init();

protected:
	virtual void createButton(const Vec2& vec2, const std::string name, PauseQuitLayer_Button type);
	virtual void createDialog() override;
	virtual void popSceneAnimation();

private:
	void showPrompt();
	void openHandBook();
	void setRestart();
	void setQuitGame();
	void keyDescription();
	void returnGame();

protected:
	EventListenerTouchOneByOne* _touchListener;

private:
	LayerColor* _promptLayer;
	static int _pauseNumbers;
	static string _layerName[6];
	char* _levelName;
};

这段代码定义了一个名为 GSPauseQuitLayer 的类,它是 OptionsMenu 类的子类。

这个类的主要特点和成员函数如下:

  • 类继承自 OptionsMenu,表示它是一个选项菜单类的扩展。

  • CREATE_FUNC(GSPauseQuitLayer) 是一个宏定义,用于创建 GSPauseQuitLayer 的实例。

  • addLayer() 是一个静态函数,返回一个 Layer* 类型的指针。

  • pauseLayer() 和 resumeLayer() 是静态函数,用于暂停和恢复图层的操作。

  • getPauseNumbers() 是静态函数,用于获取暂停次数。

  • GSPauseQuitLayer() 是构造函数。

  • ~GSPauseQuitLayer() 是析构函数。

  • init() 是一个虚函数,用于初始化图层的操作。

  • createButton() 是一个保护函数,用于创建按钮。

  • createDialog() 是一个重写的函数,用于创建对话框。

  • popSceneAnimation() 是一个保护函数,用于执行场景动画。

  • showPrompt()openHandBook()setRestart()setQuitGame()keyDescription() 和 returnGame() 是私有函数,用于处理不同按钮的点击事件。

  • _touchListener 是一个 EventListenerTouchOneByOne 类型的指针,用于监听触摸事件。

  • _promptLayer 是一个 LayerColor 类型的指针,用于显示提示信息的图层。

  • _pauseNumbers 是一个静态变量,表示暂停次数。

  • _layerName 是一个包含 6 个字符串的静态数组,表示图层的名称。

  • _levelName 是一个 char* 类型的指针,用于存储关卡名称。

该类提供了一些函数用于创建按钮、处理点击事件、执行动画等操作,并且具有一些静态变量用于记录暂停次数和图层名称。


PauseQuitLayer.cpp

构造函数

string GSPauseQuitLayer::_layerName[] = 
{ 
	"backgroundLayer","buttonLayer","animationLayer",
	"controlLayer","informationLayer","sunLayer" 
};

int GSPauseQuitLayer::_pauseNumbers = 0;

GSPauseQuitLayer::GSPauseQuitLayer() :
  _promptLayer(nullptr)
, _levelName(_global->userInformation->getCurrentCaveFileLevelWorldName())
{
}

这段代码给 GSPauseQuitLayer 类的静态成员变量 _layerName 和 _pauseNumbers 进行了初始化,并定义了 GSPauseQuitLayer 类的构造函数。

在这段代码中:

  • _layerName 是一个静态字符串数组,包含了 6 个图层的名称。

  • _pauseNumbers 是一个静态整数变量,用于记录暂停次数,初始值为 0。

  • GSPauseQuitLayer 类的构造函数 GSPauseQuitLayer() 初始化了成员变量 _promptLayer 为 nullptr,并将 _levelName 初始化为 _global->userInformation->getCurrentCaveFileLevelWorldName() 的返回值。这里使用了 _global 对象的 userInformation 成员指针来获取当前洞穴文件的级别世界名称。

通过这些代码,对 GSPauseQuitLayer 类的静态成员变量和构造函数进行了初始化,为后续的使用做好准备。


析构函数 

GSPauseQuitLayer::~GSPauseQuitLayer()
{
	_pauseNumbers = 0;
}

在析构函数中,将静态成员变量 _pauseNumbers 的值设置为 0。这意味着在销毁 GSPauseQuitLayer 对象时,会将暂停次数重置为 0。

这段代码的作用是在销毁 GSPauseQuitLayer 对象时,重置暂停次数,以便在下次使用时重新计数。


pauseLayer函数

void GSPauseQuitLayer::pauseLayer()
{
	auto director = Director::getInstance()->getRunningScene();
	for (auto name : _layerName)
	{
		if (director->getChildByName(name))
			director->getChildByName(name)->onExit();
		else
			return;
	}
	PlayMusic::stopMusic();
	++_pauseNumbers;
}

这个函数的作用是暂停图层的操作。具体的实现步骤如下:

  1. 获取当前正在运行的场景对象 director
  2. 遍历 _layerName 数组中的图层名称。
  3. 对于每个图层名称,检查是否存在对应的子节点。如果存在,则调用该子节点的 onExit() 函数进行退出操作。如果不存在任何一个图层,则直接返回。
  4. 调用 PlayMusic::stopMusic() 函数停止正在播放的音乐。
  5. 将暂停次数 _pauseNumbers 增加 1。

这段代码的功能是暂停图层,它会遍历图层名称数组并调用相应图层的退出操作,同时停止音乐播放并增加暂停次数。


resumeLayer函数 

void GSPauseQuitLayer::resumeLayer()
{
	if (!--_pauseNumbers)
	{
		auto director = Director::getInstance()->getRunningScene();
		for (auto name : _layerName)
		{
			if (director->getChildByName(name))
				director->getChildByName(name)->onEnter();
			else
				return;
		}
		PlayMusic::resumeMusic();
	}
}

这个函数的作用是恢复图层的操作。具体的实现步骤如下:

  1. 检查暂停次数 _pauseNumbers 是否为 0。如果不为 0,则将暂停次数减 1。
  2. 如果暂停次数减少后为 0,则执行以下操作:
    • 获取当前正在运行的场景对象 director
    • 遍历 _layerName 数组中的图层名称。
    • 对于每个图层名称,检查是否存在对应的子节点。如果存在,则调用该子节点的 onEnter() 函数进行进入操作。如果不存在任何一个图层,则直接返回。
    • 调用 PlayMusic::resumeMusic() 函数恢复音乐播放。

这段代码的功能是恢复图层,它会根据暂停次数判断是否执行恢复操作,如果暂停次数为 0,则遍历图层名称数组并调用相应图层的进入操作,同时恢复音乐播放。


setRestart函数 

void GSPauseQuitLayer::setRestart()
{
	_director->getScheduler()->setTimeScale(1.0f);
	UserData::getInstance()->caveUserData("BREAKTHROUGH", ++_global->userInformation->getBreakThroughNumbers());
	
	_director->replaceScene(TransitionFade::create(1.0f, SelectPlantsScene::createScene()));

	UserData::getInstance()->createNewLevelDataDocument();
	UserData::getInstance()->removeLevelData(_levelName);
}

这个函数的作用是设置重新开始游戏的操作。具体的实现步骤如下:

  1. 使用 _director 对象的 getScheduler() 函数获取调度器对象,然后调用 setTimeScale(1.0f) 将时间缩放设置为正常速度。
  2. 使用 UserData::getInstance() 获取用户数据的实例,调用 caveUserData("BREAKTHROUGH", ++_global->userInformation->getBreakThroughNumbers()) 更新用户数据中的 "BREAKTHROUGH" 字段,将 BreakThroughNumbers 值加一。
  3. 使用 _director 对象的 replaceScene() 函数切换场景,将当前场景替换为 SelectPlantsScene 场景,并使用 TransitionFade::create(1.0f, SelectPlantsScene::createScene()) 创建一个淡入淡出的过渡效果。
  4. 使用 UserData::getInstance() 创建新的关卡数据文档。
  5. 使用 UserData::getInstance() 调用 removeLevelData(_levelName) 函数,从用户数据中移除指定关卡的数据,其中 _levelName 是当前关卡的名称。

这段代码的功能是执行重新开始游戏的操作。它重置播放速度,更新用户数据,切换场景,创建新的关卡数据文档,并移除当前关卡的数据。


setQuitGame函数 

void GSPauseQuitLayer::setQuitGame()
{
	_director->getScheduler()->setTimeScale(1.0f);
	UserData::getInstance()->caveUserData("BREAKTHROUGH", ++_global->userInformation->getBreakThroughNumbers());

	UserData::getInstance()->createNewLevelDataDocument();
	UserData::getInstance()->caveLevelData(_levelName);

	popSceneAnimation();
}

这个函数的作用是设置退出游戏的操作。具体的实现步骤如下:

  1. 使用 _director 对象的 getScheduler() 函数获取调度器对象,然后调用 setTimeScale(1.0f) 将时间缩放设置为正常速度。
  2. 使用 UserData::getInstance() 获取用户数据的实例,调用 caveUserData("BREAKTHROUGH", ++_global->userInformation->getBreakThroughNumbers()) 更新用户数据中的 "BREAKTHROUGH" 字段,将 BreakThroughNumbers 值加一。
  3. 使用 UserData::getInstance() 创建新的关卡数据文档。
  4. 使用 UserData::getInstance() 调用 caveLevelData(_levelName) 函数,将当前关卡的数据保存到用户数据中,其中 _levelName 是当前关卡的名称。
  5. 调用 popSceneAnimation() 函数执行退出游戏的过渡动画,弹出当前场景。

这段代码的功能是执行退出游戏的操作。它重置播放速度,更新用户数据,创建新的关卡数据文档,并保存当前关卡的数据,然后执行退出游戏的过渡动画,弹出当前场景。


createButton函数 

void GSPauseQuitLayer::createButton(const Vec2& vec2, const std::string name, PauseQuitLayer_Button button_type)
{
	/* 创建返回主菜单按钮 */
	auto button = ui::Button::create("ButtonNew2.png", "ButtonNew.png", "", TextureResType::PLIST);
	auto label = Label::createWithTTF(name, GAME_FONT_NAME_1, 35);
	label->enableShadow(Color4B(0, 0, 0, 200));//设置阴影
	label->setScale(2.0f);
	button->setTitleLabel(label);
	button->setTitleColor(Color3B::WHITE);
	button->setPosition(vec2);
	button->setScale(0.5f);
	_option->addChild(button);

	button->addTouchEventListener([=](Ref* sender, ui::Widget::TouchEventType type)
		{
			switch (type)
			{
			case ui::Widget::TouchEventType::BEGAN:
				PlayMusic::playMusic("gravebutton");
				break;
			case ui::Widget::TouchEventType::ENDED:
				switch (button_type)
				{
				case PauseQuitLayer_Button::查看图鉴: openHandBook();   break;
				case PauseQuitLayer_Button::从新开始: setRestart();     break;
				case PauseQuitLayer_Button::退出游戏: setQuitGame();    break;
				case PauseQuitLayer_Button::按键说明: keyDescription(); break;
				case PauseQuitLayer_Button::返回游戏: returnGame();     break;
				default: break;
				}
			}
		});
}

这个函数用于创建按钮,并设置按钮的属性和触摸事件。具体的实现步骤如下:

  1. 创建一个按钮对象 button,使用图片资源 "ButtonNew2.png" 和 "ButtonNew.png",使用 TextureResType::PLIST 方式加载。
  2. 创建一个标签对象 label,使用字体文件 GAME_FONT_NAME_1 和字号 35。
  3. 设置标签的阴影效果,使用 enableShadow() 函数并传入阴影颜色 Color4B(0, 0, 0, 200)。
  4. 设置标签的缩放比例为 2.0。
  5. 将标签设置为按钮的标题标签,设置标题颜色为白色。
  6. 设置按钮的位置为 vec2
  7. 设置按钮的缩放比例为 0.5。
  8. 将按钮添加到 _option 节点中。
  9. 为按钮添加触摸事件回调函数,使用 addTouchEventListener() 函数。
  10. 在触摸事件回调函数中,根据触摸事件类型进行不同的处理:
    • 如果是触摸事件开始(BEGAN),播放 "gravebutton" 音效。
    • 如果是触摸事件结束(ENDED),根据按钮类型 button_type 执行相应的操作,包括打开图鉴、重新开始游戏、退出游戏、显示按键说明和返回游戏。

这段代码的功能是创建按钮并设置按钮的属性和触摸事件。根据按钮类型的不同,触摸事件的处理也不同,可以执行不同的操作。


其他函数 

其他函数不再一一解释,请自行查看理解。

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

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

相关文章

开源相机管理库Aravis例程学习(二)——连续采集multiple-acquisition-main-thread

开源相机管理库Aravis例程学习(二)——连续采集multiple-acquisition-main-thread 简介例程代码函数说明arv_camera_set_acquisition_modearv_camera_create_streamarv_camera_get_payloadarv_buffer_newarv_stream_push_bufferarv_camera_start_acquisi…

一周IT资讯

又降了?运维4月平均月薪1W6? 薪资作为大部分人的主要收入来源,是每个人最关注的话题之一。 最近,小编搜索了近半年的运维薪资趋势,看看你的钱包缩水了没? *数据来自看准网 据了解,运维2024年…

【6】DongshanPI-Seven 应用开发_多线程编程记录

目录 1、多线程编程1.1 测试程序 1.2 测试结果 1、多线程编程 在Linux系统中,调度是以线程为单位的,资源分配是以进程为单位的。多进程是指多个main()函数的程序,多线程,只有1个main()函数。进程和线程是多任务操作系统中的两种不…

Linux 基于 UDP 协议的简单服务器-客户端应用

目录 一、socket编程接口 1、socket 常见API socket():创建套接字 bind():将用户设置的ip和port在内核中和我们的当前进程关联 listen() accept() 2、sockaddr结构 3、inet系列函数 二、UDP网络程序—发送消息 1、服务器udp_server.hpp initS…

【Flutter】自动生成图片资源索引插件一:FlutterAssetRefGenerator

介绍 FlutterAssetRefGenerator 插件:windows上 点击生成图片索引按钮后,pubspec.yaml 会出现中文乱码,需要手动改乱码;mac上没问题。 优点:点击图标自动生成。 目录 介绍一、安装二、使用 一、安装 安装FlutterAsset…

ubunt18.04安装ROS2

本文无废话,实现了ubunt18.04 下ros2的安装,并且同时兼容ros和ros2 如果想完ros(1)的,请参考我的前一篇文章:ubunt18.04安装ROS避坑指南 参考: https://blog.csdn.net/cau_weiyuhu/article/deta…

2024年【A特种设备相关管理(锅炉压力容器压力管道)】考试内容及A特种设备相关管理(锅炉压力容器压力管道)操作证考试

题库来源:安全生产模拟考试一点通公众号小程序 2024年A特种设备相关管理(锅炉压力容器压力管道)考试内容为正在备考A特种设备相关管理(锅炉压力容器压力管道)操作证的学员准备的理论考试专题,每个月更新的…

5.Godot节点和功能及Node节点属性分析

1. 节点和功能的关系 节点 Node ,用于实现一种功能,例如,Sprite 节点,用于图片的显示一个节点的功能取决于它挂载了哪些子节点,它包含了哪些功能的子节点,就包含了对应子节点表示的功能节点是可选的&#…

Dota2 参议院

题目链接 Dota2 参议院 题目描述 注意点 senate[i] 为 ‘R’ 或 ‘D’假设每一位参议员都足够聪明,会为自己的政党做出最好的策略 解答思路 对于任意一位参议员,如果其有权利,当他后面没有另一方参议员,其会投票,…

小红书笔记写作方法和技巧分享,纯干货!

很多小伙伴感叹小红书笔记流量就是一个玄学,有时精心撰写的笔记却没有人看,自己随便写的笔记却轻轻松松上热门。实际上你还是欠点火候,小红书笔记写作是有一套方法和技巧的,总归是有套路的,如果你不知道,请…

C++ 数据结构 linux 【第一天】

1.命名空间 在C/C中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在于全局作 用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字…

【MIT6.824】lab3 Fault-tolerant Key/Value Service 实现笔记

引言 lab3A的实验要求如下: Your first task is to implement a solution that works when there are no dropped messages, and no failed servers. You’ll need to add RPC-sending code to the Clerk Put/Append/Get methods in client.go, and implement Pu…

✌粤嵌—2024/4/12—插入区间✌

代码实现: 解题思路:先将数组 newInterval 插入到数组 intervals 的末尾,再转换成合并区间 /*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returne…

组合预测 | Matlab实现ICEEMDAN-SMA-SVM基于改进完备集合经验模态分解-黏菌优化算法-支持向量机的时间序列预测

组合预测 | Matlab实现ICEEMDAN-SMA-SVM基于改进完备集合经验模态分解-黏菌优化算法-支持向量机的时间序列预测 目录 组合预测 | Matlab实现ICEEMDAN-SMA-SVM基于改进完备集合经验模态分解-黏菌优化算法-支持向量机的时间序列预测预测效果基本介绍程序设计参考资料预测效果 基本…

两个查国内产业信息新闻数据的必备网站

产业经济信息网:产业经济信息网由报业协会主管主办,成立于1997年,是由报业行业报委员会发起,几十家权威行业媒体共同组建的、国内最大的行业信息发布网站之一。网站所拥有的“产经数据库”容纳了54家行业媒体的信息数据200多万条&…

Nextjs学习入门 - 创建第一个项目

1 通过npx创建一个nextjs项目 通过命令创建: npx create-next-applatest 得到如下项目结构图: my-app- src //源代码目录- app //引用目录- favicon.ico //网站图标- globals.css //全局css- layout.tsx //布局文件- page.tsx //页面 路径"…

C语言C/S架构PACS影像归档和通信系统源码 医院PACS系统源码

C语言C/S架构PACS影像归档和通信系统源码 医院PACS系统源码 医院影像科PACS系统,意为影像归档和通信系统。它是应用在医院影像科室的系统,主要的任务是把日常产生的各种医学影像(包括核磁、CT、超声、各种X光机、各种红外仪、显微…

YOLO-World——S(cvpr2024)

文章目录 Abstract成果 MethodPre-training Formulation: Region-Text PairsModel ArchitectureYOLO DetectorText EncoderText Contrastive HeadTraining with Online VocabularyInference with Offline Vocabulary Re-parameterizable Vision-Language PANText-guided CSPLay…

JavaSE 有这一篇就够(呕心狂敲41k字,只为博君一点赞!)

目录 一. 基础语法 1. 数据类型 2. 基本数据类型转换 3. 运算符 3. 循环语句 5. 定义方法 6. 数组 二. 面向对象 1. 类和对象 2. 构造方法 3. 方法的重载 4. this关键字 5. static关键字 6. 代码块 7. 访问权限修饰符 8. 面向对象的三大特征 封装 继承…

开关到模拟量全覆盖钡铼IOy系列模块集成热电阻、热电偶等传感器

钡铼IOy系列模块作为一种创新的工业自动化解决方案,以其灵活的自由拼接设计和丰富的接口类型,在工业级DI/DO/AI/AO集成方案中扮演着重要角色。其中,其在集成热电阻、热电偶等传感器方面的能力更是为工业控制系统带来了全新的可能性。 开关到…