gpt4 book ai didi

objective-c - 将SKAction添加到Sprite队列中依次运行

转载 作者:搜寻专家 更新时间:2023-10-30 19:43:51 24 4
gpt4 key购买 nike

我听 touch 并将 SKAction 添加到 sprite。如果现有操作尚未完成,我希望将操作添加到队列中,以便它一个接一个地执行。有没有经历过类似设计的?

我确实使用了 Array 和 Block。有没有更简单的方法?

@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

最佳答案

通常,您可以使用 group 方法让 SKActions 并发运行,并使用 sequence 方法让它们按顺序运行。

但是,如果您需要一个排队系统,而不是构建自己的系统,请使用 native 操作队列来为您完成这项工作。所以你可以创建一个串行操作队列并向其中添加操作。问题是您不希望操作在 SKAction 完成之前完成。

因此,您可以将 SKAction 包装在并发的 NSOperation 子类中,该子类仅在 SKAction 完成时完成。然后你可以将你的操作添加到串行 NSOperationQueue 中,然后它不会开始下一个,直到它完成前一个。

因此,首先,创建一个如下所示的 ActionOperation(从 NSOperation 子类化):

// ActionOperation.h

#import <Foundation/Foundation.h>

@class SKNode;
@class SKAction;

@interface ActionOperation : NSOperation

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

@end

// 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

然后,例如,您可以在初始化过程中创建一个串行队列:

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

然后您可以向其中添加操作:

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

您可以稍后添加更多操作:

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

并且因为队列是串行的,所以您知道 move2move1 完成之前不会启动。

关于objective-c - 将SKAction添加到Sprite队列中依次运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22854492/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com