检测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):
- 添加
SKPhysicsContactDelegate
到班级。 - 适当设置physicsWorld,通常:
self.physicsWorld.contactDelegate = self
- 为您将拥有的每组节点创建类别。例如。
让bulletCategory = 0x1<< 0
- 为每个子弹和士兵创建SKNodes。
- 给每个子弹和士兵一个具有匹配形状的物理体。
- 将每个子弹的categoryBitMask设置为
bulletCategory
(士兵设置为soldierCategory)。 - 将每个子弹的contactBitMask设置为
soldierCategory
(士兵设置为bulletCategory )。 - 定义
didBeginContact()
处理程序。
- Add
SKPhysicsContactDelegate
to the class. - set the physicsWorld appropriately, usually:
self.physicsWorld.contactDelegate = self
- Create categories for each group of nodes you will have. E.g.
let bulletCategory = 0x1 << 0
- Create SKNodes for each bullet and soldier.
- Give each bullet and soldier a physics body with a matching shape.
- Set each bullet's categoryBitMask to the
bulletCategory
(soldiers are set to soldierCategory). - Set each bullet's contactBitMask to the
soldierCategory
(soldiers are set to bulletCategory). - 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:
- 其中一项物理机构必须是动态的
-
物理机构必须通过力/冲动或通过设定它们的速度来移动 - 物理实体的位置应与其对应的精灵/形状节点相匹配
对于(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.