Столкновение не обнаружено между узлами SKSpitekit
Я строю лабиринт, и я добавил несколько узлов 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 для каждого из них, чтобы при перемещении точки стены оставались на месте. однако, когда я двигаю точку пальцем, она просто проходит сквозь стены лабиринта, а не останавливается ими.
Я добавил оператор print в функцию didBegin, чтобы посмотреть, обнаруживает ли он хотя бы какой-нибудь контакт между спрайтами, но это не так.
Почему это?
ура!
2 ответа
Сначала в вашем didMoveTo или sceneDidLoad вам нужно установить PhysicsContactDelegate:
override func sceneDidLoad () {
physicsWorld.contactDelegate = self
buildMaze()
addDot()
}
Чтобы установить маску контакта / столкновения, вы должны сделать это следующим образом, потому что они основаны на побитовой операции:
Предположим, вы хотите столкновения между точкой и стенами
struct PhysicsCategory {
static let wall: UInt32 = 0x1 << 1
static let dot: UInt32 = 0x1 << 2
}
Вы можете поместить структуру над своим классом, если хотите
Затем, когда вы назначаете физическое тело, вы должны установить битовую маску:
Для точек:
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 об этом
Для стен:
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
Для стен действительны все соображения по точкам
Обнаружение столкновений и контактов не очень хорошо работает, когда вы непосредственно устанавливаете положение своих спрайтов.
В вашем коде строки:
dot.position.x = location.x
dot.position.y = location.y
непосредственно устанавливают положение dot
, переопределяя все, что физический движок хочет сделать с объектами.
Кроме того, вы, похоже, не настроили ни одну из необходимых категорий или битовых масок коллизий / contactTest.
Вы разрешаете ручное перемещение точки, но с обнаружением контакта со стенами, тогда вам, вероятно, нужно будет увидеть, было ли касание экрана внутри стены, а затем не перемещать точку, если это имело место. (что означало бы, что вы вообще не используете физику).
Изменить: мое пошаговое руководство для столкновений и контактов: /questions/26792762/kak-obnaruzhit-stolknovenie-v-nabore-swift-sprite/26792774#26792774
И руководство по столкновению и контактной проверке битовых масок: /questions/4357086/chto-takoe-kategoriya-maski-i-maska-stolknoveniya-ot-sprite-kit/4357093#4357093