0

Issue: A SKShapeNode sometimes doesn't draw the entire path. If it's moving each frame some frames it doesn't draw. In my real case scenario I'm using a very complex 10+ sided shape but for this demo I'm just doing a triangle. See screenshots for example (http://imgur.com/a/50mHA).

Code: See this in action by adding this to the basic template, or any scene, and move the mouse (finger) around. Some shapes show this glitching more than others but if you move around enough you'll see it on every shape.

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

    [self enumerateChildNodesWithName:@"path" usingBlock:^(SKNode *node, BOOL *stop) {
        [node removeFromParent];
    }];

    CGMutablePathRef p = CGPathCreateMutable();
    CGPathMoveToPoint(p, NULL, location.x-80, location.y-130);
    CGPathAddLineToPoint(p, NULL, location.x+80, location.y);
    CGPathAddLineToPoint(p, NULL, location.x-80, location.y+130);

    CGPathCloseSubpath(p);
    SKShapeNode *shape = [SKShapeNode node];
    shape.name = @"path";
    shape.path = p;
    shape.fillColor = [UIColor redColor];

    [self addChild:shape];
}

Any idea what's going on?

Edit: I wanted to add that the overall effect I'm trying to accomplish is dynamic lighting in a scene with physics bodies and a player (light source). I have used the information from http://ncase.me/sight-and-light/ to create a polygon. However as the player runs through the level, 99% of the time it works fine, except for that 1% where the shape glitches and doesn't draw completely. Which is what I'm showing in the example here.

ndomin
  • 428
  • 4
  • 11
  • Perhaps winding is an issue. In the example winding is clockwise, perhaps it should be counter-clockwise. Try it with the order of the points reversed, ie (-80,130),(80,0),(-80,-130) – CodeSmile May 15 '14 at 14:10
  • I think the example is counter-clockwise isn't it? Either way I tried your order and it still glitches. – ndomin May 15 '14 at 14:19
  • Uhm yes, I mixed that up. – CodeSmile May 15 '14 at 15:05

1 Answers1

1

OK, what you're doing here is very inefficient which is possibly why you're getting this effect.

What you should do is create a single shape node and store it in a property...

@property (nonatomic, strong) SKShapeNode *theShapeNode;

and when the scene loads you can create it once...

// in some method that runs once when the scene loads...

// path is relative to the shape node not the the scene it is in.
// by MOVING the shapeNode the path moves too.
CGMutablePathRef p = CGPathCreateMutable();
CGPathMoveToPoint(p, NULL, 0, -260);
CGPathAddLineToPoint(p, NULL, 160, 0);
CGPathAddLineToPoint(p, NULL, 0, 260);
CGPathCloseSubPath(p);

self.theShapeNode = [SKShapeNode node];
self.theShapeNode.path = p;
self.theShapeNode.fillColor = [UIColor redColor];
[self addChild:theShapeNode];

Then in the touches moved method...

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

    self.theShapeNode.position = location;
}

This means that each time the touch moves you're just repositioning the node that already exists. You're not having to create the path each time.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • Thanks for this. However the shape is dynamic and the body changes every frame so this won't work. I'll add more detail in the original question. – ndomin May 15 '14 at 14:20
  • You're changing body and shape every frame? Well as long as you don't do that to many bodies every frame, and for physics it depends on how you expect the constantly changing shape to behave (probably glitchy, too). – CodeSmile May 15 '14 at 15:06
  • Not the body sorry, mean the shape's path. the physics bodies don't change. the position of the light source does (see the edited original question). – ndomin May 15 '14 at 15:09