I try to convert a game which I started with SpriteKit to Cocos2d V3. I have some problems with the physics though. I create a human like playing figure. The limbs are connected via PinJoints in SpriteKit. I recreated that basic functionality via PivotJoints in Chipmunk. That works as expected.
But I need to add some friction to the joints. Right now they just rotate as fast as possible and even more important I need to limit the rotation angle of the joints. As you can imagine, most people can’t rotate their shoulders freely by 360 degrees. ;)
AFAIK I should use ChipmunkRotaryLimitJoint and ChipmunkGearJoint to achieve that. My problem is, that I can’t make it work because I don’t know how to attach them correctly. This is my code right now:
- (CCPhysicsJoint *)createPinJointWithBodyA:(CCPhysicsBody *)bodyA
                                      bodyB:(CCPhysicsBody *)bodyB
                                     anchor:(CGPoint)anchor
                                   friction:(CGFloat)friction
                                 lowerLimit:(CGFloat)lowerLimit
                                 upperLimit:(CGFloat)upperLimit
{
    CCPhysicsJoint *pin = [CCPhysicsJoint 
        connectedPivotJointWithBodyA:bodyA
                               bodyB:bodyB
                             anchorA:anchor];
    ChipmunkRotaryLimitJoint *limitJoint = [ChipmunkRotaryLimitJoint 
        rotaryLimitJointWithBodyA:bodyA.body 
                            bodyB:bodyB.body
                              min:CC_DEGREES_TO_RADIANS(lowerLimit)
                              max:CC_DEGREES_TO_RADIANS(upperLimit)];
    ChipmunkGearJoint *gearJoint = [ChipmunkGearJoint 
        gearJointWithBodyA:bodyA.body
                     bodyB:bodyB.body
                     phase:0.5
                     ratio:0.5];
    return pin;
}
(The values in the gearJoint call are just place holders!)
Does anybody have an idea how this is supposed to work? I found some things via Google, but all tutorials assume, that I use chipmunk in some other environment. Do I have to create my own CCPhysicJoint implementation for these limit and gear joints?
Thanks and best wishes, Thomas
I think I solved this problem. It turned out I had to create my own CCPhysicsJoint Category that implements the ChipmunkRotaryLimitJoint and a ChipmunkRotaryDampedSpring. It’s not exactly the same but it works good enough for now.
The code looks like this right now:
[CCPhysicsJoint connectedRotaryLimitJointWithBodyA:bodyA
                                             bodyB:bodyB
                                               min:CC_DEGREES_TO_RADIANS(lowerLimit)
                                               max:CC_DEGREES_TO_RADIANS(upperLimit)];
[CCPhysicsJoint connectedDampedRotarySpringWithBodyA:bodyA
                                               bodyB:bodyB
                                           restAngle:0
                                           stiffness:friction *1000.0f
                                             damping:10000.0f];
I just asked if this should be included in the Cocos2D codebase. For the time being, this is the wrapper:
CCPhysicsJoint+THCAdditions.h
//
//  CCPhysicsJoint+THCAdditions.h
//
//  Created by Thomas Hempel on 02.02.14.
//  Copyright (c) 2014 Thomas Hempel. All rights reserved.
//
#import "CCPhysicsBody.h"
#import "CCPhysicsJoint.h"
@interface CCPhysicsJoint (THCAdditions)
+ (CCPhysicsJoint *)connectedRotaryLimitJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB min:(CGFloat)min max:(CGFloat)max;
+ (CCPhysicsJoint *)connectedGearJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB phase:(CGFloat)phase ratio:(CGFloat)ratio;
+ (CCPhysicsJoint *)connectedSimpleMotorJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB rate:(CGFloat)rate;
+ (CCPhysicsJoint *)connectedDampedRotarySpringWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB restAngle:(CGFloat)restAngle stiffness:(CGFloat)stiffness damping:(CGFloat)damping;
@end
CCPhysicsJoint+THCAdditions.m
//
//  CCPhysicsJoint+THCAdditions.m
//
//  Created by Thomas Hempel on 02.02.14.
//  Copyright (c) 2014 Thomas Hempel. All rights reserved.
//
#import "CCPhysicsJoint+THCAdditions.h"
#import "CCPhysics+ObjectiveChipmunk.h"
// ------------------------------------------------------------------------
#pragma mark - Rotary Limit Joint
// ------------------------------------------------------------------------
@interface CCPhysicsRotaryLimitJoint : CCPhysicsJoint
@end
@implementation CCPhysicsRotaryLimitJoint {
    ChipmunkRotaryLimitJoint *_constraint;
}
- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB min:(CGFloat)min max:(CGFloat)max
{
    if ((self = [super init])){
        _constraint = [ChipmunkRotaryLimitJoint rotaryLimitJointWithBodyA:bodyA.body
                                                                    bodyB:bodyB.body
                                                                      min:min
                                                                      max:max];
        _constraint.userData = self;
    }
    return self;
}
- (ChipmunkConstraint *)constraint
{
    return _constraint;
}
- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}
@end
// ------------------------------------------------------------------------
#pragma mark - Gear Joint
// ------------------------------------------------------------------------
@interface CCPhysicsGearJoint : CCPhysicsJoint
@end
@implementation CCPhysicsGearJoint {
    ChipmunkGearJoint *_constraint;
}
- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB phase:(CGFloat)phase ratio:(CGFloat)ratio
{
    if ((self = [super init])){
        _constraint = [ChipmunkGearJoint gearJointWithBodyA:bodyA.body
                                                      bodyB:bodyB.body
                                                      phase:phase
                                                      ratio:ratio];
        _constraint.userData = self;
    }
    return self;
}
- (ChipmunkConstraint *)constraint
{
    return _constraint;
}
- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}
@end
// ------------------------------------------------------------------------
#pragma mark - Simple Motor Joint
// ------------------------------------------------------------------------
@interface CCPhysicsSimpleMotorJoint : CCPhysicsJoint
@end
@implementation CCPhysicsSimpleMotorJoint {
    ChipmunkSimpleMotor *_constraint;
}
- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB rate:(CGFloat)rate
{
    if ((self = [super init])){
        _constraint = [ChipmunkSimpleMotor simpleMotorWithBodyA:bodyA.body
                                                          bodyB:bodyB.body
                                                           rate:rate];
        _constraint.userData = self;
    }
    return self;
}
- (ChipmunkConstraint *)constraint
{
    return _constraint;
}
- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}
@end
// ------------------------------------------------------------------------
#pragma mark - Damped Rotary Spring
// ------------------------------------------------------------------------
@interface CCPhysicsDampedRotarySpring : CCPhysicsJoint
@end
@implementation CCPhysicsDampedRotarySpring {
    ChipmunkDampedRotarySpring *_constraint;
}
- (id)initWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB restAngle:    (CGFloat)restAngle stiffness:(CGFloat)stiffness damping:(CGFloat)damping
{
    if ((self = [super init])){
        _constraint = [ChipmunkDampedRotarySpring dampedRotarySpringWithBodyA:bodyA.body
                                                                        bodyB:bodyB.body
                                                                    restAngle:restAngle
                                                                    stiffness:stiffness
                                                                      damping:damping];
        _constraint.userData = self;
    }
    return self;
}
- (ChipmunkConstraint *)constraint
{
    return _constraint;
}
- (void)willAddToPhysicsNode:(CCPhysicsNode *)physics
{
}
@end
// ------------------------------------------------------------------------
#pragma mark - Implementation
// ------------------------------------------------------------------------
@implementation CCPhysicsJoint (THCAdditions)
+ (CCPhysicsJoint *)connectedRotaryLimitJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB min:(CGFloat)min max:(CGFloat)max
{
    CCPhysicsJoint *joint = [[CCPhysicsRotaryLimitJoint alloc] initWithBodyA:bodyA bodyB:bodyB min:min max:max];
    [bodyA addJoint:joint];
    [bodyB addJoint:joint];
    [bodyA.physicsNode.space smartAdd:joint];
    return joint;
}
+ (CCPhysicsJoint *)connectedGearJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB phase:(CGFloat)phase ratio:(CGFloat)ratio
{
    CCPhysicsJoint *joint = [[CCPhysicsGearJoint alloc] initWithBodyA:bodyA bodyB:bodyB phase:phase ratio:ratio];
    [bodyA addJoint:joint];
    [bodyB addJoint:joint];
    [bodyA.physicsNode.space smartAdd:joint];
    return joint;
}
+ (CCPhysicsJoint *)connectedSimpleMotorJointWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB rate:(CGFloat)rate
{
    CCPhysicsJoint *joint = [[CCPhysicsSimpleMotorJoint alloc] initWithBodyA:bodyA bodyB:bodyB rate:rate];
    [bodyA addJoint:joint];
    [bodyB addJoint:joint];
    [bodyA.physicsNode.space smartAdd:joint];
    return joint;
}
+ (CCPhysicsJoint *)connectedDampedRotarySpringWithBodyA:(CCPhysicsBody *)bodyA bodyB:(CCPhysicsBody *)bodyB restAngle:(CGFloat)restAngle stiffness:(CGFloat)stiffness damping:(CGFloat)damping
{
    CCPhysicsJoint *joint = [[CCPhysicsDampedRotarySpring alloc] initWithBodyA:bodyA bodyB:bodyB restAngle:restAngle stiffness:stiffness damping:damping];
    [bodyA addJoint:joint];
    [bodyB addJoint:joint];
    [bodyA.physicsNode.space smartAdd:joint];
    return joint;
}
@end
Best wishes, Thomas
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With