检测Swift中两个对象之间的冲突

检测Swift中两个对象之间的冲突

问题描述:

在Swift中碰撞检测非常简单 - 但在这个特定项目中,身体碰撞并不像往常一样触发 didBeginContact 事件。

Collision detection is pretty simple in Swift - yet on this particular project, body collision is not triggering the didBeginContact event as usual.

这是我的两个身体碰撞的清单(使用士兵和子弹):

Here is my checklist for two bodies colliding (using soldiers and bullets):


  1. 添加 SKPhysicsContactDelegate 到班级。

  2. 适当设置physicsWorld,通常: self.physicsWorld.contactDelegate = self

  3. 为您将拥有的每组节点创建类别。例如。 让bulletCategory = 0x1<< 0

  4. 为每个子弹和士兵创建SKNodes。

  5. 给每个子弹和士兵一个具有匹配形状的物理体。

  6. 将每个子弹的categoryBitMask设置为 bulletCategory (士兵设置为soldierCategory)。

  7. 将每个子弹的contactBitMask设置为 soldierCategory (士兵设置为bulletCategory )。

  8. 定义 didBeginContact()处理程序。

  1. Add SKPhysicsContactDelegate to the class.
  2. set the physicsWorld appropriately, usually: self.physicsWorld.contactDelegate = self
  3. Create categories for each group of nodes you will have. E.g. let bulletCategory = 0x1 << 0
  4. Create SKNodes for each bullet and soldier.
  5. Give each bullet and soldier a physics body with a matching shape.
  6. Set each bullet's categoryBitMask to the bulletCategory (soldiers are set to soldierCategory).
  7. Set each bullet's contactBitMask to the soldierCategory (soldiers are set to bulletCategory).
  8. Define didBeginContact() handler.

以下是我的完整代码。它是碰撞中最小的~20行Hello World。

Below is my complete code. It is a minimal ~20 line "Hello World" for collision.

如果你创建一个新的Game并将其粘贴到GameScene.swift中,它将会运行,不会触发任何碰撞事件。

If you create a new "Game" and copy paste this into the GameScene.swift, it will run, just no collision events will be fired.

//
//  GameScene.swift
//  Thesoldier
//
//  Created by Donald Pinkus on 12/19/14.
//  Copyright (c) 2014 Don Pinkus. All rights reserved.
//

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {
    var soldier = SKShapeNode(circleOfRadius: 40)

    let soldierCategory:UInt32 = 0x1 << 0;
    let bulletCategory:UInt32 = 0x1 << 1;

    override func didMoveToView(view: SKView) {
        self.physicsWorld.contactDelegate = self

        // THE soldier
        soldier.fillColor = SKColor.redColor()
        soldier.position = CGPoint(x: CGRectGetMidX(self.frame), y: 40)
        soldier.physicsBody = SKPhysicsBody(circleOfRadius: 20)
        soldier.physicsBody!.dynamic = false
        soldier.physicsBody!.categoryBitMask = soldierCategory
        soldier.physicsBody!.contactTestBitMask = bulletCategory
        soldier.physicsBody!.collisionBitMask = 0


        // bulletS
        var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("makeBullet"), userInfo: nil, repeats: true)

        self.addChild(soldier)
    }

    func makeBullet() {
        var bullet = SKShapeNode(rect: CGRect(x: CGRectGetMidX(self.frame), y: self.frame.height, width: 10, height: 40), cornerRadius: CGFloat(0))
        bullet.fillColor = SKColor.redColor()

        bullet.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: 10, height: 40))
        bullet.physicsBody?.dynamic = false
        bullet.physicsBody?.categoryBitMask = bulletCategory
        bullet.physicsBody?.contactTestBitMask = soldierCategory
        bullet.physicsBody?.collisionBitMask = soldierCategory

        var movebullet = SKAction.moveByX(0, y: CGFloat(-400), duration: 1)
        var movebulletForever = SKAction.repeatActionForever(movebullet)
        bullet.runAction(movebulletForever)

        self.addChild(bullet)
    }

    func didBeginContact(contact: SKPhysicsContact) {
        println("CONTACT")

    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        /* Called when a touch begins */
    }

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


以下是您的清单中缺少的一些项目:

Here are a few items missing from your checklist:


  1. 其中一项物理机构必须是动态的

  2. 物理机构必须通过力/冲动或通过设定它们的速度来移动

  3. 物理实体的位置应与其对应的精灵/形状节点相匹配

对于(2),你是每个通过 SKAction 改变其位置。

For (2), you are moving each bullet by changing its position over time with an SKAction.

对于(3),该位置每个项目符号从(0,0)开始,而形状在场景的顶部中心绘制。由于物理体以形状节点的位置为中心,因此形状和物理体之间存在不匹配;子弹的物理身体永远不会与士兵接触。要解决此问题,请尝试

For (3), the position of each bullet starts at (0, 0), while the shape is drawn at the top-center of the scene. Since the physics body is centered at the shape node's position, there is a mismatch between the locations of the shape and the physics body; the bullet's physics body never makes contact with the soldier. To resolve this, try

    var bullet = SKShapeNode(rectOfSize: CGSizeMake(10, 40))
    bullet.position = CGPointMake(self.size.width/2.0, self.size.height)

此外,物理学士兵的身体是其形状半径的一半。

Also, the physics body of the soldier is half the radius of its shape.