我试图对齐 SKSpriteNode 以匹配碰撞时 PhysicsBody 的“撞击表面”。
我正在做的是将 SpriteNode 射向立方体。我已经设置了碰撞和节点附件(固定关节)。 一切正常,但我需要找到一种方法来旋转 spriteNode 以匹配命中表面,如下所示:
请注意,立方体可以旋转等,因此我们并不总是在立方体上有固定的旋转值。
有什么解决办法吗?
提前致谢 /马格纳斯
最佳答案
以下是我认为可行的大部分答案。稍后我会更新。
基本上,目标是将两个粘性节点分别放置在接触点的磁铁和立方体上。
然后,您将磁铁的 zRotation 与立方体的旋转相匹配,然后根据两个粘性节点的位置将磁铁与立方体对齐。
我还没有完成旋转匹配或粘性对齐,但是如果你想完成其他一切都在这里,直到我稍后再做:
// Props:
class GameScene: SKScene, SKPhysicsContactDelegate {
struct Category {
static let
border = UInt32(2),
cube = UInt32(4),
magnet = UInt32(8)
}
let names = (border: "border", cube: "cube", magnet: "magnet", stickyPoint: "stickyPoint")
var flag_hitThisSimulation = false
}
// Setup:
extension GameScene {
private func setupNodes() {
border: do {
let pb = SKPhysicsBody(edgeLoopFrom: frame)
pb.categoryBitMask = Category.border
physicsBody = pb
}
cube: do {
let cubeNode = SKSpriteNode(color: .blue, size: CGSize(width: 150, height: 150))
let pb = SKPhysicsBody(rectangleOf: cubeNode.size)
pb.affectedByGravity = false
pb.isDynamic = false
pb.categoryBitMask = Category.cube
pb.contactTestBitMask = Category.magnet
cubeNode.physicsBody = pb
cubeNode.position.y += 200
cubeNode.name = names.cube
cubeNode.run(.repeatForever(.rotate(byAngle: 3.14, duration: 3)))
addChild(cubeNode)
}
magnet: do {
let magnetNode = SKSpriteNode(color: .green, size: CGSize(width: 50, height: 12))
let pb = SKPhysicsBody(rectangleOf: magnetNode.size)
pb.categoryBitMask = Category.magnet
pb.affectedByGravity = false
magnetNode.physicsBody = pb
magnetNode.name = names.magnet
addChild(magnetNode)
}
}
override func didMove(to view: SKView) {
removeAllChildren()
physicsWorld.contactDelegate = self
setupNodes()
}
}
// Physics:
extension GameScene {
private func assignNodeOfName(_ name: String, contact: SKPhysicsContact) -> SKNode? {
guard let nodeA = contact.bodyA.node, let nodeB = contact.bodyB.node else { fatalError("how are there no nodes?") }
if nodeA.name == name { return nodeA }
else if nodeB.name == name { return nodeB }
else { return nil }
}
private func addNodeToPoint(_ point: CGPoint, parent: SKNode) {
let node = SKSpriteNode(color: .orange, size: CGSize(width: 5, height: 5))
node.position = point
node.name = names.stickyPoint
parent.addChild(node)
}
func alignMagnetToCube() {
}
func didBegin(_ contact: SKPhysicsContact) {
defer { flag_hitThisSimulation = true }
if flag_hitThisSimulation { return }
let contactedNodes = contact.bodyA.categoryBitMask + contact.bodyB.categoryBitMask
switch contactedNodes {
case Category.magnet + Category.cube:
// Place the two sticky nodes:
let cube = assignNodeOfName(names.cube, contact: contact)!
let magnet = assignNodeOfName(names.magnet, contact: contact)!
let cubePoint = convert(contact.contactPoint, to: cube)
let magnetPoint = convert(contact.contactPoint, to: magnet)
addNodeToPoint(cubePoint, parent: cube)
addNodeToPoint(magnetPoint, parent: magnet)
// Set the magnet's zRotation to the cube's zRotation, then align the two stickyNodes:
// fluidity.SLEEPY(for: now)
// finish.later()
default: ()
}
}
}
// Game loop:
extension GameScene {
// Change to touchesBegan for iOS:
override func mouseDown(with event: NSEvent) {
let magnet = childNode(withName: names.magnet) as! SKSpriteNode
// Start simulation:
magnet.removeAllActions()
magnet.physicsBody!.applyImpulse(CGVector(dx: 0, dy: 25))
// End simulation:
magnet.run(.wait(forDuration: 2)) {
print("resetting simulation! \(event.timestamp)")
magnet.physicsBody!.velocity = CGVector.zero
magnet.zRotation = 0 // FIXME: This isn't working..
magnet.position = CGPoint.zero
self.flag_hitThisSimulation = false
// Remove sticky nodes:
for node in self.children {
for childNode in node.children {
if childNode.name == self.names.stickyPoint { childNode.removeFromParent() }
}
}
}
}
}
关于ios - 将 SpriteNode 与碰撞表面对齐 SpriteKit Swift3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44986417/