【求助】3.x的不规则点击,看看错在哪里

请教大佬们,不规则按钮的点击?

查找了挺多资料,多人建议的是射线检测,但是需求的图片是动态的不能提前获得区域描边范围,所以使用透明度来检测。

参考的是皮皮案例,获取点击的像素色值,看透明度判断是否有效点击。

【难点】皮皮用2.x做的案例,我改成了3.x,但是实际效果不对劲,感觉应该是点击位置的转换到图片不对,希望大家指点

点击:

主要的获取事件:

/**点击建筑物餐厅

 * @id 携带一个餐厅编号  0-4 */

private clickLevelMap(evt: EventTouch, id) {

    // this.testPosClick(id);

    Log.warn(id, "?clickLevelMap>点击建筑物餐厅>>>>>>>", evt.touch.getLocation())

    const img: Sprite = evt.target.getComponent(Sprite);

    if (img) {

        const TargetNode: Node = evt.target;

        const nodeUit = TargetNode.getComponent(UITransform);

        // 点击位置

        const touchPos = evt.getLocation()

        // 获取像素数据

        const pixelsData = RenderUtil.readPixels(img.spriteFrame.texture);

        // 截取像素颜色

        let x = touchPos.x + nodeUit.anchorX * nodeUit.width,

            y = -(touchPos.y - nodeUit.anchorY * nodeUit.height);

        const index = (nodeUit.width * 4 * Math.floor(touchPos.y)) + (4 * Math.floor(touchPos.x)),

            colors = pixelsData.slice(index, index + 4);

        // 当前点击像素颜色

        const color = new Color(colors[0], colors[1], colors[2]);

        const opacity = colors[3];

        Log.log("----截取像素颜色---4----------colors--------", x, ", ", y, colors)

        Log.log("----截取像素颜色---3----------index--------", index, color, opacity)

    }

}

/**

 * 读取渲染纹理像素信息

 * @param texture

 * @param filpY 是否翻转Y轴,默认true

 */

public static readPixels(texture: __private._cocos_asset_assets_texture_base__TextureBase, filpY?: boolean): Uint8Array {

    // 通用版本

    var { width, height } = texture, gfxTexture = texture.getGFXTexture(), gfxDevice = texture['_getGFXDevice'](), bufferViews = [],

        region = new gfx.BufferTextureCopy, buffer = new Uint8Array(width * height * 4);

    // region.texOffset.x = region.texOffset.y = 0;

    region.texExtent.width = width;

    region.texExtent.height = height;

    bufferViews.push(buffer);

    gfxDevice?.copyTextureToBuffers(gfxTexture, bufferViews, [region]);

    // 翻转

    if (filpY !== false) {

        let i = 0, len1 = height / 2, len2 = width * 4, j: number, idx0: number, idx1: number;

        while (i < len1) {

            j = 0;

            while (j < len2) {

                idx0 = i * len2 + j;

                idx1 = (height - i - 1) * len2 + j++;

                [buffer[idx0], buffer[idx1]] = [buffer[idx1], buffer[idx0]];

            }

            i++;

        }

    }

    return buffer;

    // 3.4及以上版本,有点问题

    // return texture.readPixels();

}

上传了代码:
ClickGetColor.zip (2.9 KB)

哪里需要这么复杂。。。加个包围盒,判断点击区域就完了

点击的事件返回的应该是全局坐标,要转成图片节点的局部坐标吧。

嗯 但上面说图片是动态的,不能提前加包围点的坐标,如果可以知道包围,那就用射线。如果是用描边那种算法来获取包围盒,1.点会很多?2.还是没做过,求指点

所以用透明度看来时比较直观的

嗯嗯,之前2.x那个转桌标的方法没用了,convertToNodeSpaceAR
点击图片的监听,还需要转吗

方法有的,在UITransform组件上了
getComponent(UITransform).convertToNodeSpaceAR(pos)

超哥牛逼。

我的做法是重写hittest改成多边形检测

有案例的指点吗,想要

嗯 用了。获取色值还是【0000】
可能哪里还是错误的

onLoad() {
//用一个变量来决定这个按钮是普通按钮还是多边形按钮
if (this.isPolygon) {
//@ts-ignore 重写触摸检测函数为多边形检测
this.node._hitTest = this.polygonHitTest.bind(this);
}
}
/**

  • 不规则多边形触摸测试
    • @param {触摸点} point
    • @param {监听} listener
      /
      polygonHitTest(point, listener) {
      var polygonCollider = this.node.getComponent(cc.PolygonCollider);
      if (polygonCollider) {
      //@ts-ignore
      point = this.node.convertToNodeSpaceAR(point);
      return cc.Intersection.pointInPolygon(point, polygonCollider.points);
      }
      }
      ps
      (1)cocos版本2.4.4
      ps*(2)这个方法需要提前在预制体里挂上PolygonCollider组件拿到包围点

2.4.x

_hitTest时用自定义的区域检测改变hit的值

let tmpv2 = cc.v2();
tmpv2.x = testPt.x - w / 2;
tmpv2.y = testPt.y - h / 2;
switch (this.throughType) {
	case ThroughType.POLYGON:
		if (cc.Intersection.pointInPolygon(tmpv2, this.polygon)) {
			hit = true;
		}
		break;
	case ThroughType.CIRCLE:
		if (tmpv2.len() < this.radius) {
			hit = true;
		}
		break;
}

2.4.x _hitTest源码:https://github.com/cocos/cocos-engine/blob/ca662e1d8c009e4c070be6fb12c55967f9cdd6f6/cocos2d/core/CCNode.js#L2384

3.7 hitTest源码:https://github.com/cocos/cocos-engine/blob/0673680ff0b13e85db498fcf751afaa2cf884b6d/cocos/2d/framework/ui-transform.ts#L473

想支持一下的话可以 点这 ,原理不难也可以看下源码自己改

这个好像不符合需求吧?图片是动态的,没有获取顶点或者编辑顶点的方法。
现在是计划获取点击位置色值。

你的案例还是回归到:需要提前编辑图片的顶点,除非能在渲染方面自动获取图片顶点,然后用我上面说的射线检测

这个好像不符合需求吧?图片是动态的,没有获取顶点或者编辑顶点的方法。
现在是计划获取点击位置色值。

你的案例还是回归到:需要提前编辑图片的顶点,除非能在渲染方面自动获取图片顶点,然后用射线检测或者其它办法判断就行

应该是你的RenderTexture没渲染出来,如果只是获取texture像素信息的话 直接把源码里面的函数copy出来就好了

1赞