在尝试为iOS创建游戏时我遇到了一个问题:我找不到一种方法来调用一个方法来创建一个SpriteKit节点来自另一个类"调用本身"或者以一种简单的方式在一段随机的时间后重复。
这个想法是这样的:我有一个创建场景的类。但后来我有了另一个类(SKSPriteNode的子类),它创建了我需要的不同SKSpriteNode。我有一个名为createObjectWithName的方法:名称位置:带有两个参数(名称和位置)的位置。我需要从我的场景调用这个方法(好到这里),但我还需要在随机的时间段内不断重复这个方法。因此,一旦它被调用一次,它会在一段时间后自行调用,创建更多的SKSPriteNodes。
我尝试过使用performSelector和dispatch_after,但到目前为止我还没有运气。
提前谢谢你。
答案 0 :(得分:1)
您可以在场景类中存储时间戳属性(让我们将其称为timeElapsedFromLastSpawn
并使用0初始化它)。然后,您可以在更新方法中使用此属性:
timeElapsedFromLast += timeElapsedFromLastUpdate;
if (timeElapsedFromLast > 5.0) {
[self spawnSpriteNode];
timeElapsedFromLast = 0;
}
这将每5秒产生一个新的精灵。 (你可以轻松随机化)
我还建议产卵方法不在SKSpriteNode
实例中但在外部(例如在育儿场景/节点类中),因为SKSpriteNode角色是表示精灵而不是精灵的工厂(除非它创造儿童精灵直接控制)
编辑:
要计算timeElapsedFromLastUpdate
,您可以使用以下代码(取自Ray Wenderlich的网站,该网站对此内容有很好的tutorials)
- (void)update:(NSTimeInterval)currentTime {
// Handle time delta.
// If we drop below 60fps, we still want everything to move the same distance.
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
self.lastUpdateTimeInterval = currentTime;
if (timeSinceLast > 1) { // more than a second since last update
timeSinceLast = 1.0 / 60.0;
self.lastUpdateTimeInterval = currentTime;
}
[self updateWithTimeSinceLastUpdate:timeSinceLast];
}
您应该在场景类中实现updateWithTimeSinceLastUpdate
方法,或直接在上面的update
方法中使用计算
答案 1 :(得分:1)
除非我遗漏了某些内容,否则我认为您希望使用SKAction
来解决此问题。
你可以有一个方法来启动这样的spawner:
-(void)startSpawner:(float)duration range:(float)range
{
SKAction *delay = [SKAction waitForduration:duration withRange:range];
SKAction *spawnBlock = [SKAction runBlock:^(void)
{
NSString *spawnName = @"name";
CGPoint *spawnPosition = CGPointMake(someX, someY);
SpriteNodeSubclass *node = [SpriteNodeSubclass createObjectWithName:spawnName andPosition:spawnPosition];
// do something with that node if you need to.
}];
SKAction *sequence = [SKAction sequence:@[delay, spawnBlock]];
SKAction *repeat = [SKAction repeatActionForever:sequence];
[self runAction:repeat];
}
我认为使用SKAction
而不是dispatch_after
是理想的,因为如果您暂停SpriteKit,SKAction
也会暂停。
答案 2 :(得分:0)
如果这是你从场景中调用方法的方式:
[otherClass createObjectWithName:name position:position];
然后,您可以使用GCD在以后的随机时间内安排该呼叫:
dispatch_after(dispatch_time(
DISPATCH_TIME_NOW,
(int64_t)(arc4random_uniform((u_int32_t)(MAX_SECONDS * NSEC_PER_SEC)))),
dispatch_get_main_queue(),
^{
[otherClass createObjectWithName:name position:position];
});
(假设MAX_SECONDS * NSEC_PER_SEC
小到足以用32位数量表示;否则看看用合适的模数运算打桩两个arc4random_uniform
调用)
通过__weak
安全措施以防止任意延长对象的生命周期,以一种重复的方式使用尾部调用:
- (void)scheduleNextObject
{
__weak YourClass *weakSelf = self;
dispatch_after(dispatch_time(
DISPATCH_TIME_NOW,
(int64_t)(arc4random_uniform((u_int32_t)(MAX_SECONDS * NSEC_PER_SEC)))),
dispatch_get_main_queue(),
^{
// weakSelf prevents self itself from being captured, so that self
// can be deallocated even with this loop ongoing. We'll explicitly
// check whether what was self still exists to stick with the idiom,
// though it's strictly unnecessary
YourClass *strongSelf = weakSelf;
if(!strongSelf) return;
[otherClass createObjectWithName:name position:position];
[strongSelf scheduleNextObject];
});
}