add SKAction to Sprite queue run one after another

Elliot Yap

I listen to touch and add SKAction to a sprite. If existing actions are not complete yet, I want the action to be added to a queue so it will execute one after another. Any experienced similar design?

I did using Array and Block. If there is any easier approach?

@interface GAPMyScene()
@property(strong,nonatomic)SKSpriteNode*ufo;
@property(strong,nonatomic)NSMutableArray*animationQueue;
@property(copy,nonatomic)void(^completeMove)();
@end

@implementation GAPMyScene

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
        self.ufo = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
        self.animationQueue = [[NSMutableArray alloc] init];
        __unsafe_unretained typeof(self) weakSelf = self;
        self.completeMove = ^(void){
            [weakSelf.ufo runAction:[SKAction sequence:[weakSelf.animationQueue copy]] completion:weakSelf.completeMove];
            NSLog(@"removeing %@", weakSelf.animationQueue);
            [weakSelf.animationQueue removeAllObjects];
        };
        [self addChild:self.ufo];
    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        CGPoint location = [touch locationInNode:self];
        SKAction*moveAnimation = [SKAction moveTo:location duration:2];
        if (![self.ufo hasActions]) {
            [self.ufo runAction:moveAnimation completion:self.completeMove];

        } else {
            [self.animationQueue addObject:moveAnimation];
            NSLog(@"in queue %@", self.animationQueue);
        }
    }
}

@end
Rob

Generally, you can make SKActions run concurrently using the group method, and have them run sequentially using the sequence method.

But if you need a queuing system, rather than building your own, use the native operation queue to do this for you. So you can create a serial operation queue and add operations to it. The issue is that you don't want an operation to complete until the SKAction does.

So, you can wrap your SKAction in a concurrent NSOperation subclass that only completes when the SKAction does. Then you can add your operations to a serial NSOperationQueue, and then it will won't start the next one until it finishes the prior one.

So, first, create an ActionOperation (subclassed from NSOperation) that looks like:

// ActionOperation.h

#import <Foundation/Foundation.h>

@class SKNode;
@class SKAction;

@interface ActionOperation : NSOperation

- (instancetype)initWithNode:(SKNode *)node action:(SKAction *)action;

@end

and

// ActionOperation.m

#import "ActionOperation.h"
@import SpriteKit;

@interface ActionOperation ()

@property (nonatomic, readwrite, getter = isFinished)  BOOL finished;
@property (nonatomic, readwrite, getter = isExecuting) BOOL executing;

@property (nonatomic, strong) SKNode *node;
@property (nonatomic, strong) SKAction *action;

@end

@implementation ActionOperation

@synthesize finished  = _finished;
@synthesize executing = _executing;

- (instancetype)initWithNode:(SKNode *)node action:(SKAction *)action
{
    self = [super init];
    if (self) {
        _node = node;
        _action = action;
    }
    return self;
}

- (void)start
{
    if ([self isCancelled]) {
        self.finished = YES;
        return;
    }

    self.executing = YES;

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self.node runAction:self.action completion:^{
            self.executing = NO;
            self.finished = YES;
        }];
    }];
}

#pragma mark - NSOperation methods

- (BOOL)isConcurrent
{
    return YES;
}

- (void)setExecuting:(BOOL)executing
{
    [self willChangeValueForKey:@"isExecuting"];
    _executing = executing;
    [self didChangeValueForKey:@"isExecuting"];
}

- (void)setFinished:(BOOL)finished
{
    [self willChangeValueForKey:@"isFinished"];
    _finished = finished;
    [self didChangeValueForKey:@"isFinished"];
}

@end

You could then, for example, create a serial queue during the initialization process:

self.queue = [[NSOperationQueue alloc] init];
self.queue.maxConcurrentOperationCount = 1;

You can then add the operations to it:

SKAction *move1 = [SKAction moveTo:point1 duration:2.0];
[self.queue addOperation:[[ActionOperation alloc] initWithNode:nodeToMove action:move1]];

and you can later add more actions:

SKAction *move2 = [SKAction moveTo:point2 duration:2.0];
[self.queue addOperation:[[ActionOperation alloc] initWithNode:nodeToMove action:move2]];

And because the queue is serial, you know that move2 will not be started until move1 is done.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

add SKAction to Sprite queue run one after another

From Dev

how to run function after another one completes

From Dev

Run one rake task after another completes

From Dev

Run a Program After Another in One Java File

From Dev

Run multiple scripts one after another in bash

From Dev

Run one function after another: callback issue

From Dev

RethinkDB - Run query one after another

From Dev

how to queue a command to run after another command finishes?

From Dev

how to add a column after another one in monetDB

From Dev

How do I restore the sprite into original image after swapped it to another one in coco2dx?

From Dev

How to make a javascript function to run after another one get finished?

From Dev

how to run multiple jobs one after another in jenkins

From Dev

How to run multiple python file in a folder one after another

From Dev

How do i run a for loop in bash one after another

From Dev

How to load 2 Javascript files async and run one after another?

From Dev

Eclipse: Chain many 'Run as Java Application' one after another

From Dev

How to run one statement after another in a procedural manner in Javascript?

From Dev

Do commands in a bash script run in parallel or one after another?

From Dev

Two piped programs, one continues to run after another is killed

From Dev

run another while read after first one finished

From Dev

Need to run the validation one after check another on Rails

From Dev

Run another task after executing one function successfully Using Celery

From Dev

Copy a message from one queue to another queue

From Dev

Stop SKAction that RepeatsForever - Sprite Kit

From Dev

Stopping an running SKAction - Sprite Kit

From Dev

Handling interruptions in Sprite Kit - can't get sound effects via [SKAction playSoundFileNamed: to work after interruption

From Dev

Handling interruptions in Sprite Kit - can't get sound effects via [SKAction playSoundFileNamed: to work after interruption

From Dev

Add animation one after another in div using jquery

From Dev

add string after finding another one on specific line c#

Related Related

  1. 1

    add SKAction to Sprite queue run one after another

  2. 2

    how to run function after another one completes

  3. 3

    Run one rake task after another completes

  4. 4

    Run a Program After Another in One Java File

  5. 5

    Run multiple scripts one after another in bash

  6. 6

    Run one function after another: callback issue

  7. 7

    RethinkDB - Run query one after another

  8. 8

    how to queue a command to run after another command finishes?

  9. 9

    how to add a column after another one in monetDB

  10. 10

    How do I restore the sprite into original image after swapped it to another one in coco2dx?

  11. 11

    How to make a javascript function to run after another one get finished?

  12. 12

    how to run multiple jobs one after another in jenkins

  13. 13

    How to run multiple python file in a folder one after another

  14. 14

    How do i run a for loop in bash one after another

  15. 15

    How to load 2 Javascript files async and run one after another?

  16. 16

    Eclipse: Chain many 'Run as Java Application' one after another

  17. 17

    How to run one statement after another in a procedural manner in Javascript?

  18. 18

    Do commands in a bash script run in parallel or one after another?

  19. 19

    Two piped programs, one continues to run after another is killed

  20. 20

    run another while read after first one finished

  21. 21

    Need to run the validation one after check another on Rails

  22. 22

    Run another task after executing one function successfully Using Celery

  23. 23

    Copy a message from one queue to another queue

  24. 24

    Stop SKAction that RepeatsForever - Sprite Kit

  25. 25

    Stopping an running SKAction - Sprite Kit

  26. 26

    Handling interruptions in Sprite Kit - can't get sound effects via [SKAction playSoundFileNamed: to work after interruption

  27. 27

    Handling interruptions in Sprite Kit - can't get sound effects via [SKAction playSoundFileNamed: to work after interruption

  28. 28

    Add animation one after another in div using jquery

  29. 29

    add string after finding another one on specific line c#

HotTag

Archive