如何在Swift / SpriteKit中检测与2个以上对象的冲突

时间:2015-12-26 15:30:22

标签: swift sprite-kit collision-detection

所以我正在创建一个空气曲棍球比赛,有5个主要的SKSpriteNodes。我需要检测冰球与goal1和goal2之间的碰撞。当它确实检测到碰撞时,需要将1添加到scoreLeft或scoreRight,它们是SKLabelNode的。我使用了Gamescene.sks文件来制作视觉表示。我评论了didBeginContact,因为它不起作用。先感谢您。

class GameScene: SKScene, SKPhysicsContactDelegate {

let paddle1CategoryName = "paddle1"
let paddle2CategoryName = "paddle2"
let puckCategoryName = "puck"
let goal1CategoryName = "goal1"
let goal2CategoryName = "goal2"
let scoreLeftCategoryName = "scoreLeft"
let scoreRightCategoryName = "scoreRight"
var isFingerOnPaddle1 = false
var isFingerOnPaddle2 = false


var paddle1Category: UInt32 = 0x1 << 0
var paddle2Category: UInt32 = 0x1 << 1
var puckCategory: UInt32 = 0x1 << 2
var goal1Category: UInt32 = 0x1 << 3
var goal2Category: UInt32 = 0x1 << 4

override func didMoveToView(view: SKView) {
    /* Setup your scene here */
    let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    borderBody.friction = 0
    self.physicsBody = borderBody
    let paddle1 = childNodeWithName(paddle1CategoryName) as! SKSpriteNode
    let paddle2 = childNodeWithName(paddle2CategoryName) as! SKSpriteNode
    let puck = childNodeWithName(puckCategoryName) as! SKSpriteNode
    let goal1 = childNodeWithName(goal1CategoryName) as! SKSpriteNode
    let goal2 = childNodeWithName(goal2CategoryName) as! SKSpriteNode
    let scoreLeft = childNodeWithName(scoreLeftCategoryName) as! SKLabelNode
    let scoreRight = childNodeWithName(scoreRightCategoryName) as! SKLabelNode

}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */
    var touch = touches.first! as UITouch
    var location = touch.locationInNode(self)
    if let body = physicsWorld.bodyAtPoint(location){
        if body.node!.name == paddle1CategoryName {
            print("The game has begun.")
            isFingerOnPaddle1 = true
        } else if body.node!.name == paddle2CategoryName{
            print("The game has begun.")
            isFingerOnPaddle2 = true
        }
    }
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let paddle1 = childNodeWithName(paddle1CategoryName) as! SKSpriteNode
    let paddle2 = childNodeWithName(paddle2CategoryName) as! SKSpriteNode
    let puck = childNodeWithName(puckCategoryName) as! SKSpriteNode
    let goal1 = childNodeWithName(goal1CategoryName) as! SKSpriteNode
    let goal2 = childNodeWithName(goal2CategoryName) as! SKSpriteNode
    var touch = touches.first! as UITouch
    var touchLocation = touch.locationInNode(self)
    var previousLocation = touch.previousLocationInNode(self)



    if isFingerOnPaddle1{

    let paddle1X = paddle1.position.x + (touchLocation.x - previousLocation.x)
    let paddle1Y = paddle1.position.y + (touchLocation.y - previousLocation.y)
    if (touchLocation.x <= paddle1.position.x && (touchLocation.y <= paddle1.position.y || touchLocation.y >= paddle1.position.y)){
    paddle1.position = CGPoint(x: paddle1X, y: paddle1Y)
    }
    }
    if isFingerOnPaddle2{
    let paddle2X = paddle2.position.x + (touchLocation.x - previousLocation.x)
    let paddle2Y = paddle2.position.y + (touchLocation.y - previousLocation.y)

    if (touchLocation.x >= paddle2X && (touchLocation.y >= paddle2Y || touchLocation.y < paddle2.position.y)){
        paddle2.position = CGPoint(x: paddle2X, y: paddle2Y)
    }
    }

}
/*
func didBeginContact(contact: SKPhysicsContact) {
    let scoreLeft = childNodeWithName(scoreLeftCategoryName) as! SKLabelNode
    let scoreRight = childNodeWithName(scoreRightCategoryName) as! SKLabelNode
    var score = 0
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask


    switch contactMask{
    case puckCategory | goal1Category:
        if contact.bodyA.categoryBitMask == puckCategory{
            puckCategory = contact.bodyA.categoryBitMask
            goal1Category = contact.bodyB.categoryBitMask
            score++
            scoreRight.text = "\(score)"
        }else{
            puckCategory = contact.bodyB.categoryBitMask
            goal1Category = contact.bodyA.categoryBitMask
            score++
            scoreRight.text = "\(score)"
        }
    case puckCategory | goal2Category:
        if contact.bodyA.categoryBitMask == puckCategory{
            puckCategory = contact.bodyA.categoryBitMask
            goal2Category = contact.bodyB.categoryBitMask
            score++
            scoreLeft.text = "\(score)"
        }else{
            puckCategory = contact.bodyB.categoryBitMask
            goal2Category = contact.bodyA.categoryBitMask
            score++
            scoreLeft.text = "\(score)"
        }
    default:

        // Nobody expects this, so satisfy the compiler and catch
        // ourselves if we do something we didn't plan to
        fatalError("other collision: \(contactMask)")

    }
}*/
override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
}

}

1 个答案:

答案 0 :(得分:1)

一个问题是在函数开头使用本地package com.ggl.testing; import java.util.Scanner; public class Calculator3 implements Runnable { private boolean again = true; private Scanner keyIn = new Scanner(System.in); public static void main(String args[]) { new Calculator3().run(); } @Override public void run() { while (again) { double in1 = readDouble("Type your first number: "); double in2 = readDouble("Type your second number: "); char operator = readChar("Type your operator: "); System.out.println("Your result is: " + operation(in1, in2, operator)); timer(); char yOrN = readChar("Do you want to do this again? [Y | N] "); if (Character.toLowerCase(yOrN) != 'y') { System.out.println("Well, get out of here"); again = false; } } keyIn.close(); } public double readDouble(String s) { System.out.print(s); return keyIn.nextDouble(); } public char readChar(String s) { System.out.print(s); return keyIn.next().charAt(0); } public double operation(double in1, double in2, char operator) { switch (operator) { case '+': return in1 + in2; case '-': return in1 - in2; case '/': return in1 / in2; case '*': return in1 * in2; default: return 0D; } } public void timer() { try { Thread.sleep(1500); } catch (InterruptedException e) { } } } 。去掉它。分数应存储在游戏模型中,以便可以应用关于获胜的逻辑但匹配您的代码,至少这样做。

var score = 0

此外还有

的问题
if let score = Int(scoreLeft.text) {
  scoreLeft.text = "\(score + 1)"
}

您所说的是 case puckCategory | goal1Category: if contact.bodyA.categoryBitMask == puckCategory{ puckCategory = contact.bodyA.categoryBitMask 等于contact.bodyA.categoryBitMask,然后将puckCategory设为puckCategory。这是一个无操作,没有任何变化,更重要的是,您不想更改与您的子节点进行比较的位掩码。制作contact.bodyA.categoryBitMaskpuckCategorygoal1Categoy常量。祝你好运。

跟进OP评论:

因此,抛弃设置类别掩码变量的goal2Category中的代码有两个原因。 1)将didBeginContact之类的变量设置为相同的值是浪费和混乱的。 2)由于puckCatergory之类的变量与子节点位掩码进行比较,如果它们发生了变化,那将是一场灾难。该功能应如下所示。还要确保在你走得太远之前为其他类型的联系人添加处理程序。

puckCategory