对象位置不匹配(Spritekit)

时间:2018-07-31 12:43:13

标签: swift sprite-kit position frame skscene

我正在构建一个Spritekit游戏,并且刚刚开始该项目。我在屏幕上有一个从中心开始的圆圈,当我从圆圈向外拖动手指时,它将显示连接到球的虚线/贝塞尔曲线,这将有助于用户查看瞄准球的位置。当用户抬起手指时,球将朝着瞄准线的相反方向射击。 (例如,像足球明星或台球这样的游戏)。问题是,当一切都从中间开始时,该操作首次生效:我拖动手指,球朝相反的方向射击,然后停止。但是,当我再次尝试时,瞄准线的位置说它与球相同(应该是),但随后它在屏幕上的显示距离球只有一英寸。我觉得这可能是一个问题,即物体后面的场景可能大小不一样?但是我很困惑,因为我认为我只使用一个场景。

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是相同的大小,所以我不知道是什么问题。总的来说,我只需要瞄准线不在圆心上,这不仅仅是我第一次尝试该机动时。谢谢。

1 个答案:

答案 0 :(得分:1)

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

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)

    }
}