//
// PhysicsJoints2.hpp
// day01
//
// Created by MAC on 16/7/14.
//
//
#ifndef PhysicsJoints2_hpp
#define PhysicsJoints2_hpp
#include <stdio.h>
#include <iostream>
using namespace std;
#include "cocos2d.h"
using namespace cocos2d;
#include "ui/CocosGUI.h"
using namespace cocos2d::ui;
const int DRAG_BODYS_TAG =1;
class PhysicsJoints2:public Layer{
public:
static Scene* createScene();
bool init();
CREATE_FUNC(PhysicsJoints2);
void onEnter();
void onExit();
PhysicsWorld* getPhysicsWorld();
Sprite* makeBall(Vec2 point, float radius, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT);
Sprite* makeBox(Vec2 point, Size size, int color=0, PhysicsMaterial material = PHYSICSSHAPE_MATERIAL_DEFAULT);
private:
Size visiableSize;
Vec2 center;
PhysicsBody* _touchBody;
};
#endif /* PhysicsJoints2_hpp */
//
// PhysicsJoints2.cpp
// day01
//
// Created by MAC on 16/7/14.
//
//
#include "PhysicsJoints2.hpp"
Scene* PhysicsJoints2::createScene(){
auto scene = Scene::createWithPhysics();
//set the debug
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
//设置重力(x,y)
scene->getPhysicsWorld()->setGravity(Vec2(0, 0));
auto layer = PhysicsJoints2::create();
scene->addChild(layer);
return scene;
}
bool PhysicsJoints2::init(){
if (!Layer::init()) {
return false;
}
visiableSize = Director::getInstance()->getVisibleSize();
center = Vec2(visiableSize.width/2,visiableSize.height/2);//屏幕中心
_touchBody = nullptr;
auto dispatcher = Director::getInstance()->getEventDispatcher();
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->onTouchBegan = [=](Touch* _touch,Event* _touchEvent)->bool{
PhysicsWorld* _physicsWorld = this->getPhysicsWorld();
Vec2 location = _touch->getLocation();
auto arr = _physicsWorld->getShapes(location);//物理世界中哪些形状包含这个点
for (auto& obj : arr)
{
if ((obj->getBody()->getTag() == 1) )
{
_touchBody = obj->getBody();
break;
}
}
if (_touchBody) {
return true;
}
return false;
};
touchListener->onTouchMoved = [=](Touch* _touch,Event* _touchEvent){
if (_touchBody) {
_touchBody->getNode()->setPosition(_touch->getLocation());
}
};
touchListener->onTouchEnded = [=](Touch* _touch,Event* _touchEvent){
_touchBody = nullptr;
};
dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
return true;
}
PhysicsWorld* PhysicsJoints2::getPhysicsWorld(){
return Director::getInstance()->getRunningScene()->getPhysicsWorld();
}
void PhysicsJoints2::onEnter(){
Layer::onEnter();
Vec2 offset = center; //屏幕中心
Node* node = Node::create();
PhysicsBody* box = PhysicsBody::create();
node->addComponent(box);
box->setDynamic(false); //静态
node->setPosition(Point::ZERO);
this->addChild(node);
box->addShape(PhysicsShapeEdgeBox::create(Size(100, 100), PHYSICSSHAPE_MATERIAL_DEFAULT, 1, offset));
// 别针联合,如果两个机构固定在一起它们可以独立绕锚点运动.
// auto sp1 = makeBall(center - Vec2(30, 0), 10);
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(1);
//
// auto sp2 = makeBall(center + Vec2(30, 0), 10);
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(1);
// PhysicsJointPin* joint = PhysicsJointPin::construct(sp1PhysicsBody, sp2PhysicsBody, center);//连接
// getPhysicsWorld()->addJoint(joint);
//将两个机构在一个固定的融合点. 固定接头是非常有用的,它可以用于创建复杂的图形,他也可以被打散
// auto sp1 = makeBall(center - Vec2(30, 0), 10);
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(1);
//
// auto sp2 = makeBox(center + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(1);
//
// PhysicsJointFixed* joint = PhysicsJointFixed::construct(sp1PhysicsBody, sp2PhysicsBody, center);
// getPhysicsWorld()->addJoint(joint);
//该关节用于在两个刚体之间设置一个固定距离。
// auto sp1 = makeBall(center - Vec2(30, 0), 10);
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(center + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// PhysicsJointDistance* joint = PhysicsJointDistance::construct(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO);
// getPhysicsWorld()->addJoint(joint);
//限制了两个物体之间的最大距离,就好像他们被一根绳子连接起来一样
// auto sp1 = makeBall(center - Vec2(30, 0), 10);
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(center + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// PhysicsJointLimit* joint = PhysicsJointLimit::construct(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO, 30.0f, 60.0f);
// getPhysicsWorld()->addJoint(joint);
//用于连接两个刚体,其效果相当于一个弹簧
// auto sp1 = makeBall(center - Vec2(30, 0), 10);
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(center + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// PhysicsJointSpring* joint = PhysicsJointSpring::construct(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO, 500.0f, 0.3f);
// getPhysicsWorld()->addJoint(joint);
//把第一个物体A连接到一条线上,把第二个物体连接到一个点上
// auto sp1 = makeBall(offset - Vec2(30, 0), 10);
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// PhysicsJointGroove* joint = PhysicsJointGroove::construct(sp1PhysicsBody, sp2PhysicsBody, Vec2(30, 15), Vec2(30, -15), Vec2(-30, 0));
// getPhysicsWorld()->addJoint(joint);
//与PhysicsJointSpring类似,但是刚体可以自由旋转
// auto sp1 = makeBox(offset - Vec2(30, 0), Size(30, 10));
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition()));
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition()));
// PhysicsJointRotarySpring* joint = PhysicsJointRotarySpring::construct(sp1PhysicsBody, sp2PhysicsBody, 3000.0f, 60.0f);
// getPhysicsWorld()->addJoint(joint);
//与PhysicsJointLimit类似,但是刚体可以自由旋转
// auto sp1 = makeBox(offset - Vec2(30, 0), Size(30, 10));
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition()));
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition()));
// PhysicsJointRotaryLimit* joint = PhysicsJointRotaryLimit::construct(sp1PhysicsBody, sp2PhysicsBody, 0.0f,(float) M_PI_2);
// getPhysicsWorld()->addJoint(joint);
//就像一个连接器一样用来连接两个身体
// auto sp1 = makeBox(offset - Vec2(30, 0), Size(30, 10));
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition()));
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition()));
// PhysicsJointRatchet* joint = PhysicsJointRatchet::construct(sp1PhysicsBody, sp2PhysicsBody, 0.0f, (float)M_PI_2);
// getPhysicsWorld()->addJoint(joint);
//让两个刚体之间的旋转角速度保持一个常数
// auto sp1 = makeBox(offset - Vec2(30, 0), Size(30, 10));
// auto sp1PhysicsBody = sp1->getPhysicsBody();
// sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
// auto sp2PhysicsBody = sp2->getPhysicsBody();
// sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
//
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition()));
// getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition()));
// PhysicsJointGear* joint = PhysicsJointGear::construct(sp1PhysicsBody, sp2PhysicsBody, 0.0f, 2.0f);
// getPhysicsWorld()->addJoint(joint);
//
//PhysicsJointMotor用于保证两个物体的相对角速度是一个常数
auto sp1 = makeBox(offset - Vec2(30, 0), Size(30, 10));
auto sp1PhysicsBody = sp1->getPhysicsBody();
sp1PhysicsBody->setTag(DRAG_BODYS_TAG);
auto sp2 = makeBox(offset + Vec2(30, 0), Size(30, 10));
auto sp2PhysicsBody = sp2->getPhysicsBody();
sp2PhysicsBody->setTag(DRAG_BODYS_TAG);
getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition()));
getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition()));
PhysicsJointMotor* joint = PhysicsJointMotor::construct(sp1PhysicsBody, sp2PhysicsBody, (float)M_PI_2);
getPhysicsWorld()->addJoint(joint);
}
void PhysicsJoints2::onExit(){
Director::getInstance()->getEventDispatcher()->removeEventListenersForTarget(this);
Layer::onExit();
}
Sprite* PhysicsJoints2::makeBall(Vec2 point, float radius, PhysicsMaterial material)
{
Sprite* ball = Sprite::create("ball.png");
ball->setScale(0.13f * radius);
ball->addComponent(PhysicsBody::createCircle(ball->getContentSize().width / 2, material));
ball->setPosition(Vec2(point.x, point.y));
this->addChild(ball);
return ball;
}
Sprite* PhysicsJoints2::makeBox(Vec2 point, Size size, int color, PhysicsMaterial material)
{
bool yellow = false;
if (color == 0)
yellow = CCRANDOM_0_1() > 0.5f;
else
yellow = color == 1;
auto box = yellow ? Sprite::create("YellowSquare.png") : Sprite::create("CyanSquare.png");
box->setScaleX(size.width / 100.0f);
box->setScaleY(size.height / 100.0f);
box->addComponent(PhysicsBody::createBox(box->getContentSize(), material));
box->setPosition(Vec2(point.x, point.y));
this->addChild(box);
return box;
}