SpriteKit 中坐标空间之间的转换问题

Posted

技术标签:

【中文标题】SpriteKit 中坐标空间之间的转换问题【英文标题】:Trouble converting between coordinate spaces in SpriteKit 【发布时间】:2018-03-15 03:46:09 【问题描述】:

我正在尝试让SKShapeNode 关注UITouch

我的问题是UITouch 的位置相对于屏幕的左下角,SKShapeNode 的位置相对于我创建它时给它的位置,即屏幕。

例如:ball 以 (189.0, 335.0) 为中心,即视图的中心。我点击球,触摸的位置告诉我触摸事件发生在 (189.0, 335.0),但 ball.position 会告诉我 (0.0, 0.0)。如何获取 ball 在视图坐标系中的位置?

import SpriteKit
import GameplayKit

class GameScene: SKScene 

    var touched = false
    var location = CGPoint.zero
    var ball: SKShapeNode = SKShapeNode(circleOfRadius: 15)
    var background: SKSpriteNode = SKSpriteNode(imageNamed: "background")

    override func didMove(to view: SKView) 
        background.size = frame.size
        background.position = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.height / 2)
        addChild(background)

        let path = CGMutablePath()
        path.addArc(center: CGPoint(x: view.frame.size.width / 2, y: view.frame.size.height / 2),
                    radius: 15,
                    startAngle: 0,
                    endAngle: CGFloat.pi * 2,
                    clockwise: false)
        ball = SKShapeNode(path: path) // Added to center of screen
        ball.lineWidth = 1
        ball.fillColor = .cyan
        ball.strokeColor = .cyan
        ball.glowWidth = 0.5
        addChild(ball)
        print(ball.position)
    


    override func update(_ currentTime: TimeInterval) 
        // Called before each frame is rendered
        moveNode()
    

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
        touched = true
        for touch in touches 
            location = touch.location(in: view)
        
    

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) 
        for touch in touches 
            location = touch.location(in: view)

        
    

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) 
        touched = false
    

    func moveNode() 
        if touched 
            let speed: CGFloat = 1
            if location.x < ball.position.x 
                let newLocation = ball.position.x - speed
                ball.position = CGPoint(x: newLocation, y: ball.position.y)
             else 
                let newLocation = ball.position.x + speed
                ball.position = CGPoint(x: newLocation, y: ball.position.y)
            
        
    

【问题讨论】:

如果您使用location = touch.location(in: self)location 将位于场景坐标而不是视图坐标中。 【参考方案1】:

您从未将球的位置设置为 (0,0)。问题是球在 (0,0) 处,但它的路径代表球坐标中 (189,335) 处的东西。 改为:

override func didMove(to view: SKView) 
    background.size = frame.size
    background.position = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.height / 2)
    addChild(background)

    let path = CGMutablePath()
    // construct a path relative to center of the ball
    path.addArc(center: CGPoint(x: 0, y: 0),
                radius: 15,
                startAngle: 0,
                endAngle: CGFloat.pi * 2,
                clockwise: false)
    ball = SKShapeNode(path: path)
    // locate the ball at the center of the screen
    ball.position = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.height / 2)
    ball.lineWidth = 1
    ball.fillColor = .cyan
    ball.strokeColor = .cyan
    ball.glowWidth = 0.5
    addChild(ball)
    print(ball.position)

【讨论】:

以上是关于SpriteKit 中坐标空间之间的转换问题的主要内容,如果未能解决你的问题,请参考以下文章

转载坐标转换收集的小资料

Cesium坐标系及转换

Spritekit - 屏幕坐标的底部

在 UIView 坐标系中快速转换坐标

这个 SpriteKit 设置中的坐标系有啥问题?

矩阵Matrix从Unity空间到UE4空间的转换推导