微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift中的SpriteKit物理学 – 球滑动而不是反射

在学习SpriteKit(使用Ray Wenderlich等人的教程中使用iOS游戏)的基础上,我已经创建了我自己的非常简单的测试游戏,以了解是否可以应用我学到的概念.我决定通过使用.sks文件来创建sprite节点并替换我的手动范围检查和与物理机构的碰撞来简化我的代码.

然而,我的球保持平行于墙壁/其他矩形(如同,简单地向上和向下滑动),任何时候它们以陡峭的角度与它们碰撞.这里是相关的代码 – 我把物理属性转移到代码中,使它们更加可见:

import SpriteKit

struct PhysicsCategory {
  static let None:        UInt32 = 0      //  0
  static let Edge:        UInt32 = 0b1    //  1
  static let Paddle:      UInt32 = 0b10   //  2
  static let Ball:        UInt32 = 0b100  //  4
}

var paddle: SKSpriteNode!
var ball: SKSpriteNode!

class GameScene: SKScene,SKPhysicsContactDelegate {

  override func didMovetoView(view: SKView) {

    physicsWorld.gravity = CGVector.zeroVector

    let edge = SKNode()
    edge.physicsBody = SKPhysicsBody(edgeLoopFromrect: frame)
    edge.physicsBody!.usesPreciseCollisionDetection = true
    edge.physicsBody!.categoryBitMask = PhysicsCategory.Edge
    edge.physicsBody!.friction = 0
    edge.physicsBody!.restitution = 1
    edge.physicsBody!.angulardamping = 0
    edge.physicsBody!.lineardamping = 0
    edge.physicsBody!.dynamic = false
    addChild(edge)

    ball = childNodeWithName("ball") as SKSpriteNode
    ball.physicsBody = SKPhysicsBody(rectangleOfSize: ball.size))
    ball.physicsBody!.usesPreciseCollisionDetection = true
    ball.physicsBody!.categoryBitMask = PhysicsCategory.Ball
    ball.physicsBody!.collisionBitMask = PhysicsCategory.Edge | PhysicsCategory.Paddle
    ball.physicsBody!.allowsRotation = false
    ball.physicsBody!.friction = 0
    ball.physicsBody!.restitution = 1
    ball.physicsBody!.angulardamping = 0
    ball.physicsBody!.lineardamping = 0

    physicsWorld.contactDelegate = self
}

忘了提到这个以前,但我添加一个简单的touchesBegan功能来调试弹跳 – 它只是调整速度来指向球在接触点:

override func touchesBegan(touches: NSSet,withEvent event: UIEvent) {
  let touch = touches.anyObject() as UITouch
  let movetoward = touch.locationInNode(self)
  let targetVector = (movetoward - ball.position).normalized() * 300.0
  ball.physicsBody!.veLocity = CGVector(point: targetVector)
}

normalized()函数只是将球/触摸位置增量减小到单位向量,并且有一个减号运算符的覆盖,允许CGPoint减法.

球/边缘碰撞应该始终以正确相反的角度反射球,但是由于某种原因,球真的似乎有一个直角的东西.我当然可以实现一些解决方法来手动反映球的角度,但重要的是我想使用SpriteKit中的内置物理功能来做到这一点.有没有什么明显的,我失踪了?

这似乎是碰撞检测的问题.大多数人通过使用didBeginContact找到解决方案,并以相反的方向重新施加力.注意他说didMovetoView,但是在后来的评论中纠正了自己做的BeginContact.

请参阅Ray Wenderlich教程here底部的注释

I have a fix for the problem with the ball “riding the rail” if it
strikes at a shallow angle (@aziz76 and @colinf). I added another
category,“BorderCategory” and assigned it to the border PhysicsBody
we create in didMovetoView.

一个类似的SO问题here解释为什么发生.

Even if you do that,though,many physics engines (including
SpriteKit’s) have trouble with situations like this because of
floating point rounding errors. I’ve found that when I want a body to
keep a constant speed after a collision,it’s best to force it to —
use a didEndContact: or didSimulatePhysics handler to reset the moving
body’s veLocity so it’s going the same speed it was before the
collision (but in the opposite direction).

另外我注意到,你正在使用一个正方形,而不是一个圆圈,你可能会考虑使用…

ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2)

所以原来你并不疯狂,总是很好的从别人听到,希望这将帮助您找到一个最适合您的应用程序的解决方案.

原文地址:https://www.jb51.cc/swift/318888.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐