cocos2d 中有很多中關節類,關節是為了讓兩個獨立物體之間建立某種聯系,使之猶如一體
常見的關節類有:
PhysicsJointXXX
類 | 含義 | 舉例說明 |
---|---|---|
PhysicsJointDistance | 設定兩個剛體間的固定距離 | |
PhysicsJointFixed | 将兩個剛體結合在了一起 | |
PhysicsJointGear | 使一對剛提的角速度比率保持一定比例 | 比如齒輪 |
PhysicsJointGroove | 一個剛體連到線上,另一個連到點上 | |
PhysicsJointLimit | 限制兩個剛體間的最大距離 | 比如流星錘 |
PhysicsJointMotor | 兩個剛體的相對角速度保持一個常數 | |
PhysicsJointPin | 兩個剛體獨立的圍繞錨點進行旋轉 | |
PhysicsJointRatchet | 與套筒扳手的工作類似,單向旋轉,不能轉回來,比如自行車的飛輪,正想踏實有動力的,反向是沒有動力的 | |
PhysicsJointRotoryLimit | 與限制關節類似,增加了自旋 | 地球繞太陽運動(地球同時在自旋)) |
PhysicsJointRotarySpring | 與彈簧關節相似,增加自旋 | 汽車的懸挂系統 |
PhysicsJointSpring | 永泰黃來連接配接兩個實體剛體 |
使用方式 (繩子為例)
使用 PhysicsJointDistance 将多個節點連接配接起來,實作繩子下落擺動的效果
基本步驟:
- 固定一個端點,并且設定body
- 循環增加節點,将節點addChild() 添加到場景中
- 相鄰選兩個節點建立一個關節 PhysicsJointDistance::cons
- 将關節 添加到PhysicsWorld對象 中
demo代碼片段:
#include "HelloWorldScene.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
USING_NS_CC;
using namespace cocostudio::timeline;
#define PHYSICS_MATERIAL1 PhysicsMaterial(1,1,0)
#define PHYSICS_MATERIAL2 PhysicsMaterial(1,0,0)
PhysicsWorld * world;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
//auto scene = Scene::create();
// 建立帶實體特性的世界
auto scene = Scene::createWithPhysics();
world = scene->getPhysicsWorld();
scene->getPhysicsWorld()->setGravity(Vec2(0, -980));
//scene->getPhysicsWorld()->setAutoStep(false);
//PhysicsWorld::DEBUGDRAW_JOINT
//scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
// 1. super init first
if ( !Layer::init() )
{
return false;
}
/* auto rootNode = CSLoader::createNode("MainScene.csb");
addChild(rootNode);*/
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto rootNode = CSLoader::createNode("MainScene.csb");
Sprite * edgeBox = dynamic_cast<Sprite*>(rootNode->getChildByName("Default"));
auto edgeBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICS_MATERIAL1,3);
edgeBody->setDynamic(false);
edgeBox->setPhysicsBody(edgeBody);
addChild(rootNode);
// 使用關節 實作繩子效果
Sprite * nodes[10];
PhysicsBody * bodys[10];
PhysicsJointDistance * pjd[10];
// 1. 固定第一個節點
nodes[0] = Sprite::create();
Vec2 point(visibleSize.width / 2, 9* visibleSize.height /10);
nodes[0]->setPosition(point);
addChild(nodes[0]);
bodys[0] = PhysicsBody::createCircle(20, PHYSICS_MATERIAL1);
bodys[0]->setCategoryBitmask(0);
bodys[0]->setDynamic(false);
nodes[0]->setPhysicsBody(bodys[0]);
for (int i = 1; i < 10; i++) {
nodes[i] = Sprite::create("rope05HA.png");
nodes[i]->setPosition(point.x+40*i,point.y);
addChild(nodes[i]);
bodys[i]= PhysicsBody::createCircle(20, PHYSICS_MATERIAL1);
bodys[i]->setCategoryBitmask(0);
nodes[i]->setPhysicsBody(bodys[i]);
pjd[i - 1] = PhysicsJointDistance::construct(bodys[i - 1], bodys[i], Vec2(18,0), Vec2(-18, 0));
world->addJoint(pjd[i - 1]);// 将關節加入世界
}
return true;
}
效果(這是失敗的效果):

解決:
出現問題是因為在設定關節時,設定前後兩個節點的關節作用錨點位置弄錯了,都弄到各自的中心去了
一個節點的尺寸是 40x18 的
A-B
中間的**-** 表示關節
我們想做的當然是A的末端與B的起端相連接配接,達到下面的效果
而錨點預設是在sprite 的中間,也就是(0.5,0.5) //這是按照尺寸的百分比來的
錨點位置坐标也可以小于0,也可以大于1,也就是說錨點可以不在sprite 内部
pjd[i - 1] = PhysicsJointDistance::construct(bodys[i - 1], bodys[i], Vec2(18,0), Vec2(-18, 0));
// 由于 每個節點的尺寸都是40*18 ,我們通過指定關節連接配接作用的相對于錨點的一個位置.建立連接配接
Vec2(18,0): 關節的第一個點作用于A節點的相對于錨點靠右18個像素的位置
Vec2(-18,0):關節的第二個點作用于B節點的相對于錨點靠左18個像素的位置
達到的效果大體是A節點的末端與B節點的起端相連接配接,這點可以指定
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL); 來觀察
開啟 scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
效果:
如果把那個相對位置設定大一些,可能更加直覺,看出相鄰兩個節點的之間的關節作用位置(圖中綠色的點)
設定為30吧
成功的效果:
完整的資源以及代碼已上傳至github
https://github.com/TopForethought/cocos2dx/tree/master/關節繩子
後序會嘗試做一個帶有懸挂系統的越野車,哈哈!
蹦蹦救護車已上線
代碼資源:
https://github.com/TopForethought/cocos2dx/tree/master/關節-蹦蹦車