概述:我在场景顶部添加了一个敌人。敌人最初以150 x的速度向右移动。这张地图有左墙和右墙。当敌人攻击左右墙时,他应该立即逆转方向。
问题:当我从initWithSize调用函数spawnEnemy时,当敌人击中每堵墙时,敌人的行为就像预期的那样反转方向。当我使用NSTimer每2秒调用一次spawnEnemy时,SKScene无法识别敌人与墙壁的接触,也无法逆转敌人的方向。代码如下所示。
刷出敌人方法:
-(void)spawnEnemy{
self.testingEnemy = [SKSpriteNode spriteNodeWithImageNamed:@"normalEnemy.png"];
self.testingEnemy.position = (CGPoint) {
CGRectGetMidX(self.scene.frame),
300
};
self.testingEnemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.testingEnemy.frame.size];
self.testingEnemy.physicsBody.dynamic = TRUE;
self.testingEnemy.physicsBody.affectedByGravity = TRUE;
self.testingEnemy.physicsBody.mass = 0.00150;
self.testingEnemy.physicsBody.restitution = 0.0;
self.testingEnemy.physicsBody.allowsRotation = FALSE;
self.testingEnemy.physicsBody.linearDamping = 0.0;
[self addChild:self.testingEnemy];
}
initWithSize
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
//[self spawnEnemy]; <--- This works with expected behavior
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(spawnEnemy) userInfo:nil repeats:NO];
}
return self
}
didBeginContact
- (void)didBeginContact:(SKPhysicsContact *)contact
{
if (contact.bodyA == self.testingEnemy.physicsBody && contact.bodyB == [self.map rightWall].physicsBody) {
NSLog(@"Hit right wall");
normalEnemyVelocityX = -normalEnemyVelocityX;
}
}
这里是项目文件的链接:
https://www.dropbox.com/s/e59piru3q1hcu0e/Goldrush.zip?dl=0My two cents…
- 你没有处理接触的情况。bodyA是墙和接触。bodyB是敌人。
- 你在哪里设置categoryBitMask和contactTestBitMask?
- 你应该考虑使用SKAction而不是ntimer,因为当你暂停/恢复游戏时,SKActions会适当地暂停/恢复。
这里有一个例子…
SKAction *wait = [SKAction waitForDuration:2.0];
SKAction *spawn = [SKAction performSelector:@selector(spawnEnemy) onTarget:self];
SKAction *waitThenSpawn = [SKAction sequence:@[wait, spawn]];
[self runAction:[SKAction repeatActionForever:waitThenSpawn]];
编辑:试试下面的…
1)代码没有检查接触体是否交换,如果场景中有多个敌人,它将不起作用。下面是解决这些问题的方法:
static inline SKSpriteNode *bodyToNode(SKPhysicsBody *body1,
SKPhysicsBody *body2,
NSString *name) {
SKSpriteNode *node = nil;
if ([body1.node.name isEqualToString:name]) {
node = (SKSpriteNode *)body1.node;
}
else if ([body2.node.name isEqualToString:name]) {
node = (SKSpriteNode *)body2.node;
}
return node;
}
- (void)didBeginContact:(SKPhysicsContact *)contact
{
SKSpriteNode *enemyNode = nil;
SKSpriteNode *wallNode = nil;
enemyNode = bodyToNode (contact.bodyA, contact.bodyB, @"enemy");
wallNode = bodyToNode (contact.bodyA,contact.bodyB, @"wall");
if (enemyNode && wallNode) {
NSLog(@"Hit right wall %@", self.testingEnemy);
normalEnemyVelocityX = -normalEnemyVelocityX;
}
}
2)从地图中移动以下内容。
static const uint32_t playerCategory = 1 << 0;
static const uint32_t platformCategory = 1 << 1;
3)你没有为敌人设置类别,你需要为敌人命名,这样didBeginContact才能正常工作。将以下内容添加到test方法中:
self.testingEnemy.physicsBody.categoryBitMask = playerCategory;
self.testingEnemy.name = @"enemy";
4)在地图。M,在代码的适当位置添加以下内容:
self.leftWall.name = @"wall";
self.rightWall.name = @"wall";
5)从语句中删除playerCategory:
self.bottomRightHorizWall.physicsBody.contactTestBitMask = platformCategory;