我正在尝试创建一个用Swift 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()
}
}
}
答案 0 :(得分:0)
尝试这样的事情,然后重构你的___Collided代码进行调整。
不要测试节点相等性。使用名称或.categoryBitMask来确定它是什么类型的节点。
在本教程中获取categoryBitMask; https://www.raywenderlich.com/145318/spritekit-swift-3-tutorial-beginners
或试试这个;
player.name =“player1”
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.node.name == "player1" {
playerCollided(with: contact.bodyB.node!)
} else if contact.node.name == "player1" {
playerCollided(with: contact.bodyA.node!)
}
if contact.bodyA.node.name == "ammo" {
ammoCollided(with: contact.bodyB.node!)
} else if contact.node.name == "ammo" {
ammoCollided(with: contact.bodyA.node!)
}
}