Подтвердить что ты не робот

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

4b9b3361

Ответ 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)