Some thoughts + problems after using the physics stuff

1. Why the use both Vec2 and std::vector< Vec2 >?

consider this code to trace an image and use the points to create a polygon:

auto ap = AutoPolygon("images/tst.png");
auto rect = Rect(0, 0, 300, 300);
std::vector<Vec2> ptLst = ap.trace(rect);

Vec2* ptsAry = new Vec2[ptLst.size()];

for (size_t i = 0; i < ptLst.size(); i++)
	ptsAry[i] = ptLst.at(i);

auto bottleBody = PhysicsBody::createEdgePolygon(ptsAry, ptLst.size());
bottleBody->setDynamic(true);
	
auto bottle = Node::create();
bottle->setPhysicsBody(bottleBody);

delete [] ptsAry;

trace() returns a vector; createEdgePolygon (as well as createEdgeChain and createPolygon) wants a Vec2*. In order to prepare that Vec2* I need to create that array, pick up the points I got from trace() and delete the array when I’m done.
I have two problems with this (assuming I’m doing this right): Cocos2d offers a lot of help in terms of memory management - in form of the Ref class - but here I’m forced to manage my own memory (for array creation/deletion), which kind of feels like an oversight. And also… why not just have createEdgePolygon take a std::vector - or any iterable class, I guess?

PhysicsBody::createEdgePolygon(const std::vector<Vec2> points, int count, ...

2. BodyTypes
The physicsBody class has a function called setDynamic, which toggles it between being a DYNAMIC type or a KINEMATIC type, but what about the third body type STATIC, which is what I’d normally use for walls, floors or other inanimate objects? Wouldn’t a

void PhysicsBody::setBodyType(BodyType type);

be a better method for letting the user decide which body type to use?

3. getCPBody() problem
For some reason when I type “myBody->getCPBody()->” I don’t get any auto-completion what so ever, what am I doing wrong?

4. Hmm…

I traced an image and created the above polygon (the floor is set to dynamic = false). When the U-shape falls onto the floor the game crashes and gives me this error:

Assert failed: CCNode#rotation. RotationX != RotationY. Don't know which one to return

File: CCNode.cpp
Line: 301

Expression: _rotationZ_X == _rotationZ_Y

I’ve tried everything I can think of, might have to try to remove that assert, but will that break something else for me later on?

5. Hmm indeed
This is also from a traced image, just a square. It’s drawn diagonally in the source image, but what’s strange is its behaviour. It sways slowly back and forth on one of its corners like a boat until it settles eventually on one of its sides. It’s like its center of gravity was off-screen or something. Anyone know how to fix this?

That’s all I had for now. I’m sure I’ll have more to add later!

Can you send me more of a working example to play with when I have some time? You can get it to me privately if you can’t share publicly.

it’s not much else to share than what’s in the first post, but here you go.
setup a scene with initWithPhysics(), override onEnter and setup the world and the objects:

auto org = Director::getInstance()->getVisibleOrigin();
auto screen = Director::getInstance()->getVisibleSize();
auto physWorld = Director::getInstance()->getRunningScene()->getPhysicsWorld();
physWorld->setGravity(Vec2(0, -2200));
physWorld->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
physWorld->setSubsteps(3);

make the floor - you can use any picture you want.

auto floor = Sprite::create("images/floor.png");
floor->setAnchorPoint(Vec2::ANCHOR_MIDDLE_TOP);
floor->setContentSize(Size(screen.width, floor->getContentSize().height));
floor->setPosition(org.x + screen.width * 0.5, floor->getContentSize().height);

auto floorBody = PhysicsBody::createBox(((Size(screen.width, floor->getContentSize().height))));
floorBody->setDynamic(false);
floorBody->setRotationEnable(false);
floor->setPhysicsBody(floorBody);
addChild(floor);

add traced object. actually made a small improvement so that the array’s memory is handled automatically (unique_ptr).

// only used for getting the image's size when offsetting the body's position
std::unique_ptr<Image> img = std::make_unique<Image>();
img->initWithImageFile("images/tst.png");

auto ap = AutoPolygon(img->getFilePath());
auto rect = Rect(0, 0, img->getWidth(), img->getHeight());
std::vector<Vec2> ptLst = ap.trace(rect);
std::unique_ptr<Vec2*> ptsAry = std::make_unique<Vec2*>(new Vec2[ptLst.size()]);

for (size_t i = 0; i < ptLst.size(); i++)
	(*ptsAry)[i] = ptLst.at(i);

auto bottleBody = PhysicsBody::createEdgePolygon(*ptsAry, ptLst.size());
bottleBody->setDynamic(/*true*/ false);
bottleBody->setPositionOffset(Vec2(-img->getWidth() * 0.5, -img->getHeight() * 0.5));
	
auto bottle = Node::create();
bottle->setPhysicsBody(bottleBody);
bottle->setPosition(org.x + screen.width * 0.5, screen.height * 0.5);

addChild(bottle);

use this img:
tst

that’s it!

1 Like