使用 SpriteKit 抛出一个对象

Throwing an object with SpriteKit

我目前有以下代码。即使代码构建成功,我似乎也无法让它工作。我试图做到这一点,当你轻弹物体时,它会以你开始和结束触摸的速度移动。

import SpriteKit
class GameScene: SKScene {
    var sprite: SKSpriteNode!
    var touchPoint: CGPoint = CGPoint()
    var touching: Bool = false
    override func didMoveToView(view: SKView) {
        self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
        sprite = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 50))
        sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
        sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
        self.addChild(sprite)
    }

    //for touch: AnyObject in touches {
    //let location = touch.locationInNode(self)
    //let touchedNode = self.nodeAtPoint(location)

     override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {

        let location = touch.locationInNode(self)
        if sprite.frame.contains(location) {
            touchPoint = location
            touching = true
        }
    }
    func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {
        let location = touch.locationInNode(self)
        touchPoint = location
    }
    func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
        touching = false
    }
    func update(currentTime: CFTimeInterval) {
        if touching {
            let dt:CGFloat = 1.0/60.0
            let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
            let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
            sprite.physicsBody!.velocity = velocity
        }
    }
}}}

您不小心将 touchesMovedtouchesEndedupdate 放在了 touchesBegan 中。除此之外,您的代码有效。存在问题的一个暗示是您不需要在 touchesMovedtouchesEndedupdate 前加上 override 前缀。

以后我会推荐使用断点和打印语句来检查你期望执行的方法,实际上是运行。这样做你会看到你的 touchesMovedtouchesEndedupdate 版本没有被调用。

无论如何,这里已更正它,现在可以完美运行了:

import SpriteKit
class GameScene: SKScene {
    var sprite: SKSpriteNode!
    var touchPoint: CGPoint = CGPoint()
    var touching: Bool = false
    override func didMoveToView(view: SKView) {
        self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
        sprite = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 50))
        sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
        sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
        self.addChild(sprite)
    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {

            let location = touch.locationInNode(self)
            if sprite.frame.contains(location) {
                touchPoint = location
                touching = true
            }
        }
    }

    override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)
            touchPoint = location
        }
    }

    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
        touching = false
    }

    override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
        touching = false
    }

    override func update(currentTime: NSTimeInterval) {
        if touching {
            let dt:CGFloat = 1.0/60.0
            let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
            let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
            sprite.physicsBody!.velocity = velocity
        }
    }
}

ABakerSmith 的解决方案更新为 Swift 4:

import SpriteKit
class GameScene: SKScene {
    var sprite: SKSpriteNode!
    var touchPoint: CGPoint = CGPoint()
    var touching: Bool = false
    override func didMove(to view: SKView) {
        self.physicsBody = SKPhysicsBody.init(edgeLoopFrom: self.frame)
        sprite = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
        sprite.physicsBody = SKPhysicsBody.init(rectangleOf: sprite.size)
        sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
        self.addChild(sprite)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first?.location(in: self) {
            if sprite.frame.contains(touch) {
                touchPoint = touch
                touching = true
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches {
            let location = t.location(in: self)
            touchPoint = location
        }
    }

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

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

    override func update(_ currentTime: TimeInterval) {
        if touching {
            let dt:CGFloat = 1.0/60.0
            let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
            let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
            sprite.physicsBody!.velocity = velocity
        }
    }
}

解决方案已更新,不再 touch/drag 捕捉到 sprite 的中间。如果你是 dragging/throwing 一个对象,你会希望从用户触摸对象的地方抛出,而不是捕捉到对象的中间。这会让它看起来更平滑

import SpriteKit
class GameScene: SKScene {
    var sprite: SKSpriteNode!
    var touchPoint: CGPoint = CGPoint()
    var touching: Bool = false
    var xDif = CGFloat()
    var yDif = CGFloat()

    override func didMove(to view: SKView) {
        self.physicsBody = SKPhysicsBody.init(edgeLoopFrom: self.frame)
        sprite = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
        sprite.physicsBody = SKPhysicsBody.init(rectangleOf: sprite.size)
        sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
        self.addChild(sprite)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first?.location(in: self) {
            xDif = sprite.position.x - touch.x
            yDif = sprite.position.y - touch.y

            if sprite.frame.contains(touch) {
                touchPoint = touch
                touching = true
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches {
            let location = t.location(in: self)
            touchPoint = location
        }
    }

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

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

    override func update(_ currentTime: TimeInterval) {
        if touching {
            let dt:CGFloat = 1.0/60.0
            let distance = CGVector(dx: touchPoint.x-sprite.position.x + xDif, dy: touchPoint.y-sprite.position.y + yDif)
            let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
            sprite.physicsBody!.velocity = velocity
        }
    }
}