【游戏客户端】制作你玩我猜Like玩法
【游戏客户端】制作你玩我猜Like玩法
大家好,我是Lampard猿奋~~ “你画我猜”相信大家都不陌生,当初这款小游戏可谓茶余饭后必玩之选,风头一时无二。今天要和大家分享如何实现一个你玩我猜Like的玩法。
我们可以简单的把需求拆成两个个部分:1.绘图功能的实现,2.数据传输方式
本文不贴代码只讲设计思路,希望能帮助到大家~

(一)绘图功能的实现
(1)画布
要作画我们首先需要一个画布,画布我们可以在UI编辑器中用一个image控件来显示。但是需要注意两个地方:
首先就是不要用太深的颜色作为底色(你没见过黑色的画布吧,五彩斑斓的黑当我没说...), 再者就是记得画布的透明度最好设置成255,因为之后的绘制是用目标颜色和画布进行混合渲染,因此如果透明度不为255的话,渲染出来的结果可能和设定的画笔颜色会有出入

(2)rendertexture类
紧接着就是要介绍我们实现绘图逻辑的类:RenderTexture类,怎么去理解这个类呢?大家可ui把这个类当作一张白纸,我们想要实现绘制效果,首先要在白纸上画出背景颜色(画布颜色),然后再在画布颜色的基础上,继续增加各式各样我们想要绘制的图形
此时问题很多的小明就要问了:为啥不直接用UI管理器导入的Image作为真正的画布?还要搞什么白纸的概念呢?

这是因为我们要实现画笔所划过的地方与画布进行混合渲染,而RenderTexture类支持这个功能,而UI编辑器中封装好的UI类Image和Sprite是不支持的
RenderTexture类底层是调用了OpenGL的glBlendFunc的混合绘制方法,关于RenderTexture的研究我们在之前做过了。
function clsWidgetScratch:initRenderTexture()local renderTexture = cc.RenderTexture:create(self.width, self.height)self:addChild(renderTexture)renderTexture:addChild(self.drawNode)renderTexture:addChild(self.rubberImg)return renderTexture
end
如果大家想了解cocos中如何调用RenderTexture来进行混合绘制,可以看看我之前写的这一篇文章:【游戏客户端】实现刮刮乐效果
如果大家想要了解RenderTexture的底层openGL渲染逻辑,可以看看这一篇文章:glBlendFunc颜色混合
(3)画笔DrawNode
方才我们已经创建了一个Rendtexture的对象,然后把画布的颜色渲染了上去,紧接着我们只需要创造出画笔绘制的内容,然后和画布进行混合渲染就可以实现我们的绘图功能
我们知道画画是需要从点到线再到面的,因此我们可以实例化一个带颜色的DrawNode对象用来描绘画笔点下的一个点
而想要绘制出不同的颜色,只需要调整drawSolidCircle接口中的color字段即可
function clsWidgetScratch:initDrawNode()local drawNode = cc.DrawNode:create()drawNode:setVisible(true)drawNode:setBlendFunc(gl.ONE, gl.GL_ONE_MINUS_SRC_ALPHA)drawNode:setLocalZOrder(1000)drawNode:drawSolidCircle(cc.p(self.length / 2, self.length / 2), self.length / 2, 360, 10, 1, 1, self.color)return drawNode
end
(4)调整绘制的位置

有了画布和Drawnode画出来的点,我们下一步还需要做的就是监听玩家绘制的位置
首先我们要创建一个监听用的Layout置于最上层,用onTouchMove的方法监听玩家触摸的位置。紧接着把DrawNode的position设置成玩家落笔的位置,然后调用cocos中renderTexture的混合绘制方法即可

(5)橡皮擦功能
画图需求中带有了橡皮擦功能,其实聪明的朋友已经发现,所谓的橡皮擦功能。我们可以简单的把DrawNode的颜色设置为和画布的一样,就可以把之前绘制的内容给覆盖掉了
好,我们看看目前所实现的效果:

(二)数据传输方式的选择
当看到玩法效果实现出来的时候,我也和大家一样欣喜若狂,以为这个需求快要到尾声了。然鹅,困难的地方还在后面:首先这并不是一个单机玩法,它是多人实时同步的一个游戏。那就意味着你需要把绘制的内容实时同步给所有的玩家,那么问题来了,对于一幅960*640的画布,你要如何进行实时传输呢?
(1)Http协议拉取最新的图片
首先我们可以想到用类似patch的方式,每当绘制成功后就把内容以png格式上传到资源库中,然后其他猜测的玩家则用http协议去拉取最新的资源
这样的做法好处是确保绘制内容的准确性和完整性
坏处是每一次绘制内容的更新,都要去拉取一次资源,我们知道文件的IO是非常耗时的,这样当遇到性能有点卡顿的时候,更新时就会一闪一闪,这样玩家的体验上并不好
(2)RPC协议同步像素内容
那我们可不可以去同步像素的内容呢?虽然项目的每一个像素点用的都是RGBA8888的格式记录,也就是说一个像素需要32位,但我们实际只用到了8个颜色,且透明度都是255,因此我们完全可以用8个bit去映射记录每个像素的信息
但是虽然如此优化了,但每一个像素也需要用到1B的大小去记录,而我们有960*640个像素,960 * 640 / 1024,算下来我们还要用到600KB的数据去传输这个画面。
但由于处于性能压力的监控,服务端很早之前就闲置了,每次使用RPC协议,不能交互超过100KB的数据,因为如果我们需要用到这种做法,我们还得进一步优化:可以把画布分块,像场景地图那样切成小块去分开传输,总的来说也算是一种思路
这种做法好处是确保了画面的准确性,以及省去了IO的时间
坏处是需要分块请求画面内容,比较难确保每次数据传输我每一小块的内容都可以准确的获取数据和显示

(3)RPC协议同步绘制流程
其实第二种的思路已经很接近正解了,但是唯一问题就是不想采用分块的方式,想完完整整的一幅图片同步给玩家。因此我想到了第三种方法:记录玩家的绘制流程,用RPC协议同步玩家的绘制记录。
什么意思呢?首先我们把整一个画布划分成一个3*3,或者4*4像素方块组成的整体。然后我们用一个二维数组去记录这些小方块是否被绘制,绘制的颜色映射是什么。
每当玩家绘制的时候,我们就更新二维数组中该小方块的映射值,然后把这个二维数组的记录信息,以二进制数据的形式拼接在一起上传。同时参与的玩家通过RPC协议获取最新的绘制信息,然后解码成二维数组,重新根据绘制信息重新把内容“画”出来
这样我们就可以把3*3或者4*4的像素信息融合成一份,虽然会有一些锯齿感和多花了时间进行编码和解码,但是成功把数据压缩到了100K以内,且避免了IO的卡顿
local NORMAL_LENGTH = 3local i = math.floor(y / NORMAL_LENGTH)
local j = math.floor(x / NORMAL_LENGTH)
self.nodeList[i*NORMAL_LENGTH][j*NORMAL_LENGTH] = self:getEncodeNodeIndex()
(三)最后看看我们最终的效果
你画我猜玩法视频
至此你画我猜玩法的分享到此结束~~
感谢阅读,点赞,关注!!!

相关文章:
【游戏客户端】制作你玩我猜Like玩法
【游戏客户端】制作你玩我猜Like玩法 大家好,我是Lampard猿奋~~ “你画我猜”相信大家都不陌生,当初这款小游戏可谓茶余饭后必玩之选,风头一时无二。今天要和大家分享如何实现一个你玩我猜Like的玩法。 我们可以简单的把需求拆成两个个部分&…...
分页查询从接口到实现,统一对日期类型进行格式化处理
编写Service实现类编写Mapper的sql,但复杂的sql语句需要写到mapper对应的xml文件中日期类型格式化处理 /*** 扩展springmvc框架的消息转换器* param converters*/Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> conve…...
栈和队列详解(1)
目录 一、什么是栈? 二、创建一个我们自己的栈 1.前置准备 1.1需要的三个文件 1.2结构体的创建和头文件的引用 2.接口的实现 2.1初始化栈结构体 2.2尾插(压栈) 2.3栈存放的元素个数和判断栈是否为空 2.4获取栈顶元素 2.5出栈 2.6摧毁栈 2.7测试接口 三、…...
苏州OV泛域名RSA加密算法https
RSA加密算法是一种非对称加密算法,它被广泛应用于信息安全领域。与对称加密算法不同,RSA加密算法使用了两个密钥,一个公钥和一个私钥。公钥可以公开,任何人都可以使用它加密信息,但只有私钥的持有者才能解密信息。RSA加…...
凯迪正大—微机继电保护校验仪
一、继电保护测试仪产品概述 KDJB-802继电保护测试仪是在参照电力部颁发的《微机型继电保护试验装置技术条件(讨论稿)》的基础上,听取用户意见,总结目前国内同类产品优缺点,充分使用现代的微电子技术和器件实现的一种新…...
Linux文件属性与权限管理(可读、可写、可执行)
Linux把所有文件和设备都当作文件来管理,这些文件都在根目录下,同时Linux中的文件名区分大小写。 一、文件属性 使用ls -l命令查看文件详情: 1、每行代表一个文件,每行的第一个字符代表文件类型,linux文件类型包括&am…...
Centos7.9安装lrzsz进行文件传输---Linux工作笔记059
这里咱们lrzsz命令,需要用来进行文件传输,因为如果不安装这个命令的话,那么 传输安装包什么的就不方便因为只有少数传输工具,才支持,直接拖拽的.没有的时候就可以用这个工具,用命令来传输 直接就是: sz 文件名 就可以把文件下载下来 rz 选择一个文件, 就可以把文件上传到当…...
酒吧座位全解析 小白必看
相信还有很多第一次去酒吧的朋友们还不了解吧台、散台、卡座的区分,下面我简单解说一下,如有错漏,欢迎指正!一、吧台吧台是酒吧的核心部位,走进酒吧门,首先映入眼帘的就是吧台,一排人围着吧台几…...
DAY19
题目一 空间尝试模型 一个样本做行一个样本做列 范围尝试模型 以....做分隔 dp[i][j] 为以i为左界限 以j为右界限 求这个范围内的计算值(不对 是方法数) 这& | ^ 都是双目运算符 观察一下规律 整体字符数量一定为奇数(包括运算符和数字) 对应到数组中 数组的位一定是偶数…...
Data analysis|Tableau基本介绍及可实现功能
一、基础知识介绍 (一)什么是tableau tableau 成立于 2003 年,是斯坦福大学一个计算机科学项目的成果,该项目旨在改善分析流程并让人们能够通过可视化更轻松地使用数据。Tableau可以帮助用户更好地理解和发现数据中的价值&#x…...
单元测试优化:为什么要对程序进行测试?测试有什么好处?
单元测试(Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 程序单元是应用的最小可测试部件。简单来说,就是测试数据的稳定性是否达到程序的预期。 我们日常开发时可能…...
自动装配在Spring Boot中的重要性及实现方式
这里写目录标题 自动装配在Spring Boot中的重要性及实现方式什么是自动装配?如何实现自动装配?如何使用自动装配自动装配的优势总结 手写自动装配的Java代码示例原理 自动装配在Spring Boot中的重要性及实现方式 Spring Boot是基于Spring框架的开源框架…...
校对软件在司法系统中的应用:加强刑事文书审查
校对软件在司法系统中的应用可以加强刑事文书审查,提高文书的准确性和可靠性。 以下是校对软件在刑事文书审查方面的应用: 1.语法和拼写检查:校对软件可以自动检查刑事文书中的语法错误和拼写错误。这包括句子结构、主谓一致、动词形式等方面…...
微信小程序上传图片和文件
1.从微信里选择图片或文件上传 使用的vant的上传组件 原生用 wx.chooseMessageFile() html <!-- 从微信上面选择文件 --><van-uploader file-list"{{ file }}" bind:after-read"afterRead" max-count"{{3}}" deletable"{{ true…...
拥抱AIGC浪潮,亚信科技将如何把握时代新增量?
去年底,由ChatGPT带起的AIGC浪潮以迅雷不及掩耳之势席卷全球。 当互联网技术的人口红利逐渐消退之际,AIGC就像打开通用人工智能大门的那把秘钥,加速开启数智化时代的到来。正如OpenAI CEO Sam Altman所言:一个全新的摩尔定律可能…...
【opencv】指定宽或高按比例缩放图片 拼接图片
指定宽或高按比例缩放图片 import cv2def resize_by_ratio(image, widthNone, heightNone, intercv2.INTER_AREA):img_new_size None(h, w) image.shape[:2] # 获得高度和宽度if width is None and height is None: # 如果输入的宽度和高度都为空return image # 直接返回原图…...
使用C#加载TOOLBLOCK
前言 因为Vpp文件类型包含了以下三种 QuickBuidJobToolBlock 不同类型的打开方式不同,需要提前知道vpp是什么类型 例如 这个TB.vpp文件是TOOLBLOCK,就不能直接在visionpro中打开(直接打开需要QuickBuid文件), 可以…...
MPAS-A原理及陆面模式的基本概念
跨尺度预测模式(The Model for Prediction Across Scales - MPAS)是由洛斯阿拉莫斯实验室和美国国家大气研究中心(NCAR)共同开发,其由3个部分组成,分别称为 MPAS-A(大气模型)、MPAS-O(海洋模型&…...
前端技术Html,Css,JavaScript,Vue3
Html 1.基本标签 <h1>最大的标题</h1> <h2> . . . </h2> <h3> . . . </h3> <h4> . . . </h4> <h5> . . . </h5> <h6>最小的标题</h6><p>这是一个段落。</p> <br> (换…...
实战项目——多功能电子时钟
一,项目要求 二,理论原理 通过按键来控制状态机的状态,在将状态值传送到各个模块进行驱动,在空闲状态下,数码管显示基础时钟,基础时钟是由7个计数器组合而成,当在ADJUST状态下可以调整时间&…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
