检查两个节点相互接触时的颜色是不是相同
Posted
技术标签:
【中文标题】检查两个节点相互接触时的颜色是不是相同【英文标题】:Check if two nodes are the same color when they touch each other检查两个节点相互接触时的颜色是否相同 【发布时间】:2017-03-02 09:13:13 【问题描述】:我是 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)
我已提供所有代码,以便您了解设置。提前感谢您的帮助。
【问题讨论】:
运行代码时实际看到的内容以及它与您的预期有何不同。此外,您的 func didBegin 的一半是多余的,因为您删除了任何进入函数的节点。 它与您的要求无关,但为什么要为 Color 创建枚举?为什么不在 UIColor 扩展中创建静态计算属性“randomColor”? 【参考方案1】:您没有正确设置contactBitMask,因此没有检测到联系人...默认情况下,由于性能原因,此掩码的默认值为零:
当两个 body 共享同一个空间时,每个 body 的类别掩码为 通过执行逻辑测试对另一个身体的接触面罩 与操作。如果任一比较结果为非零值,则 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)
现在,当两个实体之间发生联系时,如文档中所述,每个实体的类别位掩码都会通过执行逻辑与运算与另一个实体的联系掩码进行测试。如果结果非零,则发生联系通知。在这种情况下,这将是 1 & 1 = 1。
【讨论】:
【参考方案2】:首先,为categoryBitMask
声明一个struct
:
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
就足够了,因为我稍后会将相同颜色的body设置为相同的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)
【讨论】:
如果他想拥有 1000 种不同的颜色怎么办?或者只有 100 个,但你知道我要去的地方吗?您将没有足够的类别...并且在您当前的设置下,那些if else
块很快就会变得一团糟。以上是关于检查两个节点相互接触时的颜色是不是相同的主要内容,如果未能解决你的问题,请参考以下文章