[Solved]ChipmunkPro - Sync Sprites with Joints

Official forum for the Chipmunk2D Physics Library.
Nexus2911
Posts: 65
Joined: Wed Feb 15, 2012 12:28 am
Contact:

[Solved]ChipmunkPro - Sync Sprites with Joints

Post by Nexus2911 »

I have a truck with suspension made up of groove and spring joints. I want to sync a shock absorber (made up of two sprites - sleeve and piston) with those joints.

Because of the positioning of my wheels in relation to the chassis, the suspensions travels at roughly 45 degrees.

I realize that because my suspension is at an angle, not only will the piston sprite have to slide in and out of the sleeve sprite, but also the entire shock absorber with have to pivot as the spring joint compresses. Guess I made more work for myself - but I'm not setting for perpendicular shocks 8-)

What would be the best way to do this?

Partial Truck.m:(haven't done anything with shock sprites yet)

Code: Select all

 [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"sprites.plist"];
        chassis = [CCSprite spriteWithSpriteFrameName:@"st_chassis.png"];
        wheelFront =[CCSprite spriteWithSpriteFrameName:@"mt_front_wheel.png"];
        wheelRear =[CCSprite spriteWithSpriteFrameName:@"mt_rear_wheel.png"];
        shockPiston =[CCSprite spriteWithSpriteFrameName:@"mt_shock_piston.png"];
        shockSleve =[CCSprite spriteWithSpriteFrameName:@"mt_shock_piston.png"];

        
        cpFloat cMass = 5.0f;
        cpFloat cWidth = 172;
        cpFloat cHeight = 72;
        
        cpFloat radius = 45.0f;
        cpFloat mass = 5.0f;
        
        chassisBody = [ChipmunkCocosBody bodyWithMass:cMass andMoment:cpMomentForBox(cMass, cWidth, cHeight)];
        chassisBody.pos = pos;
        
        cpVect frontWheelPos = cpv( pos.x + cWidth/2, pos.y - radius*2);
        cpVect rearWheelPos = cpv(pos.x - cWidth/2, pos.y - radius*2);
        
        chassisShape = [ChipmunkPolyShape boxWithBody:chassisBody width:cWidth height:cHeight];
        chassisShape.friction = 0.7;
        chassisShape.group = self;
        
        wheelFrontBody = [ChipmunkCocosBody bodyWithMass:mass andMoment:cpMomentForCircle(mass, 0, radius, cpvzero)];
        wheelFrontBody.pos = frontWheelPos;
        
        wheelFrontShape = [ChipmunkCircleShape circleWithBody:wheelFrontBody radius:radius offset:cpvzero];
        wheelFrontShape.friction = 1.0;
        wheelFrontShape.group = self;
        
        
        wheelRearBody = [ChipmunkCocosBody bodyWithMass:mass andMoment:cpMomentForCircle(mass, 0, radius, cpvzero)];
        wheelRearBody.pos = rearWheelPos;
        
        wheelRearShape = [ChipmunkCircleShape circleWithBody:wheelRearBody radius:radius offset:cpvzero];
        wheelRearShape.friction = 1.0;
        wheelRearShape.group = self;
        
        float frontJointStartX = 50;
        float frontJointStartY = 16;
        
        float rearJointStartX = 50;
        float rearJointStartY = 10; 
        
        float jointEndY = 65;
        
        float frontSpringRestLength = jointEndY - frontJointStartY+30;
        float rearSpringRestLength = jointEndY - rearJointStartY+30;
        int springStiffness = 270;
        int damping = 3;
        
        int jointOffset = 57; //pushes wheel beyond jointStartX, giving us an angled connection to the chassis
        
        frontGroove = [ChipmunkGrooveJoint grooveJointWithBodyA:chassisBody 
                                                          bodyB:wheelFrontBody 
                                                       groove_a:cpv(frontJointStartX, -frontJointStartY) 
                                                       groove_b:cpv(frontJointStartX+jointOffset, -jointEndY) 
                                                         anchr2:cpvzero];
        
        rearGroove = [ChipmunkGrooveJoint grooveJointWithBodyA:chassisBody 
                                                         bodyB:wheelRearBody groove_a:cpv(-rearJointStartX, -rearJointStartY) 
                                                      groove_b:cpv(-rearJointStartX-jointOffset, -jointEndY) 
                                                        anchr2:cpvzero];
        
        sf = [ChipmunkDampedSpring dampedSpringWithBodyA:chassisBody 
                                                   bodyB:wheelFrontBody anchr1:cpv(frontJointStartX, -frontJointStartY) 
                                                  anchr2:cpvzero 
                                              restLength:frontSpringRestLength 
                                               stiffness:springStiffness 
                                                 damping:damping];
        
        sr = [ChipmunkDampedSpring dampedSpringWithBodyA:chassisBody 
                                                   bodyB:wheelRearBody 
                                                  anchr1:cpv(-rearJointStartX, -rearJointStartY) 
                                                  anchr2:cpvzero 
                                              restLength:rearSpringRestLength 
                                               stiffness:springStiffness 
                                                 damping:damping];

        
        

        chipmunkObjects = [[NSArray alloc] initWithObjects:
                           chassisBody,
                           chassisShape,
                           wheelFrontBody,
                           wheelFrontShape,
                           wheelRearBody,
                           wheelRearShape,
                           frontGroove,
                           rearGroove,
                           sf,
                           sr,
                           nil];
        
        
        sprites = [[NSArray alloc] initWithObjects:chassis, wheelFront, wheelRear, nil];
        chassisBody.syncedNodes = [NSArray arrayWithObject:chassis];
        wheelFrontBody.syncedNodes = [NSArray arrayWithObject:wheelFront];
        wheelRearBody.syncedNodes = [NSArray arrayWithObject:wheelRear];
Attachments
truck.png
truck.png (11.38 KiB) Viewed 8026 times
Last edited by Nexus2911 on Sun Jun 10, 2012 4:28 pm, edited 1 time in total.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by slembcke »

If you are using groove joints, there is no rotation though is there? Just translation along the groove.

You can get the anchor points from most joints using anchr1/anchr2, then convert those to world coordinates using the local2World: method on bodies. ex: cpVect anchrPos = [joint.bodyA local2World:joint.anchr1]

In this case it looks like you could just fix the sprite for the top part of the shock to the chassis (make it a sub sprite), and sync the bottom part to the wheel's center (change the anchor point of the sprite and it becomes trivial). Set the bottom shock's angle to match the chassis.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Nexus2911
Posts: 65
Joined: Wed Feb 15, 2012 12:28 am
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by Nexus2911 »

Correct - translation along the groove only - my mistake.

The following code will start the sleeve in the correct position but will obviously rotate the sleeve with the wheel:

Code: Select all

 wheelFrontBody.syncedNodes = [NSArray arrayWithObjects:wheelFront, shockSleve, nil];
        shockSleve.anchorPoint = ccp(0, -1);
        shockSleve.rotation = 45;
Can I somehow lock down the rotation while still taking advantage of ChipmunkCocosBody's syncedNodes?

Note:

I was looking in ChipmunkPro's documentation and noticed ChipmunkCocosBody(CCB) wasn't included. I see that class provides the syncedNodes property which facilitates updating the sprites position and rotation with a given body.

I also see that in AngryChipmunks (AC), the CCB class is in a folder called "Other Sources". So part of my issues was that I wasn't seeing the dividing line between ChipmunkPro library and syncedNodes.

It makes sense to me that CCB wouldn't be part of Chipmunk Pro library itself - because CCB (together with GameObject.m from AC demo) ties the sprites and bodies together. Not including it makes CP more conforming to the Model in the MVC pattern, correct?
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by jcmeyer5 »

I may be way out in left field, but couldn't you constrain the top of the piston to the top of the sleeve, and the bottom of the piston to the bottom of the sleeve? And then also anchor the top of the sleeve to the chassis, and the bottom of the piston to the wheel? If it retains the shortest distances between each point, then they should always be in line. I wouldn't try to link them to the constraints that are actually controlling the suspension... since this is a visual issue only, they need just enough constraint to keep them in line.

My 5th post... I might be crazy. :)
Chipmunk Pro and cocos2D 2.x branch for iOS development
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by slembcke »

Oh, I totally missed this post. :-\

ChipmunkCocosBody isn't part of Chipmunk Pro, it's just a utility class I made to help it work better with Cocos2D. I've actually modified it slightly for the current project that I'm working on to provide both a list of synced nodes, and a list of position only nodes. It was really just a bit of copy pasting.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Nexus2911
Posts: 65
Joined: Wed Feb 15, 2012 12:28 am
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by Nexus2911 »

Actually, the shock absorbers are upside down.

The shock pistons and chassis are now one image - so now I only have to be concerned with syncing the shock sleeve with the compression of the spring or the X and Y position of the center of the wheel.

In fact, the sleeve doesn't really need to be a physics node, although it my be nice for it to be part of the physics in case I have the truck parts interact with other nodes.
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by jcmeyer5 »

slembcke wrote:Oh, I totally missed this post. :-\

ChipmunkCocosBody isn't part of Chipmunk Pro, it's just a utility class I made to help it work better with Cocos2D. I've actually modified it slightly for the current project that I'm working on to provide both a list of synced nodes, and a list of position only nodes. It was really just a bit of copy pasting.
I am trying to follow the whole synced nodes concept, but before that, I really need to understand how the sprites are being linked to the bodies. I am looking through Angry Chipmunks. What I don't see is where the sprites are linked to the bodies. Typically I would expect a plist telling me where each image is in the image file. I see where the image file is loaded, however I don't see where the individual images are assigned to the bodies.
Chipmunk Pro and cocos2D 2.x branch for iOS development
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by jcmeyer5 »

I see it now. You are using coordinates from the file to select a space in the file. Okay. so you are explicitly assigning them to shapes. I got it now. So the syncNode is to update the sprite positions only... not to associate them with shapes.

Awesome.
Chipmunk Pro and cocos2D 2.x branch for iOS development
Nexus2911
Posts: 65
Joined: Wed Feb 15, 2012 12:28 am
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by Nexus2911 »

Ok, I've left this issue for a bit but now I'm revisiting.

Yes, I can get a wheel's X and Y coord by using:

Code: Select all

cpVect wheelFrontAnchrPos = [springFront.bodyB local2world:springFront.anchr2];
But that is only the initial value - not a constant sync'd value.

I don't want to have to reach outside my truck class to my main tick method to sync this node.

This has GOT to be simple, what am I missing?

I'm not even dealing with sprites at this point - so I'm just trying to get to the point where i have a square body (shock sleeve)synched along the wheel to chassis groove joint, matching my wheel's X and Y position. (Y only if my shocks were perpendicular to the chassis). Once i get the body synched, I can add the sprite.
As such, here's an excerpt of my Truck.m (absolute min. test case - only Y synching needed here ):

Code: Select all

-(id)initWithPos:(CGPoint)pos{
    
    if (self = [super init]) {

    
        cpFloat cMass = 3.0f;
        cpFloat cWidth = 234;
        cpFloat cHeight = 63;

        cpFloat radius = 33.0f;
        cpFloat mass = 2.0f;

        float friction = 1.0f;

        chassisBody = [ChipmunkCocosBody bodyWithMass:cMass andMoment:cpMomentForBox(cMass, cWidth, cHeight)];
        chassisBody.pos = pos;

        cpVect frontWheelPos = cpv( pos.x + cWidth/2, pos.y - radius*2);
        cpVect rearWheelPos = cpv(pos.x - cWidth/2, pos.y - radius*2);

        chassisShape = [ChipmunkPolyShape boxWithBody:chassisBody width:cWidth height:cHeight];
        chassisShape.friction = 0.7;
        chassisShape.group = self;

        wheelFrontBody = [ChipmunkCocosBody bodyWithMass:mass andMoment:cpMomentForCircle(mass, 0, radius, cpvzero)];
        wheelFrontBody.pos = frontWheelPos;

        wheelFrontShape = [ChipmunkCircleShape circleWithBody:wheelFrontBody radius:radius offset:cpvzero];
        wheelFrontShape.friction = friction;
        wheelFrontShape.group = self;

        wheelFrontBody = [ChipmunkCocosBody bodyWithMass:mass andMoment:cpMomentForCircle(mass, 0, radius, cpvzero)];
        wheelFrontBody.pos = frontWheelPos;

        wheelFrontShape = [ChipmunkCircleShape circleWithBody:wheelFrontBody radius:radius offset:cpvzero];
        wheelFrontShape.friction = friction;
        wheelFrontShape.group = self;


        wheelRearBody = [ChipmunkCocosBody bodyWithMass:mass andMoment:cpMomentForCircle(mass, 0, radius, cpvzero)];
        wheelRearBody.pos = rearWheelPos;

        wheelRearShape = [ChipmunkCircleShape circleWithBody:wheelRearBody radius:radius offset:cpvzero];
        wheelRearShape.friction = friction;
        wheelRearShape.group = self;

        float frontJointStartX = cWidth/2;
        float frontJointStartY = -5;
            
        float rearJointStartX = -cWidth/2;
        float rearJointStartY = 5; 

        float jointEndY = -(radius + radius / 2 +30);

        int springPressure = 20;

        float frontSpringRestLength = -jointEndY - frontJointStartY + springPressure;
        float rearSpringRestLength = -jointEndY - rearJointStartY + springPressure;

        int springStiffness = 10;
        int damping = 5;

        int frontJointOffset = 0;
        int rearJointOffset = 0; 


        frontGroove = [ChipmunkGrooveJoint grooveJointWithBodyA:chassisBody 
                                                          bodyB:wheelFrontBody 
                                                       groove_a:cpv(frontJointStartX, frontJointStartY) 
                                                       groove_b:cpv(frontJointStartX+frontJointOffset, jointEndY) 
                                                         anchr2:cpvzero];


        rearGroove = [ChipmunkGrooveJoint grooveJointWithBodyA:chassisBody 
                                                         bodyB:wheelRearBody groove_a:cpv(rearJointStartX, rearJointStartY) 
                                                      groove_b:cpv(rearJointStartX-rearJointOffset, jointEndY) 
                                                        anchr2:cpvzero];

        springFront = [ChipmunkDampedSpring dampedSpringWithBodyA:chassisBody 
                                                   bodyB:wheelFrontBody anchr1:cpv(frontJointStartX, frontJointStartY) 
                                                  anchr2:cpvzero 
                                              restLength:frontSpringRestLength 
                                               stiffness:springStiffness 
                                                 damping:damping];

        springRear = [ChipmunkDampedSpring dampedSpringWithBodyA:chassisBody 
                                                   bodyB:wheelRearBody 
                                                  anchr1:cpv(rearJointStartX, rearJointStartY) 
                                                  anchr2:cpvzero 
                                              restLength:rearSpringRestLength 
                                               stiffness:springStiffness 
                                                 damping:damping];

        motorFront = [ChipmunkSimpleMotor simpleMotorWithBodyA:wheelFrontBody bodyB:chassisBody rate:-1];


        chipmunkObjects = [[NSArray alloc] initWithObjects:
                           chassisBody,
                           chassisShape,
                           wheelFrontBody,
                           wheelFrontShape,
                           wheelRearBody,
                           wheelRearShape,
                           frontGroove,
                           rearGroove,
                           springFront,
                           springRear,
                           motorFront,
                           nil];
            
        }
    
    return self;
}

Last edited by Nexus2911 on Sun Jun 10, 2012 1:14 pm, edited 1 time in total.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: ChipmunkPro - Sync Sprites with Joints

Post by slembcke »

Oooh. Took me a minute to figure out what you were asking. Fortunately I made an example just a day or two ago that explains what you want to do: https://github.com/slembcke/SpacePatrol ... ggy.m#L299

It's using the Cocos2D 2.0 beta, but you should get the idea.

This is the best way that I know how to do this as it ensures that the graphics for a complex mechanical system always look correct without requiring that the underlying physical model be complex. It does require you to manually sync the sprites though and to understand how exactly to do it. Alternatively, you could make a CCSprite subclass that references the wheel and chassis bodies and schedules it's own update method. That seems like it would be more work to me though.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests