cocos2d-x 不规则触摸解决方案

.h

#ifndef __UI_BUTTON_PIXEL_H__
#define __UI_BUTTON_PIXEL_H__ 1
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
#include <cocos2d.h>
#include <ui/CocosGUI.h>


class CC_GUI_DLL UIButton_pixel : public cocos2d::ui::Button
{

    bool isPixelTouch;

    ccWidgetTouchCallback m_ccWidgetTouchCallback;

    cocos2d::Image *m_Image;
public:

    UIButton_pixel();

    ~UIButton_pixel();

    static UIButton_pixel* create(const std::string& normalImage,
        const std::string& selectedImage = "",
        const std::string& disableImage = "",
        TextureResType texType = TextureResType::LOCAL);


    void setPixelTouch(bool is);

    void addPixelTouchEventListener_s(const ccWidgetTouchCallback& callback);

private:

    //获取图片内的左边
    cocos2d::Vec2 getTouchImagePosition(cocos2d::Vec2 &TouchEndPos);

    //
    bool indexPixelLogic(cocos2d::Vec2 &pos);
};
#endif // !__UI_BUTTON_PIXEL_H__

.cpp

#include "UIButton_pixel.h"

UIButton_pixel::UIButton_pixel() :isPixelTouch(false), m_Image(nullptr)
{

}

UIButton_pixel::~UIButton_pixel()
{
    if (m_Image)
    {
        delete m_Image;
        m_Image = nullptr;
    }
}

UIButton_pixel* UIButton_pixel::create(const std::string& normalImage, const std::string& selectedImage, const std::string& disableImage, TextureResType texType)
{
    UIButton_pixel *btn = new (std::nothrow) UIButton_pixel;
    if (btn && btn->init(normalImage, selectedImage, disableImage, texType))
    {
        btn->autorelease();
        return btn;
    }
    CC_SAFE_DELETE(btn);
    return btn;
}

void UIButton_pixel::setPixelTouch(bool is)
{
    isPixelTouch = is;
}

void UIButton_pixel::addPixelTouchEventListener_s(const ccWidgetTouchCallback& callback)
{
    if (m_ccWidgetTouchCallback)
    {
        return;
    }
    m_ccWidgetTouchCallback = callback;

    static ccWidgetTouchCallback tmp = [&](Ref *ref, cocos2d::ui::Widget::TouchEventType e)
    {
        if (isPixelTouch && m_ccWidgetTouchCallback 
            && e == cocos2d::ui::Widget::TouchEventType::ENDED)
        {
            auto b_pos = this->getTouchBeganPosition();

            auto e_pos = this->getTouchEndPosition();

            auto pos = this->getWorldPosition();


            cocos2d::log("=============

pos(%f,%f) 
b_pos(%f,%f) 
e_pos(%f,%f)

============ = 
", pos.x, pos.y, b_pos.x, b_pos.y, e_pos.x, e_pos.y);


            auto imagePos = this->getTouchImagePosition(e_pos);

            if (this->indexPixelLogic(imagePos))
            {
                m_ccWidgetTouchCallback(ref, e);
            }
        }

    };

    this->addTouchEventListener(tmp);
}

cocos2d::Vec2 UIButton_pixel::getTouchImagePosition(cocos2d::Vec2 &TouchEndPos)
{

    auto size = this->getContentSize();
    auto ret = cocos2d::Vec2::ZERO;
    auto worldPosition = this->getWorldPosition();
    auto anchorPoint = this->getAnchorPoint();


    auto offset = worldPosition - TouchEndPos;

    /** equals to Vec2(0.5, 0.5) */
    if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE)
    {
        ret = cocos2d::Vec2(size.width * 0.5f - offset.x, size.height * 0.5f + offset.y);
    }
    /** equals to Vec2(0, 0) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_BOTTOM_LEFT)
    {
        ret = cocos2d::Vec2(-(offset.x), size.height + offset.y);
    }
    /** equals to Vec2(0, 1) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_TOP_LEFT)
    {
        ret = cocos2d::Vec2(-(offset.x), +offset.y);
    }
    /** equals to Vec2(1, 0) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_BOTTOM_RIGHT)
    {
        ret = cocos2d::Vec2(size.width - offset.x, size.height + offset.y);
    }
    /** equals to Vec2(1, 1) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_TOP_RIGHT)
    {
        ret = cocos2d::Vec2(size.width - offset.x, +offset.y);
    }
    /** equals to Vec2(1, 0.5) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_RIGHT)
    {
        ret = cocos2d::Vec2(size.width - offset.x, size.height * 0.5f + offset.y);
    }
    /** equals to Vec2(0, 0.5) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_LEFT)
    {
        ret = cocos2d::Vec2(-(offset.x), size.height * 0.5f + offset.y);
    }
    /** equals to Vec2(0.5, 1) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_TOP)
    {
        ret = cocos2d::Vec2(size.width * 0.5f - offset.x, offset.y);
    }
    /** equals to Vec2(0.5, 0) */
    else if (anchorPoint == cocos2d::Vec2::ANCHOR_MIDDLE_BOTTOM)
    {
        ret = cocos2d::Vec2(size.width * 0.5f - offset.x, size.height + offset.y);
    }
    else
    {
        cocos2d::log("anchorPoint error 
");
        return ret = cocos2d::Vec2(-1, -1);
    }

    return ret;
}

bool UIButton_pixel::indexPixelLogic(cocos2d::Vec2 &pos)
{

    
    auto texture = this->getRendererNormal()->getTexture();
    auto size = cocos2d::Size(texture->getPixelsWide(), texture->getPixelsHigh());

    if (pos != cocos2d::Vec2(-1, -1)
        && pos.x <= size.width
        &&pos.y <= size.height)
    {

        std::cout << " pixel pos : " << pos.x << " " << pos.y << std::endl;

        auto path = texture->getPath();

        if (!m_Image)
        {
            m_Image = new (std::nothrow) cocos2d::Image();
        }

        if (m_Image)
        {
            auto b = m_Image->initWithImageFile(path);
            if (b
                &&
                m_Image->getRenderFormat() == cocos2d::Texture2D::PixelFormat::RGBA8888)
            {
                auto data = m_Image->getData();
                auto dataLen = m_Image->getDataLen();
                
                if ((int)(size.width * size.height * 4) == dataLen)
                {
                    auto offsetPixel = (int)(((int)(pos.y) * size.width + (int)(pos.x)));
                    
                    auto rgba = data + offsetPixel * 4;
                    int r = (unsigned char)rgba[0];
                    int g = (unsigned char)rgba[1];
                    int b = (unsigned char)rgba[2];
                    int a = (unsigned char)rgba[3];

                    printf("R: %d G: %d B: %d A: %d
",
                        r,
                        g,
                        b, 
                        a);

                    if (a == 255)
                    {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

tolua.cpp

#include "lua_cocos2d_Ex.h"
#include <iostream>
#include "cocos2d.h"
using namespace cocos2d;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) && !defined(CC_TARGET_OS_TVOS)
#include "scripting/lua-bindings/auto/lua_cocos2dx_experimental_video_auto.hpp"
#include "scripting/lua-bindings/manual/ui/lua_cocos2dx_experimental_video_manual.hpp"
#include "scripting/lua-bindings/auto/lua_cocos2dx_experimental_webview_auto.hpp"
#include "scripting/lua-bindings/manual/ui/lua_cocos2dx_experimental_webview_manual.hpp"
#endif

#include "scripting/lua-bindings/manual/tolua_fix.h"
#include "scripting/lua-bindings/manual/LuaBasicConversions.h"
#include "scripting/lua-bindings/manual/cocos2d/LuaScriptHandlerMgr.h"
#include "scripting/lua-bindings/manual/CCLuaValue.h"
#include "ui/CocosGUI.h"
#include "scripting/lua-bindings/manual/CCLuaEngine.h"
#include "base/CCEventListenerFocus.h"
#include "UIButton_pixel.h"


static int handleUIEvent(int handler, cocos2d::Ref* sender, int eventType)
{
    LuaStack* stack = LuaEngine::getInstance()->getLuaStack();

    stack->pushObject(sender, "cc.Ref");
    stack->pushInt(eventType);

    stack->executeFunctionByHandler(handler, 2);
    stack->clean();

    return 0;
}

int lua_cocos2d_Ex_create(lua_State *tolua_S)
{
    int argc = 0;
    //UIButton_pixel* cobj = nullptr;
    bool ok = true;

#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif

    //cobj = (UIButton_pixel*)tolua_tousertype(tolua_S, 1, 0);

#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertable(tolua_S, 1, "ccui.UIButton_pixel", 0, &tolua_err)) goto tolua_lerror;
#endif

    argc = lua_gettop(tolua_S) - 1;

    if (argc == 4)
    {
        std::string arg0, arg1, arg2;
        int arg3;

        ok &= luaval_to_std_string(tolua_S, 2, &arg0, "ccui.UIButton_pixel:create");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr);
            return 0;
        }
        ok &= luaval_to_std_string(tolua_S, 3, &arg1, "ccui.UIButton_pixel:create");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr);
            return 0;
        }
        ok &= luaval_to_std_string(tolua_S, 4, &arg2, "ccui.UIButton_pixel:create");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr);
            return 0;
    }
        ok &= luaval_to_int32(tolua_S, 5, &arg3, "ccui.UIButton_pixel:create");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_create'", nullptr);
            return 0;
        }

        UIButton_pixel *ret = UIButton_pixel::create(arg0, arg1, arg2, (cocos2d::ui::TextureResType)arg3);
        object_to_luaval<UIButton_pixel>(tolua_S, "ccui.UIButton_pixel", (UIButton_pixel*)ret);
        return 1;
}
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d
 ", "ccui.UIButton_pixel:create", argc, 0);
    return 0;
#if COCOS2D_DEBUG >= 1
    tolua_lerror:
                tolua_error(tolua_S, "#ferror in function 'lua_cocos2d_Ex_create'.", &tolua_err);
#endif
                return 0;
    }
int lua_cocos2d_Ex_setPixelTouch(lua_State *tolua_S)
{
    int argc = 0;
    UIButton_pixel* cobj = nullptr;
    bool ok = true;

#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif

    cobj = (UIButton_pixel*)tolua_tousertype(tolua_S, 1, 0);

#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertable(tolua_S, 1, "ccui.UIButton_pixel", 0, &tolua_err)) goto tolua_lerror;
#endif

#if COCOS2D_DEBUG >= 1
    if (nullptr == self) {
        tolua_error(L, "invalid 'self' in function 'lua_cocos2d_Ex_setPixelTouch'
", NULL);
        return 0;
    }
#endif

    argc = lua_gettop(tolua_S) - 1;

    if (argc == 1)
    {
        bool arg0;
        ok &= luaval_to_boolean(tolua_S, 2, &arg0, "ccui.UIButton_pixel:setPixelTouch");
        if (!ok)
        {
            tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2d_Ex_setPixelTouch'", nullptr);
            return 0;
        }
        cobj->setPixelTouch(arg0);
        return 0;
    }
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d
 ", "ccui.UIButton_pixel:setPixelTouch", argc, 0);
    return 0;
#if COCOS2D_DEBUG >= 1
    tolua_lerror:
                tolua_error(tolua_S, "#ferror in function 'lua_cocos2d_Ex_setPixelTouch'.", &tolua_err);
#endif
                return 0;
}
int lua_cocos2d_Ex_addPixelTouchEventListener_s(lua_State *tolua_S)
{
    int argc = 0;
    UIButton_pixel* cobj = nullptr;
    bool ok = true;

#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif

    cobj = (UIButton_pixel*)tolua_tousertype(tolua_S, 1, 0);

#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertable(tolua_S, 1, "ccui.UIButton_pixel", 0, &tolua_err)) goto tolua_lerror;
#endif

#if COCOS2D_DEBUG >= 1
    if (nullptr == self) {
        tolua_error(L, "invalid 'self' in function 'lua_cocos2d_Ex_addPixelTouchEventListener_s'
", NULL);
        return 0;
    }
#endif

    argc = lua_gettop(tolua_S) - 1;

    if (argc == 1)
    {
#if COCOS2D_DEBUG >= 1
        if (!toluafix_isfunction(L, 2, "LUA_FUNCTION", 0, &tolua_err))
        {
            goto tolua_lerror;
        }
#endif

        LUA_FUNCTION handler = (toluafix_ref_function(tolua_S, 2, 0));

        cobj->addPixelTouchEventListener_s([=](cocos2d::Ref* ref, cocos2d::ui::Widget::TouchEventType eventType) {
            handleUIEvent(handler, ref, (int)eventType);
        });

        ScriptHandlerMgr::getInstance()->addCustomHandler((void*)cobj, handler);
        return 0;
    }
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d
 ", "ccui.UIButton_pixel:addPixelTouchEventListener_s", argc, 0);
    return 0;
#if COCOS2D_DEBUG >= 1
    tolua_lerror:
                tolua_error(tolua_S, "#ferror in function 'lua_cocos2d_Ex_addPixelTouchEventListener_s'.", &tolua_err);
#endif
                return 0;
}



int lua_register_cocos2d_Ex(lua_State* tolua_S)
{
    tolua_usertype(tolua_S, "ccui.UIButton_pixel");
    tolua_cclass(tolua_S, "UIButton_pixel", "ccui.UIButton_pixel", "ccui.Button", nullptr);

    tolua_beginmodule(tolua_S, "UIButton_pixel");
    if (true)
    {

        tolua_function(tolua_S, "create", lua_cocos2d_Ex_create);
        tolua_function(tolua_S, "setPixelTouch", lua_cocos2d_Ex_setPixelTouch);
        tolua_function(tolua_S, "addPixelTouchEventListener_s", lua_cocos2d_Ex_addPixelTouchEventListener_s);


    }
    tolua_endmodule(tolua_S);
    std::string typeName = typeid(UIButton_pixel).name();
    g_luaType[typeName] = "ccui.UIButton_pixel";
    g_typeCast["UIButton_pixel"] = "ccui.UIButton_pixel";
    return 1;
}

int register_cocos2d_Ex(lua_State* tolua_S)
{
    tolua_open(tolua_S);

    tolua_module(tolua_S, "ccui", 0);
    tolua_beginmodule(tolua_S, "ccui");

    lua_register_cocos2d_Ex(tolua_S);

    tolua_endmodule(tolua_S);
    return 1;
}

int lua_cocos2d_Ex(lua_State* L)
{
    lua_getglobal(L, "_G");
    if (lua_istable(L, -1))
    {
        register_cocos2d_Ex(L);
        if (L)
        {
            lua_pushstring(L, "ccui.UIButton_pixel");
            lua_rawget(L, LUA_REGISTRYINDEX);
            lua_pop(L, 1);
        }
    }
    lua_pop(L, 1);
    return 0;
}

test

    local filename = "res/GameList/GameAni/_12/skeleton.png"
    local btn = ccui.UIButton_pixel:create(filename,filename,filename,0)
    btn:setPixelTouch(true)
    btn:addPixelTouchEventListener_s(function(ref,type)
        print("UIButton_pixel touch");
    end)
    btn:setPosition(display.center)
    self:addChild(btn)
原文地址:https://www.cnblogs.com/YZFHKMS-X/p/14380180.html