SKSpitekit 节点之间未检测到碰撞
collision not detected between SKSpitekit nodes
我正在建造一个迷宫,我为墙壁添加了一些 SKSpritekit 节点,为玩家添加了一个点。然而,当点和墙壁发生碰撞时,不会检测到碰撞。我的代码如下:
import UIKit
import SpriteKit
import GameplayKit
import Foundation
import GameplayKit
class level1: SKScene, SKPhysicsContactDelegate {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
var dot = SKSpriteNode()
override func sceneDidLoad () {
buildMaze()
addDot()
func addDot() {
let startNum = x * (y - 1)
startCoord = coordArray[startNum]
dot = SKSpriteNode(imageNamed: "redDot")
dot.physicsBody?.isDynamic = true
dot.size = CGSize(width: 20, height: 20)
dot.position = startCoord
dot.physicsBody = SKPhysicsBody(circleOfRadius: 10)
dot.physicsBody?.mass = 0
dot.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(dot)
}
func buildMaze() {
let difference = coordArray[1].x - coordArray[0].x
let wallDistance = difference/2
let thickness = CGFloat(3)
let length = difference - CGFloat(thickness)/2
var count = 0
for point in coordArray {
let northWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: length, height: thickness))
northWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: length, height: thickness))
northWall.physicsBody?.mass = 200000
let southWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: length, height: thickness))
southWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: length, height: thickness))
southWall.physicsBody?.mass = 200000
let eastWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: thickness, height: length ))
eastWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: thickness, height: length))
eastWall.physicsBody?.mass = 200000
let westWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: thickness, height: length ))
westWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: thickness, height: length))
westWall.physicsBody?.mass = 200000
if !instructions[count].contains("N") {
//print("added north wall")
northWall.position = CGPoint (x: point.x , y: point.y + wallDistance)
if nodes(at: northWall.position) == [] {
addChild(northWall)}
else {print("north wall already there")}
}
if !instructions[count].contains("S") {
//print("added south wall")
southWall.position = CGPoint (x: point.x , y: point.y - wallDistance)
if nodes(at: southWall.position) == [] {
addChild(southWall)}
else {//print("southwall already there")
}
}
if !instructions[count].contains("E") {
//print("added east wall")
eastWall.position = CGPoint (x: point.x + wallDistance , y: point.y)
if nodes(at: eastWall.position) == [] {
addChild(eastWall)}
else {//print("east already there")
}
}
if !instructions[count].contains("W") {
//print("added west wall")
westWall.position = CGPoint (x: point.x - wallDistance , y: point.y)
if nodes(at: westWall.position) == [] {
addChild(westWall)}
else {//print("west wall already there")
}
}
count = count + 1
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches {
let location = t.location(in: self)
dot.position.x = location.x
dot.position.y = location.y
}
}
func didBegin(_ contact: SKPhysicsContact) {
print("contact!")
}
墙的样子和我想要的一样,点也在正确的位置。
我为它们中的每一个添加了 20000 的 masso,这样当我移动点时,墙壁会保持原位。然而,当我用手指移动圆点时,它直接穿过迷宫的墙壁,而不是被它们停下来。
我在 didBegin 函数中添加了一个打印语句,以查看它是否至少检测到精灵之间的任何接触,但它没有。
这是为什么?
干杯!
当您直接设置精灵的位置时,碰撞和接触检测效果不佳。
在您的代码中,行:
dot.position.x = location.x
dot.position.y = location.y
直接设置 dot
的位置,覆盖物理引擎想要对对象执行的任何操作。
此外,您似乎没有设置任何必要的类别或 collision/contactTest 位掩码。
您允许手动移动点,但要检测与墙壁的接触,那么您可能需要查看屏幕上的触摸是否在墙内,如果是的话则不要移动点。 (这意味着您根本没有使用物理学)。
编辑:我的碰撞和接触分步指南:
以及碰撞和接触测试位掩码指南:
首先在你的didMoveTo或者sceneDidLoad中,你需要设置physicsContactDelegate:
override func sceneDidLoad () {
physicsWorld.contactDelegate = self
buildMaze()
addDot()
}
要设置 contact/collision 掩码,你必须这样做,因为它们是基于位运算的:
假设您想要 dot 和 walls[ 之间的碰撞=44=]
struct PhysicsCategory {
static let wall: UInt32 = 0x1 << 1
static let dot: UInt32 = 0x1 << 2
}
You can put the struct above you class if you want
然后,当你分配物理体时,你必须设置位掩码:
对于点:
dot.physicsBody?.categoryBitMask = PhysicsCategory.dot
dot.physicsBody?.contactTestBitMask = PhysicsCategory.wall
dot.physicsBody?.collisionBitMask = PhysicsCategory.wall
//Collision is different from contact, so if you want to avoid collision
//dot.physicsBody?.collisionBitMask = PhysicsCategory.dot
碰撞不同于接触,检查apple documentation about it
墙面:
northWall.physicsBody?.categoryBitMask = PhysicsCategory.wall
northWall.physicsBody?.contactTestBitMask = PhysicsCategory.dot
northWall.physicsBody?.collisionBitMask = PhysicsCategory.dot
//Do the same for all walls
如果您希望墙壁与多个物体接触或碰撞:
northWall.physicsBody?.contactTestBitMask = PhysicsCategory.dot | PhysicsCategory.other
northWall.physicsBody?.collisionBitMask = PhysicsCategory.dot | PhysicsCategory.other
对于墙是有效的,所有考虑都按点
我正在建造一个迷宫,我为墙壁添加了一些 SKSpritekit 节点,为玩家添加了一个点。然而,当点和墙壁发生碰撞时,不会检测到碰撞。我的代码如下:
import UIKit
import SpriteKit
import GameplayKit
import Foundation
import GameplayKit
class level1: SKScene, SKPhysicsContactDelegate {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
var dot = SKSpriteNode()
override func sceneDidLoad () {
buildMaze()
addDot()
func addDot() {
let startNum = x * (y - 1)
startCoord = coordArray[startNum]
dot = SKSpriteNode(imageNamed: "redDot")
dot.physicsBody?.isDynamic = true
dot.size = CGSize(width: 20, height: 20)
dot.position = startCoord
dot.physicsBody = SKPhysicsBody(circleOfRadius: 10)
dot.physicsBody?.mass = 0
dot.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(dot)
}
func buildMaze() {
let difference = coordArray[1].x - coordArray[0].x
let wallDistance = difference/2
let thickness = CGFloat(3)
let length = difference - CGFloat(thickness)/2
var count = 0
for point in coordArray {
let northWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: length, height: thickness))
northWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: length, height: thickness))
northWall.physicsBody?.mass = 200000
let southWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: length, height: thickness))
southWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: length, height: thickness))
southWall.physicsBody?.mass = 200000
let eastWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: thickness, height: length ))
eastWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: thickness, height: length))
eastWall.physicsBody?.mass = 200000
let westWall = SKSpriteNode(color: SKColor.black, size : CGSize (width: thickness, height: length ))
westWall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: thickness, height: length))
westWall.physicsBody?.mass = 200000
if !instructions[count].contains("N") {
//print("added north wall")
northWall.position = CGPoint (x: point.x , y: point.y + wallDistance)
if nodes(at: northWall.position) == [] {
addChild(northWall)}
else {print("north wall already there")}
}
if !instructions[count].contains("S") {
//print("added south wall")
southWall.position = CGPoint (x: point.x , y: point.y - wallDistance)
if nodes(at: southWall.position) == [] {
addChild(southWall)}
else {//print("southwall already there")
}
}
if !instructions[count].contains("E") {
//print("added east wall")
eastWall.position = CGPoint (x: point.x + wallDistance , y: point.y)
if nodes(at: eastWall.position) == [] {
addChild(eastWall)}
else {//print("east already there")
}
}
if !instructions[count].contains("W") {
//print("added west wall")
westWall.position = CGPoint (x: point.x - wallDistance , y: point.y)
if nodes(at: westWall.position) == [] {
addChild(westWall)}
else {//print("west wall already there")
}
}
count = count + 1
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches {
let location = t.location(in: self)
dot.position.x = location.x
dot.position.y = location.y
}
}
func didBegin(_ contact: SKPhysicsContact) {
print("contact!")
}
墙的样子和我想要的一样,点也在正确的位置。
我为它们中的每一个添加了 20000 的 masso,这样当我移动点时,墙壁会保持原位。然而,当我用手指移动圆点时,它直接穿过迷宫的墙壁,而不是被它们停下来。
我在 didBegin 函数中添加了一个打印语句,以查看它是否至少检测到精灵之间的任何接触,但它没有。
这是为什么?
干杯!
当您直接设置精灵的位置时,碰撞和接触检测效果不佳。
在您的代码中,行:
dot.position.x = location.x
dot.position.y = location.y
直接设置 dot
的位置,覆盖物理引擎想要对对象执行的任何操作。
此外,您似乎没有设置任何必要的类别或 collision/contactTest 位掩码。
您允许手动移动点,但要检测与墙壁的接触,那么您可能需要查看屏幕上的触摸是否在墙内,如果是的话则不要移动点。 (这意味着您根本没有使用物理学)。
编辑:我的碰撞和接触分步指南:
以及碰撞和接触测试位掩码指南:
首先在你的didMoveTo或者sceneDidLoad中,你需要设置physicsContactDelegate:
override func sceneDidLoad () {
physicsWorld.contactDelegate = self
buildMaze()
addDot()
}
要设置 contact/collision 掩码,你必须这样做,因为它们是基于位运算的:
假设您想要 dot 和 walls[ 之间的碰撞=44=]
struct PhysicsCategory {
static let wall: UInt32 = 0x1 << 1
static let dot: UInt32 = 0x1 << 2
}
You can put the struct above you class if you want
然后,当你分配物理体时,你必须设置位掩码:
对于点:
dot.physicsBody?.categoryBitMask = PhysicsCategory.dot
dot.physicsBody?.contactTestBitMask = PhysicsCategory.wall
dot.physicsBody?.collisionBitMask = PhysicsCategory.wall
//Collision is different from contact, so if you want to avoid collision
//dot.physicsBody?.collisionBitMask = PhysicsCategory.dot
碰撞不同于接触,检查apple documentation about it
墙面:
northWall.physicsBody?.categoryBitMask = PhysicsCategory.wall
northWall.physicsBody?.contactTestBitMask = PhysicsCategory.dot
northWall.physicsBody?.collisionBitMask = PhysicsCategory.dot
//Do the same for all walls
如果您希望墙壁与多个物体接触或碰撞:
northWall.physicsBody?.contactTestBitMask = PhysicsCategory.dot | PhysicsCategory.other
northWall.physicsBody?.collisionBitMask = PhysicsCategory.dot | PhysicsCategory.other
对于墙是有效的,所有考虑都按点