我是sprite kit的新手。我曾尝试用2名球员进行简单的球弹跳比赛,另一名球员慢慢跟踪球。但我发现了一个问题。当我将线移动到球(带边缘)时,球从屏幕上消失。另一次不是问题,球弹跳。有什么问题?
我有一个GameScene,sks和ViewController。我的精灵节点来自sks。如果有人解释这个案子。会更好。我已经附上了我在下面做的事情。
我的GameScene:
class GameScene: SKScene {
var ball = SKSpriteNode()
var enemy = SKSpriteNode()
var main = SKSpriteNode()
override func didMove(to view: SKView) {
ball = self.childNode(withName: "ball") as! SKSpriteNode
enemy = self.childNode(withName: "enemy") as! SKSpriteNode
main = self.childNode(withName: "main") as! SKSpriteNode
ball.physicsBody?.applyImpulse(CGVector(dx: -20, dy: -20))
ball.physicsBody?.linearDamping = 0
ball.physicsBody?.angularDamping = 0
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.5))
}
查看控制器:
class GameViewController: UIViewController {
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
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
}
}
override var prefersStatusBarHidden: Bool {
return true
}
打击垫设置:
球设置:
一些更新
我在更新功能中尝试了一些消息,然后遇到同样的情况,球从设备的左侧出来(使用iPhone 6S)
2016-12-08 14:27:54.436485 Pong [14261:3102941]致命错误:球出界:文件
答案 0 :(得分:2)
你正在和敌人一起把球撞到墙上。这意味着力最终足以产生足够的球移动速度/力来克服物理系统,因此它会穿过墙壁。如果你让敌人在将球撞向墙壁之前停下来,你应该没事。
由于这行代码而发生这种“引脚”:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.5))
这使得敌人追逐球,这对于一场球赛来说是一个好主意,但是因为它被移动的方式是错误的。使用动作意味着敌人有无限的力量施加在它上面,并且瞄准球的中间。
所以当球到达墙壁时,它会被一个拥有无限静力的物理物体挡住,然后这个敌人出现并从另一侧施加无限的力......然后球在敌人的范围内弹出或者在墙的另一边,因为它被无限的力量压碎了。
所以要么你需要非常好地照顾你如何使用行动来控制敌人,或者使用力来控制敌人,因为这些不会是无限的,物理系统将能够击退敌人
答案 1 :(得分:1)
重现问题有多容易?在update()
中,打印球的位置以查看它“消失”时的位置。 (这将产生大量输出,因此请注意)。
根据您发布的内容,看起来球似乎不会与边界碰撞,这意味着球不会对边框做出反应(即反弹)并且边框本身不会移动(因为它是边缘)基于物理的身体)。这一点,加上高速球(来自一次重击)可能会让你用'主'精灵击中球很可能已经穿过边界 - 使用preciseCollisionDetection=true
可以解决这个问题但是给出首先是边界类别,然后将其添加到球的collisionBitMask
。
答案 2 :(得分:1)
这是史蒂夫所说的(在你的.update()
)
if ball.position.x > frame.maxX { fatalError(" ball out of right bounds") }
if ball.position.x < frame.minX { fatalError(" ball out of left bounds") }
if ball.position.y > frame.maxY { fatalError(" ball out of top bounds") }
if ball.position.y < frame.minY { fatalError(" ball out of bottom bounds) }
您也可以将调试窗口垃圾邮件:
print(ball.position)
这将帮助您了解发生了什么 - 如果您的球飞过边界,或者它在某处被摧毁,或者其他可能的错误。
作为一种解决方法(目前)我只会替换上面的&#34; fatalError&#34;用&#34; ball.position = CGPoint(x: 0, y: 0)
&#34;或者其他一些职位来重置&#34;球在它迷路的情况下。
您甚至可以将其存储在变量中的最后位置,然后将其恢复为上述if语句触发时的位置。
var lastBallLocation = CGPoint(x: 0, y: 0) // Just to initialize
override func update( prams ) {
if ball.position.x > frame.maxX { ball.position = lastBallLocation }
// .. copy the other three cases
lastBallLocation = ball.position // update only on successful position
或者,您可以尝试使墙壁更厚(使用形状节点或spritenode并将它们放置在框架的外部,例如房屋的墙壁,并且您在屏幕上的视图是&#34;房间&#34 ;)
每个墙都有一个弹跳的物理体: