Introduction
In this brief article we’ll be taking a look at an efficient way of creating ropes in our cocos2d games that use box2d, starting from a cocos2s+box2d template project.
We will be using box2d’s latest addition, the b2RopeJoint to constrict two bodies with a rope joint (a maximum distance joint, one might also call it), so as always big thanks to Erin Catto for all his hard work on box2d.
We will also be using a small set of classes I wrote, VRope, that use Verlet integration to calculate the points of the rope, using a CCSpriteBatchNode to visually draw the rope in our game.
It’s worth mentioning that using Box2D isn’t strictly necessary, you could still use the VRope class to draw a rope between two given points in other scenarios (for example using Chipmunk, your own physics system, or simply updating the two points manually) and have it react under gravity. With that in mind, the class also has some helper methods to use it with CGPoints only. (somethingWithPoints methods)
Setting up the project
First things first, make sure you have the latest version of Cocos2D and create a new project with the “Cocos2d Box2d Application” template. You will then need to update Box2D to the latest committed version, which you can find at http://code.google.com/p/box2d/source/checkout
To update Box2D in your current project:
- From within XCode, delete the Box2D folder group from the “cocos2d Sources” folder (Delete References)
- From Finder, go to your project’s folder and delete the Box2D folder
- Copy over the latest version of Box2D back into your project’s folder (make sure you only copy the most deep rooted “Box2D” folder, and delete CMakeLists.txt and Box2DConfig.cmake)
- Back to XCode, Project -> Add to Project, select the Box2D folder, make sure create groups (not folder reference) is selected, Add
This should give you a working Cocos2D project, updated with the latest Box2D source that has the b2RopeJoint ready to use.
If you’re not running the latest version of cocos2d (0.99.5-rc0) but still want to use VRope, you’ll need to rename CCSpriteBatchNode back to CCSpriteSheet, the rest should work as is.
Using b2RopeJoint
Using the new b2RopeJoint is very easy, it’s similar to the b2DistanceJoint, but unlike other joints it doesn’t have an Initialize method.
//define rope joint, params: two b2bodies, two local anchor points, length of rope b2RopeJointDef jd; jd.bodyA=body1; //define bodies jd.bodyB=body2; jd.localAnchorA = b2Vec2(0,0); //define anchors jd.localAnchorB = b2Vec2(0,0); jd.maxLength= (body2->GetPosition() - body1->GetPosition()).Length(); //define max length of joint = current distance between bodies world->CreateJoint(&jd); //create joint
Verlet Integration
Now that we know how to constrict two bodies with a rope joint, we need to find an elegant and efficient way of drawing the rope, drum roll, enter screen right: Verlet integration.
The implementation you’ll find below is based on a very informative tutorial by YoAmbulante.com (for Flash) that allowed even a simple minded person such as myself to grasp the basic concepts of Verlet integration, so big thanks to the author of that tutorial.
The “Verlet integration” consists in dots and links between these dots where each dot has remembered which was its previous position to determine its next step, the new position of x is equal to x + x – previous_x (same for y) and then each of these dots are associated (grouped) by pairs that try to keep same distance between each other as they were when the program started.
Based on this, I decided to design 3 classes (rather than use structs, each to his own)
- VPoint – store a point’s current and previous position
- VStick – connect two VPoints and keep them at constant distance
- VRope – keeps arrays of VPoints and VSticks, update logic, CCSpriteBatchNode to render rope
Rather than go trough all the source code, we’ll be taking a look at how to implement it into our test project.
In the main header file (VRope.h) you can find instructions on usage, and the code is slightly commented and easy to understand, so more advanced users could easily adapt it further to their own needs.
Using VRope
Download the VRope class here, unzip, copy it over to your project’s folder and add it to your project from XCode.
First, you’ll want to import VRope.h into HelloWorldScene.h
#import "VRope.h"
Still in the HelloWorldScene.h file, add these lines in the @interface declaration:
b2Body* anchorBody; //reference to anchor body CCSpriteBatchNode* ropeSpriteSheet; //sprite sheet for rope segment NSMutableArray* vRopes; //array to hold rope references
Now we’ll add some code to our main class, HelloWorldScene.mm.
In the init method of HelloWorldScene, remove the creation of the groundBody and all it’s shapes and in it’s place add:
// +++ Add anchor body b2BodyDef anchorBodyDef; anchorBodyDef.position.Set(screenSize.width/PTM_RATIO/2,screenSize.height/PTM_RATIO*0.7f); //center body on screen anchorBody = world->CreateBody(&anchorBodyDef); // +++ Add rope spritesheet to layer ropeSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"rope.png" ]; [self addChild:ropeSpriteSheet]; // +++ Init array that will hold references to all our ropes vRopes = [[NSMutableArray alloc] init];
In the addNewSpriteWithCoords method, add these lines at the bottom:
// +++ Create box2d joint b2RopeJointDef jd; jd.bodyA=anchorBody; //define bodies jd.bodyB=body; jd.localAnchorA = b2Vec2(0,0); //define anchors jd.localAnchorB = b2Vec2(0,0); jd.maxLength= (body->GetPosition() - anchorBody->GetPosition()).Length(); //define max length of joint = current distance between bodies world->CreateJoint(&jd); //create joint // +++ Create VRope VRope *newRope = [[VRope alloc] init:anchorBody body2:body spriteSheet:ropeSpriteSheet]; [vRopes addObject:newRope];
In the draw method, add these lines at the bottom:
// +++ Update rope sprites
for(uint i=0;i<[vRopes count];i++) {
[[vRopes objectAtIndex:i] updateSprites];
}
In the tick method, add these lines at the bottom:
// +++ Update rope physics
for(uint i=0;i<[vRopes count];i++) {
[[vRopes objectAtIndex:i] update:dt];
}
Copy rope.png to your Resources folder and add it to your project (rope.png can be found in the archive of the test project below)
Build & Run! If all went well, you should have the same result as the video at the beginning of the article.
As I mentioned at the beginning, the code is very simple and fast (no thanks to me), so adapting it to other uses should be pretty simple.
Downloads
VRope class
Cocos2D VRope Test Project
About the author
I’ve been using cocos2d for over a year and a half and I’m a regular on the forums, so feel free to ask questions in the thread about VRope.
The VRope class was originally created to be used in Paper Bridge, a physics based bridge construction puzzle game developed by Clever Hamster Games (aka: me).







Thanks a lot for sharing this!
Marco
Great Work patrick it looks great!
Thanks for sharing this!
GGGGGGGOOOOOOOOOOOODDDDDDDDDDDDDDD!!!!!!!!! THANKSSSSSSSSSSSSSSSS!!!!!!!!!!!!!!!!!!!!!!!!!!
Thanks for sharing this!! Great implementation of Rope Physics
Hi, I’m so glad you found useful that “verlet integration” article. It is very interesting what you have done here, Wicked! I like the boxes collisions mixing concept. I did something similar a while ago applying different forces to the rope and linking the dots by using spline curves, the result is a bit interesting http://www.yoambulante.com/en/labs/balloon.php thank you very much for sharing.
Thanks for the article,
I seem to get a double rope when Retina is enabled. Any idea as to how to adjust this? I’ve looked around and played with a few settings and i only mange to remove one but have the rope off center.
A quick fix was to change the following in VRope:
[[[spriteSheet textureAtlas] texture] pixelsHigh]
I changed it to match my image height… 8
Why it keeps swinging…? It’s unrealistic.
Hi:
Thanks so much for this tuto-implementation. It’s just great.
Are there any plans to include VRope as a class in Cocos2D? Is better one you have everything in one single package and I was wondering that.
Sry for doble posting but I forgot this:
I see in the code above you do “alloc init” y some VRopes, it is necessary to do an autorelease there? or how is the memory management done for this objects?
Thanks!
Great rope app! Love it. I am new to cocos2d, if anyone can help with one simple question, I would be much appreciated. I see there is a function to remove the ropes. I remove the ropes but the letter blocks still stay there. I tried to remove all children but when i do that, the app just exists. Can anyone shine some light on how to remove all the ropes and letter blocks? I would like to create a button to RESET and have the one rope there. Thanks in advance!
Dave
Thanks for Providing such a wonderful code free of cost!
I have gone through your game its fabulous.
Please Answer ASAP!
I have a doubt regarding this Rope.
Suppose i want it to anchor it to some body . i can do it very easily I know.
But problem is rope always anchored in center of the body.I want to tight one end on edge of rectangle and other end on the center of cube.
Regards,
Narender badsara
how would i go about replacing the anchorBodyDef to a sprite instead of having it on a set point?
Plz help it is not solved yet!
For last 3 days i stuck on this particular problem..
Example:
One cuboid like a rod… long rod…
i want to tie a rope on that end …same as we use for fishing…
Problem is .
How to tie on extreme end for bodyA.I am using the same varlet code for reference…
I am able to tie it on the middle of rod but i want it on extreme end.
I used anchor point for this,but found no success..
Please suggest me!
//define rope joint, params: two b2bodies, two local anchor points, length of rope
b2RopeJointDef jd;
jd.bodyA=body1; //define bodies
jd.bodyB=body2;
jd.localAnchorA = b2Vec2(5,0); //define anchors
jd.localAnchorB = b2Vec2(0,0);
jd.maxLength= (body2->GetPosition() – body1->GetPosition()).Length(); //define max length of joint = current distance between bodies
world->CreateJoint(&jd); //create joint
It will Work bro!
use it
Here You can put But problem here is rope is always connected to the center of the rod.
Can anybody help how to translate
VRope *newRope = [[VRope alloc] init:anchorBody body2:body spriteSheet:ropeSpriteSheet];
[vRopes addObject:newRope];
it takes anchorbody center coordinate to make a rope not deal with anchor point… hw to handle it so that rope starts with rope’s anchor point
@narender badsara
I was able to fix this problem in the library… just need to replace the lines:
CGPoint pointA = ccp(bodyA->GetPosition().x*PTM_RATIO,bodyA->GetPosition().y*PTM_RATIO);
CGPoint pointB = ccp(bodyB->GetPosition().x*PTM_RATIO,bodyB->GetPosition().y*PTM_RATIO);
in functions init, reset and update in the file VRope.mm for these new ones:
CGPoint pointA = ccp(bodyA->GetJointList()->joint->GetAnchorA().x*PTM_RATIO,
bodyA->GetJointList()->joint->GetAnchorA().y*PTM_RATIO);
CGPoint pointB = ccp(bodyA->GetJointList()->joint->GetAnchorB().x*PTM_RATIO,
bodyA->GetJointList()->joint->GetAnchorB().y*PTM_RATIO);
And it will take the correct anchor points.
To slow down the swinging, give some linearDamping to the box:
bodyDef.linearDamping = 0.2;
Hello Patrick,
First, thank you very much for what you’ve done and provided to the community here. It’s probably the single good reference for Verlet Rope integration on the web.
Second, I do unfortunately have a question. I am probably being a good bit retarded, but for the life of me I can’t figure out why I’m having this particular issue:
I’m re-creating the verlet rope (to achieve the proper number of segments) on touch, and passing the touch location and the player’s body as the two points to attach between. The problem I’m having, is the rope is attaching to the complete opposite end of where the touch is designated on the y axis. So, if say, a touch occurs at 240, 320 (iPhone), the attachment appears to happen at 240,0, and the other end successfully attaches to the player’s body.
Not that it matters a whole lot, but I’m using Chipmunk (and the initwithpoints method).
If you have the time, would you mind shedding some light on the issue? (If possible)
I’ll continue to dig in the meantime.
Thank you for your time, have a wonderful afternoon.
-Tagger
I would just like to say that it was due to my own retardation. I figured it out. Thank you very much again.
how can i make the rope to be flexible???
Wow geat info! I have also an addition to dinghing’s question about rope flexibility – how can we manage to adjust the gravitation and is it possible at all?
Hi,
I want to cut this rope by swiping gesture.
Can you please discuss this, it can really bring so many new games in the market.
Regards,
Paresh
hi,
i also want to know about rope cutting.
can any one give any idea about rope cutting
regards,
venkat
Hello,
I want to do two tasks :
1. Keep the rope swinging for infinite times even if accelerometer does not change.
2. Reset the ropes so if I have added more than one ropes in parallel, they move in opposite direction in alternative manner.
Please help me ASAP.
Thanks,
Nishant
Hey,
It seems link doesn’t work.
Where I can VRope class?
Thanks
can u help me to make make a body for the rope so the rope can collide with another body ?
ah, for you who searching sample to cut a rope by swiping, check this site : http://muhammedalee.wordpress.com/2011/08/21/cut-the-rope-like-rope-shooter/
can anyone please help me get a free hanging rope with no body. I followed the instructions but it’s not working. Thanks in advance!
怎么切割绳子呢,谢谢
how to make an elastic rope effect
hi,
we’re using a modified VRope 0.4 in our latest game (Bee Leader, http://www.flightless.co.nz/beeleader) so we’ve put the changes up on github at https://github.com/mb1/VRope.
Changes include initialising a rope using a b2RopeJoint (instead of two bodies), allowing for changing gravity, and a retina fix (tested on iPhone4s and iPad 3).
There’s still some testing, cleanup and other changes to be done, but it’s working. Thanks to patrickC for the original code and tutorial.
cheers,
// greg
greg@flightless.co.nz
Hi,
We created a port of vrope 0.4 to cocos2d-x / c++ if anybody is interested. Can be found in github at https://github.com/teemukorh/VRope-x
Hello everyone and thanks for the verlet rope !
Is it possible to animate sprites which are used in the CCSpriteBatchNode?
Thanks !
Anyone tried to make such a rope stretchy yet?
how to join the rope to two blocks in a straight line and cut it. y we are creating sprite sheets for ropes.
I implemented this https://github.com/mb1/VRope
It seems that whenever I tap the anchor area (top of the rope), the app crashes.
Hi,how can I get the start position of rope. I want to change the location of it,and create lot of rope in different first position.Thanks!
Thank you very much Erin Catto and other guys for everythings…