How to fix SKPhysicsContactDelegate not being called - swift

My sprites are supposed to contact each other and print to console, however, one goes behind the other and they do not actually touch. Needless to say, nothing is being printed to console.
I've tried using many different "types" of if statements in the function, however, none of them have worked. For example, I've tried using:
if bodyA.categoryBitMask == 1 && bodyB.categoryBitMask == 2 || bodyA.categoryBitMask == 2 && bodyB.categoryBitMask == 1
as well as:
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask
Help would be much appreciated! :)
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var e = SKSpriteNode()
var square = SKSpriteNode()
var timer:Timer!
let squareCategory:UInt32 = 0x1 << 1
let eCategory:UInt32 = 0x1 << 2
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
square = SKSpriteNode(imageNamed: "square")
square.size = CGSize(width: 100, height: 100)
square.physicsBody = SKPhysicsBody(rectangleOf: square.size)
square.position = CGPoint(x: 0, y: -590)
square.physicsBody = SKPhysicsBody(rectangleOf: e.size)
square.name = "square"
square.physicsBody?.categoryBitMask = squareCategory
square.physicsBody?.contactTestBitMask = eCategory
square.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(square)
let swipeRight: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(GameScene.swipedRight(sender:)))
swipeRight.direction = .right
view.addGestureRecognizer(swipeRight)
let swipeLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector (GameScene.swipedLeft(sender:)))
swipeLeft.direction = .left
view.addGestureRecognizer(swipeLeft)
timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(self.adde), userInfo: nil, repeats: true)
}
#objc func swipedRight(sender: UISwipeGestureRecognizer) {
//middle
if square.position == CGPoint(x: 0, y: -590) {
square.position = CGPoint(x: 200, y: -590)
}
//left
if square.position == CGPoint(x: -200, y: -590) {
square.position = CGPoint(x: 0, y: -590)
}
}
#objc func swipedLeft(sender: UISwipeGestureRecognizer) {
//middle
if square.position == CGPoint(x: 0, y: -590) {
square.position = CGPoint(x: -200, y: -590)
}
//right
if square.position == CGPoint(x: 200, y: -590) {
square.position = CGPoint(x: 0, y: -590)
}
}
#objc func adde() {
e = SKSpriteNode(imageNamed: "e")
let ePosition = GKRandomDistribution(lowestValue: -414, highestValue: 414)
let position = CGFloat(ePosition.nextInt())
e.size = CGSize(width: 75, height: 75)
e.position = CGPoint(x: position, y: 640)
e.physicsBody = SKPhysicsBody(rectangleOf: e.size)
e.name = "e"
e.physicsBody?.categoryBitMask = eCategory
e.physicsBody?.contactTestBitMask = squareCategory
e.physicsBody?.isDynamic = true
self.addChild(e)
let animationDuration:TimeInterval = 6
var actionArray = [SKAction]()
actionArray.append(SKAction.move(to: CGPoint(x: position, y: -705), duration: animationDuration))
actionArray.append(SKAction.removeFromParent())
e.run(SKAction.sequence(actionArray))
}
func didBegin(_ contact: SKPhysicsContact) {
let bodyAName = contact.bodyA.node?.name
let bodyBName = contact.bodyB.node?.name
if bodyAName == "square" && bodyBName == "e" || bodyAName == "e" && bodyBName == "square"{
if bodyAName == "square" {
contact.bodyA.node?.removeFromParent()
} else if bodyBName == "e" {
contact.bodyB.node?.removeFromParent()
}
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
I am supposed to get the message, but the "e" goes behind the "square" and I don't get any message.

There is an error in your code.
Change the following:
square = SKSpriteNode(imageNamed: "square")
square.size = CGSize(width: 100, height: 100)
square.physicsBody = SKPhysicsBody(rectangleOf: square.size)
square.position = CGPoint(x: 0, y: -590)
square.physicsBody = SKPhysicsBody(rectangleOf: e.size)
square.name = "square"
to
square = SKSpriteNode(imageNamed: "square")
square.color = UIColor.red
square.size = CGSize(width: 100, height: 100)
square.physicsBody = SKPhysicsBody(rectangleOf: square.size)
square.position = CGPoint(x: 0, y: horizotaly)
//square.physicsBody = SKPhysicsBody(rectangleOf: e.size)
square.physicsBody?.affectedByGravity = false
square.name = "square"
Your problem is solved.

Related

Trying to load images from the assets folder in xcode into an array but having hard time

import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate{
var picsArray = [String]()
var scoreLabel: SKLabelNode!
var editLabel: SKLabelNode!
var editingMode = false{
didSet{
if editingMode{
editLabel.text = "Done"
}
else{
editLabel.text = "Edit"
}
}
}
var score = 0 {
didSet{
scoreLabel.text = " score: \(score)"
}
}
override func didMove(to view: SKView) {
let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)
for item in items {
if item.hasPrefix("ball"){
picsArray.append(item)
}
print(picsArray.count)
}
physicsWorld.contactDelegate = self
let background = SKSpriteNode(imageNamed: "background")
background.position = CGPoint(x: 512, y: 384)
background.blendMode = .replace
background.zPosition = -1
addChild(background)
scoreLabel = SKLabelNode(fontNamed: "chalkduster")
scoreLabel.text = "Score: 0"
scoreLabel.horizontalAlignmentMode = .right
scoreLabel.position = CGPoint(x: 980, y: 700)
addChild(scoreLabel)
editLabel = SKLabelNode(fontNamed: "chalkduster")
editLabel.text = "Edit"
editLabel.position = CGPoint(x: 80, y: 700)
addChild(editLabel)
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
makeSlots(at: CGPoint(x: 128, y: 0), isGood: true)
makeSlots(at: CGPoint(x: 384, y: 0), isGood: false)
makeSlots(at: CGPoint(x: 640, y: 0), isGood: true)
makeSlots(at: CGPoint(x: 896, y: 0), isGood: false)
makeBouncer(at: CGPoint(x: 0, y: 0))
makeBouncer(at: CGPoint(x: 256, y: 0))
makeBouncer(at: CGPoint(x: 512, y: 0))
makeBouncer(at: CGPoint(x: 768, y: 0))
makeBouncer(at: CGPoint(x: 1024, y: 0))
// Get label node from scene and store it for use later
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else{return}
let location = touch.location(in: self)
let objects = nodes(at: location)
if objects.contains(editLabel){
editingMode.toggle()
}
else{
if editingMode{
let size = CGSize(width: Int.random(in: 16...128), height: 16)
let box = SKSpriteNode(color: UIColor(red: CGFloat.random(in: 0...1), green: CGFloat.random(in: 0...1), blue: CGFloat.random(in: 0...1), alpha: 1), size: size)
box.zRotation = CGFloat.random(in: 0...3)
box.position = location
box.physicsBody = SKPhysicsBody(rectangleOf: box.size)
box.physicsBody?.isDynamic = false
addChild(box)
}
else{
let ball = SKSpriteNode(imageNamed: "ballRed")
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2.0)
ball.physicsBody?.restitution = 0.4
ball.physicsBody?.contactTestBitMask = ball.physicsBody?.collisionBitMask ?? 0
ball.position = location
ball.name = "ball"
addChild(ball)
}
}
}
func makeBouncer(at position: CGPoint){
let bouncer = SKSpriteNode(imageNamed: "bouncer")
bouncer.position = position
bouncer.physicsBody = SKPhysicsBody(circleOfRadius: bouncer.size.width/2)
bouncer.physicsBody?.isDynamic = false
addChild(bouncer)
}
func makeSlots(at position: CGPoint, isGood: Bool){
var slotBase: SKSpriteNode
var slotGlow: SKSpriteNode
if isGood{
slotBase = SKSpriteNode(imageNamed: "slotBaseGood")
slotGlow = SKSpriteNode(imageNamed: "slotGlowGood")
slotBase.name = "good"
} else{
slotBase = SKSpriteNode(imageNamed: "slotBaseBad")
slotGlow = SKSpriteNode(imageNamed: "slotGlowBad")
slotBase.name = "bad"
}
slotGlow.position = position
slotBase.position = position
slotBase.physicsBody = SKPhysicsBody(rectangleOf: slotBase.size)
slotBase.physicsBody?.isDynamic = false
addChild(slotGlow)
addChild(slotBase)
let spin = SKAction.rotate(byAngle: .pi, duration: 1)
let spinforever = SKAction.repeatForever(spin)
slotGlow.run(spinforever)
}
func collision(between ball: SKNode, object: SKNode){
if object.name == "good"{
destroy(ball: ball)
score+=1
}
else{
if object.name == "bad"{
destroy(ball: ball)
score-=1
}
}
}
func destroy(ball: SKNode){
ball.removeFromParent()
}
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else{return}
guard let nodeB = contact.bodyB.node else{return}
if nodeA.name == "ball"{
collision(between: nodeA, object: nodeB)
}
else if nodeB.name == "ball"{
collision(between: nodeB, object: nodeA)
}
}
}

Swift: No contact detection between nodes

Issue
This is my code for my game. A brick falls and hits a side of a square. To differentiate what side is hit, four triangles are spawned that make the square. They are invisible from a low opacity. I am not receiving any contact between the brick node and the triangle node. The brick piece just falls right through the square. Any help?
Game Code
import SpriteKit
class GameScene: SKScene {
let basicTop = SKSpriteNode(imageNamed: "basic top");
let basicBottom = SKSpriteNode(imageNamed: "basic bottom");
let basicLeft = SKSpriteNode(imageNamed: "basic left");
let basicRight = SKSpriteNode(imageNamed: "basic right");
let brickTop = SKSpriteNode(imageNamed: "Top Side");
let brickBottom = SKSpriteNode(imageNamed: "Bottom Side");
let brickLeft = SKSpriteNode(imageNamed: "Left Side");
let brickRight = SKSpriteNode(imageNamed: "Right Side copy 2");
let basicBrick = SKSpriteNode(imageNamed: "Basic Brick")
override func didMove(to view: SKView) {
isUserInteractionEnabled = true
layoutScene()
}
func layoutScene() {
backgroundColor = UIColor(red: 10/255, green: 75/255, blue: 150/255, alpha: 1.0)
spawnBrick()
spawnBasicTop()
spawnBasicBottom()
spawnBasicLeft()
spawnBasicRight()
backgroundScene()
spawnBasicBrick()
setupPhysics()
}
func setupPhysics() {
physicsWorld.gravity = CGVector(dx: 0.0, dy: -0.1)
physicsWorld.contactDelegate = self
}
func spawnBrick() {
let randomFunc = [self.spawnbrickTop, self.spawnbrickBottom, self.spawnbrickLeft, self.spawnbrickRight]
let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count)))
randomFunc[randomResult]()
}
func spawnbrickTop() {
brickTop.size = CGSize(width: 210, height: 105)
brickTop.name = "BrickTop"
brickTop.position = CGPoint(x: frame.midX, y: frame.maxY)
brickTop.zPosition = 1
//physics stuff begins here
brickTop.physicsBody = SKPhysicsBody(circleOfRadius: max(brickTop.size.width / 2,
brickTop.size.height / 2))
brickTop.physicsBody?.categoryBitMask = PhysicsCategories.brickTopCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickTop.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
addChild(brickTop)
}
func spawnbrickBottom() {
brickBottom.size = CGSize(width: 150, height: 101)
brickBottom.name = "BrickBottom"
brickBottom.position = CGPoint(x: frame.midX, y: frame.maxY)
brickBottom.zPosition = 1
//physics stuff begins here
brickBottom.physicsBody = SKPhysicsBody(circleOfRadius: max(brickBottom.size.width / 2,
brickBottom.size.height / 2))
brickBottom.physicsBody?.categoryBitMask = PhysicsCategories.brickBottomCategory
brickBottom.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickBottom.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
addChild(brickBottom)
}
func spawnbrickLeft() {
brickLeft.size = CGSize(width: 170, height: 80)
brickLeft.name = "BrickLeft"
brickLeft.position = CGPoint(x: frame.midX, y: frame.maxY)
brickLeft.zPosition = 1
//physics stuff begins here
brickLeft.physicsBody = SKPhysicsBody(circleOfRadius: max(brickLeft.size.width / 2,
brickLeft.size.height / 2))
brickLeft.physicsBody?.categoryBitMask = PhysicsCategories.brickLeftCategory
brickLeft.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickLeft.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
addChild(brickLeft)
}
func spawnbrickRight() {
brickRight.size = CGSize(width: 140, height: 95)
brickRight.name = "BrickRight"
brickRight.position = CGPoint(x: frame.midX, y: frame.maxY)
brickRight.zPosition = 1
//physics stuff begins here
brickRight.physicsBody = SKPhysicsBody(circleOfRadius: max(brickRight.size.width / 2,
brickRight.size.height / 2))
brickRight.physicsBody?.categoryBitMask = PhysicsCategories.brickRightCategory
brickRight.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickRight.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
addChild(brickRight)
}
func turnBasicTop() {
basicTop.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicBottom() {
basicBottom.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicLeft() {
basicLeft.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicRight() {
basicRight.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func turnBasicBrick() {
basicBrick.run(SKAction.rotate(byAngle: .pi/2, duration: 0.25))
}
func gameOver() {
print("Game Over!")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
turnBasicTop()
turnBasicBottom()
turnBasicLeft()
turnBasicRight()
turnBasicBrick()
}
func spawnBasicBrick() {
basicBrick.size = CGSize(width: 200, height: 177.6)
basicBrick.position = CGPoint(x: frame.midX, y: frame.minY + basicBrick.size.width)
basicBrick.zPosition = 1
basicBrick.physicsBody = SKPhysicsBody(rectangleOf: basicBrick.size)
basicBrick.physicsBody?.categoryBitMask = PhysicsCategories.basicBrickCategory
basicBrick.physicsBody?.isDynamic = false
basicBrick.physicsBody?.allowsRotation = true
addChild(basicBrick)
}
func spawnBasicTop() {
basicTop.size = CGSize(width: 400, height: 400)
basicTop.position = CGPoint(x: 230, y: 200)
basicTop.zPosition = 1
basicTop.alpha = 0.3
basicTop.name = "BasicTop"
//physics stuff begins here
basicTop.physicsBody = SKPhysicsBody(rectangleOf: basicTop.size)
basicTop.physicsBody?.categoryBitMask = PhysicsCategories.basicTopCategory
basicTop.physicsBody?.isDynamic = false
basicTop.physicsBody?.allowsRotation = true
//bye bye physics
addChild(basicTop)
}
func spawnBasicBottom() {
basicBottom.size = CGSize(width: 400, height: 400)
basicBottom.position = CGPoint(x: 230, y: 200)
basicBottom.zPosition = 1
basicBottom.alpha = 0.3
basicBottom.name = "BasicBottom"
//physics stuff begins here
basicBottom.physicsBody = SKPhysicsBody(rectangleOf: basicBottom.size)
basicBottom.physicsBody?.categoryBitMask = PhysicsCategories.basicBottomCategory
basicBottom.physicsBody?.isDynamic = false
//bye bye physics
addChild(basicBottom)
}
func spawnBasicLeft() {
basicLeft.size = CGSize(width: 400, height: 400)
basicLeft.position = CGPoint(x: 230, y: 200)
basicLeft.zPosition = 1
basicLeft.alpha = 0.3
basicLeft.name = "BasicLeft"
//physics stuff begins here
basicLeft.physicsBody = SKPhysicsBody(rectangleOf: basicLeft.size)
basicLeft.physicsBody?.categoryBitMask = PhysicsCategories.basicLeftCategory
basicLeft.physicsBody?.isDynamic = false
//bye bye physics
addChild(basicLeft)
}
func spawnBasicRight() {
basicRight.size = CGSize(width: 400, height: 400)
basicRight.position = CGPoint(x: 230, y: 200)
basicRight.zPosition = 1
basicRight.alpha = 0.3
basicRight.name = "BasicRight"
//physics stuff begins here
basicRight.physicsBody = SKPhysicsBody(rectangleOf: basicRight.size)
basicRight.physicsBody?.categoryBitMask = PhysicsCategories.basicRightCategory
basicRight.physicsBody?.isDynamic = false
//bye bye physics
addChild(basicRight)
}
func backgroundScene() {
let constructionSite = SKSpriteNode(imageNamed: "Background Image")
constructionSite.size = frame.size
constructionSite.position = CGPoint(x: frame.midX, y: frame.midY)
constructionSite.zPosition = -1
addChild(constructionSite)
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
//01
//10
//11
let contactMask = contact.bodyA.categoryBitMask |
contact.bodyB.categoryBitMask
if contactMask == PhysicsCategories.brickTopCategory |
(PhysicsCategories.basicTopCategory) {
if let brickTop = contact.bodyA.node?.name == "BrickTop" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if brickTop == basicTop {
print("Correct!")
brickTop.run(SKAction.fadeOut(withDuration: 0.05), completion: {
brickTop.removeFromParent()
self.spawnBrick()
})
}
}
else if contactMask == PhysicsCategories.brickBottomCategory |
(PhysicsCategories.basicBottomCategory) {
if let brickBottom = contact.bodyA.node?.name == "BrickBottom" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if brickBottom == basicBottom {
print("Correct!")
brickBottom.run(SKAction.fadeOut(withDuration: 0.05), completion: {
brickBottom.removeFromParent()
self.spawnBrick()
})
}
}
else if contactMask == PhysicsCategories.brickLeftCategory |
(PhysicsCategories.basicLeftCategory) {
if let brickLeft = contact.bodyA.node?.name == "BrickLeft" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if brickLeft == basicLeft {
print("Correct!")
brickLeft.run(SKAction.fadeOut(withDuration: 0.05), completion: {
brickLeft.removeFromParent()
self.spawnBrick()
})
}
}
else if contactMask == PhysicsCategories.brickRightCategory |
(PhysicsCategories.basicRightCategory) {
if let brickRight = contact.bodyA.node?.name == "BrickRight" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if brickRight == basicRight {
print("Correct!")
brickRight.run(SKAction.fadeOut(withDuration: 0.05), completion: {
brickRight.removeFromParent()
self.spawnBrick()
})
}
}
else {
gameOver()
}
}
}
}
}
}
}
Settings File:
enum PhysicsCategories {
static let none: UInt32 = 0
static let brickCategory: UInt32 = 0x1//01
static let brickTopCategory: UInt32 = 0x1 //01
static let brickBottomCategory: UInt32 = 0x1//01
static let brickLeftCategory: UInt32 = 0x1//01
static let brickRightCategory: UInt32 = 0x1//01
static let basicTopCategory: UInt32 = 0x1 //10; shifts all bits to the left
static let basicBottomCategory: UInt32 = 0x1 //10; shifts all bits to the left
static let basicLeftCategory: UInt32 = 0x1 //10; shifts all bits to the left
static let basicRightCategory: UInt32 = 0x1 //10; shifts all bits to the left
static let basicBrickCategory: UInt32 = 0x1
}

How to prevent Sprite Nodes from pushing each other?

3 Sprite Nodes are moving up at different speed levels. You see that the gorilla likes to rest, but the lobster is pushing it slowly upwards. Expected behaviour would be, that the lobster would rest also and continue going upwards when the gorilla starts moving again. Using .isDynamic = false did not work — the Sprite Nodes were overlaying and lobster ignored the physical body of the hedgehog and the gorilla totally.
Recording of my Playground Scene: https://youtu.be/l47kaJiJvkM
Screenshot of the video:
Code:
import SpriteKit
public class WalkingScene: SKScene {
public override func didMove(to view: SKView) {
backgroundColor = .white
view.showsPhysics = true
let hedgehog = SKSpriteNode(imageNamed: "hedgehog")
hedgehog.size = CGSize(width: 64, height: 64)
hedgehog.position = CGPoint(x: size.width/2, y: 400)
hedgehog.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 80, height: 80))
hedgehog.physicsBody?.affectedByGravity = false
hedgehog.physicsBody?.allowsRotation = false
let gorilla = SKSpriteNode(imageNamed: "gorilla")
gorilla.size = CGSize(width: 64, height: 64)
gorilla.position = CGPoint(x: size.width/2, y: 140)
gorilla.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 80, height: 80))
gorilla.physicsBody?.affectedByGravity = false
gorilla.physicsBody?.allowsRotation = false
let lobster = SKSpriteNode(imageNamed: "lobster")
lobster.size = CGSize(width: 64, height: 64)
lobster.position = CGPoint(x: size.width/2, y: 20)
lobster.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 80, height: 80))
lobster.physicsBody?.affectedByGravity = false
lobster.physicsBody?.allowsRotation = false
// hedgehog.physicsBody?.isDynamic = false
// gorilla.physicsBody?.isDynamic = false
// lobster.physicsBody?.isDynamic = false
// hedgehog.physicsBody?.usesPreciseCollisionDetection = true
// hedgehog.physicsBody?.collisionBitMask = 0
// gorilla.physicsBody?.usesPreciseCollisionDetection = true
// gorilla.physicsBody?.collisionBitMask = 0
// lobster.physicsBody?.usesPreciseCollisionDetection = true
// lobster.physicsBody?.collisionBitMask = 0
self.addChild(lobster)
self.addChild(hedgehog)
self.addChild(gorilla)
self.moveGorilla(gorilla)
self.moveLobster(lobster)
self.moveHedgeHog(hedgehog)
}
func moveGorilla(_ passenger: SKSpriteNode) {
let moveLeft = CGVector(dx: 0, dy: 200)
let aYYY = CGVector(dx: 200, dy: 0)
let moving = SKAction.move(by: moveLeft, duration: 1)
let turnAYY = SKAction.move(by: aYYY, duration: 1)
let chill = SKAction.wait(forDuration: 3)
passenger.run(SKAction.sequence([moving, chill, moving, chill, turnAYY])) {
print("Gorilla arrived")
}
}
func moveLobster(_ passenger: SKSpriteNode) {
let moveLeft = CGVector(dx: 0, dy: 200)
let moving = SKAction.move(by: moveLeft, duration: 1.2)
passenger.run(SKAction.sequence([moving, moving, moving, moving, moving, moving, moving, moving, moving])) {
print("Lobster arrived")
}
}
func moveHedgeHog(_ passenger: SKSpriteNode) {
let moveLeft = CGVector(dx: 0, dy: 200)
let moving = SKAction.move(by: moveLeft, duration: 1)
let chill = SKAction.wait(forDuration: 2)
passenger.run(SKAction.sequence([chill, moving, moving, moving])) {
print("Hedgehog arrived")
}
}
}
You can set those dynamics this way:
hedgehog.physicsBody?.isDynamic = true
gorilla.physicsBody?.isDynamic = false
lobster.physicsBody?.isDynamic = true
By this strategy, you can extend this example to other situations.
If isDynamic = true is treated as 0 , and the isDynamic = false, ie static, treated as infinity,
there is something between which can be controlled by the mass of a physics body.
hedgehog.physicsBody?.isDynamic = false. (mass = Infinity)
gorilla.physicsBody?.isDynamic = true. (mass = big)
lobster.physicsBody?.isDynamic = true (mass = 0)
gorilla.physicsBody?.mass = 1000

Looping my code so that the user can continue to play

import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
let balls = [
SKSpriteNode(imageNamed: "blueball.png"),
SKSpriteNode(imageNamed: "greenball.png"),
SKSpriteNode(imageNamed: "realredball.png"),
]
let redRectangle = SKSpriteNode(imageNamed: "redrectangle.png")
let blueRectangle = SKSpriteNode(imageNamed: "bluerectangle.png")
let greenRectangle = SKSpriteNode(imageNamed: "greenrectangle.png")
let wall1 = SKSpriteNode(imageNamed: "drop_wall.png")
let wall2 = SKSpriteNode(imageNamed: "drop_wall.png")
let bottom = SKSpriteNode(imageNamed:"drop_bottom.png")
let top = SKSpriteNode(imageNamed:"drop_bottom.png")
let blueBallCategory :UInt32 = 0x1 << 0
let greenBallCategory :UInt32 = 0x1 << 1
let realRedBallCategory :UInt32 = 0x1 << 2
let redRectangleCategory : UInt32 = 0x1 << 3
let blueRectangleCategory : UInt32 = 0x1 << 4
let greenRectangleCategory : UInt32 = 0x1 << 5
override func didMove(to view: SKView) {
spawnBalls()
spawnRectangles()
physicsWorld.contactDelegate = self
moveRectangles()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for ball in balls{
ball.isUserInteractionEnabled = false
}
physics()
}
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case blueBallCategory | blueRectangleCategory:
for ball in balls{
ball.removeFromParent()
}
print("Alive! Blue ball has hit blue rectangle.")
case greenBallCategory | greenRectangleCategory:
print("Alive! Green ball has hit green rectangle.")
case realRedBallCategory | redRectangleCategory:
print("Alive! Red ball has hit red rectangle.")
case blueBallCategory | redRectangleCategory:
print("dead")
case blueBallCategory | greenRectangleCategory:
print("dead")
case realRedBallCategory | blueRectangleCategory:
print("dead")
case realRedBallCategory | greenRectangleCategory:
print("dead")
case greenBallCategory | redRectangleCategory:
print("dead")
case greenBallCategory | blueRectangleCategory:
print("dead")
default:
print("missed")
}
}
func spawnRectangles() {
redRectangle.position = CGPoint(x: 0, y: -400)
redRectangle.size = CGSize(width: 200, height: 20)
blueRectangle.position = CGPoint(x: -300, y: -200)
blueRectangle.size = CGSize(width: 200, height: 20)
greenRectangle.position = CGPoint(x: 100, y: -550)
greenRectangle.size = CGSize(width: 200, height: 20)
self.addChild(redRectangle)
self.addChild(blueRectangle)
self.addChild(greenRectangle)
wall1.position = CGPoint(x: -367.04, y: 0)
wall1.size = CGSize(width: 20, height: 1350)
wall1.physicsBody = SKPhysicsBody(rectangleOf: wall1.size)
wall1.physicsBody?.isDynamic = false
wall1.physicsBody?.affectedByGravity = false
self.addChild(wall1)
wall2.position = CGPoint(x: 367.04, y: 0)
wall2.size = CGSize(width: 20, height: 1350)
wall2.physicsBody = SKPhysicsBody(rectangleOf: wall2.size)
wall2.physicsBody?.isDynamic = false
wall2.physicsBody?.affectedByGravity = false
self.addChild(wall2)
top.position = CGPoint(x: 0, y: 657)
top.size = CGSize(width: 765, height: 20)
top.physicsBody = SKPhysicsBody(rectangleOf: top.size)
top.physicsBody?.isDynamic = false
top.physicsBody?.affectedByGravity = false
self.addChild(top)
bottom.size = CGSize(width: 765, height: 20)
bottom.position = CGPoint(x: 0, y: -657)
bottom.physicsBody = SKPhysicsBody(rectangleOf: bottom.size)
bottom.physicsBody?.isDynamic = false
bottom.physicsBody?.affectedByGravity = false
self.addChild(bottom)
}
func physics(){
for ball in balls{
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/2)
ball.physicsBody?.contactTestBitMask = blueRectangleCategory | greenRectangleCategory | redRectangleCategory
}
redRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
redRectangle.physicsBody?.affectedByGravity = false
redRectangle.physicsBody?.isDynamic = false
blueRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
blueRectangle.physicsBody?.affectedByGravity = false
blueRectangle.physicsBody?.isDynamic = false
greenRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
greenRectangle.physicsBody?.isDynamic = false
greenRectangle.physicsBody?.affectedByGravity = false
balls[0].physicsBody?.categoryBitMask = blueBallCategory
balls[1].physicsBody?.categoryBitMask = greenBallCategory
balls[2].physicsBody?.categoryBitMask = realRedBallCategory
redRectangle.physicsBody?.categoryBitMask = redRectangleCategory
blueRectangle.physicsBody?.categoryBitMask = blueRectangleCategory
greenRectangle.physicsBody?.categoryBitMask = greenRectangleCategory
}
func moveRectangles(){
let redMoveRight = SKAction.moveTo(x: 300, duration: 2)
let redMoveLeft = SKAction.moveTo(x: -280, duration: 2)
let redWholeMovement = SKAction.repeatForever(SKAction.sequence([redMoveRight,redMoveLeft]))
redRectangle.run(redWholeMovement)
let blueMoveRight = SKAction.moveTo(x: 300, duration: 2)
let blueMoveLeft = SKAction.moveTo(x: -280, duration: 1.5)
let blueWholeMovement = SKAction.repeatForever(SKAction.sequence([blueMoveRight,blueMoveLeft]))
blueRectangle.run(blueWholeMovement)
let greenMoveRight = SKAction.moveTo(x: 300, duration: 2)
let greenMoveLeft = SKAction.moveTo(x: -280, duration: 1.5)
let greenWholeMovement = SKAction.repeatForever(SKAction.sequence([greenMoveLeft,greenMoveRight]))
greenRectangle.run(greenWholeMovement)
}
func spawnBalls(){
let ball = balls[Int(arc4random_uniform(UInt32(balls.count)))]
ball.position = CGPoint(x: 0, y: 250)
ball.size = CGSize(width: 70, height: 70)
self.addChild(ball)
}
}
I want a new ball to spawn at the top of the screen if a ball hits a same colored rectangle. Right now when I run the app a randomly colored ball is spawned at the top and when the user clicks the ball drops. If the ball makes contact with a moving rectangle of the same color of the ball the game is supposed to keep going. But it just ends after. If anyone could help that would be great.Thanks!
You only spawn one ball in spawnBalls(). So when you touch only one ball appears. You should try to move spawnBalls() to touchesBegan().

Use random number (arc4random_uniform) to display random shapes

The purpose for this code is to do random number to display random shapes but the simulator displays them in the same spot which is the bottom left corner of the screen, for some reason the random for the position which is a is not working.
Code:
import UIKit
import SpriteKit
import Darwin
class StartGame: SKScene {
var scoreLabel = SKLabelNode(fontNamed: "cholkDuster")
var square = SKSpriteNode(imageNamed: "square")
var circle = SKSpriteNode(imageNamed: "circle")
var rectangle = SKSpriteNode(imageNamed: "rectangle")
var triangle = SKSpriteNode(imageNamed: "triangle")
let bg = SKSpriteNode(imageNamed: "background.png")
var score = 0
override func didMoveToView(view: SKView) {
//random number for the shapes
var timecreatShapes = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("creatShapes"), userInfo: nil, repeats: true)
//background image
bg.position = CGPoint(x: CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
bg.size.width = self.frame.size.width
bg.size.height = self.frame.size.height
self.addChild(bg)
self.scoreLabel.text = "0"
self.scoreLabel.fontSize = 42
self.scoreLabel.position = CGPoint(x: CGRectGetMidX(self.frame) , y: CGRectGetMidY(self.frame))
self.addChild(scoreLabel)
scoreLabel.zPosition = 2
self.physicsWorld.gravity = CGVectorMake(0, -0.5)
//declaring a square image
square.size = CGSize(width: 150, height: 100)
square.color = SKColor.redColor()
square.physicsBody = SKPhysicsBody(circleOfRadius: square.size.height / 2)
square.physicsBody?.dynamic = true
square.physicsBody?.allowsRotation = false
//declaring a circle image
circle.size = CGSize(width: 150, height: 100)
circle.physicsBody = SKPhysicsBody(circleOfRadius: square.size.height / 2)
circle.physicsBody?.dynamic = true
circle.physicsBody?.allowsRotation = false
//declaring a triangle
triangle.size = CGSize(width: 150, height: 100)
triangle.physicsBody = SKPhysicsBody(circleOfRadius: square.size.height / 2)
triangle.physicsBody?.dynamic = true
triangle.physicsBody?.allowsRotation = false
//declaring rectangle
rectangle.size = CGSize(width: 150, height: 100)
rectangle.physicsBody = SKPhysicsBody(circleOfRadius: square.size.height / 2)
rectangle.physicsBody?.dynamic = true
rectangle.physicsBody?.allowsRotation = false
}
func creatShapes () {
var x = Int ( arc4random_uniform(4) + 1)
var a = CGFloat ( arc4random_uniform(1000) + 1)
switch(x){
case 1:
circle.position = CGPoint (x: a , y: self.frame.size.height)
self.addChild(SKSpriteNode(imageNamed:"circle"))
case 2:
square.position = CGPoint(x: a , y: self.frame.size.height)
self.addChild(SKSpriteNode(imageNamed:"square"))
case 3:
rectangle.position = CGPoint(x: a , y: self.frame.size.height)
self.addChild(SKSpriteNode(imageNamed:"rectangle"))
case 4:
triangle.position = CGPoint(x: a , y: self.frame.size.height)
self.addChild(SKSpriteNode(imageNamed:"triangle"))
default:
break
}
println(x)
println(a)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if (self.nodeAtPoint(location) == self.square || self.nodeAtPoint(location) == self.triangle || self.nodeAtPoint(location) == self.circle || self.nodeAtPoint(location) == self.rectangle){
self.score++
}
self.scoreLabel.text = String(self.score)
}
}