box2d实力触摸不规则图片

原文地址:http://www.cocoachina.com/bbs/read.php?tid=209290

HelloWorldScene文件

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
    cocos2d::Sprite* sp_2dx = nullptr;
    cocos2d::LabelTTF*  status_label = nullptr;
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    void menuCloseCallback(cocos2d::Ref* pSender);
    bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
    void onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event);
    void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);

    Node* nodeUnderTouch(cocos2d::Touch* touch);
    CREATE_FUNC(HelloWorld);
};

#endif 

#include "HelloWorldScene.h"
#include "MyBodyParser.h"
USING_NS_CC;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::createWithPhysics();
    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
	closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Point::ZERO);
    this->addChild(menu, 1);
    
    auto label = LabelTTF::create("Physics Body Loader Demo", "Arial", 24);
    label->setPosition(Point(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));

    this->addChild(label, 1);

    status_label = LabelTTF::create("Touch anywhere!", "Arial", 36);
    status_label->setPosition(Point(origin.x + visibleSize.width/2, 1.2*status_label->getContentSize().height));
    this->addChild(status_label);

    sp_2dx = Sprite::create("2dx.png");
    sp_2dx->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    MyBodyParser::getInstance()->parseJsonFile("bodies.json");
    auto _body = MyBodyParser::getInstance()->bodyFormJson(sp_2dx, "2dx");
    if (_body != nullptr) {
        _body->setDynamic(false);
        _body->setCollisionBitmask(0x000000);
        sp_2dx->setPhysicsBody(_body);
    }

    this->addChild(sp_2dx, 0);

    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
    touchListener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
    touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);

    return true;
}

Node* HelloWorld::nodeUnderTouch(cocos2d::Touch *touch)
{
    Node* node = nullptr;
    //转换到layer内的坐标
    auto location = this->convertTouchToNodeSpace(touch);
    //得到当前点下方的物理shapes
    auto scene = Director::getInstance()->getRunningScene();
    auto arr = scene->getPhysicsWorld()->getShapes(location);
    
    //遍历当前点击到的所有shapes, 看看有没有我们的2dx!
    for (auto& obj : arr)
    {
        if ( obj->getBody()->getNode() == sp_2dx)
        {
            node = obj->getBody()->getNode();
            break;
        }
    }
    return node;
}

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
    auto current_node = nodeUnderTouch(touch);

    if (current_node == sp_2dx)
    {
        status_label->setColor(Color3B::GREEN);
        status_label->setString("Ohoo, U catch me!");
    }
    else
    {
        status_label->setColor(Color3B::RED);
        status_label->setString("Haha, touch outside!");
    }

    return true;
}

void HelloWorld::onTouchMoved(Touch* touch, Event* event){}

void HelloWorld::onTouchEnded(Touch* touch, Event* event)
{
    status_label->setColor(Color3B::WHITE);
    status_label->setString("Touch anywhere!");
}

void HelloWorld::menuCloseCallback(Ref* pSender){}

MyBodyParser文件

#pragma once

#include <string>
#include "cocos2d.h"
USING_NS_CC;
#include "json/document.h"

class MyBodyParser {
    MyBodyParser(){}
    rapidjson::Document doc;
public:
    static MyBodyParser* getInstance();
    bool parseJsonFile(const std::string& pFile);
    bool parse(unsigned char* buffer, long length);
    void clearCache();
    PhysicsBody* bodyFormJson(Node* pNode, const std::string& name);
};

#include "MyBodyParser.h"

MyBodyParser* MyBodyParser::getInstance()
{
    static MyBodyParser* sg_ptr = nullptr;
    if (nullptr == sg_ptr)
    {
        sg_ptr = new MyBodyParser;
    }
    return sg_ptr;
}

bool MyBodyParser::parse(unsigned char *buffer, long length)
{
    bool result = false;
    std::string js((const char*)buffer, length);
    doc.Parse<0>(js.c_str());
    if(!doc.HasParseError())
    {
        result = true;
    }
    return result;
}

void MyBodyParser::clearCache()
{
    doc.SetNull();
}

bool MyBodyParser::parseJsonFile(const std::string& pFile)
{
    auto content = FileUtils::getInstance()->getDataFromFile(pFile);
    bool result = parse(content.getBytes(), content.getSize());
    return result;
}

//从json文件加载正确的body
PhysicsBody* MyBodyParser::bodyFormJson(cocos2d::Node *pNode, const std::string& name)
{
    PhysicsBody* body = nullptr;
    rapidjson::Value &bodies = doc["rigidBodies"];
    if (bodies.IsArray())
    {
        //遍历文件中的所有body
        for (int i=0; i<bodies.Size(); ++i)
        {
            //找到了请求的那一个
            if (0 == strcmp(name.c_str(), bodies[i]["name"].GetString()))
            {
                rapidjson::Value &bd = bodies[i];
                if (bd.IsObject())
                {
                    //创建一个PhysicsBody, 并且根据node的大小来设置
                    body = PhysicsBody::create();
                    float width = pNode->getContentSize().width;
                    
                    //多边形的锚点默认都是左下角,精灵的不一定,
                    float offx = - pNode->getAnchorPoint().x * pNode->getContentSize().width;
                    float offy = - pNode->getAnchorPoint().y * pNode->getContentSize().height;

                    Point origin( bd["origin"]["x"].GetDouble(), bd["origin"]["y"].GetDouble());
                    rapidjson::Value &polygons = bd["polygons"];
                    for (int i = 0; i<polygons.Size(); ++i)
                    {
                        int pcount = polygons[i].Size();
                        Point* points = new Point[pcount];
                        for (int pi = 0; pi<pcount; ++pi)
                        {
                            points[pi].x = offx + width * polygons[i][pcount-1-pi]["x"].GetDouble();
                            points[pi].y = offy + width * polygons[i][pcount-1-pi]["y"].GetDouble();
                        }
                        body->addShape(PhysicsShapePolygon::create(points, pcount, PHYSICSBODY_MATERIAL_DEFAULT));
                        delete [] points;
                    }
                }
                else
                {
                    CCLOG("body: %s not found!", name.c_str());
                }
                break;
            }
        }
    }
    return body;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值