碰撞检测问题 swift 2.0 spritekit
Trouble with collision detection swift 2.0 spritekit
我第一次为 iOS 制作游戏。我非常接近,但是我很早就让碰撞检测工作了,然后我改变了一些东西,但我失去了它的工作。我试图回到过去,但没有成功。这是我到目前为止所拥有的,但没有任何效果。我正在尝试在网上找到的不同版本的碰撞检测,但我坚持要让这个起作用。只是不明白我哪里做错了。
先谢谢你。
import SpriteKit
enum ColliderType: UInt32 {
case Player = 1
case Traffic = 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMoveToView(view: SKView) {
createWalls()
self.backgroundColor = SKColor.whiteColor()
self.physicsWorld.gravity = CGVectorMake(0, 0)
player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody?.dynamic = true
player.physicsBody!.categoryBitMask = ColliderType.Player.rawValue
player.physicsBody!.contactTestBitMask = ColliderType.Traffic.rawValue
player.zPosition = 3
player.name = "player"
player.position = CGPoint(x: self.frame.midX, y: (self.frame.midY)/3)
player.setScale(1.0)
self.addChild(player)
_ = NSTimer.scheduledTimerWithTimeInterval(2.5, target: self, selector: #selector(GameScene.makeTraffic), userInfo: nil, repeats: true)
}
func makeTraffic(){
var aNumber = Int(arc4random_uniform(2))
let Pos1 = Int(self.frame.midX/2)+30
let Pos2 = Int((self.frame.size.width)/2)
let Pos3 = Int(self.frame.size.width-300)
let array = [Pos1, Pos2, Pos3]
let randomIndex = Int(arc4random_uniform(UInt32(array.count)))
let randomPOS = CGPoint(x:Int(array[randomIndex]), y:Int(self.frame.height))
if aNumber == 0 {
aNumber = aNumber + 1
}
switch aNumber {
case 1:
let car1 = SKSpriteNode(imageNamed: "Car_Green_Front")
car1.position = randomPOS
car1.zPosition = 3
car1.setScale(1.0)
car1.physicsBody = SKPhysicsBody(rectangleOfSize: car1.size)
car1.physicsBody?.dynamic = true
car1.physicsBody!.categoryBitMask = ColliderType.Player.rawValue
car1.physicsBody!.contactTestBitMask = ColliderType.Traffic.rawValue
self.addChild(car1)
case 2:
let car2 = SKSpriteNode(imageNamed: "Car_Purple_Front")
car2.position = randomPOS
car2.zPosition = 3
car2.setScale(1.0)
car2.physicsBody = SKPhysicsBody(rectangleOfSize: car2.size)
car2.physicsBody?.dynamic = true
car2.physicsBody!.categoryBitMask = ColliderType.Traffic.rawValue
car2.physicsBody!.contactTestBitMask = ColliderType.Player.rawValue
self.addChild(car2)
default:
return
}
}
func createWalls(){
let wallSize = CGSize(width: 5, height: self.frame.size.height)
let rightwall = SKShapeNode(rectOfSize: wallSize)
rightwall.physicsBody = SKPhysicsBody(rectangleOfSize: wallSize)
rightwall.physicsBody!.dynamic = false
rightwall.position = CGPoint(x: self.frame.maxX-300, y: self.frame.size.height/2)
rightwall.fillColor = UIColor.clearColor()
self.addChild(rightwall)
let leftwall = SKShapeNode(rectOfSize: wallSize)
leftwall.physicsBody = SKPhysicsBody(rectangleOfSize: wallSize)
leftwall.physicsBody!.dynamic = false
leftwall.position = CGPoint(x: self.frame.minX+300, y: self.frame.size.height/2)
leftwall.fillColor = UIColor.clearColor()
self.addChild(leftwall)
}
func didBeginContact(contact: SKPhysicsContact) {
print("Contact")
if contact.bodyA.categoryBitMask == ColliderType.Traffic.rawValue && contact.bodyB.categoryBitMask == ColliderType.Player.rawValue {
print("Hi")
} else {
print("Hello") }
}
}
你的代码看起来不错,虽然我会做一些小的改动。
1) 我会像这样写我的对撞机类型
struct ColliderType {
static let player: UInt32 = 0x1 << 0
static let traffic: UInt32 = 0x1 << 1
}
因为这样你只需要将最后一个数字增加 1。
如果你决定添加更多类别,你的方式是下一个必须是 4,而不是 8,而不是 16 等,这更令人困惑(你正在处理 32 位整数)
不如这么用
...categoryBitMask = ColliderType.player
2) 建议在添加physicsBody前给sprite位置。您正在以相反的方式进行操作,这可能会导致意外问题。
3) 将您的碰撞方法更改为此
func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if (firstBody.categoryBitMask == ColliderType.player) && (secondBody.categoryBitMask == ColliderType.traffic) {
// player hit traffic, do something
}
}
4) 最后最重要的部分是你需要设置我在你的代码中看不到的委托。
在 DidMoveToView 中调用这个
physicsWorld.contactDelegate = self
否则 DidBeginContact 方法永远不会触发。
另外,如果您遵循 apples 的命名约定也是个好主意。所以只有 类、协议、枚举和结构应该以大写字母开头。
希望对您有所帮助
更简洁的编码方式 didBeginContact
是:
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case ColliderType.player | ColliderType.traffic:
// player and traffic have contacted
print("Collision between player and traffic")
default :
//Some other contact has occurred
print("Some other contact")
}
}
您可以添加任意数量的 case ColliderType.object1 | ColliderType.object2:
。
我第一次为 iOS 制作游戏。我非常接近,但是我很早就让碰撞检测工作了,然后我改变了一些东西,但我失去了它的工作。我试图回到过去,但没有成功。这是我到目前为止所拥有的,但没有任何效果。我正在尝试在网上找到的不同版本的碰撞检测,但我坚持要让这个起作用。只是不明白我哪里做错了。
先谢谢你。
import SpriteKit
enum ColliderType: UInt32 {
case Player = 1
case Traffic = 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMoveToView(view: SKView) {
createWalls()
self.backgroundColor = SKColor.whiteColor()
self.physicsWorld.gravity = CGVectorMake(0, 0)
player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody?.dynamic = true
player.physicsBody!.categoryBitMask = ColliderType.Player.rawValue
player.physicsBody!.contactTestBitMask = ColliderType.Traffic.rawValue
player.zPosition = 3
player.name = "player"
player.position = CGPoint(x: self.frame.midX, y: (self.frame.midY)/3)
player.setScale(1.0)
self.addChild(player)
_ = NSTimer.scheduledTimerWithTimeInterval(2.5, target: self, selector: #selector(GameScene.makeTraffic), userInfo: nil, repeats: true)
}
func makeTraffic(){
var aNumber = Int(arc4random_uniform(2))
let Pos1 = Int(self.frame.midX/2)+30
let Pos2 = Int((self.frame.size.width)/2)
let Pos3 = Int(self.frame.size.width-300)
let array = [Pos1, Pos2, Pos3]
let randomIndex = Int(arc4random_uniform(UInt32(array.count)))
let randomPOS = CGPoint(x:Int(array[randomIndex]), y:Int(self.frame.height))
if aNumber == 0 {
aNumber = aNumber + 1
}
switch aNumber {
case 1:
let car1 = SKSpriteNode(imageNamed: "Car_Green_Front")
car1.position = randomPOS
car1.zPosition = 3
car1.setScale(1.0)
car1.physicsBody = SKPhysicsBody(rectangleOfSize: car1.size)
car1.physicsBody?.dynamic = true
car1.physicsBody!.categoryBitMask = ColliderType.Player.rawValue
car1.physicsBody!.contactTestBitMask = ColliderType.Traffic.rawValue
self.addChild(car1)
case 2:
let car2 = SKSpriteNode(imageNamed: "Car_Purple_Front")
car2.position = randomPOS
car2.zPosition = 3
car2.setScale(1.0)
car2.physicsBody = SKPhysicsBody(rectangleOfSize: car2.size)
car2.physicsBody?.dynamic = true
car2.physicsBody!.categoryBitMask = ColliderType.Traffic.rawValue
car2.physicsBody!.contactTestBitMask = ColliderType.Player.rawValue
self.addChild(car2)
default:
return
}
}
func createWalls(){
let wallSize = CGSize(width: 5, height: self.frame.size.height)
let rightwall = SKShapeNode(rectOfSize: wallSize)
rightwall.physicsBody = SKPhysicsBody(rectangleOfSize: wallSize)
rightwall.physicsBody!.dynamic = false
rightwall.position = CGPoint(x: self.frame.maxX-300, y: self.frame.size.height/2)
rightwall.fillColor = UIColor.clearColor()
self.addChild(rightwall)
let leftwall = SKShapeNode(rectOfSize: wallSize)
leftwall.physicsBody = SKPhysicsBody(rectangleOfSize: wallSize)
leftwall.physicsBody!.dynamic = false
leftwall.position = CGPoint(x: self.frame.minX+300, y: self.frame.size.height/2)
leftwall.fillColor = UIColor.clearColor()
self.addChild(leftwall)
}
func didBeginContact(contact: SKPhysicsContact) {
print("Contact")
if contact.bodyA.categoryBitMask == ColliderType.Traffic.rawValue && contact.bodyB.categoryBitMask == ColliderType.Player.rawValue {
print("Hi")
} else {
print("Hello") }
}
}
你的代码看起来不错,虽然我会做一些小的改动。
1) 我会像这样写我的对撞机类型
struct ColliderType {
static let player: UInt32 = 0x1 << 0
static let traffic: UInt32 = 0x1 << 1
}
因为这样你只需要将最后一个数字增加 1。 如果你决定添加更多类别,你的方式是下一个必须是 4,而不是 8,而不是 16 等,这更令人困惑(你正在处理 32 位整数)
不如这么用
...categoryBitMask = ColliderType.player
2) 建议在添加physicsBody前给sprite位置。您正在以相反的方式进行操作,这可能会导致意外问题。
3) 将您的碰撞方法更改为此
func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if (firstBody.categoryBitMask == ColliderType.player) && (secondBody.categoryBitMask == ColliderType.traffic) {
// player hit traffic, do something
}
}
4) 最后最重要的部分是你需要设置我在你的代码中看不到的委托。
在 DidMoveToView 中调用这个
physicsWorld.contactDelegate = self
否则 DidBeginContact 方法永远不会触发。
另外,如果您遵循 apples 的命名约定也是个好主意。所以只有 类、协议、枚举和结构应该以大写字母开头。
希望对您有所帮助
更简洁的编码方式 didBeginContact
是:
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case ColliderType.player | ColliderType.traffic:
// player and traffic have contacted
print("Collision between player and traffic")
default :
//Some other contact has occurred
print("Some other contact")
}
}
您可以添加任意数量的 case ColliderType.object1 | ColliderType.object2:
。