2015-07-03 3 views
4

Я встречаюсь с очень странной ошибкой, которую я просто не могу понять. В моей игре вы управляете автомобилем на двухмерном самолете, пытаясь избежать препятствий (например, рок или автомобиль). Препятствия могут появляться на 3 разных дорожках. Иногда на любом из путей есть только одно препятствие, или иногда на двух из трех путей есть два препятствия.Strange SpriteKit For Loop Bug

Проблема, с которой я столкнулся, заключается в том, что при появлении двух препятствий, а затем удаляются, когда они выходят из экрана, одно из препятствий, перемещающихся в данный момент на экране, также «удаляется» (я знаю это, потому что консоль печатает «удаленные» объект "3 раза). Но препятствие, которое случайным образом «удаляется», не удаляется из поля зрения. Вместо этого он замерзает там, где он был раньше, и никогда не уходит.

Вот блок кода У меня возникли проблемы с:

var canGetScore = true 
for (num,obj) in enumerate(obstaclesToMove) { 
    obj.position.y -= CGFloat(gameSpeed) 
    if obj.position.y <= userCar.position.y && obj.name == "NotPassed" { 
     obj.name = "Passed" 
     if canGetScore { 
      canGetScore = false 
      score += 1 
      scoreLabel.text = "\(score)" 
     } 
    } 
    if obj.position.y <= -CGRectGetMidY(self.frame) { 
     obj.removeFromParent() 
     obstaclesToMove.removeAtIndex(num) 
     println("deleted object") 
    } 
} 

Variable Ключ:

  • "obstaclesToMove" является массивом препятствий (SKSpriteNodes), которые должны быть перемещены вниз по экрану ,

  • «gameSpeed» - это целое число пикселей, которое экран перемещает каждый кадр (в этом случае значение равно 5).

  • «userCar» - это символ, который пользователь контролирует (SKSpriteNode).

«canGetScore» вещь - устранить еще одну ошибку, с которой я столкнулся раньше. Я знаю, что это не вызывает текущую ошибку, которую я испытываю.

Есть ли у кого-нибудь идеи, почему это происходит? Если вам нужно больше объяснений, просто спросите.

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: Автомобиль пользователя технически никогда не перемещается, но фон и препятствия перемещаются.

ответ

1

Мне кажется, что проблема заключается в том, как вы удалите свой объект из obstaclesToMove

Представьте у вас есть три объекта в массиве:

obstaclesToMove = [object1, object2, object3] 

Вы должны удалить объект 1 & 2, потому что они должны уйти с экрана, поэтому то, что вы делаете в своем коде, сначала удаляет объект 1, а затем объект 2, за исключением кода, который он переводит на:

obstaclesToMove.removeAtIndex(0) 
obstaclesToMove.removeAtIndex(1) 

Вы думали бы, что это не проблема, за исключением того, посмотрите, что происходит в вашем массиве, когда вы делаете что:

obstaclesToMove = [object1, object2, object3] 
obstaclesToMove.removeAtIndex(0) 
// obstaclesToMove = [object2, object3] 
obstaclesToMove.removeAtIndex(1) 
// obstaclesToMove = [object2] 

Обычно это плохая идея, чтобы удалить объект из массива, который вы Перебор.Что вы могли бы сделать, чтобы сделать его более безопасным является:

  • Соберите все индекс вам нужно удалить в массиве
  • сортировать их в обратном порядке
  • Удаление элементов из массива

Вы можете сделать это так:

var indexToDelete: [MyObstacleObject] = [] 
var canGetScore = true 
for (num,obj) in enumerate(obstaclesToMove) { 
    obj.position.y -= CGFloat(gameSpeed) 
    if obj.position.y <= userCar.position.y && obj.name == "NotPassed" { 
     obj.name = "Passed" 
     if canGetScore { 
      canGetScore = false 
      score += 1 
      scoreLabel.text = "\(score)" 
     } 
    } 
    if obj.position.y <= -CGRectGetMidY(self.frame) { 
     indexToDelete.append(num) 
    } 
} 

indexToDelete.sort({ $0 > $1 }) 

for item in indexToDelete { 
    obstaclesToMove[item].removeFromParent() 
    obstaclesToMove.removeAtIndex(item) 
    println("deleted object") 
} 

Таким образом, когда вы удаляете элементы из своего массива, вы можете быть уверены, что они будут у больных есть правильный индекс, так как вы будете сначала удалять предметы с более высоким индексом.

+1

OP также может перебирать элементы в 'препятствияToMove' в обратном порядке с помощью' stride (from: through: by:) 'и избегать дополнительного массива/цикла. – 0x141E

+1

Я не знаю, как я не мог этого видеть. Я обязательно буду использовать ваш ответ. Благодаря! – gooroo7

1

У меня было то же самое, что и в моей игре, которая очень похожа на вашу, поэтому я думаю, что все, что я сделал, можно применить к вашей ситуации. То, что я вместо того, чтобы использовать индексы, чтобы устранить препятствия на пути из массива препятствий является то, что я использовал addObject и removeObjectIdenticalTo методы (self.obstacles является NSMutableArray):

[self.obstacles addObject:asteroide]; //asteroide is subclass of SKSpriteNode 
[self.obstacles addObject:enemyShip];//enemyShip is subclass of SKSpriteNode 

И когда я удалить их, я просто сделать что-то вроде:

[self.obstacles removeObjectIdenticalTo:asteroide]; 
[self.obstacles removeObjectIdenticalTo:enemyShip]; 

Это сработало для меня ... Еще одна вещь, на которую я хотел бы обратить внимание, - это то, как вы можете устранить препятствия, когда вы находитесь на экране, иначе, чем ваш. Это, как я могу это сделать:

SKAction *sequence = [SKAction sequence:@[moveAsteroide,[SKAction runBlock:^{[asteroide removeFromParent]; [self.obstacles removeObjectIdenticalTo:asteroide]; 
       }]]]; 

    [asteroide runAction:sequence withKey:@"moving"]; 

Так я бегу последовательность, первый объект двигаться в нужном месте, и что некоторая точка, закадровый (у = -obstacle.size.height) и после этого, я удалить его из родителей и обновить массив препятствий. Это работает для меня, потому что я использую действия для перемещения препятствий, но, возможно, это может сработать для вас, если вы так же перемещаете препятствия. Мне нравится это больше, чем постоянная проверка местоположения препятствия в методе обновления.

Это как раз мой путь, и все это можно сделать разными способами, и вам нужно выбрать, какой из них вам подходит. Надеюсь, что это имеет смысл и помогает немного :-)