Как повернуть SKNode, не меняя его положения?

У меня есть SKNode, который состоит из 4 SKSpriteNodes, образующих квадратную форму (надеюсь, я правильно выразился). Каждая сторона квадрата имеет свой цвет, и я пытаюсь повернуть весь квадрат, не меняя его положения. То, как я пытаюсь, всегда приводит его к изменению его положения, когда он начинает вращение. Вот как я к этому подошел:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var shape = SKNode()

    override func didMoveToView(view: SKView) {

    self.addChild(shape)
    self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
    self.physicsWorld.contactDelegate = self

    let greenLine = SKSpriteNode(imageNamed: "Green")
    greenLine.position = CGPoint(x: size.width / 2, y: size.height / 2.5)

    let yellowLine = SKSpriteNode(imageNamed: "Yellow")
    yellowLine.position = CGPoint(x: greenLine.position.x - greenLine.frame.width / 2, y: frame.size.height / 2)

    let redLine = SKSpriteNode(imageNamed: "Red")
    redLine.position = CGPoint(x: greenLine.position.x + greenLine.frame.width / 2, y: frame.size.height / 2)
    let blueLine = SKSpriteNode(imageNamed: "Blue")
    blueLine.position = CGPoint(x: frame.size.width / 2, y: redLine.position.y + redLine.frame.height / 2.3)

    shape.addChild(greenLine)
    shape.addChild(yellowLine)
    shape.addChild(redLine)
    shape.addChild(blueLine)

    let rotateAction = SKAction.rotateByAngle(CGFloat(M_PI_4) * 2, duration: 5)
    shape.runAction(rotateAction)
}

Я тоже пробовал zRotation, но это вообще не сработало. Когда вращение происходит с помощью SKAction, при вращении вся форма перемещается влево, а не остается на одном месте.

Редактировать

Код:

 var shape = SKNode()

override func didMoveToView(view: SKView) {

    self.addChild(shape)
    self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
    self.physicsWorld.contactDelegate = self

    backgroundColor = UIColor.whiteColor()

    let greenLine = SKSpriteNode(imageNamed: "Green")
    greenLine.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2.5)

    let yellowLine = SKSpriteNode(imageNamed: "Yellow")
    yellowLine.position = CGPoint(x: greenLine.position.x - greenLine.frame.width / 2, y: frame.size.height / 2)

    let redLine = SKSpriteNode(imageNamed: "Red")
    redLine.position = CGPoint(x: greenLine.position.x + greenLine.frame.width / 2, y: frame.size.height / 2)

    let blueLine = SKSpriteNode(imageNamed: "Blue")
    blueLine.position = CGPoint(x: frame.size.width / 2, y: redLine.position.y + redLine.frame.height / 2.3)

    shape.position = CGPoint(x: 0, y: 0)
    shape.addChild(greenLine)
    shape.addChild(yellowLine)
    shape.addChild(redLine)
    shape.addChild(blueLine)

    let center = SKSpriteNode(color: .redColor(), size: CGSize(width: 50, height: 50))
    center.position = CGPoint(x: frame.midX, y: frame.midY)
    shape.addChild(center)

    let rotateAction = SKAction.rotateByAngle(CGFloat(M_PI_4) * 2, duration: 30)
    shape.runAction(rotateAction)


}

person Sharukh    schedule 23.03.2016    source источник


Ответы (1)


Вы, наверное, не понимаете разницы между разными системами координат. Вы добавляете узел формы на сцену. Поэтому, когда вы устанавливаете положение фигуры, вы должны работать в системе координат сцены. Та же логика применима и к другим узлам (линиям). Здесь вы добавляете их к фигуре, что означает, что вы должны «думать» в системе координат фигуры. Взгляните на этот пример:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var shape = SKNode()

    override func didMoveToView(view: SKView) {

        self.addChild(shape)
        self.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
        self.physicsWorld.contactDelegate = self

        let greenLine = SKSpriteNode(color: .greenColor(), size: CGSize(width: 50, height: 50))
        greenLine.position = CGPoint(x: -30, y: 30)

        let yellowLine =  SKSpriteNode(color: .yellowColor(), size: CGSize(width: 50, height: 50))
        yellowLine.position = CGPoint(x: 30, y: 30)

        let redLine = SKSpriteNode(color: .redColor(), size: CGSize(width: 50, height: 50))
        redLine.position = CGPoint(x: 30, y: -30 )
        let blueLine =  SKSpriteNode(color: .blueColor(), size: CGSize(width: 50, height: 50))
        blueLine.position = CGPoint(x:-30, y:-30)

        shape.position = CGPoint(x: frame.midX, y: frame.midY)
        shape.addChild(greenLine)
        shape.addChild(yellowLine)
        shape.addChild(redLine)
        shape.addChild(blueLine)

        let center = SKSpriteNode(color: .redColor(), size: CGSize(width: 5, height: 5))

        shape.addChild(center)

        let rotateAction = SKAction.rotateByAngle(CGFloat(2 * M_PI), duration: 5)
        shape.runAction(rotateAction)

    }
}

Результат:

вращающийся

Обратите внимание на центральный узел. Это фактическое положение узла формы. И это точка вокруг других узлов, которые вращаются.

person Whirlwind    schedule 23.03.2016
comment
Я понимаю большую часть того, что вы сказали, за исключением того, что я не думал о системе координат сцены. То, как вы объяснили, имеет смысл, и я полностью это понимаю, но моя проблема связана со строкой shape.position = CGPoint(x: frame.midX y: frame.midY). Я пробовал это раньше и делал снова, и когда я запускаю свой проект с этой строкой, он переносит shape в правый верхний угол и начинает вращаться за пределами сцены. - person Sharukh; 24.03.2016
comment
Может ли это быть из-за того, как я позиционирую lines? - person Sharukh; 24.03.2016
comment
@Sharukh Да, это основано на том, как вы позиционируете дочерние элементы узла формы. Как я уже сказал, не забывайте, что линии располагаются в системе координат формы. Кроме того, чтобы узнать положение узла фигуры, просто добавьте к нему маленькую точку, как я сделал с центральным узлом. Поместите его в CGPoint(0,0), и вы увидите, где находится узел формы. - person Whirlwind; 24.03.2016
comment
Я все еще немного смущен, как решить эту проблему. Я обновил свой вопрос новыми строками кода, которые у меня есть, и при запуске shape вращается вокруг левого нижнего угла экрана в точке (0,0). - person Sharukh; 24.03.2016
comment
@Sharukh Просто расположите свои узлы по-другому. Вы поставили простую точку, чтобы показать, где находится центр контейнера формы? Затем используйте эту точку как (0,0) и расположите относительно нее узлы. Не знаю, как вам лучше объяснить. Прямо сейчас кажется, что ваши узлы расположены так, как если бы они были добавлены как дочерние элементы на сцену напрямую... - person Whirlwind; 24.03.2016
comment
Когда вы размещаете контейнер формы в позиции (frame.midX, frame.midY), он будет расположен в центре экрана (сцены). Как в моем примере. Затем, если вы добавите линию к узлу фигуры в позиции CGPoint(x:0, y:0), линия будет размещена прямо там, где находится фигура. Но, например, если вы добавите в сцену линию в позиции (0,0), она будет помещена в нижний левый угол экрана. Поэтому, когда вы добавляете линию в контейнер фигуры, она будет располагаться относительно узла фигуры, где (0,0) — позиция фигуры. - person Whirlwind; 24.03.2016
comment
Эй, да, извини. Я понял, когда вы снова объяснили, как поставить точку. Я реализовал это и заставил его работать, и теперь это имеет смысл. Как только я говорю shape.position, это становится источником, и я должен соответствующим образом позиционировать дочерние элементы. Спасибо, спасибо за помощь :) - person Sharukh; 24.03.2016
comment
Да, у меня нет опыта программирования, поэтому мне требуется целая вечность, чтобы понять даже такие маленькие понятия, как эти, лол. - person Sharukh; 24.03.2016