I am building a maze and I have added some SKSpritekit nodes for the walls and a dot for the player. however when the dot and the walls collide, there is no detection of collision. my code is as follows:
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!")
}
The walls appear just as I wanted them, and the dot is also in the right position.
I added a masso of 20000 for each of them so that when I move the dot, the walls stay in place. however, when I move the dot with my finger, it just goest straight through the walls of the maze instead of being stopped by them.
I added a print statement to the didBegin function to see if at least it was detecting any contact between the sprites, but it does not.
Why is this?
cheers!
First in your didMoveTo or sceneDidLoad, you need to set the physicsContactDelegate:
override func sceneDidLoad () {
physicsWorld.contactDelegate = self
buildMaze()
addDot()
}
To set the contact/collision mask, you have to do it this way, because they're based on bitwise operation:
Let's suppose you want collision between dot and walls
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
Then, when you assign physics body, you have to set the bitmask:
For dots:
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
Collision is different from contact, check apple documentation about it
For walls:
northWall.physicsBody?.categoryBitMask = PhysicsCategory.wall
northWall.physicsBody?.contactTestBitMask = PhysicsCategory.dot
northWall.physicsBody?.collisionBitMask = PhysicsCategory.dot
//Do the same for all walls
If you want walls to contact or collide with more than one object:
northWall.physicsBody?.contactTestBitMask = PhysicsCategory.dot | PhysicsCategory.other
northWall.physicsBody?.collisionBitMask = PhysicsCategory.dot | PhysicsCategory.other
For walls are valid all consideration as per dots