2016-07-21 9 views
1

Я новичок в SpriteKit, и я не уверен, что то, что я пытаюсь выполнить, уже не возможно со встроенными объектами, такими как SKPhysics и SKRegion.SKScene, обнаруживают, когда 2 SKSpriteNodes становятся в пределах x друг от друга?

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

Я создаю RTS, и до сих пор самой большой проблемой, с которой я столкнулся в течение нескольких дней, является то, как иметь 2 SKSpriteNodes, чтобы определить, находятся ли они в близком расстоянии друг от друга.

Прямо сейчас, мое решение довольно хаки, похоже. Перед тем, как SKSpriteNode в моем SKScene перемещает 50 или -50 очков на X или Y в любом месте сцены, он сначала проверяет, разрешено ли это движение.

Вот пример моего абстрактного класса «PathFindingUnit»:

override func OrderUnitToMoveOneStepLEFT() -> Bool { 
    if isDead == true { return false } 
    sprite.playFaceLeftAnimation() 
    angleFacing = UnitFaceAngle.Left 

    updateMovementBlockerPosition() 
    let destination = round(sprite.position.x) - UnitDefaultProperty.Movement.Range 
    var pointDestination = sprite.position 
    pointDestination.x = destination 


    if thereIsAnObstacleInTheWay(pointDestination) == false { 
     activateEnemiesNearby(pointDestination) 
     sprite.playWalkLEFTAnimation() 

      self.sprite.runAction(SKAction.moveToX(self.roundToFifties(destination), duration: 0.2)) 


     angleFacing = UnitFaceAngle.Left 
     unitDidMove(pointDestination) 

     return true 
    } else { 
     return false 
    } 
} 

Если этот метод возвращает истину, спрайт блока будет выполнять SKAction двигаться -50 по размерности X. В противном случае ничего не произойдет.

Это как блок спрайтов определяет, будет ли это или нет нормально двигаться:

func thereIsAnObstacleInTheWay(destination: CGPoint) -> Bool { 
    let getNodesAtDestination = ReferenceOfGameScene!.nodesAtPoint(destination) 
    for node in getNodesAtDestination { 
     if node is SKBlockMovementSpriteNode { 
      return true 
     } 
    } 
    return false 
} 

По большей части, это столь же мощным, как первопрохождения для единиц в Warcraft II. Но всякий раз, когда я пытаюсь улучшить этот метод, я постоянно работаю в:

Exception: EXC_BAD_ACCESS (code=1, address=0xf91002028))

Я начал получать этот вопрос много, как только я реализовал: activateEnemiesNearby(pointDestination)

Поскольку блок self буду активировать другие блоки и приказать атаковать self.

Таким образом, в заключении следует Units с SKSpriteNode в SKScene быть вызов методов других единиц с подобным SKSpriteNode путем вызова метода MOVE_TO_POINT вражеского юнита в себе с помощью ссылочных переменных о противнике единице внутри себя?

Я пробовал использовать SKPhysics, которые работали несколько хорошо, но положение SKSpriteNodes вызывает колебания из-за эффектов столкновения, которые происходят, когда 2 SKSpriteNodes касаются.

Я думал об использовании SKRegion, но у меня было много хлопот выяснить, как они вызываются и вставляются в SKScene, и официальные яблочные документы на SKRegion кажется весьма ограниченными: https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKRegion_Ref/

ли SKRegions лучше всего подходит для «Единица зрения»? чтобы подразделения могли обнаружить, что противник приближается?

+0

SKRegion - это не то, что вы хотите, которое не будет отправлять какие-либо события, оно используется для определения того, находится ли точка в регионе, поэтому вы использовали бы это, чтобы определить спрайт на землю, если вы хотите увидеть если 2 спрайта находятся в радиусе действия, то SKPhysicsBody может помочь, но может быть дорогостоящим. если не сделано правильно – Knight0fDragon

+0

по умолчанию для маски столкновения установлено значение 0xFFFFFFFF на всех телах, установите его на 0 – Knight0fDragon

ответ

0

Я наклонная использовать SKPhysicsBody, чтобы обнаружить, если тело сталкивается с определенной зоной, обозначенной другой SKPhysicBody, например, зона, созданная с определенной CGPath, так что вы можете сделать:

SKPhysicsBody.init(edgeLoopFromPath: zonePath!) // zonePath is a CGPath 

Однако если вы не хочу, чтобы использовать его там тоже эта маленькая функция, которая может помочь вам с вашими расчетами:

func getDistance(p1:CGPoint,p2:CGPoint)->CGFloat { 
    let xDist = (p2.x - p1.x) 
    let yDist = (p2.y - p1.y) 
    return CGFloat(sqrt((xDist * xDist) + (yDist * yDist))) 
} 

О последнем пути, вы могли бы найти полезные и эти методы:

/* Return true if `point' is contained in `rect', false otherwise. */ 

@available(iOS 2.0, *) 
public func CGRectContainsPoint(rect: CGRect, _ point: CGPoint) -> Bool 

/* Return true if `rect2' is contained in `rect1', false otherwise. `rect2' 
    is contained in `rect1' if the union of `rect1' and `rect2' is equal to 
    `rect1'. */ 

@available(iOS 2.0, *) 
public func CGRectContainsRect(rect1: CGRect, _ rect2: CGRect) -> Bool 

/* Return true if `rect1' intersects `rect2', false otherwise. `rect1' 
    intersects `rect2' if the intersection of `rect1' and `rect2' is not the 
    null rect. */ 

@available(iOS 2.0, *) 
public func CGRectIntersectsRect(rect1: CGRect, _ rect2: CGRect) -> Bool 
+1

Это RTS, я бы избегал SQRT как можно больше, расстояние квадрата отлично работает, ему просто нужно убедиться, что враг ближе, чем квадрат расстояния – Knight0fDragon

Смежные вопросы