首页 > 代码库 > 1.物理系统PhysicsWorld,RayCast

1.物理系统PhysicsWorld,RayCast

??

1 3.0物理系统PhysicsWorld

T07PhysicsWorld.h

#ifndef __T07PhysicsWorld_H__

#define __T07PhysicsWorld_H__

 

#include "T32.h"

 

class T07PhysicsWorld : public Layer

{

public:

    CREATE_FUNC(T07PhysicsWorld);

 

    bool init();

    Scene* getScene(){ return (Scene*)getParent(); }

};

 

#endif

T07PhysicsWorld.cpp

#include "T07PhysicsWorld.h"

 

 

bool T07PhysicsWorld::init()

{

    Layer::init();

 

    PhysicsBody* bodyA;

    PhysicsBody* bodyB;

 

    {

        //后面的三个參数值分别表示的是:密度,弹性值。摩擦力

        PhysicsBody* body = PhysicsBody::createCircle(20, PhysicsMaterial(1.0f, 1.0f, 0.0f));

        bodyA = body;

        //创建精灵

        Sprite* sprite = Sprite::create();

        //设置

        sprite->setPhysicsBody(body);

        addChild(sprite);

        //设置精灵的位置

        sprite->setPosition(winSize.width / 2, winSize.height / 2);

        //设置速度

        body->setVelocity(Vect(100, 200));

    }

 

    {

        PhysicsBody* body = PhysicsBody::createEdgeBox(winSize, PhysicsMaterial(1.0f, 1.0f, 0.0f));

        bodyB = body;

        Sprite* sprite = Sprite::create();

        addChild(sprite);

        sprite->setPhysicsBody(body);

        sprite->setPosition(winSize.width / 2, winSize.height / 2);

    }

 

    {

        bodyA->setContactTestBitmask(0x1);

        bodyB->setContactTestBitmask(0x1);

        bodyA->setGroup(1);

        bodyB->setGroup(2);

 

        //设置精灵的

        auto ev = EventListenerPhysicsContactWithBodies::create(bodyA, bodyB);

        ev->onContactBegin = [](PhysicsContact& contact){

            CCLog("Began Contact...........");

            return true;

        };

 

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

    }

 

    {

        auto ev = EventListenerPhysicsContactWithShapes::create(bodyA->getShapes().at(0),

            bodyB->getShapes().at(0));

 

        ev->onContactBegin = [](PhysicsContact& contact){

            CCLog("Shape Began Contact...........");

            return true;

        };

 

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

    }

 

    {

        auto ev = EventListenerPhysicsContactWithGroup::create(3);

        ev->onContactBegin = [](PhysicsContact& contact){

            CCLog("Group Began Contact...........");

            return true;

        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

 

    }

 

    return true;

}

TMenu.h

#ifndef __TMenu_H__

#define __TMenu_H__

 

#include "T32.h"

 

class TMenu : public Layer

{

public:

    CREATE_FUNC(TMenu);

 

    bool init();

 

    bool TouchBegan(Touch*, Event*);

};

 

#endif

TMenu.cpp

#include "TMenu.h"

#include "TBack.h"

#include "T01CPP11.h"

#include "T02Vector.h"

#include "T03Map.h"

#include "T04Label.h"

#include "T05Touch.h"

#include "T06Box2D.h"

#include "T07PhysicsWorld.h"

 

static const char* title[] = {

    "T01CPP11",

    "T02Vector",

    "T04Label",

    "T05Touch",

    "T06Box2D",

    "T07PhysicsWorld"

};

 

bool TMenu::init()

{

    Layer::init();

 

    Menu* menu = Menu::create();

    addChild(menu);

 

    for (int i = 0; i < sizeof(title) / sizeof(*title); ++i)

    {

        MenuItemFont* item = MenuItemFont::create(title[i], [](Ref* sender){

 

            MenuItem* item = (MenuItem*)sender;

            int i = item->getTag() - 1000;

            Layer* l = NULL;

 

            if (title[i] == "T01CPP11")   l = T01CPP11::create();

            if (title[i] == "T02Vector")   l = T02Vector::create();

            if (title[i] == "T04Label") l = T04Label::create();

            if (title[i] == "T05Touch") l = T05Touch::create();

            if (title[i] == "T06Box2D") l = T06Box2D::create();

            if (title[i] == "T07PhysicsWorld") l = T07PhysicsWorld::create();

 

            if (l)

            {

                TBack* b = TBack::create();

                Scene* s = Scene::createWithPhysics();

 

 

                PhysicsWorld* world = s->getPhysicsWorld();

                world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

 

                s->addChild(b);

                s->addChild(l);

                Director::getInstance()->pushScene(s);

            }

        });

        menu->addChild(item);

        item->setTag(1000 + i);

    }

 

    menu->alignItemsVertically();

 

    // 触摸

    auto ev = EventListenerTouchOneByOne::create();

#if 0

    ev->onTouchBegan = [](Touch*, Event*){

        return true;

    };

#endif

 

    //ev->onTouchBegan = std::bind(&TMenu::TouchBegan, this, std::placeholders::_1, std::placeholders::_2);

 

    ev->onTouchBegan = CC_CALLBACK_2(TMenu::TouchBegan, this);

 

    ev->onTouchMoved = [&](Touch* touch, Event*){

        setPositionY(getPositionY() + touch->getDelta().y);

    };

    _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

 

    return true;

}

 

bool TMenu::TouchBegan(/*TMEnu* this, */Touch*, Event*)

{

    return true;

}

执行结果:

技术分享

射线的做法

T08RayCast.h

#ifndef __T08RayCast_H__

#define __T08RayCast_H__

 

#include "T32.h"

class T08RayCast :public Layer

{

public:

    CREATE_FUNC(T08RayCast);

 

    bool init();

    void onEnter();

    void update(float);

 

    Sprite* _cat;

    int _angle;

    int _distance;

    float _nearDis;

    PhysicsShape* _food;

 

    DrawNode* _drawNode;

};

 

#endif

T08RayCast.cpp

#include "T08RayCast.h"

 

void T08RayCast::onEnter()

{

    Layer::onEnter();

 

    Scene* scene = (Scene*)getParent();

    scene->getPhysicsWorld()->setGravity(Vec2(0, 0));

}

 

bool T08RayCast::init()

{

    Layer::init();

 

    // 创建猫。猫不是Body,仅仅是一个简单的精灵

    {

        Sprite* cat = Sprite::create("CloseNormal.png");

        addChild(cat);

        cat->setPosition(winSize.width / 2, winSize.height / 2);

        _cat = cat;

    }

 

    // 投放食物。食物必须是body

    {

        auto ev = EventListenerTouchOneByOne::create();

        ev->onTouchBegan = [&](Touch* touch, Event*){

            //得到触摸点

            Vec2 pt = touch->getLocation();

            //创建一个圆形的PhysicsBody

            PhysicsBody* body = PhysicsBody::createCircle(10);

            Sprite* sprite = Sprite::create();

            sprite->setPhysicsBody(body);

            addChild(sprite);

            sprite->setPosition(pt);

 

            return true;

        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

    }

 

    {

        _angle = 0;      //角度

        _distance = 100; //距离

        _nearDis = _distance + 100;

        _food = NULL;

        _drawNode = NULL;

    }

    scheduleUpdate();

 

    return true;

}

 

void T08RayCast::update(float dt)

{

    Scene* scene = (Scene*)getParent();

    PhysicsWorld* world = scene->getPhysicsWorld();

 

    //获得猫的位置

    Vec2 start = _cat->getPosition();

    Vec2 end;

 

    //当前时刻扫描到的终点位置

    end.x = start.x + sinf(_angle / 180.0 * M_PI)*_distance;

    end.y = start.y + cosf(_angle / 180.0 * M_PI)*_distance;

 

    // 显示扫描距离

    if (_drawNode) _drawNode->removeFromParent();

    //以下的代码用于画线段

    _drawNode = DrawNode::create();

    _drawNode->drawSegment(start, end, 1, Color4F(1, 0, 0, 1));

    addChild(_drawNode);

 

    // 扫描回调函数

    //bool(PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data)

    auto callback = [&](PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data){

 

        if (info.shape == NULL)

            return true;

 

        //假设点包括猫的点

        float dis = info.contact.getDistance(_cat->getPosition());

        if (dis < _nearDis)

        {

            _nearDis = dis;

            _food = info.shape;

        }

 

        // 扫描到一个就不要再继续了

        return false;

    };

    //通过rayCast画一条射线

    world->rayCast(callback, start, end, NULL);

 

    //每次角度加2

    _angle += 2;

    //假设角度为360

    if (_angle == 360)

    {

        //假设存在食物

        if (_food)

        {

            // 吃掉食物

            Node* node = _food->getBody()->getNode();

            //将猫的的位置数值到新的位置

            _cat->setPosition(node->getPosition());

            node->removeFromParent();

 

            _food = NULL;

            _nearDis = _distance + 100;

        }

 

        _angle = 0;

    }

}

执行结果:




1 3.0物理系统PhysicsWorld


T07PhysicsWorld.h

#ifndef __T07PhysicsWorld_H__

#define __T07PhysicsWorld_H__

 

#include "T32.h"

 

class T07PhysicsWorld : public Layer

{

public:

    CREATE_FUNC(T07PhysicsWorld);

 

    bool init();

    Scene* getScene(){ return (Scene*)getParent(); }

};

 

#endif

T07PhysicsWorld.cpp

#include "T07PhysicsWorld.h"

 

 

bool T07PhysicsWorld::init()

{

    Layer::init();

 

    PhysicsBody* bodyA;

    PhysicsBody* bodyB;

 

    {

        //后面的三个參数值分别表示的是:密度,弹性值。摩擦力

        PhysicsBody* body = PhysicsBody::createCircle(20, PhysicsMaterial(1.0f, 1.0f, 0.0f));

        bodyA = body;

        //创建精灵

        Sprite* sprite = Sprite::create();

        //设置

        sprite->setPhysicsBody(body);

        addChild(sprite);

        //设置精灵的位置

        sprite->setPosition(winSize.width / 2, winSize.height / 2);

        //设置速度

        body->setVelocity(Vect(100, 200));

    }

 

    {

        PhysicsBody* body = PhysicsBody::createEdgeBox(winSize, PhysicsMaterial(1.0f, 1.0f, 0.0f));

        bodyB = body;

        Sprite* sprite = Sprite::create();

        addChild(sprite);

        sprite->setPhysicsBody(body);

        sprite->setPosition(winSize.width / 2, winSize.height / 2);

    }

 

    {

        bodyA->setContactTestBitmask(0x1);

        bodyB->setContactTestBitmask(0x1);

        bodyA->setGroup(1);

        bodyB->setGroup(2);

 

        //设置精灵的

        auto ev = EventListenerPhysicsContactWithBodies::create(bodyA, bodyB);

        ev->onContactBegin = [](PhysicsContact& contact){

            CCLog("Began Contact...........");

            return true;

        };

 

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

    }

 

    {

        auto ev = EventListenerPhysicsContactWithShapes::create(bodyA->getShapes().at(0),

            bodyB->getShapes().at(0));

 

        ev->onContactBegin = [](PhysicsContact& contact){

            CCLog("Shape Began Contact...........");

            return true;

        };

 

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

    }

 

    {

        auto ev = EventListenerPhysicsContactWithGroup::create(3);

        ev->onContactBegin = [](PhysicsContact& contact){

            CCLog("Group Began Contact...........");

            return true;

        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

 

    }

 

    return true;

}

TMenu.h

#ifndef __TMenu_H__

#define __TMenu_H__

 

#include "T32.h"

 

class TMenu : public Layer

{

public:

    CREATE_FUNC(TMenu);

 

    bool init();

 

    bool TouchBegan(Touch*, Event*);

};

 

#endif

TMenu.cpp

#include "TMenu.h"

#include "TBack.h"

#include "T01CPP11.h"

#include "T02Vector.h"

#include "T03Map.h"

#include "T04Label.h"

#include "T05Touch.h"

#include "T06Box2D.h"

#include "T07PhysicsWorld.h"

 

static const char* title[] = {

    "T01CPP11",

    "T02Vector",

    "T04Label",

    "T05Touch",

    "T06Box2D",

    "T07PhysicsWorld"

};

 

bool TMenu::init()

{

    Layer::init();

 

    Menu* menu = Menu::create();

    addChild(menu);

 

    for (int i = 0; i < sizeof(title) / sizeof(*title); ++i)

    {

        MenuItemFont* item = MenuItemFont::create(title[i], [](Ref* sender){

 

            MenuItem* item = (MenuItem*)sender;

            int i = item->getTag() - 1000;

            Layer* l = NULL;

 

            if (title[i] == "T01CPP11")   l = T01CPP11::create();

            if (title[i] == "T02Vector")   l = T02Vector::create();

            if (title[i] == "T04Label") l = T04Label::create();

            if (title[i] == "T05Touch") l = T05Touch::create();

            if (title[i] == "T06Box2D") l = T06Box2D::create();

            if (title[i] == "T07PhysicsWorld") l = T07PhysicsWorld::create();

 

            if (l)

            {

                TBack* b = TBack::create();

                Scene* s = Scene::createWithPhysics();

 

 

                PhysicsWorld* world = s->getPhysicsWorld();

                world->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

 

                s->addChild(b);

                s->addChild(l);

                Director::getInstance()->pushScene(s);

            }

        });

        menu->addChild(item);

        item->setTag(1000 + i);

    }

 

    menu->alignItemsVertically();

 

    // 触摸

    auto ev = EventListenerTouchOneByOne::create();

#if 0

    ev->onTouchBegan = [](Touch*, Event*){

        return true;

    };

#endif

 

    //ev->onTouchBegan = std::bind(&TMenu::TouchBegan, this, std::placeholders::_1, std::placeholders::_2);

 

    ev->onTouchBegan = CC_CALLBACK_2(TMenu::TouchBegan, this);

 

    ev->onTouchMoved = [&](Touch* touch, Event*){

        setPositionY(getPositionY() + touch->getDelta().y);

    };

    _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

 

    return true;

}

 

bool TMenu::TouchBegan(/*TMEnu* this, */Touch*, Event*)

{

    return true;

}

执行结果:


射线的做法


T08RayCast.h

#ifndef __T08RayCast_H__

#define __T08RayCast_H__

 

#include "T32.h"

class T08RayCast :public Layer

{

public:

    CREATE_FUNC(T08RayCast);

 

    bool init();

    void onEnter();

    void update(float);

 

    Sprite* _cat;

    int _angle;

    int _distance;

    float _nearDis;

    PhysicsShape* _food;

 

    DrawNode* _drawNode;

};

 

#endif

T08RayCast.cpp

#include "T08RayCast.h"

 

void T08RayCast::onEnter()

{

    Layer::onEnter();

 

    Scene* scene = (Scene*)getParent();

    scene->getPhysicsWorld()->setGravity(Vec2(0, 0));

}

 

bool T08RayCast::init()

{

    Layer::init();

 

    // 创建猫,猫不是Body,仅仅是一个简单的精灵

    {

        Sprite* cat = Sprite::create("CloseNormal.png");

        addChild(cat);

        cat->setPosition(winSize.width / 2, winSize.height / 2);

        _cat = cat;

    }

 

    // 投放食物。食物必须是body

    {

        auto ev = EventListenerTouchOneByOne::create();

        ev->onTouchBegan = [&](Touch* touch, Event*){

            //得到触摸点

            Vec2 pt = touch->getLocation();

            //创建一个圆形的PhysicsBody

            PhysicsBody* body = PhysicsBody::createCircle(10);

            Sprite* sprite = Sprite::create();

            sprite->setPhysicsBody(body);

            addChild(sprite);

            sprite->setPosition(pt);

 

            return true;

        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(ev, this);

    }

 

    {

        _angle = 0;      //角度

        _distance = 100; //距离

        _nearDis = _distance + 100;

        _food = NULL;

        _drawNode = NULL;

    }

    scheduleUpdate();

 

    return true;

}

 

void T08RayCast::update(float dt)

{

    Scene* scene = (Scene*)getParent();

    PhysicsWorld* world = scene->getPhysicsWorld();

 

    //获得猫的位置

    Vec2 start = _cat->getPosition();

    Vec2 end;

 

    //当前时刻扫描到的终点位置

    end.x = start.x + sinf(_angle / 180.0 * M_PI)*_distance;

    end.y = start.y + cosf(_angle / 180.0 * M_PI)*_distance;

 

    // 显示扫描距离

    if (_drawNode) _drawNode->removeFromParent();

    //以下的代码用于画线段

    _drawNode = DrawNode::create();

    _drawNode->drawSegment(start, end, 1, Color4F(1, 0, 0, 1));

    addChild(_drawNode);

 

    // 扫描回调函数

    //bool(PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data)

    auto callback = [&](PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data){

 

        if (info.shape == NULL)

            return true;

 

        //假设点包括猫的点

        float dis = info.contact.getDistance(_cat->getPosition());

        if (dis < _nearDis)

        {

            _nearDis = dis;

            _food = info.shape;

        }

 

        // 扫描到一个就不要再继续了

        return false;

    };

    //通过rayCast画一条射线

    world->rayCast(callback, start, end, NULL);

 

    //每次角度加2

    _angle += 2;

    //假设角度为360

    if (_angle == 360)

    {

        //假设存在食物

        if (_food)

        {

            // 吃掉食物

            Node* node = _food->getBody()->getNode();

            //将猫的的位置数值到新的位置

            _cat->setPosition(node->getPosition());

            node->removeFromParent();

 

            _food = NULL;

            _nearDis = _distance + 100;

        }

 

        _angle = 0;

    }

}

执行结果:

技术分享

技术分享


 




 

1.物理系统PhysicsWorld,RayCast