Sprite Kit,使多个精灵遵循相同的方法
Posted
技术标签:
【中文标题】Sprite Kit,使多个精灵遵循相同的方法【英文标题】:Sprite Kit, make multiple sprites obey same method 【发布时间】:2014-02-23 19:17:36 【问题描述】:如果有一个玩家和 12 个“敌人”,我正在为 iPhone 开发一款精灵套件游戏。这些敌人中的每一个都是以相同的方式创建的。我在 initWithSize 方法中使用 for 循环来做到这一点。
for (int i = 1; i <= 12; i++)
[self spawnChargesWithNumber:i];
实际生成敌人的方法(spawnChargesWithNumber)如下。
- (void)spawnChargesWithNumber:(NSInteger)number
self.chargedBall = [[ChargedBall alloc] initWithImageNamed:[NSString stringWithFormat:@"ChargedBall%li", (long)number]];
int minX = self.chargedBall.size.width / 2;
int maxX = self.frame.size.width - self.chargedBall.size.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
self.chargedBall.position = CGPointMake(actualX, 568);
self.chargedBall.name = [NSString stringWithFormat:@"chargeNumber%li", (long)number];
self.chargedBall.zPosition = 15;
self.chargedBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:13.0f];
self.chargedBall.physicsBody.dynamic = YES;
self.chargedBall.physicsBody.affectedByGravity = NO;
self.chargedBall.physicsBody.mass = 0.1;
[self.map addChild:self.chargedBall];
这确实创建了 12 个不同的敌人,但只有最后一个实际上是chargedBall 对象。我有一个名为 ChargedBall 的对象,其中有一个 .h 和 .m 文件。在 .m 文件中,我有一个方法可以更新对象的位置。
在 update:currentTime 方法中,我调用此方法来更新球的位置,并在此方法中检查与 tileMap 的碰撞。
-(void)update:(CFTimeInterval)currentTime
NSTimeInterval delta = currentTime - self.previousUpdateTime;
if (delta > 0.02)
delta = 0.02;
self.previousUpdateTime = currentTime;
[self.player update:delta];
[self.chargedBall update:delta];
[self checkForAndResolveCollisionsForPlayer:self.player forLayer:self.walls];
[self checkForAndResolveCollisionsForCharge:self.chargedBall forLayer:self.walls];
[self processUserMotionForUpdate:currentTime];
[self setViewPointCenter:self.player.position];
如果我只有一个敌人/chargedBall,这会非常有效。如果我有多个chargedBalls,那么只有最后一个会按应有的方式运行。其他人只是停留在屏幕上。我认为这与我制作chargedBall 的方式有关。我每次都重新创建chargedBall 对象,因此只有最后一个实际上是chargedBall,而不是其他对象,因为我覆盖了它们。所以我的最终问题是,我怎样才能让所有敌人/chargedBall 对象的行为方式相同并遵循相同的方法来更新自己?非常感谢您的任何帮助
【问题讨论】:
【参考方案1】:将所有ChargedBall
对象存储在一个数组中。声明一个属性:
@property (nonatomic, strong) NSMutableArray *enemies.
每次创建敌人时,将其添加到 enemies
数组中。
- (void)spawnChargesWithNumber:(NSInteger)number
ChargedBall *enemy = [[ChargedBall alloc] ...];
// Your code ...
if (!_enemies)
_enemies = [[NSMutableArray alloc] init];
[_enemies addObject:enemy];
然后对数组中的每个ChargedBall
用update
方法更新它:
for(ChargedBall *enemy in self.enemies)
[self checkForAndResolveCollisionsForCharge:enemy forLayer:self.walls];
旁注:
这不适用于这个问题,但很高兴知道。
如果你想调用每个敌人的方法,你可以使用NSArray
的makeObjectsPerformSelector:
方法在一行中完成。示例:
[_enemies makeObjectsPerformSelector:@selector(selfDestruct)];
【讨论】:
非常感谢。这就像一个魅力!而且,我真的很喜欢使用 makeObjectsPerformSelector 的 selfDestruct 方法:NSArray 的方法!再次感谢您的时间和帮助。【参考方案2】:您已经为您的chargedBall 定义了一个属性,但是您需要一个可变数组。定义一个属性来容纳所有的球。像这样的:
@property (nonatomic, strong) NSMutableArray *chargedBalls.
然后将你的 for 循环更改为这个(确保你已经在某处初始化了数组):
- (void)spawnChargesWithNumber:(NSInteger)number
ChargedBall *chargedBall = [[ChargedBall alloc] initWithImageNamed:[NSString stringWithFormat:@"ChargedBall%li", (long)number]];
int minX = chargedBall.size.width / 2;
int maxX = self.frame.size.width - chargedBall.size.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
chargedBall.position = CGPointMake(actualX, 568);
chargedBall.name = [NSString stringWithFormat:@"chargeNumber%li", (long)number];
chargedBall.zPosition = 15;
chargedBall.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:13.0f];
chargedBall.physicsBody.dynamic = YES;
chargedBall.physicsBody.affectedByGravity = NO;
chargedBall.physicsBody.mass = 0.1;
[self.map addChild:chargedBall];
[self.chargedBalls addObject:chargedBall];
然后您可以迭代数组并确定是否与任何球发生碰撞。但是,如果您使用 SpriteKit 的物理引擎,您可以让引擎本身通知您发生碰撞。
【讨论】:
感谢您的帮助。我使用了两个答案的组合,所以我只能接受一个,但我为你的时间投了你的票!以上是关于Sprite Kit,使多个精灵遵循相同的方法的主要内容,如果未能解决你的问题,请参考以下文章
使用 Swift 在 sprite kit 中的多个场景中重用相同的 sprite 节点