对象位置不匹配(Spritekit)

Objects Position Not Matching Up (Spritekit)

我正在构建一个 spritekit 游戏并且刚刚开始这个项目。我在屏幕上有一个从中心开始的圆圈,当我从圆圈向外拖动我的手指时,它会显示一个与球相连的虚线 line/bezierpath,这将帮助用户看到球的瞄准位置.当用户抬起手指时,球将朝瞄准线的相反方向射出。 (想想足球明星或桌球之类的游戏)。问题是当一切都从中间开始时,这个动作第一次起作用:我拖动我的手指,球向相反的方向射击然后停止。但是当我再次尝试时,瞄准线的位置说它与球相同(应该是),但随后它在屏幕上显示离球一英寸远。我觉得这可能是物体后面的场景大小可能不同的问题?但是我很困惑,因为我认为我只使用了一个场景。

GameViewController viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()

    if let view = self.view as! SKView? {
        // Load the SKScene from 'GameScene.sks'
        if let scene = SKScene(fileNamed: "GameScene") {
            // Set the scale mode to scale to fit the window
            scene.scaleMode = .aspectFill
            scene.size = view.bounds.size
            //scene.anchorPoint = CGPoint(x: 0.0, y: 0.0)


            // Present the scene
            view.presentScene(scene)
        }

        view.ignoresSiblingOrder = true

        view.showsFPS = true
        view.showsNodeCount = true
    }
}

GameScene 代码(怀疑您是否需要所有代码,但无论如何):

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    var ball = SKShapeNode(circleOfRadius: 35)
    var touchingBall = false
    var aimLine = SKShapeNode()

    var startAimPoint = CGPoint()
    var endAimPoint = CGPoint()

    let damping:CGFloat = 0.94

    override func didMove(to view: SKView) {

        ball.fillColor = SKColor.orange
        ball.name = "ball"

        let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        borderBody.friction = 0
        self.physicsBody = borderBody
        physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)

        var physicsBody = SKPhysicsBody(circleOfRadius: 35)
        ball.physicsBody = physicsBody
        ball.physicsBody?.affectedByGravity = false
        ball.physicsBody?.friction = 10.0

        ball.position = CGPoint(x: frame.midX, y: frame.midY)

        self.addChild(ball)
    }


    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("TOUCHES BEGAN.")
        for touch in touches {
            print("TB: \(touchingBall)")
            let location = touch.location(in: self)
            let node : SKNode = self.atPoint(location)
            if node.name == "ball" {
                // touched inside node
                if ball.physicsBody!.angularVelocity <= 0.0{
                    touchingBall = true

                    startAimPoint = ball.position

                    print(touchingBall)
                }
            }
        }

    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("TOCUHES MOVED.")
        for touch in touches {
            let location = touch.location(in: self)
            if touchingBall{
                endAimPoint = location

                assignAimLine(start: startAimPoint, end: endAimPoint)
                print("Moving touched ball")

            }
        }

    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("Touches ended. \(touchingBall)")
        if touchingBall == true{

            ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x - startAimPoint.x) * 3, dy: -(endAimPoint.y - startAimPoint.y) * 3))

        }

        touchingBall = false
        aimLine.removeFromParent()
        print(touchingBall)

    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {

        print("Touches cancelled. \(touchingBall)")
        if touchingBall == true{

            ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x - startAimPoint.x) * 3, dy: -(endAimPoint.y - startAimPoint.y) * 3))

        }

        touchingBall = false
        aimLine.removeFromParent()
        print(touchingBall)

    }


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

        print(ball.physicsBody!.velocity)
        let dx2 = ball.physicsBody!.velocity.dx * damping
        let dy2 = ball.physicsBody!.velocity.dy * damping
        ball.physicsBody!.velocity = CGVector(dx: dx2, dy: dy2)


    }
    func assignAimLine(start: CGPoint, end: CGPoint){

        aimLine.removeFromParent()

        var bezierPath = UIBezierPath()
        bezierPath.move(to: start)
        bezierPath.addLine(to: shortenedEnd(startPoint: start, endPoint: end))

        var pattern : [CGFloat] = [10.0, 10.0]
        let dashed = SKShapeNode(path: bezierPath.cgPath.copy(dashingWithPhase: 2, lengths: pattern))

        aimLine = dashed
        aimLine.position = ball.position

        aimLine.zPosition = 0

        self.addChild(aimLine)



    }
    func hypotenuse(bp: UIBezierPath) -> Double{
        var a2 = bp.cgPath.boundingBox.height * bp.cgPath.boundingBox.height
        var b2 = bp.cgPath.boundingBox.width * bp.cgPath.boundingBox.width
        return Double(sqrt(a2 + b2))
    }
    func hypotenuse(startP: CGPoint, endP: CGPoint) -> Double{
        var bezierPath = UIBezierPath()
        bezierPath.move(to: startP)
        bezierPath.addLine(to: endP)
        return hypotenuse(bp: bezierPath)
    }
    func shortenedEnd(startPoint: CGPoint, endPoint: CGPoint) -> CGPoint{

        var endTemp = endPoint
        //while hypotenuse(startP: startPoint, endP: endTemp) > 150{
                endTemp = CGPoint(x: endTemp.x / 1.01, y: endTemp.y / 1.01)
        //}
        return endTemp
    }
    func addTestPoint(loc: CGPoint, color: UIColor){
        var temp = SKShapeNode(circleOfRadius: 45)
        temp.fillColor = color
        temp.position = loc
        self.addChild(temp)

    }
}

我尝试打印场景的帧大小,它说 400 x 700(我正在 iPhone 6 Plus 上测试),它说 UIScreen 大小相同,所以我不知道什么问题。总的来说,我只需要瞄准线在圆心上,而不是第一次尝试这个动作时。谢谢

正如我在评论中提到的,您的问题在于您如何布置路径。下面的代码使路径相对于球而不是绝对的场景。我还解决了每次创建新形状的问题。

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    var ball = SKShapeNode(circleOfRadius: 35)
    var touchingBall = false
    var aimLine = SKShapeNode()

    var endAimPoint = CGPoint()


    override func didMove(to view: SKView) {

        ball.fillColor = SKColor.orange
        ball.name = "ball"

        let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        borderBody.friction = 0
        self.physicsBody = borderBody
        physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
        ball.position = CGPoint(x: frame.midX, y: frame.midY)

        let physicsBody = SKPhysicsBody(circleOfRadius: 35)
        physicsBody.affectedByGravity = false
        physicsBody.friction = 10.0
        physicsBody.linearDamping = 0.94
        ball.physicsBody = physicsBody

        self.addChild(ball)
    }


    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("TOUCHES BEGAN.")
        for touch in touches {
            print("TB: \(touchingBall)")
            let location = touch.location(in: self)
            let node : SKNode = self.atPoint(location)
            if node.name == "ball" {
                // touched inside node
                if ball.physicsBody!.angularVelocity <= 0.0{
                    touchingBall = true
                    aimLine.path = nil
                    self.addChild(aimLine)

                    print(touchingBall)
                }
            }
        }

    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("TOCUHES MOVED.")
        for touch in touches {
            let location = touch.location(in: self)
            if touchingBall{
                endAimPoint = self.convert(location, to: ball)
                assignAimLine(end: endAimPoint)
                print("Moving touched ball")

            }
        }

    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("Touches ended. \(touchingBall)")
        if touchingBall == true{
            ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x) * 3, dy: -(endAimPoint.y) * 3))
        }

        touchingBall = false

        aimLine.removeFromParent()
        print(touchingBall)

    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {

        print("Touches cancelled. \(touchingBall)")
        if touchingBall == true{

            ball.physicsBody!.applyImpulse(CGVector(dx: -(endAimPoint.x) * 3, dy: -(endAimPoint.y) * 3))

        }

        touchingBall = false
        aimLine.removeFromParent()
        print(touchingBall)

    }


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

        print(ball.physicsBody!.velocity)
        //let dx2 = ball.physicsBody!.velocity.dx * damping
        //let dy2 = ball.physicsBody!.velocity.dy * damping
        //ball.physicsBody!.velocity = CGVector(dx: dx2, dy: dy2)


    }
    func assignAimLine(end: CGPoint){


        let bezierPath = UIBezierPath()
        bezierPath.move(to: CGPoint.zero)
        bezierPath.addLine(to: end)

        let pattern : [CGFloat] = [10.0, 10.0]


        aimLine.position = ball.position
        aimLine.path = bezierPath.cgPath.copy(dashingWithPhase: 2, lengths: pattern)
        aimLine.zPosition = 0



    }

    func addTestPoint(loc: CGPoint, color: UIColor){
        var temp = SKShapeNode(circleOfRadius: 45)
        temp.fillColor = color
        temp.position = loc
        self.addChild(temp)

    }
}