Swift 3 我的游戏结束代码无法正常工作
Swift 3 my game over code doesn't work correctly
如果我触摸除了按钮之外的游戏就会崩溃。我能做什么?如何?我想忽略按钮以外的所有触摸。我怎样才能做到这一点?
这是我的 touchesBegan:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self),
let node = self.nodes(at: location).first {
var player = SKSpriteNode()
if node.name == "BlueButton" {
player = playerB
playerB.isHidden = false
} else if node.name == "RedButton" {
player = playerR
playerR.isHidden = false
} else if node.name == "YellowButton" {
player = playerY
playerY.isHidden = false
} else if node.name == "GreenButton" {
player = playerG
playerG.isHidden = false
}
for sprite in [playerB, playerW, playerR, playerY, playerG] {
sprite?.removeFromParent()
}
player.position = CGPoint(x: 0, y: -60)
addChild(player)
}
}
这是我的 touchesEnded 函数
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
addChild(playerW)
playerB.removeFromParent()
playerR.removeFromParent()
playerY.removeFromParent()
playerG.removeFromParent()
}
我觉得这个条件
if firstBody.node?.name == "BLUE" && secondBody.node?.name == "BLUEBLOCK" ||
firstBody.node?.name == "RED" && secondBody.node?.name == "REDBLOCK" ||
firstBody.node?.name == "YELLOW" && secondBody.node?.name == "YELLOWBLOCK" &&
firstBody.node?.name == "GREEN" && secondBody.node?.name == "GREENBLOCK"
应该看起来像
if (firstBody.node?.name == "BLUE" && secondBody.node?.name == "BLUEBLOCK") ||
(firstBody.node?.name == "RED" && secondBody.node?.name == "REDBLOCK") ||
(firstBody.node?.name == "YELLOW" && secondBody.node?.name == "YELLOWBLOCK") ||
(firstBody.node?.name == "GREEN" && secondBody.node?.name == "GREENBLOCK")
它看起来还是很丑,但必须工作
好吧,坦白说有点乱,尤其是 didBeginContact 函数。如果我没看错你的意图,它应该是这样的:
- 与 "white" 方块的任何接触都应该结束游戏。
- 对于除 一个 之外的所有其他颜色的接触,特定颜色应该结束游戏。
- 联系与特定颜色应该增加分数。
如果这确实是我们的目标,那么像下面这样的东西应该可以工作,尽管我仍然建议进一步重构以避免将 game-logic 的如此重要的部分基于 flakey string-matching:
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else {
// this and the one blow are good places to add a breakpoint to inspect what's going on if still having problems
return
}
guard let nodeB = contact.bodyB.node else {
return
}
// Some Bools to make the below logic more readable
let blueContacted = nodeA.name == "BLUEBLOCK" || nodeB.name == "BLUEBLOCK"
let redContacted = nodeA.name == "REDBLOCK" || nodeB.name == "REDBLOCK"
let yellowContacted = nodeA.name == "YELLOWBLOCK" || nodeB.name == "YELLOWBLOCK"
let greenContacted = nodeA.name == "GREENBLOCK" || nodeB.name == "GREENBLOCK"
var removableNodeName: String?
if blueContacted && yellowContacted {
removableNodeName = "YELLOWBLOCK"
} else if redContacted && greenContacted {
removableNodeName = "GREENBLOCK"
} else if yellowContacted && blueContacted {
removableNodeName = "BLUEBLOCK"
} else if greenContacted && redContacted {
removableNodeName = "REDBLOCK"
}
if let nodeName = removableNodeName {
score += 1
scoreLabel?.text = "\(score)"
if nodeA.name == nodeName {
nodeA.run(SKAction.move(to: CGPoint(x: 0 , y: 360), duration: 0.3))
nodeA.run(SKAction.fadeOut(withDuration: 0.3))
} else {
nodeB.run(SKAction.move(to: CGPoint(x: 0 , y: 360), duration: 0.3))
nodeB.run(SKAction.fadeOut(withDuration: 0.3))
}
} else { // Any other contact means game over
nodeA.removeFromParent()
nodeB.removeFromParent()
score = 0
scoreLabel?.text = "\(score)"
gameOver()
}
}
编辑:添加了一些守卫以根据下面的讨论检查 physicsBodies 上是否存在节点。
根据我在其他回答中的讨论,我 猜测 您的 touchesBegan
的复杂性导致您偶尔会添加多个版本的 player-sprite .下面应该只添加每个 playerSprite 一次 并且一次只添加 一个 这应该可以更容易地避免由于精灵覆盖精灵等而导致的意外接触。 ..
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self),
let node = self.nodes(at: location).first {
var player = SKSpriteNode()
if node.name == "BlueButton" {
player = playerB
} else if node.name == "RedButton" {
player = playerR
} else if node.name == "YellowButton" {
player = playerY
} else if node.name == "GreenButton" {
player = playerG
}
for sprite in [playerB, playerW, playerR, playerY, playerG] {
sprite.removeFromParent()
}
player.position = CGPoint(x: 0, y: -50)
addChild(player)
}
}
如果我触摸除了按钮之外的游戏就会崩溃。我能做什么?如何?我想忽略按钮以外的所有触摸。我怎样才能做到这一点? 这是我的 touchesBegan:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self),
let node = self.nodes(at: location).first {
var player = SKSpriteNode()
if node.name == "BlueButton" {
player = playerB
playerB.isHidden = false
} else if node.name == "RedButton" {
player = playerR
playerR.isHidden = false
} else if node.name == "YellowButton" {
player = playerY
playerY.isHidden = false
} else if node.name == "GreenButton" {
player = playerG
playerG.isHidden = false
}
for sprite in [playerB, playerW, playerR, playerY, playerG] {
sprite?.removeFromParent()
}
player.position = CGPoint(x: 0, y: -60)
addChild(player)
}
}
这是我的 touchesEnded 函数
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
addChild(playerW)
playerB.removeFromParent()
playerR.removeFromParent()
playerY.removeFromParent()
playerG.removeFromParent()
}
我觉得这个条件
if firstBody.node?.name == "BLUE" && secondBody.node?.name == "BLUEBLOCK" ||
firstBody.node?.name == "RED" && secondBody.node?.name == "REDBLOCK" ||
firstBody.node?.name == "YELLOW" && secondBody.node?.name == "YELLOWBLOCK" &&
firstBody.node?.name == "GREEN" && secondBody.node?.name == "GREENBLOCK"
应该看起来像
if (firstBody.node?.name == "BLUE" && secondBody.node?.name == "BLUEBLOCK") ||
(firstBody.node?.name == "RED" && secondBody.node?.name == "REDBLOCK") ||
(firstBody.node?.name == "YELLOW" && secondBody.node?.name == "YELLOWBLOCK") ||
(firstBody.node?.name == "GREEN" && secondBody.node?.name == "GREENBLOCK")
它看起来还是很丑,但必须工作
好吧,坦白说有点乱,尤其是 didBeginContact 函数。如果我没看错你的意图,它应该是这样的:
- 与 "white" 方块的任何接触都应该结束游戏。
- 对于除 一个 之外的所有其他颜色的接触,特定颜色应该结束游戏。
- 联系与特定颜色应该增加分数。
如果这确实是我们的目标,那么像下面这样的东西应该可以工作,尽管我仍然建议进一步重构以避免将 game-logic 的如此重要的部分基于 flakey string-matching:
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else {
// this and the one blow are good places to add a breakpoint to inspect what's going on if still having problems
return
}
guard let nodeB = contact.bodyB.node else {
return
}
// Some Bools to make the below logic more readable
let blueContacted = nodeA.name == "BLUEBLOCK" || nodeB.name == "BLUEBLOCK"
let redContacted = nodeA.name == "REDBLOCK" || nodeB.name == "REDBLOCK"
let yellowContacted = nodeA.name == "YELLOWBLOCK" || nodeB.name == "YELLOWBLOCK"
let greenContacted = nodeA.name == "GREENBLOCK" || nodeB.name == "GREENBLOCK"
var removableNodeName: String?
if blueContacted && yellowContacted {
removableNodeName = "YELLOWBLOCK"
} else if redContacted && greenContacted {
removableNodeName = "GREENBLOCK"
} else if yellowContacted && blueContacted {
removableNodeName = "BLUEBLOCK"
} else if greenContacted && redContacted {
removableNodeName = "REDBLOCK"
}
if let nodeName = removableNodeName {
score += 1
scoreLabel?.text = "\(score)"
if nodeA.name == nodeName {
nodeA.run(SKAction.move(to: CGPoint(x: 0 , y: 360), duration: 0.3))
nodeA.run(SKAction.fadeOut(withDuration: 0.3))
} else {
nodeB.run(SKAction.move(to: CGPoint(x: 0 , y: 360), duration: 0.3))
nodeB.run(SKAction.fadeOut(withDuration: 0.3))
}
} else { // Any other contact means game over
nodeA.removeFromParent()
nodeB.removeFromParent()
score = 0
scoreLabel?.text = "\(score)"
gameOver()
}
}
编辑:添加了一些守卫以根据下面的讨论检查 physicsBodies 上是否存在节点。
根据我在其他回答中的讨论,我 猜测 您的 touchesBegan
的复杂性导致您偶尔会添加多个版本的 player-sprite .下面应该只添加每个 playerSprite 一次 并且一次只添加 一个 这应该可以更容易地避免由于精灵覆盖精灵等而导致的意外接触。 ..
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self),
let node = self.nodes(at: location).first {
var player = SKSpriteNode()
if node.name == "BlueButton" {
player = playerB
} else if node.name == "RedButton" {
player = playerR
} else if node.name == "YellowButton" {
player = playerY
} else if node.name == "GreenButton" {
player = playerG
}
for sprite in [playerB, playerW, playerR, playerY, playerG] {
sprite.removeFromParent()
}
player.position = CGPoint(x: 0, y: -50)
addChild(player)
}
}