Растянуть SKSpriteNode между двумя точками / касаниями - PullRequest
1 голос
/ 27 июня 2019

У меня есть SKSpriteNode, в котором я установил свойство centerRect, чтобы узел можно было растянуть, чтобы он выглядел как стилизованная линия. Я хочу, чтобы пользователь коснулся экрана и нарисовал / перетащил прямую линию с узлом. Линия будет поворачиваться вокруг точки привязки, чтобы оставаться прямыми.

В touchesBegan: добавлен узел:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let positionInScene = touch.location(in: self)
    if let _ = fgNode.childNode(withName: "laser") {
        print("already there")
    } else {
        laser.centerRect = CGRect(x: 0.42857143, y: 0.57142857, width: 0.14285714, height: 0.14285714)
        laser.anchorPoint = CGPoint(x: 0, y: 0.5)
        laser.position = positionInScene
        fgNode.addChild(laser)
    }
}

И скорректировано в touchesMoved::

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let positionInScene = touch.location(in: self)
    stretchLaserTo(positionInScene)
}

Узел растягивается и вращается с двумя функциями:

func stretchLaserTo(_ point: CGPoint) {
    let offset = point - laser.anchorPoint
    let length = offset.length()
    let direction = offset / CGFloat(length)
    laser.xScale = length
    rotate(sprite: laser, direction: direction)
}


func rotate(sprite: SKSpriteNode, direction: CGPoint) {
    sprite.zRotation = atan2(direction.y, direction.x)
}

Я думаю, что я на правильном пути. Линия вращается с моим прикосновением и расширяется, однако она чрезвычайно чувствительна и не остается с моим прикосновением. Может я ошибаюсь. Есть ли стандартная техника для выполнения чего-то подобного?

Пример этой работы можно увидеть здесь: https://imgur.com/A83L45i

1 Ответ

2 голосов
/ 28 июня 2019

Я предлагаю вам установить опорную точку спрайта на (0, 0), установить шкалу спрайта на расстояние между позицией спрайта и текущим местоположением касания, а затем повернуть спрайт.

Сначала создайте спрайт и установите его опорную точку.

let laser = SKSpriteNode(color: .white, size: CGSize(width: 1, height: 1))

override func didMove(to view: SKView) {
    laser.anchorPoint = CGPoint(x: 0, y: 0)
    addChild(laser)
}

В touchesBegan установите положение спрайта в положение касания. В этом случае это также начало строки.

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let positionInScene = touch.location(in: self)
    laser.position = positionInScene
    laser.setScale(1)
}

Обновите спрайт так, чтобы он образовывал линию, которая начинается в позиции спрайта и заканчивается в текущем месте касания.

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let positionInScene = touch.location(in: self)
    stretchLaserTo(positionInScene)
}

Растяните спрайт, установив его xScale на расстояние от начала строки до местоположения текущего касания, а затем поверните спрайт.

func stretchLaserTo(_ point: CGPoint) {
    let dx = point.x - laser.position.x
    let dy = point.y - laser.position.y
    let length = sqrt(dx*dx + dy*dy)
    let angle = atan2(dy, dx)
    laser.xScale = length
    laser.zRotation = angle
}
...