Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
424 views
in Technique[技术] by (71.8m points)

cocos2d x - cocos2dx+box2d:Object stops abruptly, tied two ropes

cocos2dx+box2d: Hello. I actually have a problem. I did a bit of rope and she behaves normally. But if the object tie two ropes, it somehow as it stops abruptly. Can anyone understand why this is happening and can help? I recorded a video with two ropes, which shows that the object sharply ostanavliaetsya. And the video with one rope, where all is well:

One rope:http://youtu.be/Yh4x8qrgmgo

Two rope: http://youtu.be/iRPVPLrC9ZQ Because of what the object may stop so abruptly?

Add Rope:

GameScene::createRope(blk1,groundBody,blk1->GetLocalCenter(), cc_to_b2Vec(580, screen.height/1) ,1.0);
    GameScene::createRope(groundBody,blk1,cc_to_b2Vec(380, screen.height/2),  blk1->GetLocalCenter() ,1.1);

Create Rope:

void GameScene::createRope(b2Body *bodyA, b2Body *bodyB, b2Vec2 anchorA, b2Vec2 anchorB, float sag)
{
    b2RopeJointDef jd;
    jd.bodyA = bodyA;
    jd.bodyB = bodyB;

    jd.localAnchorA = anchorA;
    jd.localAnchorB = anchorB;
    jd.collideConnected = true;

    // Max length of joint = current distance between bodies * sag
    float32 ropeLength = (bodyA->GetWorldPoint(anchorA)- bodyB->GetWorldPoint(anchorB)).Length()*sag;
    jd.maxLength = ropeLength;

    // Create joint
    b2RopeJoint *ropeJoint = (b2RopeJoint *)world->CreateJoint(&jd);

    VRope *newRope = new VRope(ropeJoint, _ropeSpriteSheet);
    _ropes.push_back(newRope);
}

http://youtu.be/Lchc1II3cjY - The ropes are arranged at the same height. Essentially the same object should swing up and down a bit

In fact, the rope taut, but the sprite does not look stretched, and therefore it seems that the object should swing. I do not know how to fix it ... create Rope:

void VRope::createRope(const CCPoint& pointA, const CCPoint& pointB,float distance)
{
    // 16; //12; //increase value to have less segments per rope, decrease to have more segments
    int segmentFactor = 20;
    numPoints = (int) distance/segmentFactor;

    CCPoint diffVector = ccpSub(pointB,pointA);
    float multiplier = distance / (numPoints-1);
    antiSagHack = 0.1f; //HACK: scale down rope points to cheat sag. set to 0 to disable, max suggested value 0.1
    for(int i=0;i<numPoints;i++) {
        CCPoint tmpVector = ccpAdd(pointA, ccpMult(ccpNormalize(diffVector), multiplier*i*(1-antiSagHack)));        
        VPoint *tmpPoint = new VPoint();
        tmpPoint->setPos(tmpVector.x, tmpVector.y);
        vPoints.push_back(tmpPoint);
    }
    for(int i=0;i<numPoints-1;i++) {
        VStick* tmpStick = new VStick(vPoints[i], vPoints[i+1]);
        vSticks.push_back(tmpStick);
    }

    if(spriteSheet) {
        for(int i=0;i<numPoints-1;i++) {
            VPoint* point1 = vSticks[i]->getPointA();
            VPoint* point2 = vSticks[i]->getPointB();
            CCPoint stickVector = ccpSub(ccp(point1->x,point1->y),ccp(point2->x,point2->y));
            float stickAngle = ccpToAngle(stickVector);

            float f = spriteSheet->getTextureAtlas()->getTexture()->getPixelsHigh() / CC_CONTENT_SCALE_FACTOR();
            CCRect r = CCRectMake(0, 0, multiplier, f);
            CCSprite* tmpSprite = CCSprite::createWithTexture(spriteSheet->getTexture(), r);

            ccTexParams params = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
            tmpSprite->getTexture()->setTexParameters(&params);
            tmpSprite->setPosition(ccpMidpoint(ccp(point1->x, point1->y), ccp(point2->x, point2->y)));
            tmpSprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(stickAngle));
            spriteSheet->addChild(tmpSprite);
            ropeSprites.push_back(tmpSprite);
        }
    }
}

if I increase the number of segments that the rope will be stretched, but not look beautiful. and yes I cut by joint, so cutting is not accurate ....

If you increase the number of segments (reduced number of points and the rope looks like a stick)

http://youtu.be/hn8ALt2P8pE

If you increase the number of segments (reduced number of points and the rope looks like a stick) And if you reduce the surprising number of segments, it is not really too sagging look. What am I doing wrong? All code on the ropes

http://github.com/Banck/Rope

Help me please

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I suspect the problem you are encountering is in setting the length of your second rope. How you set it will make the object swing more/less.

I took the default cocos2d-x box2d template and modified it to make the "swinging boxes" demo. Here is a screen shot of what it looks like:

enter image description here

There are three ropes attached to each box when it is created.

The first rope attaches a point at the top of the scene (relative to the ground box) to the block. If left to swing free, the box would swing back and forth like a pendulum.

The second rope is attached from the left side (at the height the box started at) and has a length equal to the distance from the x position of the top joint to the x position the box was created. This keeps the box from swinging "too far" to the right.

The third joint is on the attached like the second rope. It keeps the box from swinging too far to the left.

The swing looks very natural but if it is bumped by another box, it can't swing more than the original distance to the left/right. If you make them shorter, the box will only swing in the range of the shortened distance.

Here is the code I used to create the joints:

  // Calculate the local position of the
   // top of screen in the local space
   // of the ground box.
   CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
   b2Vec2 groundWorldPos = b2Vec2((scrSize.width/2)/PTM_RATIO,(scrSize.height)/PTM_RATIO);
   b2Vec2 groundLocalPos = m_pGround->GetLocalPoint(groundWorldPos);

   // Now create the main swinging joint.
   b2RopeJointDef jointDef;
   jointDef.bodyA = m_pGround;
   jointDef.bodyB = body;
   jointDef.localAnchorA = groundLocalPos;
   jointDef.localAnchorB = b2Vec2(0.0f,0.0f);
   jointDef.maxLength = (groundWorldPos-body->GetWorldCenter()).Length();
   jointDef.collideConnected = true;
   world->CreateJoint(&jointDef);

   // Now create a second/third rope to "constrain" the swing.
   // These one will be attached to the side of the screen.
   b2Vec2 groundWorldPos2 = b2Vec2(0,body->GetWorldCenter().y);
   b2Vec2 groundLocalPos2 = m_pGround->GetLocalPoint(groundWorldPos2);

   jointDef.localAnchorA = groundLocalPos2;
   // Setting the length of the side rope...
   // What we want to do here is use the distance from the center as
   // the length of the rope.  Then add length to it so that the box
   // can have at least one full swing which ever side it is on (left or
   // right half of the scene).
   float32 distToCenter = (fabs(scrSize.width/2 - (body->GetWorldCenter().x)*PTM_RATIO))/PTM_RATIO;
   jointDef.maxLength = distToCenter + (scrSize.width/2)/PTM_RATIO;
   world->CreateJoint(&jointDef);

   // Now for the last rope, other side of the scene.
   // Now create a second/third rope to "constrain" the swing.
   // These one will be attached to the side of the screen.
   b2Vec2 groundWorldPos3 = b2Vec2((scrSize.width)/PTM_RATIO,body->GetWorldCenter().y);
   b2Vec2 groundLocalPos3 = m_pGround->GetLocalPoint(groundWorldPos3);
   jointDef.localAnchorA = groundLocalPos3;
   world->CreateJoint(&jointDef);

If you modify the value of distToCenter, for example multiplying it by 0.5, you will see the box will quickly "snap" to the shortened swing and then "bounce" against the other rope length as it completes the swing. Overall, the physics looks about right. You can even add more boxes by tapping and see the whole thing bounce around (something like a Newton Pendulum).

You can not connect either of the ropes and the box will be able to swing further in that direction.

The entire code solution is posted on github here.

Was this helpful?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...