用 SpriteKit 抛出一个对象
Posted
技术标签:
【中文标题】用 SpriteKit 抛出一个对象【英文标题】:Throwing an object with SpriteKit 【发布时间】:2015-05-22 11:03:19 【问题描述】:我目前有以下代码。即使代码构建成功,我似乎也无法让它工作。我正在努力做到这一点,因此当您轻弹对象时,它会以您开始和结束触摸的速度移动。
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
【问题讨论】:
不是 100% 确定这会有所帮助,但我认为您只想在完成轻弹后应用速度。因为您正在应用每个更新,所以您正在应用非常小的速度。您可能想尝试在 touchesMoved 中更改精灵的位置,然后根据距起点和终点的距离在 touches 结束时应用速度。您也可以根据电影的开始时间和电影的结束时间来确定它。如果你解释你得到的结果不是它的构建,也可能会有所帮助:) 在这里查看我的答案! ***.com/a/28259980/2158465 how to throw SKSpriteNode?的可能重复 【参考方案1】:您不小心将touchesMoved
、touchesEnded
和update
放在touchesBegan
中。除此之外,您的代码有效。存在问题的提示是,您不需要在 touchesMoved
、touchesEnded
或 update
前加上 override
。
以后,我会建议使用断点和打印语句来检查您期望执行的方法,实际上是在运行。这样做你会看到touchesMoved
、touchesEnded
和update
的版本没有被调用。
不管怎样,这里已经纠正了它,现在它可以完美地工作了:
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
【讨论】:
非常感谢!它现在可以工作了:) 快速的问题,我将如何制作它以便精灵在你轻弹它之前不会移动?所以你不能拖动它,所以它有一个原始位置? 我建议查看this 以获取有关获取手势识别器速度的信息(您可以使用与SKScene
中相同的方法)。然后你可以在touchesEnded
中给出精灵速度。另外,如果答案解决了您的问题,您会考虑将其标记为正确吗? :)
很高兴为您提供帮助 :) 祝您项目顺利!【参考方案2】:
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
【讨论】:
【参考方案3】:解决方案更新为不让触摸/拖动捕捉到精灵的中间。如果您正在拖动/投掷一个对象,您将希望该投掷来自用户触摸对象的位置,而不是捕捉到对象的中间。这会让它看起来更流畅
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
【讨论】:
以上是关于用 SpriteKit 抛出一个对象的主要内容,如果未能解决你的问题,请参考以下文章