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;

}

运行结果:

1.物理系统PhysicsWorld,RayCast

射线的做法

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

1.物理系统PhysicsWorld,RayCast

上一篇:JavaScript中的事件循环机制跟函数柯里化


下一篇:postgres=# psql -U postgres -h 127.0.0.1 -p 5432 -d dreamstart_dev -w