个人自学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文件夹就可以
教程已经结束,有什么要问的我会尽量解答


