この度、読者様からご連絡いただき、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() } }