この度、読者様からご連絡いただき、P199にあります リスト9-2 のコードに誤りがあることがわかりました。コメントをくださいました読者の方に深く感謝いたします。
具体的には、「パーティクルの表示位置が常に画面中央になってしまう」というバグになります。
31行目からはじまる didBegin メソッドの中で、衝突したノードを削除するコードがあります(34, 35行目)。このタイミングで衝突したノードを削除すると、ポジションが CGPoint(0, 0) が設定されることになってしまい、結果としてパーティクルの表示位置が画面中央になってしまいます。
※P217 の didBegin メソッドも同様です。
正しいコードは以下の通りです。
「炎のパーティクルの読み込みと表示」と「衝突したノードを削除する」を入れ替えてあります。このことにより、炎のパーティクルを正しい位置に表示した後にノードを削除するようになります。
/// 衝突時のメソッド
func didBegin(_ contact: SKPhysicsContact) {
// 炎のパーティクルの読み込みと表示
let explosion = SKEmitterNode(fileNamed: "explosion")
explosion?.position = contact.bodyA.node?.position ?? CGPoint(x: 0, y: 0)
addChild(explosion!)
// 衝突したノードを削除する
contact.bodyA.node?.removeFromParent()
contact.bodyB.node?.removeFromParent()
// 炎のパーティクルアニメーションを0.5秒表示して削除
self.run(SKAction.wait(forDuration: 0.5)) {
explosion?.removeFromParent()
}
}