【问题标题】:Cocos2d 2.0 - Ignoring touches to transparent areas of layers/spritesCocos2d 2.0 - 忽略对图层/精灵透明区域的触摸
【发布时间】:2012-06-08 23:46:15
【问题描述】:

我有一个应用程序,其中有几个由具有透明度的 PNG 图像创建的图层。这些图层都在屏幕上彼此重叠。当用户点击图层的非透明区域时,我需要能够忽略对图层透明区域的触摸,并且能够检测为触摸......参见图片......

我该怎么做?谢谢。

【问题讨论】:

  • 透明层是清晰的还是上面显示的图案?您还知道如何检测任何区域的触摸吗?
  • 图案代表透明度。是的,我知道如何检测触摸,我只是检查触摸是否在 sprite.boundingBox 内......我需要知道它是否在 boundingBox 内并且是一个不透明的像素。
  • 嗯,好的,所以我建议在不透明的父级上放置一个空白的 CCMenuItemImage 并这样做。否则,您将处理大量您不想要的像素代码。
  • 你想让触摸穿过透明区域吗? (即最顶层是透明的,但您触摸它的位置是在下面的层中同一位置有一个不透明的像素)
  • 是的,我希望它忽略对图层透明区域的任何触摸,但是如果下面有一个图层并且这个触摸点对应于该图层上的一个非透明点,我想要这个下面的层被触发。

标签: cocos2d-iphone


【解决方案1】:

这里有一个可能的解决方案。

在CCLayer上实现一个扩展并提供这个方法:

- (BOOL)isPixelTransparentAtLocation:(CGPoint)loc 
{   
    //Convert the location to the node space
    CGPoint location = [self convertToNodeSpace:loc];

    //This is the pixel we will read and test
    UInt8 pixel[4];

    //Prepare a render texture to draw the receiver on, so you are able to read the required pixel and test it    
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    CCRenderTexture* renderTexture = [[CCRenderTexture alloc] initWithWidth:screenSize.width
                                                                     height:screenSize.height
                                                                pixelFormat:kCCTexture2DPixelFormat_RGBA8888];

    [renderTexture begin];

    //Draw the layer
    [self draw];    

    //Read the pixel
    glReadPixels((GLint)location.x,(GLint)location.y, kHITTEST_WIDTH, kHITTEST_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, pixel);

    //Cleanup
    [renderTexture end];
    [renderTexture release];

    //Test if the pixel's alpha byte is transparent
    return (pixel[3] == 0);
}

【讨论】:

  • 你能扩展答案吗?我尝试制作“扩展”,但它实际上应该是一个类别吗? kHITTEST_WIDTH 和 kHITTEST_HEIGHT 也未定义。它们应该是 1x1 还是 40x40?有人可以发布整个解决方案吗?
  • 您好,扩展确实是该类的一个类别。您可以创建它并立即将此方法添加为其中的一部分。至于未定义的常量,可以用 1 替换。
【解决方案2】:

如果 Lio 的解决方案不起作用,您可以添加透明精灵作为您的孩子,将其放在您的非透明区域下方,该区域的大小与此非透明区域相同,并通过这个新的透明精灵恢复所有触摸,但不是原始精灵。

【讨论】:

    【解决方案3】:

    这是我对您要求的解决方案,让我知道它是否有效

    在 CCMenu 上创建一个名称为透明的类别 文件 CCMenu+Tranparent.h

    #import "CCMenu.h"
    
    @interface CCMenu (Transparent)
    @end
    

    文件 CCMenu+Tranparent.m

    #import "CCMenu+Transparent.h"
    #import "cocos2d.h"
    @implementation CCMenu (Transparent)
    -(CCMenuItem *) itemForTouch: (UITouch *) touch{
        CGPoint touchLocation = [touch locationInView: [touch view]];
        touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
    
        CCMenuItem* item;
        CCARRAY_FOREACH(children_, item){
            UInt8 data[4];
    
            // ignore invisible and disabled items: issue #779, #866
            if ( [item visible] && [item isEnabled] ) {
                CGPoint local = [item convertToNodeSpace:touchLocation];
                /*
                 TRANSPARENCY LOGIC
                 */
                //PIXEL READING 1 PIXEL AT LOCATION
    
    
                CGRect r = [item rect];
                r.origin = CGPointZero;
    
                if( CGRectContainsPoint( r, local ) ){
                    if([NSStringFromClass(item.class) isEqualToString:NSStringFromClass([CCMenuItemImage class])]){
                        CCRenderTexture* renderTexture = [[CCRenderTexture alloc] initWithWidth:item.boundingBox.size.width * CC_CONTENT_SCALE_FACTOR()
                                                                                         height:item.boundingBox.size.height * CC_CONTENT_SCALE_FACTOR()
                                                                                    pixelFormat:kCCTexture2DPixelFormat_RGBA8888];
    
                        [renderTexture begin];
                        [[(CCMenuItemImage *)item normalImage] draw];
    
                        data[3] = 1;
                        glReadPixels((GLint)local.x,(GLint)local.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
    
                        [renderTexture end];
                        [renderTexture release];
                        if(data[3] == 0){
                            continue;
                        }
    
                    }
                    free(data);
                    return item;
                }
    
            }
        }
        return nil;
    }
    
    @end
    

    这将检查像素以返回 CCMenuItem。 它在这里工作正常.. 如果您遇到任何问题,请告诉我

    -Paresh Rathod Cocos2d 情人

    【讨论】:

      【解决方案4】:

      对我来说效果很好的解决方案是使用 Sprite 表格。我使用 TexturePacker 创建精灵表。使用 TexturePacker 创建精灵表的步骤: 1. 将所有图像 (.png) 文件加载到 TexturePacker。 2. 数据格式选择coco2d,纹理格式选择PVR。 3. 将精灵表加载到您的代码中并从精灵表中提取图像。

      详细说明见here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-16
        • 2011-12-27
        • 2023-01-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多