先上一个辛苦弄出来的gif效果。写公众号时间不长,不少技巧还在慢慢跟小伙伴学习。可关注公众号,回复“绘图”或者“填色”均可得到demo的git地址。请使用Creator2.4.0运行
node
填色游戏种类也挺多的,我今天要说的是一种相对简单的填色。
对于填色游戏的作法,我在论坛里搜到很多帖子,尤为是这个帖子的留言比较多:油漆桶填色效果怎么实现啊,找了两天都找不到资源
其中有一条留言跟个人想法不谋而合,
尤为是作了以前的取色,绘图等功能后,对webgl的readPixels()函数返回的数据处理起来愈来愈顺手。因此就用了替换数据的方式。
还有一种填色游戏采用的纯Graphics的方式,各类贝塞尔曲线,矩形,直线和moveTo,实现几个区块填指定颜色的填色游戏,我感受那种应该是借助工具的,由于生成的文件至关大。若是有知道的同窗能够在下方留言,一块儿交流。git
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,就有参考价值;可是不要拿来主义,要根据你本身的状况,酌情考虑。web
前几天公众号好不容易凑够了500人,开了广告。可是感受仅凭广告的收入,不说了,都是眼泪。数组
之后更新的速度可能会慢不少,一周两篇,或者一篇或者没有,还请你们见谅。毕竟不能靠这个养活本身,并且还至关耗费时间。微信
欢迎扫码关注公众号《微笑游戏》,浏览更多内容。函数