【问题标题】:how to throw SKSpriteNode?如何抛出 SKSpriteNode?
【发布时间】:2015-03-30 12:07:18
【问题描述】:

所以基本上在我的游戏中我需要扔东西。到目前为止,我有一个精灵,它可以拖动但不能扔。游戏的想法是抛出一个精灵与另一个精灵碰撞。我想要我们称之为 testNode 的精灵,移动用户扔它的位置

意思是,当我释放精灵时,我希望它继续朝着我移动它的方向前进。我花了很长时间试图解决这个问题,但我做不到。我正在为 iOS 8+ 使用 SpriteKit。如果有人可以帮忙,请做。

我看到了一个视频,但它是与 GameSalad 相关的,这是另一个故事。你可以看看

https://www.youtube.com/watch?v=nn3lWa5jUGE

(如果您可能需要进一步联系,请回复)

import Foundation;
import SpriteKit;

class Level:SKScene {

TestNode:Test? //Test is a class I made

//Removed the update and touches began due to it being irrelevant to what I need help with. 

  override func didMoveToView(view: SKView){
    testNode = Fruit(imageNamed: "apple_idle")
    testNode?.position = CGPointMake(60, 294)
    testNode?.xScale = 0.5
    testNode?.yScale = 0.5
    self.addChild(testNode!)
  }
  override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {

    var nodeTouched = SKNode()
    var currentNodeTouched = SKNode()

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

        nodeTouched = self.nodeAtPoint(location)
        testNode?.position = location
    }
}

 override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {

    var touch: UITouch = touches.anyObject() as UITouch
    var location: CGPoint = touch.locationInNode(self) as CGPoint


}

【问题讨论】:

    标签: ios swift sprite-kit


    【解决方案1】:

    这是我写的一个简单的例子,它通过在游戏循环中模拟它的速度而不是直接设置位置来移动精灵。这使精灵更具动态性(即您可以“扔”它,并在拖动精灵时让它与其他物理体交互)。不需要角度计算,我只是计算在一段时间内将精灵移动到触摸位置所需的速度。在这种情况下,我将时间设置为 1/60,以便立即应用运动,使对象看起来非常灵敏。

    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) {
            let touch = touches.first as! UITouch
            let location = touch.locationInNode(self)
            if sprite.frame.contains(location) {
                touchPoint = location
                touching = true
            }
        }
        override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
            let touch = touches.first as! UITouch
            let location = touch.locationInNode(self)
            touchPoint = location
        }
        override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
            touching = false
        }
    
        override 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
            }
        }
    }
    

    您可以自己微调物理计算以获得所需的效果。但是这段代码应该足以让你开始。我能想到的一些增强功能可能会限制速度,这样物体在释放时就不会移动得太快。为触摸拖动添加延迟,以便移动精灵但在最后意外停止,继续抛出对象。

    【讨论】:

    • 非常感谢,它完美运行,你不知道我有多需要这个!
    • @Jesster2k10 太棒了,很高兴它成功了。如果您认为答案回答了您的问题,也请将答案标记为已接受。如果您需要任何其他帮助,请告诉我。
    • 我标记为已接受!我唯一的问题是,如果你触摸屏幕上的任何地方,精灵就会移动到那里。我真的不希望这种情况发生。如果精灵被触摸,我只想移动它。这里有更多的解释。 dropbox.com/s/evkzetluuucld8k/Apple.mov?dl=0
    • @Jesster2k10 这应该很简单,只需要检查点是否在精灵内部。我现在出去了,但是当我稍后回来时,我会为此更新代码。
    • @Jesster2k10 太好了!祝你的游戏好运。
    【解决方案2】:

    如果您正在拖动精灵,那么这应该不会太难。听起来您需要在游戏中添加一些物理特性。

    在设置 yScale 后将其添加到 testNode

    testNode.physicsBody = SKPhysicsBody(rectangleOfSize: testNode.size)
    

    现在运行游戏。您应该会看到 testNode 掉到屏幕底部。您不希望这种情况发生,因此我们将屏幕边框作为物理体。

    didMoveToView的顶部添加这个

    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    

    这将使屏幕边缘包含您的 testNode。你现在应该可以把它捡起来扔了

    您可能需要稍微调整一下这个公式才能真正抛出精灵。

    您可能需要比较上一次触摸位置和当前触摸位置,获取它们之间的角度并对精灵施加脉冲。

    【讨论】:

    • 天啊,没想到反应这么快。我会试试的
    • “用这个公式调整”是什么意思?
    • 我的意思是你必须写更多的代码和做更多的研究,但这会让你开始
    • 好的,有什么我应该看的文档或特定的类吗?
    • 这是一个很好的教程。你可以学习spritekit的物理引擎基础知识raywenderlich.com/49721/…
    【解决方案3】:

    这里是 Swift 3.0/ 4.0 版本的答案

    class GameScene: SKScene {
    var sprite: SKSpriteNode!
    var touchPoint: CGPoint = CGPoint()
    var touching: Bool = false
    override func didMove(to view: SKView) {
        let physicsFrame = CGRect(x: 0, y: 50, width: self.frame.size.width, height: self.frame.size.height - 100)
        self.physicsBody = SKPhysicsBody.init(edgeLoopFrom: physicsFrame)
        sprite = SKSpriteNode(color: UIColor.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?) {
        let touch = touches.first!
        let location = touch.location(in:self)
        if sprite.frame.contains(location) {
            touchPoint = location
            touching = true
        }
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first!
        let location = touch.location(in: self)
        touchPoint = location
    }
    
    override func touchesEnded(_ 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
        }
    }}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 2012-04-12
      • 2012-03-31
      • 1970-01-01
      • 2014-08-19
      相关资源
      最近更新 更多