cocos2d-x 3.x版本 像素级物理碰撞(个人原创)

个人自学cocos2d-x 已经3个月了,还没找到工作,没事干发个关于cocos2d-x 3.x版本 像素级物理碰撞的教程

刚才发了一次被永久禁言 真伤心

好了废话不多说下面进入教程

一、首先看一下效果图

二、使用的软件和版本

PhysicsEditor 1.0.9

Visual Studio 2013

cocos2d-x 3.3(前几天官方发布的coco 1.0 preview带的)

plistEditor 1.0.2

三、全代码

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
USING_NS_CC;

class HelloWorld : public cocos2d::Layer
{
public:

    PhysicsWorld* m_world;

    void setPhyWorld(PhysicsWorld* world){ m_world = world; };

    static cocos2d::Scene* createScene();

    virtual bool init();

    CREATE_FUNC(HelloWorld);
    //添加碰撞精灵
    void addNewSpriteAtPosition(Point p);

};

#endif // __HELLOWORLD_SCENE_H__


```



HelloWorldScene.cpp

#include "HelloWorldScene.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"

USING_NS_CC;

using namespace cocostudio::timeline;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::createWithPhysics();

    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

    auto layer = HelloWorld::create();

    layer->setPhyWorld(scene->getPhysicsWorld());

    scene->addChild(layer);

    scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    auto visibleSize = Director::getInstance()->getVisibleSize();
    auto origin = Director::getInstance()->getVisibleOrigin();
    //碰撞边框
    auto edgeSp = Sprite::create();
    auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
    edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
    edgeSp->setPhysicsBody(boundBody);
    this->addChild(edgeSp);
    //单点触控
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = (Touch* t, Event* e) { 
        this->addNewSpriteAtPosition(Point(t->getLocation().x, t->getLocation().y));
        return false;
    };
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);

    return true;
}

void HelloWorld::addNewSpriteAtPosition(Point p)
{
    
    //这里读取对应的plist文件

    ValueMap root_val = FileUtils::getInstance()->getValueMapFromFile("coco.plist");

    ValueMap bodies_val = root_val"bodies"].asValueMap();

    ValueMap coco_val = bodies_val"coco"].asValueMap();

    ValueVector fixtures_val = coco_val"fixtures"].asValueVector();

    ValueMap array_val = fixtures_val.at(0).asValueMap();

    ValueVector polygons_val = array_val"polygons"].asValueVector();

    auto body = PhysicsBody::create();
    for (int i = 0; i < polygons_val.size(); i++)
    {
        ValueVector m_array = polygons_val.at(i).asValueVector();
        Point* points = new Point;
        for (int j = 0; j < m_array.size(); j++)
        {
            std::string pointString = m_array.at(j).asString();
            int x = atoi(pointString.substr(pointString.find("{") + 1, pointString.find(",") - 1).c_str());
            int y = atoi(pointString.substr(pointString.find(",") + 1, pointString.length() - pointString.find(",")).c_str());
            points = Point(x,y);
        }
        body->addShape(PhysicsShapePolygon::create(points, m_array.size()));
        delete] points;
    }
    //创建精灵
    Sprite* coco = Sprite::create("coco.png", Rect(0, 0, 75, 95));
    coco->setPosition(p);
    coco->setPhysicsBody(body);
    this->addChild(coco);
    // add the fixture definitions to the body  

}


```



四、plist文件解析


  


3.x 容器对应(只要知道容器的对应关系就能很容易明白了)


ValueMap对应的是Dictionary


ValueVector对应的是Array


其实上面的解析也可以只解析坐标部分,但是要截取plist文件中的坐标那一部分(这样可以减少数据量,但是每次修改都需要截取)


五、plist文件的获得


使用PhysicsEditor来编辑很方便教程网上也有,但是有个地方要注意


  


要注意选择chipmunk,cocos2d-x 3.3默认的是chipmunk,当然也可以选box2D,只不过需要修改一些东西网上也有方法


好了把图片和plist导入项目res文件夹就可以


教程已经结束,有什么要问的我会尽量解答

只是近似像素判断,而且很麻烦,真正像素级的还是要用RenderTexture来判断,而且能考虑到缩放和旋转

RenderTexture还没用过,有时间去研究研究,我感觉2d游戏这样级别的就够用了

图片都是破的

什么意思?

图片看不到,显示此图片来自QQ空间,未经允许不可引用

请教如何获取字典的名称(字符串)呢

留个名字,以后有需要看。

请问精灵和刚体错位是怎么回事

我知道了,是锚点设错了 有个问题就是如果我一个骨骼动画的精灵要这样绑定刚体,骨骼动画的图又是一张合图 那怎么办啊 不能给小图合成的大图导进去确定形状吧 大神知道怎么弄么