0

Okay, I have had a few questions floating around stackoverflow now, and most of them are related to this one question. I've been trying to get it myself, and I have a couple of times but the result is never quite what I expected. I am trying to develop a chain that my sprite can throw.

So far what I have done is thrown the lead of the hook from the centre of the sprite outward. Once it travels 10 pixels away from the sprites position it generates another link in the chain. The chain is then rotated to match the lead chains rotation and attached to it using a joint pin. It actually works fairly well. The only problem is it only works when I set the physics world speed to 0.01. If I return it to normal physics it throws the lead link in the chain but basically skips over everything else. Before this I tried containing the lead link in a physics body and calling a didEndContact to attach the other links but that didn't work nearly as well.

Does anyone have any ideas on how I can accomplish this? I just need the chain to extend from the sprites position, to a maximum length, and then afterwards retract. I had no idea it was going to be this difficult. Thank you in advance for all of your help, if you would like me to post my code I would be glad to, but considering I don't think it will work I haven't added it yet. Once again thank you very much in advance I have been racking my brain over this for weeks and it seems like I'm getting nowhere, although I have learnt many invaluable concepts which I am deeply appreciative to the stackoverflow community for.

Ryoku
  • 101
  • 1
  • 8
  • Have you considered drawing a line that extends, over time, from the sprite to the destination? – 0x141E Oct 06 '14 at 19:11
  • I would like to have rope physics implemented with the chain, but if it is the only way it might work I'm gonna have to take it. Would I be able to attach a physics body to the extending line as well? I so would I have to recreate the line and its physics body every frame in accordance with its length increase? – Ryoku Oct 13 '14 at 08:24
  • I created chains connected with SKPhysicsJointPins but was never happy with the way it interacted with other physics bodies. – 0x141E Oct 13 '14 at 08:28
  • I just posted an example of how to draw a line that can extend. – 0x141E Oct 13 '14 at 08:31

1 Answers1

1

This is a simple example of how to draw a line that is updated continuously...

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];

    startingPoint = positionInScene;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];

    // Remove temporary line if it exist
    [lineNode removeFromParent];

    CGMutablePathRef pathToDraw = CGPathCreateMutable();
    CGPathMoveToPoint(pathToDraw, NULL, startingPoint.x, startingPoint.y);
    CGPathAddLineToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);

    lineNode = [SKShapeNode node];
    lineNode.path = pathToDraw;
    CGPathRelease(pathToDraw);
    lineNode.strokeColor = [SKColor whiteColor];
    lineNode.lineWidth = 1;
    [self addChild:lineNode];
}

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];

    // Remove temporary line
    [lineNode removeFromParent];

    CGMutablePathRef pathToDraw = CGPathCreateMutable();
    CGPathMoveToPoint(pathToDraw, NULL, startingPoint.x, startingPoint.y);
    CGPathAddLineToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);

    SKShapeNode *finalLineNode = [SKShapeNode node];
    finalLineNode.path = pathToDraw;
    CGPathRelease(pathToDraw);
    finalLineNode.strokeColor = [SKColor redColor];
    finalLineNode.lineWidth = 1;
    [self addChild:finalLineNode];
}

EDIT: This method detects when a line, defined by points start and end, intersects with one or more physics bodies.

- (void) rotateNodesAlongRayStart:(CGPoint)start end:(CGPoint)end
{
    [self.physicsWorld enumerateBodiesAlongRayStart:start end:end
                    usingBlock:^(SKPhysicsBody *body, CGPoint point,
                                    CGVector normal, BOOL *stop)
    {
        SKNode *node = body.node;
        [node runAction:[SKAction rotateByAngle:M_PI*2 duration:3]];
    }];
}
0x141E
  • 12,613
  • 2
  • 41
  • 54
  • That is awesome thank you so much! For the chain to be effective though I am going to need to detect collisions with it. I am also going to have to specify collisions for the "head" of the chain with other objects. Should I do that by attaching a physics body to line (to detect collisions across its body) and then add an additional node at the front with its own phyiscs body (to represent the head). Or do you think this would give unpredictable physics results and/or dropped frame rate? – Ryoku Oct 13 '14 at 08:42
  • It depends on what you are trying to simulate. You could at a separate sprite at the head of the line and detect collisions with that. Why do you need to detect when the line collides with other physics bodies? – 0x141E Oct 13 '14 at 08:48
  • I want the line to sever if it comes into contact with certain objects – Ryoku Oct 13 '14 at 09:35
  • That works wonderfully thank you again. Now I only have one more task, and that is to find a way to effectively create the chain images along the line. That is I need to make the "links" to the chain and the "head" of the chain. I was thinking of just constructing nodes along the length of the line, but I am afraid because that would mean removing and reconstructing the nodes at each frame and I am worried that it might be too tasking for the application. What do you think? – Ryoku Oct 25 '14 at 23:22
  • You might want to consider drawing the chain by stringing together circles and lines, for example, 0-0-0-0-0. You can use bezier paths to create an image and then rotate the image from the top as the character swings with the chain. – 0x141E Oct 28 '14 at 06:47
  • Sorry for the very slow response. So I researched bezier paths and started using core graphics paths to construct the chain. Basically I have a for loop running the CGPathAddElipseInRect command for the number of links in the chain. It draws it perfectly fine. The only problem I am having is that after it is drawn, as long as it exists the framerate drops instantly from 60 fps to 45-50 fps. Is it suppose to be this expensive? – Ryoku Mar 22 '15 at 06:45