cocos2d-x 使用lua实现像素点击检测

本文介绍了一种使用像素检测技术区分游戏中重叠透明区域的方法。通过详细步骤和代码示例,展示了如何准确判断玩家点击的具体位置,尤其是在游戏元素紧密排列的情况下。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在做一些类似QQ农场游戏的时候,农田排列比较紧凑,每块田矩形透明区域难免会有重叠,那这种情况下如何正确区分开玩家点击了哪块田,这种需求就可以用像素检测来实现了。主要原理就是先判断玩家是否点击到一张图片的矩形区域,再判断玩家点击到的地方是否为该图片的透明区域。
楼主使用的cocos2d-x 3.2, 实现语言是C++和lua。
具体实现如下:

--@param node 用于判断是否被点击的节点
--@param x      屏幕X坐标
--@param y    屏幕Y坐标
--@return     是否被点击
function checkIfTouch(node, x, y )
    local nsp = node:convertToNodeSpace(cc.p(x, y))
    local contentSize = node:getContentSize()
    local rect = cc.rect(0, 0, contentSize.width, contentSize.height)
    return cc.rectContainsPoint(rect, nsp)
end

--@param sprite 用于判断是否被点击的图片(Sprite,ImageView测试可用)
--@param x      屏幕X坐标
--@param y    屏幕Y坐标
--@return     非透明区域是否被点击
function checkIfTouchWithTransparent(sprite, x, y)
    if not checkIfTouch(sprite, x, y) then return false end
    local oldPos = cc.p(sprite:getPosition())
    local size = sprite:getContentSize()
    local pos = sprite:convertToNodeSpace(cc.p(x, y))
    --以下三行代码主要在ScaleFactor不为1时有效(比如高清资源)
    local scale = cc.Director:getInstance():getContentScaleFactor()
    pos.x = pos.x * scale
    pos.y = pos.y * scale
    local render = cc.RenderTexture:create(size.width, size.height)
    sprite:setPosition(cc.p(size.width/2, size.height/2))
    render:begin()
    sprite:visit()
    render:endToLua()
    --该接口为自定义导出,原始cocos没有提供该接口(主要原因是Director没有对Lua暴露getRenderer接口)
    cc.Director:getInstance():flushScene()
    sprite:setPosition(oldPos)
    local image = render:newImage()
    pos.y = image:getHeight() - pos.y
    --该接口为自定义导出,原始cocos没有提供该接口(主要原因是Image没有对Lua暴露getData接口)
    local rgba = image:getPixelColor(pos)
    image:release()
    return (rgba.a ~= 0)
end<pre name="code" class="cpp">//CCDirector.cpp接口实现
void Director::flushScene()
{
    _renderer->render();
}
//CCImage.cpp接口实现
Color4B Image::getPixelColor( const Vec2& pos )
{
    Color4B color = {0, 0, 0, 0};
    if ( pos.x < 0 || pos.x >= this->getWidth() || pos.y < 0 || pos.y >= this->getHeight() ) {
        return color;
    }
    auto data = this->getData();
    auto pixel = (unsigned int*) data;
    auto x = (int)pos.x;
    auto y = (int)pos.y;
    pixel = pixel + (y * this->getWidth() ) * 1 + x * 1;
    //R通道
    color.r = *pixel & 0xff;
    //G通道
    color.g = (*pixel >> 8) & 0xff;
    //B通过
    color.b = (*pixel >> 16) & 0xff;
    //Alpha通道,我们有用的就是Alpha
    color.a = (*pixel >> 24) & 0xff;
    return color;
}
这里新增了两个C++接口,主要是因为部分原始引擎接口没有对lua暴露,如果用C++语言开发的小伙伴就不需要新增这两个接口了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值