0
votes

I'm new to sprite kit and game physics in general. I want my character to stand up upright whenever he falls over or knocked down. A bit like a floor-mounted punch bag. Here's my current code:

#import "MyScene.h"

@interface MyScene () <SKPhysicsContactDelegate> {
    SKSpriteNode *_body;
    SKSpriteNode *_leg1;
    SKSpriteNode *_leg2;
    SKSpriteNode *_foot1;
    SKSpriteNode *_foot2;
}
@end

@implementation MyScene

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {

        //self.backgroundColor = [SKColor greenColor];

        self.physicsWorld.gravity = CGVectorMake(0, -2.0);
        self.physicsWorld.contactDelegate = self;
        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];

        SKSpriteNode *button = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(50, 50)];
        button.position = CGPointMake(40, 40);
        button.zPosition = 10;
        button.name = @"button";
        [self addChild: button];

        [self createCharacter];

    }
    return self;
}

-(void)createCharacter {

    // Add sprites

    _body = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(40, 60)];
    _body.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    [self addChild: _body];

    _leg1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(14, 60)];
    _leg1.position = CGPointMake(_body.position.x+20-7, _body.position.y-65);
    [self addChild:_leg1];

    _foot1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(20, 10)];
    _foot1.position = CGPointMake(_leg1.position.x-2.5, _leg1.position.y-40);
    [self addChild:_foot1];

    _leg2 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(14, 60)];
    _leg2.position = CGPointMake(_body.position.x-20+7, _body.position.y-65);
    [self addChild:_leg2];

    _foot2 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(20, 10)];
    _foot2.position = CGPointMake(_leg2.position.x-2.5, _leg2.position.y-40);
    [self addChild:_foot2];

    // Add physics bodies to sprites

    _body.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_body.size];

    _leg1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_leg1.size];
    _foot1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_foot1.size];
    _foot1.physicsBody.mass = 1;

    _leg2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_leg2.size];
    _foot2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_foot2.size];
    _foot2.physicsBody.mass = 0.5;

    // Add joints

    SKPhysicsJoint *hipJoint = [SKPhysicsJointFixed jointWithBodyA:_body.physicsBody bodyB:_leg1.physicsBody anchor:_leg1.position];
    SKPhysicsJoint *ankleJoint = [SKPhysicsJointFixed jointWithBodyA:_leg1.physicsBody bodyB:_foot1.physicsBody anchor:_foot1.position];

    SKPhysicsJointPin *hipJoint2 = [SKPhysicsJointPin jointWithBodyA:_body.physicsBody bodyB:_leg2.physicsBody anchor:CGPointMake(_leg2.position.x, CGRectGetMaxY(_leg2.frame))];
    [hipJoint2 setShouldEnableLimits:YES];
    [hipJoint2 setLowerAngleLimit:-M_PI_2];
    [hipJoint2 setUpperAngleLimit:0.0];
    SKPhysicsJoint *ankleJoint2 = [SKPhysicsJointFixed jointWithBodyA:_leg2.physicsBody bodyB:_foot2.physicsBody anchor:_foot2.position];

    [self.scene.physicsWorld addJoint:hipJoint];
    [self.scene.physicsWorld addJoint:ankleJoint];

    [self.scene.physicsWorld addJoint:hipJoint2];
    [self.scene.physicsWorld addJoint:ankleJoint2];

}

-(void)characterJump {

    CGFloat radianFactor = 0.0174532925;
    CGFloat rotationInDegrees = _body.zRotation / radianFactor;
    CGFloat newRotationDegrees = rotationInDegrees + 90;
    CGFloat newRotationRadians = newRotationDegrees * radianFactor;

    CGFloat r = 500;

    CGFloat dx = r * cos(newRotationRadians);
    CGFloat dy = r * sin(newRotationRadians);

    [_body.physicsBody applyImpulse:CGVectorMake(dx, dy)];

    NSLog(@"leg2 rotation: %f", _foot2.zRotation / radianFactor);
}

-(void)characterKick {
    NSLog(@"Kick..");
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];

    if ([node.name isEqualToString:@"button"]) {
        [self characterJump];
        [self characterKick];
    }
}

-(void)update:(CFTimeInterval)currentTime {

}

@end

Run the code and tap the button to make him jump and eventually fall over. Also, the joint limits don't work as it breaks through the limits sometimes.

Help would be really appreciated.

1
Can anybody help please? - shahidaltaf

1 Answers

1
votes

I resolved this issue by checking the _body SKSpriteNode's 'y' position in the scene's update method. If the 'y' position was below a certain limit, I applied an impulse to the body's physicsBody from below to stand it up again.

This worked as required/desired.

-(void)update:(CFTimeInterval)currentTime {
    if(_body.position.y < 30) {
        [self upOnYourFeet];
    }
}

-(void)upOnYourFeet {
    [_body.physicsBody applyImpulse:CGVectorMake(0, 80)];
}