简体   繁体   English

检测Swift中两个对象之间的碰撞

[英]Detect collision between two objects in Swift

Collision detection is pretty simple in Swift - yet on this particular project, body collision is not triggering the didBeginContact event as usual. Swift 中的碰撞检测非常简单——但在这个特定项目中,身体碰撞并没有像往常一样触发didBeginContact事件。

Here is my checklist for two bodies colliding (using soldiers and bullets):这是我的两个物体碰撞的清单(使用士兵和子弹):

  1. Add SKPhysicsContactDelegate to the class.SKPhysicsContactDelegate添加到类中。
  2. set the physicsWorld appropriately, usually: self.physicsWorld.contactDelegate = self适当地设置物理世界,通常: self.physicsWorld.contactDelegate = self
  3. Create categories for each group of nodes you will have.为您将拥有的每组节点创建类别。 Eg let bulletCategory = 0x1 << 0例如let bulletCategory = 0x1 << 0
  4. Create SKNodes for each bullet and soldier.为每个子弹和士兵创建 SKNode。
  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).将每个子弹的categoryBitMask 设置为bulletCategory (士兵设置为soldierCategory)。
  7. Set each bullet's contactBitMask to the soldierCategory (soldiers are set to bulletCategory).将每个子弹的contactBitMask 设置为soldierCategory (soldiers 设置为bulletCategory)。
  8. Define didBeginContact() handler.定义didBeginContact()处理程序。

Below is my complete code.下面是我的完整代码。 It is a minimal ~20 line "Hello World" for collision.它是用于碰撞的最小约 20 行“Hello World”。

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 中,它将运行,只是不会触发任何碰撞事件。

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) {
        print("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. One of the physics bodies must be dynamic物理体之一必须是动态的
  2. The physics bodies must be moved by a force/impulse or by setting their velocities物理物体必须通过力/脉冲或通过设置它们的速度来移动
  3. The positions of the physics bodies should match their corresponding sprite/shape nodes物理体的位置应与其对应的精灵/形状节点匹配

For (2), you are moving each bullet by changing its position over time with an SKAction .对于(2),您通过使用SKAction随时间改变其位置来移动每个子弹。

For (3), the position of each bullet starts at (0, 0), while the shape is drawn at the top-center of the scene.对于 (3),每个子弹的位置从 (0, 0) 开始,而形状绘制在场景的顶部中心。 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.此外,士兵的物理身体是其形状半径的一半。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM