分享Creator点击事件透明穿透问题

应该往这段代码里加像素点判断吗?有像素点判断的代码吗兄弟 我不会太加

CCC如何获取像素点呢?

mark

不错哈

mark

let _textureIdMapRenderTexture = {}

cc.Class({
    extends: cc.Component,

    properties: {
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        this.node._hitTest = this.hitTest.bind(this)
    },

    start() {

    },

    hitTest(location) {
               let spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame
        if (spriteFrame == null) {
            return false
        }
        let posInNode = this.node.convertToNodeSpaceAR(location)
        let rect = spriteFrame.getRect()
        let offset = spriteFrame.getOffset()

        var type = this.node.getComponent("DecorateItemPrefab").m_type
        // cc.log(type + "--", "xxxxxxxxxxxxxx", type)
        // cc.log(type + "--", "posInNode", posInNode)
        // cc.log(type + "--", "rect", rect)
        // cc.log(type + "--", "offset", offset)
        if ((posInNode.x < offset.x - rect.width / 2) || (posInNode.y < offset.y - rect.height / 2)
            || (posInNode.x > (offset.x + rect.width / 2)) || (posInNode.y > (offset.y + rect.height / 2))) {
            return false
        }
        else {
            let posInRect = cc.v2(parseInt(posInNode.x - offset.x + rect.width / 2), parseInt(posInNode.y - offset.y + rect.height / 2))
            // cc.log(type + "--", "posInRect",  posInRect)
            // cc.log(type + "--", "isRotated", spriteFrame.isRotated())

            let tex = spriteFrame.getTexture()
            var rt = _textureIdMapRenderTexture[tex.getId()]
            if (!rt) {
                rt = new cc.RenderTexture()
                rt.initWithSize(tex.width, tex.height)
                rt.drawTextureAt(tex, 0, 0)
                _textureIdMapRenderTexture[tex.getId()] = rt
            }

            // data就是这个texture的rgba值数组
            let data
            if (spriteFrame.isRotated())
            {
                data = rt.readPixels(null, rect.x + posInRect.y, rect.y + posInRect.x, 1, 1)
                // cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
            }
            else{
                data = rt.readPixels(null, rect.x + posInRect.x, rect.y + rect.height - posInRect.y, 1, 1)
                // cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
            }

            //if ((data[0] <= 0 && data[1] <= 0 && data[2] <= 0) || data[3] <= 0) {
            if (data[3] <= 0) {
                return false
            }
            else {
                return true
            }
        }
    },

    onDestroy(){
     let spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame
        if (spriteFrame == null) {
            return false
        }

        let tex = spriteFrame.getTexture()
        let id = tex.getId()
        if (_textureIdMapRenderTexture[id]) {
            _textureIdMapRenderTexture[id].destroy()
            delete _textureIdMapRenderTexture[id]
        }
    }
    // update (dt) {},
});

目前仅支持cc.Sprite 如下模式, 其他模式其实也可以按需改代码适配, sprite的mode 和 type 主要是决定,我们如何使用触摸的location

按照panda 大大的写了一个组件,用RenderTexture实现,用于过滤透明区域。
我的经验是
1,游戏内存基本不会增加,游戏性能也基本没有影响,游戏GPU相关的图片对应的内存会翻倍

不知道是否是这样,底层不是很了解。

2赞

mark

@panda
在玩一玩平台,实测renderTexture readPixels接口读出来的全部是0。。。 求解

打印gl.readPixels之后发现是个空函数

@panda 可以看一看玩一玩这个问题么

mark

@panda 大神帮忙看一下可以不
https://forum.cocos.com/t/rendertexture-gl-readpixels/68802

@wangzhe 哲大大
https://forum.cocos.com/t/rendertexture-gl-readpixels/68802

试着使用这种方法去获取数据
https://forum.cocos.com/t/cocos-creator/60736/11

好的, 谢谢,我试一下,不过顺便说一下的是,我在web mobile 和 cocos creator 模拟器上跑,我上面使用的RenderTexure
gl.readPixels都是可以获取到像素来判断透明区域的哦,而且不会卡顿。而且就算你说的新方法可以,我还是想知道为什么我的方法在玩一玩平台不行, 玩一玩平台的gl.readPixels 为什么不工作

谢啦

let _textureIdMapRenderTexture = {}

cc.Class({
    extends: cc.Component,

    properties: {
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        this.node._hitTest = this.hitTest.bind(this)
    },

    start() {

    },

    hitTest(location) {
        let spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame
        if (spriteFrame == null) {
            return false
        }
        let posInNode = this.node.convertToNodeSpaceAR(location)
        let rect = spriteFrame.getRect()
        let offset = spriteFrame.getOffset()

        var type = "哈哈哈"
        cc.log(type + "--", "xxxxxxxxxxxxxx", type)
        cc.log(type + "--", "posInNode", posInNode)
        cc.log(type + "--", "rect", rect)
        cc.log(type + "--", "offset", offset)
        if ((posInNode.x < offset.x - rect.width / 2) || (posInNode.y < offset.y - rect.height / 2)
            || (posInNode.x > (offset.x + rect.width / 2)) || (posInNode.y > (offset.y + rect.height / 2))) {
            return false
        }
        else {
            let posInRect = cc.v2(parseInt(posInNode.x - offset.x + rect.width / 2), parseInt(posInNode.y - offset.y + rect.height / 2))
            cc.log(type + "--", "posInRect", posInRect)
            cc.log(type + "--", "isRotated", spriteFrame.isRotated())

            let tex = spriteFrame.getTexture()
            var rt = _textureIdMapRenderTexture[tex.getId()]

            /* RenderTexure方式
            if (!rt) {
                rt = new cc.RenderTexture()
                rt.initWithSize(tex.width, tex.height)
                rt.drawTextureAt(tex, 0, 0)
                _textureIdMapRenderTexture[tex.getId()] = rt
            }

            // data就是这个texture的rgba值数组
            let data
            if (spriteFrame.isRotated()) {
                data = rt.readPixels(null, rect.x + posInRect.y, rect.y + posInRect.x, 1, 1)
                //data = rt.getImageData(rect.x + posInRect.y, rect.y + posInRect.x, 1, 1)
                cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
            }
            else {
                //data = rt.getImageData(rect.x + posInRect.x, rect.y + rect.height - posInRect.y, 1, 1)
                data = rt.readPixels(null, rect.x + posInRect.x, rect.y + rect.height - posInRect.y, 1, 1)
                cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
            }

            */

            //Web 方式
            if (!rt) {
                var cvs = document.createElement("canvas")
                var rt = cvs.getContext('2d')
                cvs.width = tex.width
                cvs.height = tex.height
                rt.drawImage(tex.getHtmlElementObj(), 0, 0, tex.width, tex.height, 0, 0, tex.width, tex.height)
                _textureIdMapRenderTexture[tex.getId()] = rt
            }

            let data
            if (spriteFrame.isRotated()) {
                data = rt.getImageData(rect.x + posInRect.y, rect.y + posInRect.x, 1, 1).data
                cc.log(type + "--", "data", data, rect.x + posInRect.y, rect.y + posInRect.x)
            }
            else {
                data = rt.getImageData(rect.x + posInRect.x, rect.y + rect.height - posInRect.y, 1, 1).data
                cc.log(type + "--", "data", data, rect.x + posInRect.x, rect.y + rect.height - posInRect.y)
            }

            if (data[3] <= 0) {
                return false
            }
            else {
                return true
            }
        }
    },

    onDestroy() {
        let spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame
        if (spriteFrame == null) {
            return false
        }

        let tex = spriteFrame.getTexture()
        let id = tex.getId()
        if (_textureIdMapRenderTexture[id]) {
            _textureIdMapRenderTexture[id].destroy()
            delete _textureIdMapRenderTexture[id]
        }
    }
    // update (dt) {},
});

@huanxinyin ,两种方式我都试啦,qq玩一玩还是不行, 在浏览器里面调试都没问题,qq玩一玩就是不行,
1, Canvas方式在玩一玩平台读出来的都是1, 0, 1, 0
2, qq玩一玩 使用Rendtexture 方式我能确定的是, RenderTexture肯定是画上去的,因为我把他赋值给一个sprite, 这张纹理就能显示, 所以只是readPixels失败,Canvas 方式我就不清楚了

麻烦帮忙看看,刚好一个游戏要移植到qq玩一玩平台,之前都只在web上测试 :cry:

应该是玩玩没有实现 gl.readPixels 这个接口导致的。

@huanxinyin 能提供点思路么,我看他qqPlayCore里面这些接口都在用,不知道什么原因,在外部就没了,是不是CocosCreator适配的问题

这个已经咨询了玩一玩官方,这个接口没有支持的计划,qqPlayCore 提供的是空函数。

好的,谢谢

那在玩一玩平台, 使用Canvas 的方式最终也会映射到gl.readPixels 这个接口把?因为我上面测试来看也是行不通的,只在web上可以
所以我需要放弃这种方式?

看来canva也是没戏了, 最新的Creator2.05 qq-adapter里面的代码,难怪我读出来都是1, 0, 1, 0