Creator填色游戏的一种实现方案

前言

先上一个辛劳弄出来的gif效果。写民众号时间不长,许多技巧还在逐步跟小伙伴学习。可关注民众号,回复“绘图”或者“填色”都可获得demo的git地址。请使用Creator2.4.0运行
Creator填色游戏的一种实现方案

填色游戏种类也挺多的,我今天要说的是一种相对简朴的填色。
对于填色游戏的做法,我在论坛里搜到不少帖子,尤其是这个帖子的留言比较多:油漆桶填色效果怎么实现啊,找了两天都找不到资源
其中有一条留言跟我的想法不约而同,
Creator填色游戏的一种实现方案
尤其是做了之前的取色,绘图等功能后,对webgl的readPixels()函数返回的数据处置起来越来越随手。以是就用了替换数据的方式。
另有一种填色游戏接纳的纯Graphics的方式,种种贝塞尔曲线,矩形,直线和moveTo,实现几个区块填指定颜色的填色游戏,我感受那种应该是借助工具的,由于天生的文件相当大。若是有知道的同砚可以在下方留言,一起交流。

制作方式

  1. 先上一张图
    Creator填色游戏的一种实现方案
    这是一张我在《绘图游戏调色盘取色方式》的文章中展示的一张图,图片左侧的色盘是原始图,右侧是使用相机截屏获得的数据更新后的图。那时是为了验证截屏的正确性而做的。这次正好用来做填色游戏。
  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,就有参考价值;然则不要拿来主义,要根据你自己的情形,酌情思量。

Windows 最值得推荐的装机必备“神器”软件大合集

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

Creator填色游戏的一种实现方案

以后更新的速率可能会慢许多,一周两篇,或者一篇或者没有,还请人人见谅。究竟不能靠这个养活自己,而且还相当花费时间。

迎接扫码关注民众号《微笑游戏》,浏览更多内容。若是您以为文章还可以,点赞、在看、分享、赞助、点下广告都是对我最大的激励,在下将感激涕零。

Creator填色游戏的一种实现方案
迎接扫码关注民众号《微笑游戏》,浏览更多内容。

原创文章,作者:28x29新闻网,如若转载,请注明出处:https://www.28x29.com/archives/21012.html