cocos2d-x 如何从 png 图像中检索可见纹理

How to retrieve the visible texture from a png image in cocos2d-x

我正在制作一个问答游戏,其中答案图像是由 png 图像制成的精灵。

答案图片是这样的:

我正在像这样在图像上做矩形:

Rect rect = Rect(answerSprites.at(i)->getBoundingBox().origin.x,
                    answerSprites.at(i)->getBoundingBox().origin.y,
                    answerSprites.at(i)->getBoundingBox().size.width,
                    answerSprites.at(i)->getBoundingBox().size.height);

然后我检测到矩形上的触摸为:

void HelloWorld::onTouchesBegan(const std::vector<Touch*>& touches,
        Event *unused_event) {
    auto target = static_cast<Sprite*>(unused_event->getCurrentTarget());
    auto touchPointBegan = (Touch*) touches.front();
    Vec2 locationBegan = touchPointEnded->getLocation();
    Point locationInNode = target->convertToNodeSpace(locationEnded);
    Size s = target->getContentSize();
        if (rect.containsPoint(locationInNode)) {
            log(“Correct Touch”);
        }
}

代码工作正常,但问题是它正在检测整个 png 上的触摸,但我只想检测花上的触摸。 花可以在png的任意位置。

如何只在花上制作矩形?

您创建的矩形覆盖了整个图像。将花和框架分开会是一个更好的方法。

为框架图像创建一个 Sprite,为花朵图像创建一个 Button。然后将按钮作为子按钮添加到框架中。

auto spriteFrame = Sprite::create("frame.png");
spriteFrame->setPosition(Vec2(300,300));
addChild(spriteFrame);

auto btn = ui::Button::create("flower.png");
btn->setZoomScale(0);
// Place in the middle of the frame sprite
btn->setPosition(Vec2(spriteFrame->getContentSize().width*.5, spriteFrame->getContentSize().height*.5));
btn->addClickEventListener([=](Ref* sender){
    log("Correct Touch");
});
spriteFrame->addChild(btn);

使用以下代码检查触摸位置的透明度:

// Answer sprite
m_sprite = Sprite::create("answer-1.png");
m_sprite->setPosition( Vec2(winSize.width*.5, winSize.height*.5)  );
addChild(m_sprite);

bool HelloWorld::onTouchBegan(const cocos2d::Touch *touch, cocos2d::Event *event)
{
    _originPoint = touch->getLocation();
    _destinationPoint = _originPoint;

    Vec2 locationInNode = m_sprite->convertToNodeSpace(touch->getLocation());

    Rect rect = Rect(m_sprite->getBoundingBox().origin.x,
                     m_sprite->getBoundingBox().origin.y,
                     m_sprite->getContentSize().width,
                     m_sprite->getContentSize().height);


    if (rect.containsPoint(touch->getLocation() )) {

        if (tapsOnNonTransparent(locationInNode, "answer-1.png" )) {
            log("Correct Touch");
        }

    }

    return true;
}

const bool HelloWorld::tapsOnNonTransparent( const cocos2d::Point& tap, const std::string &spritePath )
{
    auto imgPtr = std::make_unique<cocos2d::Image>();
    imgPtr->initWithImageFile( spritePath );

    const int width = imgPtr ->getWidth();
    const int height = imgPtr ->getHeight();

    unsigned x = unsigned( tap.x ) % width;
    /// Don't forget to invert y coordinate.
    unsigned y = unsigned( height - tap.y ) % height;
    unsigned index = x + y * width;
    unsigned dataLen = imgPtr ->getDataLen();
    CCAssert( index < dataLen, "index is bigger than image size." );
    unsigned char* pixel = imgPtr->getData() + (4 * index);
    return !isZeroPixel( pixel );
}

const bool HelloWorld::isZeroPixel( const unsigned char* pixel )
{
    return 0 == pixel[0] && 0 == pixel[1] && 0 == pixel[2] && 0 == pixel[3];
}