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

1.物理系统PhysicsWorld,RayCast



1 3.0物理系统PhysicsWorld

T07PhysicsWorld.h

#ifndef__T07PhysicsWorld_H__

#define__T07PhysicsWorld_H__

 

#include"T32.h"

 

classT07PhysicsWorld :publicLayer

{

public:

   CREATE_FUNC(T07PhysicsWorld);

 

   boolinit();

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

};

 

#endif

T07PhysicsWorld.cpp

#include"T07PhysicsWorld.h"

 

 

boolT07PhysicsWorld::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);

 

       //设置精灵的

       autoev =EventListenerPhysicsContactWithBodies::create(bodyA,bodyB);

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

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

           returntrue;

       };

 

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

   }

 

   {

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

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

 

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

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

           returntrue;

       };

 

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

   }

 

   {

       autoev =EventListenerPhysicsContactWithGroup::create(3);

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

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

           returntrue;

       };

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

 

   }

 

   returntrue;

}

TMenu.h

#ifndef__TMenu_H__

#define__TMenu_H__

 

#include"T32.h"

 

classTMenu :publicLayer

{

public:

   CREATE_FUNC(TMenu);

 

   boolinit();

 

   boolTouchBegan(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"

 

staticconstchar*title[] = {

   "T01CPP11",

   "T02Vector",

   "T04Label",

   "T05Touch",

   "T06Box2D",

   "T07PhysicsWorld"

};

 

boolTMenu::init()

{

   Layer::init();

 

   Menu*menu =Menu::create();

   addChild(menu);

 

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

   {

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

 

           MenuItem*item = (MenuItem*)sender;

           inti =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();

 

   //触摸

   autoev =EventListenerTouchOneByOne::create();

#if 0

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

       returntrue;

   };

#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);

 

   returntrue;

}

 

boolTMenu::TouchBegan(/*TMEnu* this, */Touch*,Event*)

{

   returntrue;

}

运行结果:

射线的做法

T08RayCast.h

#ifndef__T08RayCast_H__

#define__T08RayCast_H__

 

#include"T32.h"

classT08RayCast :publicLayer

{

public:

   CREATE_FUNC(T08RayCast);

 

   boolinit();

   voidonEnter();

   voidupdate(float);

 

   Sprite*_cat;

   int_angle;

   int_distance;

   float_nearDis;

   PhysicsShape*_food;

 

   DrawNode*_drawNode;

};

 

#endif

T08RayCast.cpp

#include"T08RayCast.h"

 

voidT08RayCast::onEnter()

{

   Layer::onEnter();

 

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

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

}

 

boolT08RayCast::init()

{

   Layer::init();

 

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

   {

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

       addChild(cat);

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

       _cat =cat;

   }

 

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

   {

       autoev =EventListenerTouchOneByOne::create();

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

           //得到触摸点

           Vec2pt =touch->getLocation();

           //创建一个圆形的PhysicsBody

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

           Sprite*sprite =Sprite::create();

           sprite->setPhysicsBody(body);

           addChild(sprite);

           sprite->setPosition(pt);

 

           returntrue;

       };

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

   }

 

   {

       _angle = 0;     //角度

       _distance = 100;//距离

       _nearDis =_distance + 100;

       _food =NULL;

       _drawNode =NULL;

   }

   scheduleUpdate();

 

   returntrue;

}

 

voidT08RayCast::update(floatdt)

{

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

   PhysicsWorld*world =scene->getPhysicsWorld();

 

   //获得猫的位置

   Vec2start =_cat->getPosition();

   Vec2end;

 

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

   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)

   autocallback = [&](PhysicsWorld&world,constPhysicsRayCastInfo&info,void*data){

 

       if (info.shape == NULL)

           returntrue;

 

       //如果点包含猫的点

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

       if (dis < _nearDis)

       {

           _nearDis =dis;

           _food =info.shape;

       }

 

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

       returnfalse;

   };

   //通过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"

 

classT07PhysicsWorld :publicLayer

{

public:

   CREATE_FUNC(T07PhysicsWorld);

 

   boolinit();

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

};

 

#endif

T07PhysicsWorld.cpp

#include"T07PhysicsWorld.h"

 

 

boolT07PhysicsWorld::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);

 

       //设置精灵的

       autoev =EventListenerPhysicsContactWithBodies::create(bodyA,bodyB);

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

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

           returntrue;

       };

 

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

   }

 

   {

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

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

 

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

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

           returntrue;

       };

 

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

   }

 

   {

       autoev =EventListenerPhysicsContactWithGroup::create(3);

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

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

           returntrue;

       };

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

 

   }

 

   returntrue;

}

TMenu.h

#ifndef__TMenu_H__

#define__TMenu_H__

 

#include"T32.h"

 

classTMenu :publicLayer

{

public:

   CREATE_FUNC(TMenu);

 

   boolinit();

 

   boolTouchBegan(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"

 

staticconstchar*title[] = {

   "T01CPP11",

   "T02Vector",

   "T04Label",

   "T05Touch",

   "T06Box2D",

   "T07PhysicsWorld"

};

 

boolTMenu::init()

{

   Layer::init();

 

   Menu*menu =Menu::create();

   addChild(menu);

 

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

   {

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

 

           MenuItem*item = (MenuItem*)sender;

           inti =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();

 

   //触摸

   autoev =EventListenerTouchOneByOne::create();

#if 0

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

       returntrue;

   };

#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);

 

   returntrue;

}

 

boolTMenu::TouchBegan(/*TMEnu* this, */Touch*,Event*)

{

   returntrue;

}

运行结果:


射线的做法


T08RayCast.h

#ifndef__T08RayCast_H__

#define__T08RayCast_H__

 

#include"T32.h"

classT08RayCast :publicLayer

{

public:

   CREATE_FUNC(T08RayCast);

 

   boolinit();

   voidonEnter();

   voidupdate(float);

 

   Sprite*_cat;

   int_angle;

   int_distance;

   float_nearDis;

   PhysicsShape*_food;

 

   DrawNode*_drawNode;

};

 

#endif

T08RayCast.cpp

#include"T08RayCast.h"

 

voidT08RayCast::onEnter()

{

   Layer::onEnter();

 

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

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

}

 

boolT08RayCast::init()

{

   Layer::init();

 

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

   {

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

       addChild(cat);

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

       _cat =cat;

   }

 

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

   {

       autoev =EventListenerTouchOneByOne::create();

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

           //得到触摸点

           Vec2pt =touch->getLocation();

           //创建一个圆形的PhysicsBody

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

           Sprite*sprite =Sprite::create();

           sprite->setPhysicsBody(body);

           addChild(sprite);

           sprite->setPosition(pt);

 

           returntrue;

       };

       _eventDispatcher->addEventListenerWithSceneGraphPriority(ev,this);

   }

 

   {

       _angle = 0;     //角度

       _distance = 100;//距离

       _nearDis =_distance + 100;

       _food =NULL;

       _drawNode =NULL;

   }

   scheduleUpdate();

 

   returntrue;

}

 

voidT08RayCast::update(floatdt)

{

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

   PhysicsWorld*world =scene->getPhysicsWorld();

 

   //获得猫的位置

   Vec2start =_cat->getPosition();

   Vec2end;

 

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

   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)

   autocallback = [&](PhysicsWorld&world,constPhysicsRayCastInfo&info,void*data){

 

       if (info.shape == NULL)

           returntrue;

 

       //如果点包含猫的点

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

       if (dis < _nearDis)

       {

           _nearDis =dis;

           _food =info.shape;

       }

 

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

       returnfalse;

   };

   //通过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