0

Okay, so I have a sprite, and I have a platform above it. The sprite starts at the point (0,scene.frame.size.height/2) and the platform at (scene.frame.size.width/2,scene.frame.size.height-10). So the sprite is on the left, and the platform is centred at the top of the screen.

I am going to apply a powerful impulse onto the sprite. Vector of the impulse will have an X but no Y. Basically I'm going to throw it right.

It should go underneath the platform, and it will. What I want it to do, is to follow a pendulum path with the pivot point being the platforms centre. More so, I want to force this path. Regardless of the objects x momentum I want it to have to swing along that pendulum path without just passing straight underneath it

If it helps picture swinging from a vine. I would like it to take into account the sprites speed before grabbing onto the vine, but unlike in the real world, I want it to force the sprite to plunge down on an angle and back up on an angle, through a pendulum like path.

I am having a hard time figuring out how I could go about something like this so any help would be greatly appreciated. I know that I will probably need a joint to connect the two, and that if it is all Y momentum I am worried about I could probably get away with just a limit joint, but its the enforcing the pendulum path and converting the momentum part that I am stuck on.

Thank you in advance for all of your help.

Ryoku
  • 101
  • 1
  • 8
  • if you need to enforce specific behavior you can't rely on using a physics simulation, much less if bodies will be colliding. Just try to make it work with as little deviation from the path as possible but expect the unexpected, don't expect physics to never ever do something you don't want it to do. It won't. – CodeSmile Oct 01 '14 at 07:36
  • From Apple's documentation, "An SKPhysicsJointPin object allows two physics bodies to independently rotate around the anchor point as if pinned together." – 0x141E Oct 01 '14 at 08:23

1 Answers1

2

Here's an example of how to implement an SKPhysicsJointPin:

-(id)initWithSize:(CGSize)size {

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

        CGPoint location = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);

        // Create the pendulum's pivot
        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:size];
        sprite.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];
        sprite.physicsBody.dynamic = NO;

        sprite.position = location;
        sprite.size = CGSizeMake(8, 8);

        [self addChild:sprite];

        location = CGPointMake(self.frame.size.width/2-100, self.frame.size.height/2);
        size = CGSizeMake(50, 200);

        // Create the pendulum's bob
        SKSpriteNode *sprite2 = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:size];
        sprite2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:sprite.size];
        sprite2.physicsBody.dynamic = YES;
        sprite2.physicsBody.affectedByGravity = YES;
        sprite2.physicsBody.linearDamping = 0;

        sprite2.physicsBody.mass = 0.1;

        sprite2.size = CGSizeMake(32, 32);
        sprite2.position = location;
        [self addChild:sprite2];

        CGPoint point = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);

        // Create a joint that connects the pivot and the bob
        SKPhysicsJointPin *pinJoint = [SKPhysicsJointPin jointWithBodyA:sprite.physicsBody
                                                                  bodyB:sprite2.physicsBody anchor:point];

        // Add the joint to the world
        [self.physicsWorld addJoint:pinJoint];
    }
    return self;
}
0x141E
  • 12,613
  • 2
  • 41
  • 54
  • This is perfect thank you very much. There is just one thing that it seems to be missing. I set sprite2's affectedByGravity property to NO for this test. I ran an action to give sprite2 an impulse with the vectors (10,0). The result was that the sprites didn't move at all. When I applied the same force downward it worked near perfectly. I then moved sprite 2 down 20 and then tried it. It worked, but the conversion was very low. It seems that it only converts a portion of the momentum depending on the angle. How could I go about ensuring all momentum is converted to pendulum momentum? – Ryoku Oct 03 '14 at 10:50
  • Do you think it might work if I was to make sure that the impulse being applied was at a 90 degree (0.5 radian) angle from sprite1 and sprite 2? If so, how would I recalculate the impulse to match the the given angle (basically how would I convert the impulse from 10,0 to whatever it needs to be to match the necessary angle)? – Ryoku Oct 03 '14 at 11:05
  • Yes, you will need to apply an impulse that is perpendicular to the angle from sprite and sprite2. I will update my answer when I get a chance. – 0x141E Oct 03 '14 at 20:05
  • I think I got it. I know it is going to require normalization of the distance from sprite1 to sprite2. After gathering the normalization I simply took the result, lets call it norm. And did something like this: `norm = CGPointMake(norm.y, norm.x)` (swapping the x value with the y value and vice versa). After getting the norm I just multiply the norm by a scalar that represents the impulse I want to impart. Is that in the ball park? It seems to work, but I haven't yet tested it under all situations. – Ryoku Oct 04 '14 at 18:42
  • I was looking at that last night. You will need to handle the cases where the pendulum's bob is in the different quadrants. – 0x141E Oct 04 '14 at 18:53
  • Why would I need to separate the quadrants? If I just swapped the x and y of the normalized length between the two sprites, wouldn't that be enough? If not, how would I go about handling the different quadrants? Thanks by the way for the help, I know I'm being a little needy right now. – Ryoku Oct 04 '14 at 18:57
  • No problem. If you apply an impulse in quadrant 1 (Q1), the impulse should be +dx and -dy (actually, -dy for all cases). If in Q2, it should be -dx and Q3: +dx and Q4: -dx. – 0x141E Oct 04 '14 at 19:05
  • I couldn't figure out how to do that without multiple "if" statements. – 0x141E Oct 04 '14 at 19:07
  • hm. I see, that is quite the predicament. Lets see. If I take the difference between the two like this: `CGPoint difference = CGPointMake(sprite1.position.x - sprite2.position.x, sprite1.position.y - sprite2.position.y)` and then found the length of that difference like so: `float length = sqrtf(difference.x*difference.x + difference.y*difference.y)`, then normalize the length like so: `CGPoint norm = CGPointMake(difference.x/length, difference.y/length`. Then swapped the x and y to make it perpendicular like so: `norm = CGPointMake(norm.y, norm.x)`. That should give -x in Q2 and Q3 I think? – Ryoku Oct 04 '14 at 19:28
  • Maybe you should take the absolute value for x and y, set y = -|y|, and set x = -|x| if in Q3 or Q4. – 0x141E Oct 04 '14 at 20:58
  • That sounds good, I'll give it a shot. Hey if you don't mind, since you've been so much amazing with this question I have another one posted here on stackoverflow, about extendible chains, here is a link: [How to Make an Extending Chain](http://stackoverflow.com/questions/26195900/how-to-make-an-extending-chain) thanks so much once again, you really have been wonderful. – Ryoku Oct 05 '14 at 18:43