(十一)C++自制植物大战僵尸游戏客户端更新实现

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


更新检查

游戏启动后会下载服务器中的版本号然后与本地版本号进行对比,如果本地版本号小于服务器版本号就会弹出更新提示。让用户选择是否更新客户端。

在弹出的更新对话框中有显示最新版本更新的内容,以及更新按钮等。用户可以选择更新方式或者进行更新。


文件位置 

代码文件实现位置在Class\Scenes\MainMenuScene文件夹中。 


UpdateClient.h 

客户端更新类继承与对话框类(Dialog),因为客户端更新也是一个对话对话框供玩家操作。UpdateClient头文件定义如下。

class UpdateClient :public Dialog
{
public:CREATE_FUNC(UpdateClient);CC_CONSTRUCTOR_ACCESS:UpdateClient();virtual bool init();private:enum class Update_Button{百度网盘下载,腾讯微云下载,直接下载,退出游戏,确定};void createDiglog();	                                                       /* 创建对话框 */void createButton(const std::string& name, Vec2& vec2, Update_Button button);  /* 创建按钮 */void showText();void addScrollView();void addMouseEvent();void downloadHistoryText();void downloadData();void downloadProgress();void downloadSuccess();void downloadError();private:Sprite* _dialog;    /* 对话框 */std::unique_ptr<network::Downloader> _downloader;Label* _remindText;Label* _progressText;Label* _explanText;Label* _historyText;Sprite* _loadBarBackground;ui::LoadingBar* _loadingBar;ui::ScrollView* _textScrollView;bool _isNewDowndload;
};

UpdateClient.cpp

构造函数

在构造函数中对变量进行初始化操作。

UpdateClient::UpdateClient() :_dialog(nullptr), _remindText(nullptr), _progressText(nullptr), _explanText(nullptr), _loadBarBackground(nullptr), _loadingBar(nullptr), _historyText(nullptr), _isNewDowndload(true)
{_downloader.reset(new network::Downloader());
}

init函数

创建游戏更新对话框,首先会调用init函数。在init函数中首先会在场景中创建一个黑色半透明的遮罩层,使用场景变黑,让玩家聚焦到此对话框中。然后调用createShieldLayer(this)函数屏蔽除本层之外的所以事件监听,该函数的实现在自定义对话框教程(教程九)中有介绍,作用是让玩家只能和该对话框进行交互。最后使用createDialog()函数创建更新菜单。

bool UpdateClient::init()
{if (!LayerColor::initWithColor(Color4B(0, 0, 0, 180)))return false;createShieldLayer(this);createDialog();return true;
}

createDialog()函数

在该函数中主要实现整个更新菜单的界面。

void UpdateClient::createDialog()
{_dialog = Sprite::createWithSpriteFrameName("LevelObjiectivesBg.png");_dialog->setPosition(_director->getWinSize() / 2);_dialog->setScale(0.9f);this->addChild(_dialog);/* 创建触摸监听 */createTouchtListener(_dialog);auto PauseAnimation = SkeletonAnimation::createWithData(_global->userInformation->getAnimationData().find("PauseAnimation")->second);PauseAnimation->setAnimation(0, "animation", true);PauseAnimation->setPosition(Vec2(530, 650));_dialog->addChild(PauseAnimation);showText();createButton(_global->userInformation->getGameText().find("百度网盘下载")->second, Vec2(165, 100), Update_Button::百度网盘下载);createButton(_global->userInformation->getGameText().find("腾讯微云下载")->second, Vec2(405, 100), Update_Button::腾讯微云下载);createButton(_global->userInformation->getGameText().find("直接下载")->second, Vec2(645, 100), Update_Button::直接下载);createButton(_global->userInformation->getGameText().find("关闭游戏")->second, Vec2(885, 100), Update_Button::退出游戏);createButton(_global->userInformation->getGameText().find("确定")->second, Vec2(520, 100), Update_Button::确定);}

创建更新菜单背景,设置位置到屏幕中心,缩放0.9倍大小。 

_dialog = Sprite::createWithSpriteFrameName("LevelObjiectivesBg.png");
_dialog->setPosition(_director->getWinSize() / 2);
_dialog->setScale(0.9f);
this->addChild(_dialog);

对创建好的背景进行触摸监听,可以实现更新菜单的拖动。 

/* 创建触摸监听 */
createTouchtListener(_dialog);

 显示文字内容以及创建多个按钮。

showText();createButton(_global->userInformation->getGameText().find("百度网盘下载")->second, Vec2(165, 100), Update_Button::百度网盘下载);
createButton(_global->userInformation->getGameText().find("腾讯微云下载")->second, Vec2(405, 100), Update_Button::腾讯微云下载);
createButton(_global->userInformation->getGameText().find("直接下载")->second, Vec2(645, 100), Update_Button::直接下载);
createButton(_global->userInformation->getGameText().find("关闭游戏")->second, Vec2(885, 100), Update_Button::退出游戏);
createButton(_global->userInformation->getGameText().find("确定")->second, Vec2(520, 100), Update_Button::确定);

downloadData()函数

客户端内文件下载更新函数。创建文件下载进度条以及文字信息。

void UpdateClient::downloadData()
{if (!_loadBarBackground){_loadBarBackground = Sprite::createWithSpriteFrameName("bgFile.png");_loadBarBackground->setPosition(Vec2(_dialog->getContentSize().width / 2.f, _dialog->getContentSize().height / 2.f - 100));_loadBarBackground->setScale(1.5f);_dialog->addChild(_loadBarBackground);}if (!_loadingBar){_loadingBar = ui::LoadingBar::create();_loadingBar->loadTexture("progressFile.png", TextureResType::PLIST);_loadingBar->setDirection(LoadingBar::Direction::LEFT); /* 设置加载方向 */_loadingBar->setPercent(0);_loadingBar->setScale(1.5f);_loadingBar->setPosition(Vec2(_dialog->getContentSize().width / 2.f, _dialog->getContentSize().height / 2.f - 100));_dialog->addChild(_loadingBar);}_explanText->setColor(Color3B::BLACK);_explanText->setString("");const static string sNameList = _global->userInformation->getGameText().find("资源名称")->second + UserInformation::getNewEditionName(true) + ".rar";const static string path = _global->userInformation->getGameText().find("存放路径")->second + sNameList;_downloader->createDownloadFileTask(_global->userInformation->getGameText().find("资源网址")->second, path, sNameList);downloadProgress();downloadSuccess();downloadError();
}

创建下载任务,传入服务器文件地址 、文件路径、文件名称。

_downloader->createDownloadFileTask(_global->userInformation->getGameText().find("资源网址")->second, path, sNameList);

调用下载进度、下载成功、下载失败函数 。下载过程会调用downloadProgress()函数,下载成功调用downloadSuccess()函数,下载失败调用downloadError()函数。

downloadProgress();
downloadSuccess();
downloadError();

downloadProgress()函数

onTaskProgress lamda函数中,会实时计算下载进度,bytesReceived参数是当前下载的文大小,totalBytesExpected是文件总大小,totalBytesReceived是总下载大小。通过这三个参数可以计算下载完成所需事件。

void UpdateClient::downloadProgress()
{_downloader->onTaskProgress = [=](const network::DownloadTask& task,int64_t bytesReceived,int64_t totalBytesReceived,int64_t totalBytesExpected){_explanText->setString(_global->userInformation->getGameText().find("解释说明_慢")->second);float percent = float(totalBytesReceived * 100) / totalBytesExpected;_loadingBar->setPercent(percent);int hour = (totalBytesExpected - totalBytesReceived) / (bytesReceived * 10) / 3600;int min = ((totalBytesExpected - totalBytesReceived) / (bytesReceived * 10) - hour * 3600) / 60;int second = (totalBytesExpected - totalBytesReceived) / (bytesReceived * 10) - hour * 3600 - min * 60;char buf[128];if (bytesReceived / 1024.f * 10 >= 1000){std::snprintf(buf, 128, "%.1fMB/s  %dKB/%dKB  %.2f%%  time:%02d:%02d:%02d",bytesReceived / 1024.f / 1024.f * 10, int(totalBytesReceived / 1024), int(totalBytesExpected / 1024), percent, hour, min, second);_progressText->setString(buf);}else{std::snprintf(buf, 128, "%.1fKB/s  %dKB/%dKB  %.2f%%  time:%02d:%02d:%02d",bytesReceived / 1024.f * 10, int(totalBytesReceived / 1024), int(totalBytesExpected / 1024), percent, hour, min, second);_progressText->setString(buf);}_remindText->setString(_global->userInformation->getGameText().find("文件正在下载中!请稍等!")->second);};
}

downloadSuccess()函数

成功下载文件后会调用onFileTaskSuccess lamda函数。在函数中显示下载成功文字信息,将按钮隐藏,然后提示用户退出重新启动游戏。

void UpdateClient::downloadSuccess()
{_downloader->onFileTaskSuccess = [this](const cocos2d::network::DownloadTask& task){_progressText->setString(_global->userInformation->getGameText().find("下载成功")->second +_global->userInformation->getGameText().find("存放路径")->second + task.identifier + " ]");_remindText->setString(_global->userInformation->getGameText().find("点击确定退出游戏!")->second);_explanText->setString(_global->userInformation->getGameText().find("下载成功说明")->second);((Button*)_dialog->getChildByName("0"))->setVisible(false);((Button*)_dialog->getChildByName("1"))->setVisible(false);((Button*)_dialog->getChildByName("2"))->setVisible(false);((Button*)_dialog->getChildByName("3"))->setVisible(false);((Button*)_dialog->getChildByName("4"))->setVisible(true);};
}

downloadError()函数

如果下载失败,会调用onTaskError lamda函数,在函数中先错误信息提示用户。errorCode的是错误代码,errorStr是错误信息,errorCodeInternal是内部错误代码。

void UpdateClient::downloadError()
{_downloader->onTaskError = [this](const cocos2d::network::DownloadTask& task,int errorCode,int errorCodeInternal,const std::string& errorStr){_remindText->setString(_global->userInformation->getGameText().find("下载失败")->second);((Button*)_dialog->getChildByName("2"))->setEnabled(true);((Button*)_dialog->getChildByName("3"))->setEnabled(true);char str[256];snprintf(str, 256, "Failed to download : 资源文件, identifier(%s) error code(%d), internal error code(%d) desc(%s) 请检查网络连接是否正常!如果网络连接正常请多试几次!或更换其他方式下载!", task.identifier.c_str(), errorCode, errorCodeInternal, errorStr.c_str());_explanText->setString(str);_explanText->setColor(Color3B::RED);
#ifdef DEBUGlog("Failed to download : %s, identifier(%s) error code(%d), internal error code(%d) desc(%s)", task.requestURL.c_str(), task.identifier.c_str(), errorCode, errorCodeInternal, errorStr.c_str());
#endif // DEBUG};
}

其他函数

showText()、createButton()、addScrollView()、addMouseEvent()等函数不再一一列举,可自行查看。

void UpdateClient::showText()
{addScrollView();_historyText = Label::createWithTTF(_global->userInformation->getGameText().find("更新信息加载中!")->second, GAME_FONT_NAME_1, 50);_historyText->setAnchorPoint(Vec2::ANCHOR_MIDDLE_TOP);_historyText->setColor(Color3B::BLACK);_historyText->setMaxLineWidth(650); _textScrollView->addChild(_historyText);_textScrollView->setInnerContainerSize(_historyText->getContentSize());_historyText->setPosition(Vec2(_dialog->getContentSize().width / 2.f - 150, _textScrollView->getInnerContainerSize().height - 150));downloadHistoryText();/* 标题 */_remindText = Label::createWithTTF(_global->userInformation->getGameText().find("检测到有新版本,请选择更新方式!")->second, GAME_FONT_NAME_1, 50);_remindText->setPosition(Vec2(_dialog->getContentSize().width / 2.f, _dialog->getContentSize().height / 2.f + 200));_remindText->setColor(Color3B::BLACK);_remindText->setMaxLineWidth(900);_remindText->setName("Update");_dialog->addChild(_remindText);/* 进度文字 */_progressText = Label::createWithTTF("", GAME_FONT_NAME_1, 25);_progressText->setMaxLineWidth(900);_progressText->setPosition(Vec2(_dialog->getContentSize().width / 2.f, _dialog->getContentSize().height / 2.f));_dialog->addChild(_progressText);/* 说明文字 */_explanText = Label::createWithTTF("", GAME_FONT_NAME_1, 30);_explanText->setPosition(Vec2(_dialog->getContentSize().width / 2.f, _dialog->getContentSize().height / 2.f + 100));_explanText->setColor(Color3B::BLACK);_explanText->setMaxLineWidth(900);_dialog->addChild(_explanText);
}void UpdateClient::addScrollView()
{_textScrollView = ui::ScrollView::create();_textScrollView->setDirection(ui::ScrollView::Direction::VERTICAL);_textScrollView->setAnchorPoint(Vec2::ANCHOR_MIDDLE);_textScrollView->setContentSize(Size(720.0f, 320.0f));_textScrollView->setPosition(_dialog->getContentSize() / 2.0f);_textScrollView->setBounceEnabled(true);_textScrollView->setScrollBarPositionFromCorner(Vec2(20, 0));_textScrollView->setScrollBarWidth(10);_textScrollView->setScrollBarColor(Color3B::BLACK);_dialog->addChild(_textScrollView);addMouseEvent();
}void UpdateClient::addMouseEvent()
{/* 鼠标滑动监听 */auto mouse = EventListenerMouse::create();mouse->onMouseScroll = [=](Event* event){auto mouseEvent = static_cast<EventMouse*>(event);float movex = mouseEvent->getScrollY() * 5;auto minOffset = 0.f;auto maxOffset = 100.f;auto offset = _textScrollView->getScrolledPercentVertical();offset += movex;if (offset < minOffset){offset = minOffset;}else if (offset > maxOffset){offset = maxOffset;}_textScrollView->scrollToPercentVertical(offset, 0.5f, true);};Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(mouse, _textScrollView);
}void UpdateClient::downloadHistoryText()
{const string sURLList = _global->userInformation->getGameText().find("更新信息网址")->second;_downloader->createDownloadDataTask(sURLList);_downloader->onDataTaskSuccess = [this](const cocos2d::network::DownloadTask& task,std::vector<unsigned char>& data){string historyNetWork;for (auto p : data){historyNetWork += p;}TTFConfig ttfConfig(GAME_FONT_NAME_1, 25, GlyphCollection::DYNAMIC);_historyText->setTTFConfig(ttfConfig);_historyText->setString(historyNetWork);_textScrollView->setInnerContainerSize(_historyText->getContentSize());_historyText->setPosition(Vec2(350, _textScrollView->getInnerContainerSize().height));};_downloader->onTaskError = [this](const cocos2d::network::DownloadTask& task,int errorCode,int errorCodeInternal,const std::string& errorStr){_historyText->setString(_global->userInformation->getGameText().find("更新信息加载失败!")->second);_textScrollView->setInnerContainerSize(_historyText->getContentSize());};
}

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

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

相关文章

2024五一杯数学建模A题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

光学雨量计雨量传感器的工作原理与实时数据采集

光学雨量计雨量传感器的工作原理与实时数据采集 河北稳控科技光学雨量计是一种常用的雨量传感器&#xff0c;其工作原理基于光学原理和实时数据采集技术。它的主要作用是测量雨水的大小和强度&#xff0c;为气象、农业、水文等领域提供重要的数据支持。 光学雨量计的工作原理是…

单片机之ESP8266模块

目录 ESP8266简介 前言 ESP8266的工作模式 ESP8266引脚说明 ESP8266测试 步骤 单片机与esp8266交互 前言 收到数据的格式 AP模式 服务器模式 外部执行命令 代码内执行命令 代码部分 客户端模式 外部执行命令 内部执行命令 代码部分 STA模式 服务器模式 外…

10个常用的损失函数及Python代码实现

本文深入理解并详细介绍了10个常用的损失函数及Python代码实现。 什么是损失函数&#xff1f; 损失函数是一种衡量模型与数据吻合程度的算法。损失函数测量实际测量值和预测值之间差距的一种方式。损失函数的值越高预测就越错误&#xff0c;损失函数值越低则预测越接近真实值…

LUCF-Net:轻量级U形级联 用于医学图像分割的融合网络

LUCF-Net&#xff1a;轻量级U形级联 用于医学图像分割的融合网络 摘要IntroductionRelated WorkProposed MethodLocal-Global Feature ExtractionEncoder and DecoderFeature FusionLoss Function LUCF-Net: Lightweight U-shaped Cascade Fusion Network for Medical Image Se…

Android zxing库实现扫码识别

第一步 加库zxing库 //导入二维码识别库ZXingimplementation("com.journeyapps:zxing-android-embedded:4.2.0") 第二部获取摄像机权限 <uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="andro…

【日常记录】【CSS】利用动画延迟实现复杂动画

文章目录 1、介绍2、原理3、代码4、参考链接 1、介绍 对于这个效果而言&#xff0c;最先想到的就是 监听滑块的input事件来做一些操作 ,但是会发现&#xff0c;对于某一个节点的时候&#xff0c;这个样式操作起来比较麻烦 只看这个代码的话&#xff0c;发现他用的是动画&#x…

超详细!Python中 pip 常用命令

相信对于大多数熟悉Python的人来说&#xff0c;一定都听说并且使用过pip这个工具&#xff0c;但是对它的了解可能还不一定是非常的透彻&#xff0c;今天小编就来为大家介绍10个使用pip的小技巧&#xff0c;相信对大家以后管理和使用Python当中的标准库会有帮助。 安装 当然在…

【算法一则】编辑距离 【动态规划】

题目 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作&#xff1a; 插入一个字符 删除一个字符 替换一个字符 示例 1&#xff1a;输入&#xff1a;word1 "horse", word2 "…

16 - Debian如何配置vsftpd(1)实现匿名上传下载

作者&#xff1a;网络傅老师 特别提示&#xff1a;未经作者允许&#xff0c;不得转载任何内容。违者必究&#xff01; Debian如何配置vsftpd&#xff08;1&#xff09;实现匿名上传下载 《傅老师Debian小知识库系列之16》——原创 前言 傅老师Debian小知识库特点&#xff1a…

微信小程序获取蓝牙信标

/*** 搜索设备界面*/ import Dialog from vant/weapp/dialog/dialog; Page({data: {list: []},onPullDownRefresh: function () {wx.request({url: https://wwz.jingyi.icu/app/Explain/index,data: {scenic_id: 3},method: POST,success: (res) > {console.log(res);let th…

重磅!国内首个基于单张图片的3D人脸重建课程

3D人脸重建在计算机视觉和图形学中一直是一个经典且热门的研究方向&#xff0c;在游戏、影视、娱乐等众多行业也有着广泛的应用。早期人脸重建主要基于多视角相机或深度相机&#xff0c;随着深度学习的兴起&#xff0c;基于单张图片的人脸重建成为可能&#xff0c;且重建的精度…

数学建模---Matlab学习笔记

1.经典例题 &#xff08;1&#xff09;判断质数 给定一个大于100的数字&#xff0c;判断是否为质数 先设定布尔值是true,也就是假设这个数字是质数&#xff0c;利用for循环进行遍历直到n-1&#xff0c;如果被任意的数字整除&#xff0c;就说明不是质数&#xff0c;我们就把布…

2024 年排名前 5 的 CSS 框架

文章目录 1、Bootstrap2、Tailwind CSS3、Foundation4、Bulma5、UIKit 1、Bootstrap Bootstrap框架是由Twitter的设计师Mark Otto和Jacob Thornton合作开发的&#xff0c;于2011年8月在GitHub上发布。它是目前最受欢迎的前端框架之一&#xff0c;被广泛应用于各种Web项目中。Bo…

最新Latex2024安装教程 超简单

Latex是一款常用的论文写作工具&#xff0c;今天小菜介绍Latex的安装配置过程。 1. 来到官网下载镜像文件 https://www.tug.org/texlive/ 按步骤点击&#xff1a; 就会进入一个最近的镜像网站&#xff0c;选择textlive2024.iso即可 下载完成之后解压&#xff0c;安装路径…

Linux02(项目部署,手动和自动部署,JDK版本问题,安装软件,安装软件,安装JDK,Tomcat,MySQL,Irzsz)

目录 一、安装软件 1. 安装准备工作 1 Linux里的软件安装方式 2 上传软件到Linux 3 拍照虚拟机快照 2. 安装JDK 1 卸载自带jdk 2 解压JDK 3 配置环境变量 4 测试JDK 3. 安装Tomcat 1 解压Tomcat 2 修改防火墙设置 3 测试Tomcat 启动Tomcat 访问Tomcat 查看Tom…

git 小记

一、 github新建仓库 git clone 。。。。。。。。。。。 &#xff08;增删查补&#xff0c;修改&#xff09; git add . git commit -m "修改” git push (git push main) 二、branch 分支 branch并不难理解&#xff0c;你只要想像将代码拷贝到不同目录…

MongoDB的CURD(增删改查操作)

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 ✈️如果喜欢这篇文章的话 &#x1f64f;大大们可以动动发财的小手&#x1f449;&#…

刷代码随想录有感(34):前k个高频元素

本题代码涉及到了多个陌生概念&#xff0c;题干如下&#xff1a; 代码; class Solution { public:class mycomparison{//自定义规则&#xff0c;使优先队列可以自动排序public:bool operator()(pair<int, int> & lhs, pair<int, int> & rhs){return lhs.s…

第十五届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组(基础题)

试题 C: 好数 时间限制 : 1.0s 内存限制: 256.0MB 本题总分&#xff1a;10 分 【问题描述】 一个整数如果按从低位到高位的顺序&#xff0c;奇数位&#xff08;个位、百位、万位 &#xff09;上 的数字是奇数&#xff0c;偶数位&#xff08;十位、千位、十万位 &…