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

填色游戏种类也挺多的,我今天要说的是一种相对简单的填色。
对于填色游戏的做法,我在论坛里搜到不少帖子,尤其是这个帖子的留言比较多:油漆桶填色效果怎么实现啊,找了两天都找不到资源
其中有一条留言跟我的想法不谋而合,

尤其是做了之前的取色,绘图等功能后,对webgl的readPixels()函数返回的数据处理起来越来越顺手。所以就用了替换数据的方式。
还有一种填色游戏采用的纯Graphics的方式,各种贝塞尔曲线,矩形,直线和moveTo,实现几个区块填指定颜色的填色游戏,我感觉那种应该是借助工具的,因为生成的文件相当大。如果有知道的同学可以在下方留言,一起交流。

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人,开了广告。但是感觉仅凭广告的收入,不说了,都是眼泪。

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

欢迎扫码关注公众号《微笑游戏》,浏览更多内容。
原文:https://www.cnblogs.com/cgw0827/p/13266442.html