Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve this animation with Spritekit?

Question:

How to achieve this animation with Spritekit?

enter image description here

What I've done:

enter image description here

Problem:

1) I can draw all four petals,but once I lift my finger to draw the circle, it will still create a line from the previous point where I lift my finger to the new touches begin point. refer to gif below:

enter image description here

2) How to remove the solid orange line from the view incrementally (mine is too abrupt)?

3) Need to tune the .sks file properties.

4) https://stackoverflow.com/questions/29792443/set-the-initial-state-of-skemitternode

This is my code:

#import "GameScene.h"

@interface GameScene()

@property (nonatomic) SKEmitterNode* fireEmmitter;
@property (nonatomic) SKEmitterNode* fireEmmitter2;

@end

@implementation GameScene

NSMutableArray *_wayPoints;
NSTimer* myTimer;

-(void)didMoveToView:(SKView *)view {

_wayPoints = [NSMutableArray array];

//Setup a background
self.backgroundColor = [UIColor blackColor];

//setup a fire emitter
NSString *fireEmmitterPath = [[NSBundle mainBundle] pathForResource:@"magic" ofType:@"sks"];
_fireEmmitter = [NSKeyedUnarchiver unarchiveObjectWithFile:fireEmmitterPath];
_fireEmmitter.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2 - 200);
_fireEmmitter.name = @"fireEmmitter";
_fireEmmitter.zPosition = 1;
_fireEmmitter.targetNode = self;
_fireEmmitter.particleBirthRate = 0;
[self addChild: _fireEmmitter];

//setup another fire emitter
NSString *fireEmmitterPath2 = [[NSBundle mainBundle] pathForResource:@"fireflies" ofType:@"sks"];
_fireEmmitter2 = [NSKeyedUnarchiver unarchiveObjectWithFile:fireEmmitterPath2];
_fireEmmitter2.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
_fireEmmitter2.name = @"fireEmmitter";
_fireEmmitter2.zPosition = 1;
_fireEmmitter2.targetNode = self;
_fireEmmitter2.particleBirthRate = 0;
[self addChild: _fireEmmitter2];


//Setup a LightNode
SKLightNode* light = [[SKLightNode alloc] init];
light.categoryBitMask = 1;
light.falloff = 1;
light.ambientColor = [UIColor whiteColor];
light.lightColor = [[UIColor alloc] initWithRed:1.0 green:1.0 blue:0.0 alpha:0.5];
light.shadowColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.3];
[_fireEmmitter addChild:light];

}

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

CGPoint touchPoint = [[touches anyObject] locationInNode:self.scene];

CGMutablePathRef ref = CGPathCreateMutable();

CGPoint p = touchPoint;
p = [self.scene convertPointToView:p];
CGPathMoveToPoint(ref, NULL, p.x, p.y);

_fireEmmitter.position = CGPointMake(touchPoint.x, touchPoint.y);
_fireEmmitter.particleBirthRate = 2000;

}

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

CGPoint touchPoint = [[touches anyObject] locationInNode:self.scene];

//On Dragging make the emitter with the attached light follow the position
for (UITouch *touch in touches) {
    [self addPointToMove:touchPoint];

    CGPoint location = [touch locationInNode:self];
    [self childNodeWithName:@"fireEmmitter"].position = CGPointMake(location.x, location.y);
}
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
_fireEmmitter.particleBirthRate = 0;

[self performSelector:@selector(userHasCompletedTheDrawing) withObject:nil afterDelay:3];
}

- (void)userHasCompletedTheDrawing{
CGMutablePathRef path = CGPathCreateMutable();
if (_wayPoints && _wayPoints.count > 0) {
    CGPoint p = [(NSValue *)[_wayPoints objectAtIndex:0] CGPointValue];
    //p = [self.scene convertPointToView:p];
    CGPathMoveToPoint(path, nil, p.x, p.y);

    _fireEmmitter2.position = CGPointMake(p.x,p.y);
    _fireEmmitter2.particleBirthRate = 1000;

    for (int i = 0; i < _wayPoints.count; ++i) {
        p = [(NSValue *)[_wayPoints objectAtIndex:i] CGPointValue];
        CGPathAddLineToPoint(path, nil, p.x, p.y);
    }
    SKAction *followTrack = [SKAction followPath:path asOffset:NO orientToPath:YES duration:1];
    [_fireEmmitter2 runAction:followTrack completion:^{

        _fireEmmitter2.particleBirthRate = 0;

        [_fireEmmitter2 runAction:[SKAction waitForDuration:1] completion:^{
            //_fireEmmitter2.particleBirthRate = 0;
        }];
    }];
}


//myTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(removePointToMove) userInfo: nil repeats: YES];
[self performSelector:@selector(removeAllPointToMove) withObject:nil afterDelay:1];

}

- (void)addPointToMove:(CGPoint)point {
[_wayPoints addObject:[NSValue valueWithCGPoint:point]];
}

- (void)removeAllPointToMove{
[_wayPoints removeAllObjects];
}

- (void)removePointToMove{

if ([_wayPoints count]>0) {
    [_wayPoints removeObjectAtIndex:0];
}
}

- (void)drawLines {
//1

NSMutableArray *temp = [NSMutableArray array];
for(CALayer *layer in self.view.layer.sublayers) {
    if([layer.name isEqualToString:@"line"]) {
        [temp addObject:layer];
    }
}

[temp makeObjectsPerformSelector:@selector(removeFromSuperlayer)];

//3
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.name = @"line";
lineLayer.strokeColor = [UIColor orangeColor].CGColor;
lineLayer.fillColor = nil;
lineLayer.lineWidth = 3;
lineLayer.lineJoin = kCALineJoinRound; /* The join style used when stroking the path. Options are `miter', `round'
                                        * and `bevel'. Defaults to `miter'. */
lineLayer.zPosition = -1;

//4
CGPathRef path = [self createPathToMove];
lineLayer.path = path;
CGPathRelease(path);
[self.view.layer addSublayer:lineLayer];

}

- (CGPathRef)createPathToMove {
//1
CGMutablePathRef ref = CGPathCreateMutable();

//2
for(int i = 0; i < [_wayPoints count]; ++i) {
    CGPoint p = [_wayPoints[i] CGPointValue];
    p = [self.scene convertPointToView:p];
    //3
    if(i == 0 ) {
        CGPathMoveToPoint(ref, NULL, p.x, p.y);
    } else {
        CGPathAddLineToPoint(ref, NULL, p.x, p.y);
    }
}

return ref;
}

-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */

[self drawLines];

if ([_wayPoints count]==0) {
    [myTimer invalidate];
}

}
@end

This is my .sks files properties:

enter image description hereenter image description here

like image 626
user1872384 Avatar asked Apr 22 '15 09:04

user1872384


People also ask

Can you use SpriteKit with SwiftUI?

Even though the default Game Xcode Template creates the project based on a UIKit application, you can create a SwiftUI app and put your SpriteKit game inside it without any hustle thanks to the SpriteView view!


1 Answers

Concerning your first question, you need to split your CGPathRef into multiple subpaths so that no line gets drawn between the petals and the center. Use the CGPathCloseSubpath function when you are done drawing the petals so that you can call CGPathMoveToPoint and CGPathAddLineToPoint afterwards.

like image 51
Dalzhim Avatar answered Sep 30 '22 19:09

Dalzhim