我是Swift的新手,如果我犯了一个菜鸟错误,请道歉。如果两个盒子的颜色相同,我试图让两个盒子在触摸时消失。到目前为止,我有以下代码:
此代码设置游戏:
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
physicsWorld.contactDelegate = self
let background = SKSpriteNode(imageNamed: "background.jpg")
background.size = self.frame.size;
background.position = CGPoint(x: 0, y: 0)
background.blendMode = .replace
background.zPosition = -1
addChild(background)
}
生成随机颜色的代码:
enum Color {
case ColorRed
case ColorGreen
case ColorBlue
public var color: UIColor {
switch self {
case .ColorRed: return UIColor(red: 255, green: 0, blue: 0, alpha: 1)
case .ColorGreen: return UIColor(red: 0, green: 255, blue: 0, alpha: 1)
case .ColorBlue: return UIColor(red: 0, green: 0, blue: 255, alpha: 1)
}
}
static var all: [Color] = [.ColorRed, .ColorGreen, .ColorBlue]
static var randomColor: UIColor {
let randomIndex = Int(arc4random_uniform(UInt32(all.count)))
return all[randomIndex].color
}
}
这是重要的部分 - 对象之间的实际联系:
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
let firstBody = contact.bodyA.node as! SKSpriteNode!
let secondBody = contact.bodyB.node as! SKSpriteNode!
if firstBody!.color == secondBody!.color {
firstBody!.removeFromParent()
secondBody!.removeFromParent()
}
} else {
let firstBody = contact.bodyB.node as! SKSpriteNode!
let secondBody = contact.bodyA.node as! SKSpriteNode!
if firstBody!.color == secondBody!.color {
firstBody!.removeFromParent()
secondBody!.removeFromParent()
}
}
}
最后是用户触摸屏幕时的代码:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let box = SKSpriteNode(color: UIColor.red, size: CGSize(width: 64, height: 64))
box.color = Color.randomColor
box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 64, height: 64))
box.position = location
addChild(box)
}
}
我提供了所有代码,因此您了解了设置。提前感谢您的帮助。
答案 0 :(得分:3)
您尚未正确设置contactBitMask,因此未检测到任何联系人...默认情况下,由于性能原因,此掩码的默认值为零:
当两个物体共享相同的空间时,每个物体的类别掩码都是 通过执行逻辑来测试另一个身体的接触面罩 和操作。如果任一比较结果为非零值,则为 创建SKPhysicsContact对象并将其传递给物理世界 代表。为获得最佳性能,仅在触点掩码中设置位 您感兴趣的互动。
默认值为0x00000000(清除所有位)。
要解决此问题,请将联系人和类别位掩码都设置为适当的值,如下所示:
class GameScene: SKScene,SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
physicsWorld.contactDelegate = self
}
func didBegin(_ contact: SKPhysicsContact) {
if let bodyA = contact.bodyA.node as? SKSpriteNode,
let bodyB = contact.bodyB.node as? SKSpriteNode{
//Of course this is simple example and you will have to do some "filtering" to determine what type of objects are collided.
// But the point is , when appropriate objects have collided, you compare their color properties.
if bodyA.color == bodyB.color {
bodyA.run(SKAction.removeFromParent())
bodyB.run(SKAction.removeFromParent())
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let box = SKSpriteNode(color: UIColor.red, size: CGSize(width: 64, height: 64))
box.color = Color.randomColor
box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 64, height: 64))
box.physicsBody?.contactTestBitMask = 0b1
box.physicsBody?.categoryBitMask = 0b1
box.position = location
addChild(box)
}
}
}
现在当两个机构之间发生接触时,如文档中所述,通过执行逻辑AND操作,每个机体的类别位掩码再次测试另一个机构的接触掩模。如果结果非零,则发生联系通知。在这种情况下,这将是1&amp; 1 = 1。
答案 1 :(得分:0)
首先,为struct
声明categoryBitMask
:
struct ColorMask {
static let Red: UInt32 = 0x1 << 0
static let Green: UInt32 = 0x1 << 1
static let Blue: UInt32 = 0x1 << 2
}
其次,将枚举声明更改为以下内容:
enum Color {
case ColorRed
case ColorGreen
case ColorBlue
public var color: UIColor {
switch self {
case .ColorRed: return UIColor(red: 255, green: 0, blue: 0, alpha: 1)
case .ColorGreen: return UIColor(red: 0, green: 255, blue: 0, alpha: 1)
case .ColorBlue: return UIColor(red: 0, green: 0, blue: 255, alpha: 1)
}
}
static var all: [Color] = [.ColorRed, .ColorGreen, .ColorBlue]
static var randomColor: Color {
let randomIndex = Int(arc4random_uniform(UInt32(all.count)))
return all[randomIndex]
}
}
我刚刚更改了上面的代码以返回Color
而不是UIColor
。
第三,将didBegin
修改为:
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == contact.bodyB.categoryBitMask {
let firstBody = contact.bodyA.node as! SKSpriteNode!
let secondBody = contact.bodyB.node as! SKSpriteNode!
firstBody!.removeFromParent()
secondBody!.removeFromParent()
}
}
在上面的代码中,只需比较categoryBitMask
即可,因为稍后我会将相同的颜色设置为相同的categoryBitMask
。
最后,使用以下代码将categoryBitMask
设置为框:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let box = SKSpriteNode(color: UIColor.red, size: CGSize(width: 64, height: 64))
let color = Color.randomColor
box.color = color.color
box.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 64, height: 64))
if color == Color.ColorRed {
box.physicsBody?.categoryBitMask = ColorMask.Red
} else if color == Color.ColorGreen {
box.physicsBody?.categoryBitMask = ColorMask.Green
}else if color == Color.ColorBlue {
box.physicsBody?.categoryBitMask = ColorMask.Blue
}
box.physicsBody?.contactTestBitMask = ColorMask.Red | ColorMask.Green | ColorMask.Blue
box.position = location
addChild(box)
}
}