前言

先上一个辛苦弄出来的gif效果。写公众号时间不长,很多技巧还在慢慢跟小伙伴学习。可关注公众号,回复“绘图”或者“填色”都可获得demo的git地址。请使用Creator2.4.0运行

填色游戏种类也挺多的,我今天要说的是一种相对简单的填色。

对于填色游戏的做法,我在论坛里搜到不少帖子,尤其是这个帖子的留言比较多:油漆桶填色效果怎么实现啊,找了两天都找不到资源

其中有一条留言跟我的想法不谋而合,



尤其是做了之前的取色,绘图等功能后,对webgl的readPixels()函数返回的数据处理起来越来越顺手。所以就用了替换数据的方式。

还有一种填色游戏采用的纯Graphics的方式,各种贝塞尔曲线,矩形,直线和moveTo,实现几个区块填指定颜色的填色游戏,我感觉那种应该是借助工具的,因为生成的文件相当大。如果有知道的同学可以在下方留言,一起交流。

制作方式

  1. 先上一张图



    这是一张我在《绘图游戏调色盘取色方法》的文章中展示的一张图,图片左侧的色盘是原始图,右侧是使用相机截屏获得的数据更新后的图。当时是为了验证截屏的正确性而做的。这次正好用来做填色游戏。
  2. 制作原理

    实际上更改的就是右侧这张图使用的数据。左侧的图接收触摸事件,通过触摸点的位置,更新颜色数据。所以只要将两张图片重叠,用右边的图片盖住左边的图片,然后使用处理过的颜色数据更新右边的这张图,效果也就出来了。这里需要说一嘴,为什么要用两张图,就是相机截屏获得的数据初始化出来的纹理,正好是y反转的,所以右侧的图的scaleY我给了-1.否则就是倒着的。
  3. 接收事件的处理

    接收事件,获得点击坐标位置,这个没什么可多说的。
  4. 更新数据

    更新数据的时候我是从点击的点向四周扩散,因为颜色的点太多,所以不能用递归操作,因此做了每帧更新多少个点的方式,目前我给的是5000,OPPO A9真机实测不卡。使用一个数组记录更新过的点,避免重复更新消耗时间。
  5. 坑与新玩法

    我没有做在更新数据时不可以更换颜色操作,所以在更新数据时如果点击了左侧的色盘,那么右侧的颜色会跟着更新,这个也可以说是坑,也可以说是玩法。

    色盘也是通过相机截屏获得的数据获取的,但是这种获取有缺陷,就是点击的色盘上的点不能有阴影,但是我使用的色盘刚好有,所以有的时候获取的颜色会是黑色或者灰色。

代码

import TextureRenderUtils from "../TextureRenderUtils";

const { ccclass, property } = cc._decorator;

@ccclass
export default class FillColorV1 extends cc.Component { @property([cc.Component.EventHandler])
callback: cc.Component.EventHandler[] = []; @property(cc.Camera)
camera: cc.Camera = null; @property(cc.Sprite)
target: cc.Sprite = null; @property(cc.Node)
renderNode: cc.Node = null; private pointList: number[] = []
private r: number;
private g: number;
private b: number; protected textureHelper: TextureRenderUtils = new TextureRenderUtils() private grid: number[] = [] private imgData: ArrayBufferView = null; start() {
this.node.on(cc.Node.EventType.TOUCH_START, this.touchStart, this)
this.init();
} getTextureInfo() {
return this.textureHelper.getTextureInfo();
} getDataUrl() {
return this.textureHelper.getDataUrl()
} changeColor(color: cc.Color) {
this.r = color.r;
this.g = color.g;
this.b = color.b; } init() { this.textureHelper.init(this.camera, this.renderNode) this.textureHelper.render() let data = this.textureHelper.getData() if (data.length > 0) {
this.imgData = data;
cc.log('FillColorV1 width ', this.renderNode.width, ' height ', this.renderNode.height)
cc.log(' 实际上有多少个点 == ', data.length / 4)
let count = this.renderNode.width * this.renderNode.height;
cc.log(" 应该有多少个点的颜色 ", count)
if (this.target) {
let tTexture = this.target.spriteFrame.getTexture()
tTexture.setFlipY(false)
this.target.node.scaleY = -1 tTexture.initWithData(data, tTexture.getPixelFormat(), this.renderNode.width, this.renderNode.height) }
} } update(dt: number) {
let flag = false;
let count = 0;
let width = this.textureHelper.width;
let r = this.r;
let g = this.g;
let b = this.b;
//当发现有点击坐标的时候开始执行。这个5000
while (this.pointList.length >= 2 && count++ <= 5000) {
flag = true;
let x = this.pointList.shift();
let y = this.pointList.shift();
this.paintPoint(x, y, width, r, g, b)
} if (flag) {
let texture = this.target.spriteFrame.getTexture();
texture.initWithData(this.imgData, texture.getPixelFormat(), texture.width, texture.height)
} } paintPoint(x: number, y: number, width: number, r: number, g: number, b: number) {
let data = this.imgData;
let rowW = Math.floor(width) * 4//一行的长度
x = Math.floor(x)
let srow = Math.floor(y);//行开始位置
let startX = srow * rowW + x * 4;//列开始位置
if (!this.grid[startX]) {
this.grid[startX] = 1
// cc.log('r g b%{} ', data[startX + 0], data[startX + 1], data[startX + 2])
if (data[startX + 0] > 100 || data[startX + 1] > 100 || data[startX + 2] > 50) {
data[startX + 0] = r;
data[startX + 1] = g;
data[startX + 2] = b; this.pointList.push(x - 1)
this.pointList.push(y);
this.pointList.push(x + 1)
this.pointList.push(y);
this.pointList.push(x)
this.pointList.push(y - 1)
this.pointList.push(x)
this.pointList.push(y + 1)
}
}
}
//用于打印点击的位置,无关紧要
showPointColor(x: number, y: number, width: number) {
let data = this.imgData;
let rowW = Math.floor(width) * 4//一行的长度
x = Math.floor(x)
let srow = Math.floor(y);//行开始位置
let startX = srow * rowW + x * 4;//列开始位置
cc.log('r g b', data[startX + 0], data[startX + 1], data[startX + 2]) } touchStart(e: cc.Touch) {
let pos = e.getLocation();
pos = this.node.convertToNodeSpaceAR(pos)
cc.log('touchStart x ', pos.x, ' y = ', pos.y)
this.pointList.length = 0;
this.grid.length = 0;
this.pointList.push(pos.x)
this.pointList.push(pos.y)
this.showPointColor(pos.x, pos.y, this.textureHelper.width)
} }

结语

以上是我做的一种填色方案,并没有涉及到很大的图案,也没有涉及到放大缩小。我没有说我的方案是最好的,我相信方案有很多种,很多方案都有它的局限性,有它的适用范围;只要没有bug,就有参考价值;但是不要拿来主义,要根据你自己的情况,酌情考虑。

前几天公众号好不容易凑够了500人,开了广告。但是感觉仅凭广告的收入,不说了,都是眼泪。

以后更新的速度可能会慢很多,一周两篇,或者一篇或者没有,还请大家见谅。毕竟不能靠这个养活自己,而且还相当耗费时间。

欢迎扫码关注公众号《微笑游戏》,浏览更多内容。如果您觉得文章还可以,点赞、在看、分享、赞助、点下广告都是对我最大的鼓励,在下将感激不尽。



欢迎扫码关注公众号《微笑游戏》,浏览更多内容。

Creator填色游戏的一种实现方案的更多相关文章

  1. 123457123456#0#-----com.twoapp.ErTongHuaHua01--前拼后广--儿童绘画填色游戏jiemei

    com.twoapp.ErTongHuaHua01----儿童绘画填色游戏jiemei

  2. hdu 4559 涂色游戏(SG)

    在一个2*N的格子上,Alice和Bob又开始了新游戏之旅. 这些格子中的一些已经被涂过色,Alice和Bob轮流在这些格子里进行涂色操作,使用两种涂色工具,第一种可以涂色任意一个格子,第二种可以涂色 ...

  3. bzoj 5393 [HAOI2018] 反色游戏

    bzoj 5393 [HAOI2018] 反色游戏 Link Solution 最简单的性质:如果一个连通块黑点个数是奇数个,那么就是零(每次只能改变 \(0/2\) 个黑点) 所以我们只考虑偶数个黑 ...

  4. @NOIP2018 - D2T2@ 填数游戏

    目录 @题目描述@ @题解@ @代码@ @题目描述@ 小 D 特别喜欢玩游戏.这一天,他在玩一款填数游戏. 这个填数游戏的棋盘是一个 n×m 的矩形表格.玩家需要在表格的每个格子中填入一个数字(数字 ...

  5. P4494 [HAOI2018]反色游戏

    P4494 [HAOI2018]反色游戏 题意 给你一个无向图,图上每个点是黑色或者白色.你可以将一条边的两个端点颜色取反.问你有多少种方法每个边至多取反一次使得图上全变成白色的点. 思路 若任意一个 ...

  6. 【BZOJ5303】[HAOI2018]反色游戏(Tarjan,线性基)

    [BZOJ5303][HAOI2018]反色游戏(Tarjan,线性基) 题面 BZOJ 洛谷 题解 把所有点全部看成一个\(01\)串,那么每次选择一条边意味着在这个\(01\)串的基础上异或上一个 ...

  7. 【逆向笔记】2017年全国大学生信息安全竞赛 Reverse 填数游戏

    2017年全国大学生信息安全竞赛 Reverse 填数游戏 起因是吾爱破解大手发的解题思路,觉得题挺有意思的,就找来学习学习 这是i春秋的下载链接 http://static2.ichunqiu.co ...

  8. TOJ 1220 填数字游戏 / 深搜

    填数字游戏 时间限制(普通/Java):1000MS/10000MS     运行内存限制:65536KByte 描述 有个小游戏,让你填写以下方框,要求: a1+a2+a3+M=b1+b2+b3+M ...

  9. [BZOJ5303] [HAOI2018] 反色游戏

    题目链接 LOJ:https://loj.ac/problem/2524 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303 洛谷:https ...

随机推荐

  1. gitee+picgo搭建个人博客图床

    gitee+picgo搭建个人博客图床 准备 首先需要去码云注册一个账号,并新建一个仓库.接着下载PicGO并安装好. 过程 点击左下方的插件设置. image 在搜索框中输入gitee搜索插件,安装 ...

  2. Java 入门教程

    Java 入门教程 Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言. Java可运行于多个平台,如Windows, Mac OS,及其他多种UNIX版本的系统 ...

  3. 你都这么拼了,面试官TM怎么还是无动于衷?

    前言 面试,对于每个人而然并不陌生,可以说是必须经历的一个过程了,小到一场考试,大到企业面试,甚至大型选秀...... 有时自己明明很努力了,但偏偏会在面试环节出了插曲,比如,紧张就是最容易出现的了. ...

  4. [CF1270F]Awesome Substrings

    题目   点这里看题目. 分析   设前缀和\(s_r=\sum_{i=1}^r [S_i='1']\)   考虑满足要求的子串\((l,r]\)的要求: \[\exists k\in N_+, r- ...

  5. 基于移动最小二乘法的点云曲面拟合(python)

    1.移动最小二乘法介绍 为了更好地对数据量大且形状复杂的离散数据进行拟合,曾清红等人[1]开发出一种新的算法——移动最小二乘法.这种新的最小二乘算法为点云数据的处理提供了新的方法.使用点云数据拟合曲面 ...

  6. numpy中数组(矩阵)的乘法

    我们知道在处理数据的时候,使用矩阵间的运算将会是方便直观的.matlab有先天的优势,算矩阵是它的专长.当然我们用python,经常要用到的可能是numpy这个强大的库. 矩阵有两种乘法,点乘和对应项 ...

  7. Paper templates for Word(Word论文模板)

    经常看论文的朋友可能会发现,像一些大的会议的论文格式都是相同的,他们的格式一般都十分固定,这些论文是用什么软件做出来的呢?一开始我想当然的认为是用LaTeX,因为LaTeX提供了一些文类,我自然而然的 ...

  8. 使用numpy生成二维正态分布

    参考资料: https://www.zhihu.com/question/39823283?sort=created https://www.zhihu.com/question/288946037/ ...

  9. 【JMeter_05】创建第一个简单的接口脚本

    聚合数据:提供了很多开放的API,可以去练习使用https://www.juhe.cn/ 如果有小伙伴对HTTP协议不是很了解,可以看下这里 http://home.ustc.edu.cn/~xie1 ...

  10. 深入理解Java虚拟机学习笔记(三)-----类文件结构/虚拟机类加载机制

    第6章 类文件结构 1. 无关性 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(即扩展名为 .class 的文件) 是构成平台无关性的基石. 字节码(即扩展名为 .class 的文 ...