非常感谢任何帮助。我对此比较陌生,只是觉得我开始理解编码。
我的问题-----
我很难通过SpriteKit教程解决问题,我一直在加强这种教程,以此来磨练和提高我作为新手的技能。
当我的播放器在地面“崩溃”时,我正在经历多次接触。
删除了多个生命,这会导致我的游戏生成“尝试添加已存在父级的SKNode:”错误将播放器添加回场景。 我已经尝试过player.removeFromParent在我的代码中可以想到的任何地方。
只要我“撞到”空中的“敌人”,游戏就能完美无瑕地运作。一旦玩家接触到地面,它就会全部结束。如果我在与地面接触时“杀死”玩家,则没有问题,但是只要玩家仍然拥有生命,无论是接触地面还是敌人,我都希望游戏继续进行。如果可以解决多重联系问题,我真的相信问题会解决。
class GameScene: SKScene, SKPhysicsContactDelegate {
// Set up the Texure Atlases
var images = SKSpriteNode()
var textureAtlas = SKTextureAtlas()
var textureArray = [SKTexture]()
var touchingScreen = false
var obstacle = SKSpriteNode()
// Generates a Random number between -350 and 350 (the center of the axis being 0)
let rand = GKRandomDistribution(lowestValue: -350, highestValue: 350)
var timer: Timer?
// This method is called when the Game Launches
override func didMove(to view: SKView) {
// Adds a pixel perfect physicsBody to the player
player.physicsBody = SKPhysicsBody(texture: player.texture!, size: player.texture!.size())
player.physicsBody?.categoryBitMask = 1
player.position = CGPoint(x: -400, y: 275)
// Disables the affects of a collisions (+pushing, rotation etc.) on the player when a collision with another SKSpriteNode occurs
player.physicsBody?.allowsRotation = false
player.physicsBody?.collisionBitMask = 0
addChild(player)
physicsWorld.gravity = CGVector(dx: 0, dy: -2)
physicsWorld.contactDelegate = self
timer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)
}
// This method is called when the User touches the Screen
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touchingScreen = true
}
// This method is called when the User stops touching the Screen
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touchingScreen = false
}
// This method is called before each frame is rendered
override func update(_ currentTime: TimeInterval) {
// Constrains the player to the scene area
if player.position.y > 275 {
player.position.y = 275
}
// Moves the player up when the screen is being touched
if touchingScreen {
player.physicsBody?.velocity = CGVector(dx: 0, dy: 200
)
}
}
func didBegin(_ contact: SKPhysicsContact) {
// Exits the method if either node is nil (doesn't exist)
guard let nodeA = contact.bodyA.node else { return }
guard let nodeB = contact.bodyB.node else { return }
// Check to see if either node is player and, if so, call the playerHit method and pass in the other node
if nodeA == player {
playerHit(nodeB)
} else if nodeB == player {
playerHit(nodeA)
}
}
func createEnemy() {
// Check for Bonus Creation
checkForBonusCreation()
// Choose a Random Enemy
let pickEnemy = Int(arc4random_uniform(3))
switch pickEnemy {
case 0:
obstacle = SKSpriteNode(imageNamed: "enemy-balloon")
animateBalloon()
case 1:
obstacle = SKSpriteNode(imageNamed: "enemy-bird")
animateBird()
case 2:
obstacle = SKSpriteNode(imageNamed: "enemy-plane")
animatePlane()
default:
return
}
// Positions the enemy
obstacle.zPosition = -2
obstacle.position.x = 768
obstacle.size = (CGSize(width: obstacle.size.width * 0.7, height: obstacle.size.width * 0.7))
// Prevents the obstacle from being spawned too low on the scene
if obstacle.position.y < -150 {
obstacle.position.y = -150
}
addChild(obstacle)
// Adds pixel perfect collision detection to the enemies
obstacle.physicsBody = SKPhysicsBody(texture: obstacle.texture!, size: obstacle.texture!.size())
// Then we set isDynamic to false so grivty will not affect the obstacles
obstacle.physicsBody?.isDynamic = false
// Assigns 1 to it's contactTestBitMask so that it know to detect a collision with the player
obstacle.physicsBody?.contactTestBitMask = 1
// Names the obstacle so we can track collisions properly
obstacle.name = "enemy"
// Spawn an enemy at a random y-axis
obstacle.position.y = CGFloat(rand.nextInt())
// Moves the obstacles across to and off the left hand side of the screen over 9 seconds athen removes thier nodes so they don't chew up memory
let move = SKAction.moveTo(x: -768, duration: 9)
let remove = SKAction.removeFromParent()
let action = SKAction.sequence([move, remove])
obstacle.run(action)
}
func playerHit(_ node: SKNode) {
if node.name == "enemy" {
player.removeFromParent()
node.removeFromParent()
lives -= 1
balloonPop()
showLivesRemaining()
} else if node.name == "ground" {
player.removeFromParent()
lives -= 1
balloonPop()
showLivesRemaining()
}
}
func balloonPop() {
player.removeFromParent()
}
func showLivesRemaining() {
if lives >= 3 {
lives = 3
} else if lives <= 0 {
lives = 0
player.removeFromParent()
}
}
// Jump to the restart or quit scene
func restartGame() {
player.removeFromParent()
let wait = SKAction.wait(forDuration: 2.0)
let showPlayer = SKAction.run {
player.position = CGPoint(x: -400, y: 275)
self.addChild(player)
}
let sequence = SKAction.sequence([wait, showPlayer])
run(sequence)
}
// Displays GAME OVER and takes the player to the "Restart or Quit" choice scene
func endGame() {
player.removeFromParent()
let gameOver = SKSpriteNode(imageNamed: "game-over")
gameOver.zPosition = 15
addChild(gameOver)
// Waits 2 seconds and fade into the Restart Scene
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
if let scene = RestartScene(fileNamed: "RestartScene") {
scene.scaleMode = .aspectFill
self.view?.presentScene(scene, transition: SKTransition.crossFade(withDuration: 1.5))
}
}
}
}
答案 0 :(得分:0)
许多游戏所做的是在玩家被击中之后给予一段缓冲期,他们会闪现玩家或将玩家变为红色几秒钟。在此期间,玩家不会有更多的命中率,并且让玩家有机会转向安全。
func didBegin(_ contact: SKPhysicsContact) {
let contactAName = contact.bodyA.node?.name
let contactBName = contact.bodyB.node?.name
//don't detect contact if the player is hit
if ((contactAName == "player") || (contactBName == "player")) && !player.isHit {
if (contactAName == "ground") || (contactBName == "ground") {
print("groundcontact with player")
player.isHit = true
//good idea to flash player or pulse player to let user know player is hit
self.run(.wait(forDuration: 3.0)) {
//wait for 3 seconds and make the player hittable again
self.player.isHit = false
}
return
}
}
}
修改
接触检测码每秒最多发射60次。当你的玩家击中敌人时你会移除那个敌人,与敌人建立更多的联系是不可能的。然而,当玩家击中地面时,地面不会被移除,因此玩家将失去生命。在玩家击中地面后,尝试将玩家与地面相撞100px,看看是否能阻止多重接触问题。