Closed1
Box2D基本2_Jointを使ってRagDollを作る

Jointを使う事で、オブジェクト同士を繋ぐことが出来ます
今回は円と四角を複数組み合わせてRagdoll(人形)を作ってみます
(前回使ったクラスも利用します)
DrawerRagdoll.cpp
#include "DrawerRagdoll.h"
#include "DrawerBox.h"
#include "DrawerCircle.h"
DrawerRagdoll *DrawerRagdoll::create(const b2WorldId &worldId,
float x, float y) {
// New
auto obj = new DrawerRagdoll(worldId, x, y);
if (obj && obj->init()) return obj;
DX_SAFE_DELETE(obj);
return nullptr;
}
DrawerRagdoll::DrawerRagdoll(const b2WorldId &worldId,
float x, float y) :
DrawerBase(worldId, x, y) {
//LOGD("Main", "DrawerRagdoll()");
}
DrawerRagdoll::~DrawerRagdoll() {
//LOGD("Main", "~DrawerRagdoll()");
// Destroy
for (auto joint: joints) b2DestroyJoint(joint, true);
DX_SAFE_DELETE_VECTOR(bodies);
}
bool DrawerRagdoll::init() {
const int cX = pos.x;
const int cY = pos.y;
const int gSize = UtilDebug::getInstance()->getGridSize();
// Head
const auto head = DrawerCircle::create(
worldId, cX, cY, gSize, true);
bodies.push_back(head);
// Body
const auto body = DrawerBox::create(
worldId, cX, cY + gSize * 3,
gSize * 2, gSize * 4, 0, true);
bodies.push_back(body);
// Head - Body
auto jdHB = b2DefaultRevoluteJointDef();
jdHB.base.bodyIdA = head->getBodyId();
jdHB.base.bodyIdB = body->getBodyId();
jdHB.base.localFrameA.p = {0.0f, -head->getRadiusM()};
jdHB.base.localFrameB.p = {0.0f, body->getHeightM() / 2};
jdHB.base.collideConnected = false;
jdHB.enableLimit = true;
jdHB.lowerAngle = DEG_TO_RAD * -30;
jdHB.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdHB));
// Left armA
const auto leftArmA = DrawerBox::create(
worldId, cX - gSize * 2, cY + gSize * 2,
gSize * 2, gSize * 1, 0, true);
bodies.push_back(leftArmA);
// Body - Left armA
auto jdBody2LAA = b2DefaultRevoluteJointDef();
jdBody2LAA.base.bodyIdA = body->getBodyId();
jdBody2LAA.base.bodyIdB = leftArmA->getBodyId();
jdBody2LAA.base.localFrameA.p = {-body->getWidthM() / 2, body->getHeightM() / 4};
jdBody2LAA.base.localFrameB.p = {leftArmA->getWidthM() / 2, 0.0f};
jdBody2LAA.base.collideConnected = false;
jdBody2LAA.enableLimit = true;
jdBody2LAA.lowerAngle = DEG_TO_RAD * -30;
jdBody2LAA.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdBody2LAA));
// Left armB
const auto leftArmB = DrawerBox::create(
worldId, cX - gSize * 4, cY + gSize * 2,
gSize * 2, gSize * 1, 0, true);
bodies.push_back(leftArmB);
// Left armA - Left armB
auto jdLAA2LAB = b2DefaultRevoluteJointDef();
jdLAA2LAB.base.bodyIdA = leftArmA->getBodyId();
jdLAA2LAB.base.bodyIdB = leftArmB->getBodyId();
jdLAA2LAB.base.localFrameA.p = {-leftArmA->getWidthM() / 2, 0.0f};
jdLAA2LAB.base.localFrameB.p = {leftArmB->getWidthM() / 2, 0.0f};
jdLAA2LAB.base.collideConnected = false;
jdLAA2LAB.enableLimit = true;
jdLAA2LAB.lowerAngle = DEG_TO_RAD * -30;
jdLAA2LAB.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdLAA2LAB));
// Right armA
const auto rightArmA = DrawerBox::create(
worldId, cX + gSize * 2, cY + gSize * 2,
gSize * 2, gSize * 1, 0, true);
bodies.push_back(rightArmA);
// Body - Right armA
auto jdBody2RAA = b2DefaultRevoluteJointDef();
jdBody2RAA.base.bodyIdA = body->getBodyId();
jdBody2RAA.base.bodyIdB = rightArmA->getBodyId();
jdBody2RAA.base.localFrameA.p = {body->getWidthM() / 2, body->getHeightM() / 4};
jdBody2RAA.base.localFrameB.p = {-rightArmA->getWidthM() / 2, 0.0f};
jdBody2RAA.base.collideConnected = false;
jdBody2RAA.enableLimit = true;
jdBody2RAA.lowerAngle = DEG_TO_RAD * -30;
jdBody2RAA.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdBody2RAA));
// Right armB
const auto rightArmB = DrawerBox::create(
worldId, cX + gSize * 4, cY + gSize * 2,
gSize * 2, gSize * 1, 0, true);
bodies.push_back(rightArmB);
// Right armA - Right armB
auto jdLAA2RAB = b2DefaultRevoluteJointDef();
jdLAA2RAB.base.bodyIdA = rightArmA->getBodyId();
jdLAA2RAB.base.bodyIdB = rightArmB->getBodyId();
jdLAA2RAB.base.localFrameA.p = {rightArmA->getWidthM() / 2, 0.0f};
jdLAA2RAB.base.localFrameB.p = {-rightArmB->getWidthM() / 2, 0.0f};
jdLAA2RAB.base.collideConnected = false;
jdLAA2RAB.enableLimit = true;
jdLAA2RAB.lowerAngle = DEG_TO_RAD * -30;
jdLAA2RAB.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdLAA2RAB));
// Left legA
const auto leftLegA = DrawerBox::create(
worldId, cX - gSize * 1, cY + gSize * 6,
gSize * 1, gSize * 2, 0, true);
bodies.push_back(leftLegA);
// Body - Left legA
auto jdBody2LLA = b2DefaultRevoluteJointDef();
jdBody2LLA.base.bodyIdA = body->getBodyId();
jdBody2LLA.base.bodyIdB = leftLegA->getBodyId();
jdBody2LLA.base.localFrameA.p = {-body->getWidthM() / 2, -body->getHeightM() / 2};
jdBody2LLA.base.localFrameB.p = {0.0f, leftLegA->getHeightM() / 2};
jdBody2LLA.base.collideConnected = false;
jdBody2LLA.enableLimit = true;
jdBody2LLA.lowerAngle = DEG_TO_RAD * -30;
jdBody2LLA.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdBody2LLA));
const auto leftLegB = DrawerBox::create(
worldId, cX - gSize * 1, cY + gSize * 8,
gSize * 1, gSize * 2, 0, true);
bodies.push_back(leftLegB);
// Left legA - Left LegB
auto jdBody2LLB = b2DefaultRevoluteJointDef();
jdBody2LLB.base.bodyIdA = leftLegA->getBodyId();
jdBody2LLB.base.bodyIdB = leftLegB->getBodyId();
jdBody2LLB.base.localFrameA.p = {0.0f, -leftLegA->getHeightM() / 2};
jdBody2LLB.base.localFrameB.p = {0.0f, leftLegB->getHeightM() / 2};
jdBody2LLB.base.collideConnected = false;
jdBody2LLB.enableLimit = true;
jdBody2LLB.lowerAngle = DEG_TO_RAD * -30;
jdBody2LLB.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdBody2LLB));
// Right legA
const auto rightLegA = DrawerBox::create(
worldId, cX + gSize * 1, cY + gSize * 6,
gSize * 1, gSize * 2, 0, true);
bodies.push_back(rightLegA);
// Body - Right legA
auto jdBody2RLA = b2DefaultRevoluteJointDef();
jdBody2RLA.base.bodyIdA = body->getBodyId();
jdBody2RLA.base.bodyIdB = rightLegA->getBodyId();
jdBody2RLA.base.localFrameA.p = {body->getWidthM() / 2, -body->getHeightM() / 2};
jdBody2RLA.base.localFrameB.p = {0.0f, rightLegA->getHeightM() / 2};
jdBody2RLA.base.collideConnected = false;
jdBody2RLA.enableLimit = true;
jdBody2RLA.lowerAngle = DEG_TO_RAD * -30;
jdBody2RLA.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdBody2RLA));
const auto rightLegB = DrawerBox::create(
worldId, cX + gSize * 1, cY + gSize * 8,
gSize * 1, gSize * 2, 0, true);
bodies.push_back(rightLegB);
// Right legA - Right LegB
auto jdBody2RLB = b2DefaultRevoluteJointDef();
jdBody2RLB.base.bodyIdA = rightLegA->getBodyId();
jdBody2RLB.base.bodyIdB = rightLegB->getBodyId();
jdBody2RLB.base.localFrameA.p = {0.0f, -rightLegA->getHeightM() / 2};
jdBody2RLB.base.localFrameB.p = {0.0f, rightLegB->getHeightM() / 2};
jdBody2RLB.base.collideConnected = false;
jdBody2RLB.enableLimit = true;
jdBody2RLB.lowerAngle = DEG_TO_RAD * -30;
jdBody2RLB.upperAngle = DEG_TO_RAD * 30;
joints.push_back(b2CreateRevoluteJoint(worldId, &jdBody2RLB));
return true;
}
void DrawerRagdoll::update(const float delay) {
// Bodies
for (const auto body: bodies) body->update(delay);
// Joints
for (const auto joint: joints) {
b2BodyId bodyA = b2Joint_GetBodyA(joint);
b2BodyId bodyB = b2Joint_GetBodyB(joint);
auto localA = b2Joint_GetLocalFrameA(joint).p;
auto localB = b2Joint_GetLocalFrameB(joint).p;
auto pA = b2Body_GetWorldPoint(bodyA, localA);
auto pB = b2Body_GetWorldPoint(bodyB, localB);
const int fX = this->m2p(pA.x);
const int fY = this->m2p(pA.y);
const int tX = this->m2p(pB.x);
const int tY = this->m2p(pB.y);
UtilCamera::getInstance()->drawLine(fX, -fY, tX, -tY,
color, true);
}
}
このスクラップは2日前にクローズされました