SKNode convertPoint toNode & fromNode путаница?
Я немного смущен тем, как работают методы SKNode
convertPoint:fromNode:
и convertPoint:ToNode:
, я просмотрел документы, но это не так очевидно, что они делают. Например, это (см. Диаграмму ниже) является небольшим тестом, который я использовал с помощью convertPoint:fromNode:
. Черная область - это фон SKScene
, синяя область SKSpriteNode
, родившаяся на SKScene
, красная область - это еще одна SKSpriteNode
родительский синим спрайтом. Якорные точки для обоих спрайтов показаны маленькими зелеными точками. То, что я хотел сделать, это получить позицию сцены для красного спрайта, который я использовал, используя следующий код:
CGPoint positionInScene = [self convertPoint:[self position]
fromNode:[self redSprite]];
Результатом этого является
positionInScene = [105, 205]
Это то, что я ожидал, поскольку это было бы началом красного квадрата в пространстве сцены. То, что я смущен, - это аргументы. Из чего я могу догадаться:
[SKNode_A convertPoint: CGPoint_B toNode: SKScene_C]
- SKNode_A = Координатное пространство node для преобразования в...
- CGPoint_B = Точка для преобразования (не уверен, почему ее [позиция] выше)
- SKNode_C = Короткое пространство node для преобразования из...
Моя первоначальная попытка в этом была [self convertPoint:[redSprite position] fromNode:redSprite]
, потому что я хотел преобразовать источник красного спрайта в сцену. Кажется, что это немного неуклюже, чтобы развернуть свою голову, если кто-то может немного рассказать об этом и его другом convertPoint:ToNode:
, и это будет очень оценено.
![enter image description here]()
Ответы
Ответ 1
- (CGPoint) точка конверсии: (CGPoint) fromNode: (SKNode *) node
Это, по сути, означает: преобразовать точку, выраженную в другой системе координат node, в систему координат вызывающего (self). Ключ в том, что точка должна быть выражена в системе координат node, чтобы это работало. Если вы используете позицию спрайта в качестве точки, вам нужно передать родительский спрайт node в качестве последнего аргумента.
Пример: Чтобы получить положение красного квадрата в системе координат сцены:
CGPoint positionInScene = [self convertPoint:[redSprite position]
fromNode:[self blueSprite]];
[5, 5] в системе координат blueSprite → [105, 205] в системе координат сцены
Ваш пример:
CGPoint positionInScene = [self convertPoint:[self position]
fromNode:[self redSprite]];
[0, 0] в системе координат redSprite → [105, 205] в системе координат сцены
Вы получили тот же результат от своего кода, только потому, что [self position] был [0, 0], и вы использовали систему координат redSprite. Ваша первоначальная попытка была близка, вам просто нужно было предоставить систему координат, в которой была указана позиция redSprite, которая является исходной системой координат спрайтов; в этом случае, что blueSprite.
- (CGPoint) convertPoint: (CGPoint) point toNode: (SKNode *) node
Этот метод очень сильно отличается от первого метода. Он преобразует точку в системе координат вызывающего абонента в другую систему координат node. Ключом для этого метода является то, что указанная точка должна быть выражена в системе координат вызывающего абонента.
Пример: Предположим, что ваша сцена получила прикосновение к [125, 225], и вы хотели добавить новый спрайт в этом месте, который находится в ограничительной рамке redSprite. Итак, чтобы добавить новый спрайт в качестве дочернего элемента redSprite, вам нужно получить местоположение касания в системе координат redSprite. Чтобы получить это:
CGPoint positionInRedSprite = [self convertPoint:touchLocation
toNode:[self redSprite]];
[125, 225] в системе координат сцены → [20, 20] в системе координат redSprite
Ответ 2
Для простоты:
При сравнении местоположения node B с node A (пытаясь найти, насколько далеко они друг от друга)
var BInSameCoordinateSys = NodeA.parent!.convertPoint(NodeB.position, fromNode: NodeB.parent!)
Устранение неполадок путем добавления спрайта в местоположении, если он не работает, чтобы визуализировать местоположение:
let childToSeeLocation = SKShapeNode(CircleWithRadius:50)
childToSeeLocation.fillColor = UIColor.redColor
ParentofA.addChild(childToSeeLocation)
Ответ 3
После прочтения кевина. отличный ответ, я смог сделать несколько расширений для SKNode, которые являются отличным примером и удобным набором инструментов.
extension SKNode {
var frameInScene:CGRect {
get {
if let scene = self.scene {
if let parent = self.parent {
let rectOriginInScene = scene.convertPoint(self.frame.origin, fromNode: parent)
return CGRect(origin: rectOriginInScene, size: self.frame.size)
}
}
println("Just the normal frame, not the scene frame!!!")
return frame
}
}
var positionInScene:CGPoint {
get {
if let scene = self.scene {
if let parent = self.parent {
return scene.convertPoint(self.position, fromNode: parent)
}
}
println("Just the normal position, not the scene position!!!")
return position
}
}
}
Я считаю, что вы могли бы удалить каждый self.
, но я чувствовал, что он делает код более запутанным. И я не совсем уверен, что делать, если node не принадлежит к какой-либо сцене или родительскому объекту node, поэтому я просто вернул обычный фрейм и позицию и использовал println()
, чтобы дать мне предупреждение.
Если у кого-то есть какие-либо изменения/дополнения к этому коду, я бы хотел его услышать, особенно если это поможет ответить на вопрос дальше.
Ответ 4
Я знаю, что это поздний ответ, но обычно я хочу использовать родительский node как систему координат для позиции node. Итак, я нашел, что это расширение очень полезно:
extension SCNNode {
func convertPosition(node:SCNNode) -> SCNVector3 {
return self.convertPosition(node.position, fromNode:node.parentNode)
}
}
Например, вместо вызова этого:
let position = scene.rootNode.convertPosition(node.position, fromNode: node.parentNode)
вы просто вызываете это:
let position = scene.rootNode.convertPosition(node)