スウィフト3宇宙シューティングゲーム:弾丸の衝突に関する問題
私は現在、衝突が正常に動作し得ることとの難しさを持っスウィフト3で記述されたシューティングゲームを作成しようとしています。弾丸が敵に当たったら、爆発して特定の敵と弾丸をゲームから取り除く必要があります。プレイヤーが敵に当たった場合、その間に爆発が起こり、その特定の敵とプレーヤーを画面から取り外し、ゲームオーバーと呼ぶ。これは私がこれまで持っていたものですが、弾丸はちょうど衝突が起こることなく跳ね返ります。どんな助けでも大歓迎です。
import SpriteKit
import GameplayKit
enum CollisonType: UInt32 {
case player = 1
case ammo = 2
case enemy = 4
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var starfield: SKEmitterNode!
var player: SKSpriteNode!
var ammo: SKSpriteNode!
var enemy: SKSpriteNode!
var gameScore: SKLabelNode!
var score: Int = 0 {
didSet { // didSet a property observer used to update gameScore
gameScore.text = "Score: \(score)"
}
}
var possibleEnemies = ["ball", "hammer", "tv"]
var gameTimer: Timer! // Used to create enemies regularly.
var isGameOver = false // a boolean that will be set to true when we should stop increasing the player's score
override func didMove(to view: SKView) {
backgroundColor = UIColor.black
starfield = SKEmitterNode(fileNamed: "Starfield")!
starfield.position = CGPoint(x: 1024, y: 384)
starfield.advanceSimulationTime(10)
addChild(starfield)
starfield.zPosition = -1
player = SKSpriteNode(imageNamed: "player")
player.position = CGPoint(x: 100, y: 384)
player.physicsBody = SKPhysicsBody(texture: player.texture!, size: player.size)
player.physicsBody!.categoryBitMask = CollisonType.player.rawValue
player.physicsBody!.contactTestBitMask = CollisonType.enemy.rawValue
addChild(player)
gameScore = SKLabelNode(fontNamed: "Chalkduster")
gameScore.text = "Score: 0"
gameScore.horizontalAlignmentMode = .left
gameScore.position = CGPoint(x: 8, y: 8)
addChild(gameScore)
physicsWorld.gravity = CGVector(dx: 0, dy: 0)
physicsWorld.contactDelegate = self
gameTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
gameTimer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(createAmmo), userInfo: nil, repeats: true)
}
func createAmmo() {
if isGameOver {
return
}
ammo = SKSpriteNode(imageNamed: "bullet")
ammo.name = "ammo"
ammo.position = CGPoint(x: player.position.x + 100, y: player.position.y)
addChild(ammo)
ammo.physicsBody = SKPhysicsBody(texture: ammo.texture!, size: ammo.size)
ammo.physicsBody!.categoryBitMask = CollisonType.ammo.rawValue
ammo.physicsBody!.contactTestBitMask = CollisonType.enemy.rawValue
ammo.physicsBody!.velocity = CGVector(dx: 900, dy: 0)
ammo.physicsBody!.linearDamping = 0
ammo.physicsBody!.angularDamping = 0
}
func createEnemy() {
possibleEnemies = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: possibleEnemies) as! [String]
let randomDistribution = GKRandomDistribution(lowestValue: 50, highestValue: 736)
enemy = SKSpriteNode(imageNamed: possibleEnemies[0])
enemy.name = "enemy"
enemy.position = CGPoint(x: 1200, y: randomDistribution.nextInt())
addChild(enemy)
enemy.physicsBody = SKPhysicsBody(texture: enemy.texture!, size: enemy.size)
enemy.physicsBody!.categoryBitMask = CollisonType.enemy.rawValue
enemy.physicsBody!.contactTestBitMask = CollisonType.player.rawValue | CollisonType.ammo.rawValue
enemy.physicsBody!.velocity = CGVector(dx: -300, dy: 0)
enemy.physicsBody!.angularVelocity = 5
enemy.physicsBody!.linearDamping = 0
enemy.physicsBody!.angularDamping = 0
}
override func update(_ currentTime: TimeInterval) {
for node in children {
if node.position.x < -300 || node.position.x > 1300 || node.position.y < -300 || node.position.y > 1000 {
node.removeFromParent()
}
}
if !isGameOver {
score += 1
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
var location = touch.location(in: self)
if location.y < 50 {
location.y = 50
} else if location.y > 730 {
location.y = 730
}
player.position = location
}
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.node == player {
playerCollided(with: contact.bodyB.node!)
} else if contact.bodyB.node == player {
playerCollided(with: contact.bodyA.node!)
}
if contact.bodyA.node == ammo {
ammoCollided(with: contact.bodyB.node!)
} else if contact.bodyB.node == ammo {
ammoCollided(with: contact.bodyA.node!)
}
}
func playerCollided(with node:SKNode) {
if node.name == "enemy" {
let explosion = SKEmitterNode(fileNamed: "explosion")!
explosion.position = enemy.position
addChild(explosion)
player.removeFromParent()
enemy.removeFromParent()
isGameOver = true
}
}
func ammoCollided(with node:SKNode) {
if node.name == "enemy" {
let explosion = SKEmitterNode(fileNamed: "explosion")!
explosion.position = enemy.position
addChild(explosion)
ammo.removeFromParent()
enemy.removeFromParent()
}
}
}
私はあなたの提案を試みたが、それはまだ完全には機能しません。衝突の後で弾丸の3/4だけが姿を消した(一部はまだ周囲を跳ねている)。しかし、敵は消えることはありません。爆発も起こらない。爆発は、iPadの右側に散発的にしか発生しません(プレーヤーの視界の範囲外)。あなたが提供したチュートリアルのリンクに従います。ありがとうございました。 – Soja
チュートリアルのリンクに従って、私の問題を解決することができました。再びありがとう@eSpecialized! – Soja