【发布时间】:2017-09-23 21:51:53
【问题描述】:
你知道益智游戏“voi”吗?那是一款使用颜色异或逻辑的游戏。这意味着:黑色+黑色=白色。
https://www.youtube.com/watch?v=Aw5BdVcAtII
有没有办法用 sprite kit 中的两个 sprite 节点做相同的颜色逻辑?
谢谢。
【问题讨论】:
标签: ios colors sprite-kit xor
你知道益智游戏“voi”吗?那是一款使用颜色异或逻辑的游戏。这意味着:黑色+黑色=白色。
https://www.youtube.com/watch?v=Aw5BdVcAtII
有没有办法用 sprite kit 中的两个 sprite 节点做相同的颜色逻辑?
谢谢。
【问题讨论】:
标签: ios colors sprite-kit xor
当然,在 Sprite Kit 中可以做到这一点。
问题:
假设您有 2 个黑色方块,squareA 和 squareB。用户可以将这两个方块拖动到任何他想要的地方。他一次只能拖动一个方块。每当两个正方形相交时,您都希望将相交区域着色为白色。
初始设置:
在场景的顶部,我们需要创建一些变量:
private var squareA: SKSpriteNode?
private var squareB: SKSpriteNode?
private var squares = [SKSpriteNode]()
private var selectedShape: SKSpriteNode?
private var intersectionSquare: SKShapeNode?
squareA 和 squareB 只是我们最初在屏幕上看到的两个方块。squares 是一个数组,它将存储屏幕上显示的所有方块。selectedShape 将帮助我们跟踪当前正在拖动的方块。intersectionSquare 是一个白色方块,代表两个黑色方块的交集区域。然后初始化squareA和squareB,并将它们添加到squares数组中,如下所示:
squareA = SKSpriteNode(color: .black, size: CGSize(width: 190.0, height: 190.0))
if let squareA = self.squareA {
squareA.position = CGPoint(x: -200, y: 200)
squareA.name = "Square A"
squares.append(squareA)
self.addChild(squareA)
}
// Do the same for squareB or any other squares that you have on screen..
注意:如您所见,我在这里给它起了一个名字,只是为了在测试阶段更容易区分它们。
检测用户何时拖动方块:
现在,您需要检测用户何时拖动方块。为此,您可以使用:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
这些只是帮助我们的生活更轻松的方法。
然后,您需要设置touchDown、touchMoved 和touchUp 方法:
func touchDown(atPoint pos : CGPoint) {
let touchedNode = self.nodes(at: pos)
guard let selectedSquare = touchedNode.first as? SKSpriteNode else {
return
}
selectedShape = selectedSquare
}
func touchMoved(toPoint pos : CGPoint) {
guard let selectedSquare = self.selectedShape else {
return
}
selectedSquare.position = pos
checkIntersectionsWith(selectedSquare)
}
func touchUp(atPoint pos : CGPoint) {
selectedShape = nil
}
为了更详细地向您解释这里发生了什么:
touchDown方法中:好吧,我们需要用户一次只能拖动一个方块。使用nodes(at:) 方法,很容易知道触摸了哪个方格,我们可以知道将我们的selectedShape 变量设置为等于被触摸的方格。
touchMoved 方法中:这里我们基本上只是将selectedShape 移动到用户移动手指的位置。我们还调用checkIntersectionsWith() 方法,我们将在稍后设置。
touchUp 方法中:用户将手指从屏幕上松开,因此我们可以将selectedShape 设置为nil。
改变相交框的颜色:
现在让你的游戏看起来像你想要的最重要的部分是,当两个黑色方块相交时,如何将交叉框的颜色更改为白色?
嗯,这里有不同的可能性,这是一种可能的方法:
private func checkIntersectionsWith(_ selectedSquare: SKSpriteNode) {
for square in squares {
if selectedSquare != square && square.intersects(selectedSquare) {
let intersectionFrame = square.frame.intersection(selectedSquare.frame)
intersectionSquare?.removeFromParent()
intersectionSquare = nil
intersectionSquare = SKShapeNode(rect: intersectionFrame)
guard let interSquare = self.intersectionSquare else {
return
}
interSquare.fillColor = .white
interSquare.strokeColor = .clear
self.addChild(interSquare)
} else if selectedSquare != square {
intersectionSquare?.removeFromParent()
intersectionSquare = nil
}
}
}
每次调用checkIntersectionsWith() 方法时,我们都会遍历squares 数组中的节点,并使用框架的intersection() 方法检查选定的正方形是否与其中任何一个相交(除了自己)。如果是,那么我们创建一个名为intersectionSquare 的白色正方形,并将其框架设置为等于相交框架。
为了节省内存使用,您可以从场景中删除正方形,如果根本没有交叉点,则将intersectionSquare 设置为nil。
最终结果:
最终结果如下所示:
这只是我制作的快速草稿,向您展示您可以解决问题,显然您可以添加或改进很多东西(将其应用于屏幕上不仅有 2 个方块而且有很多方块的情况,或者当你的用户从屏幕上松开手指时产生一种磁性效果等),但我希望至少它能让你的项目走上正确的轨道:)
【讨论】: