多个联系人注册

时间:2018-03-19 15:47:02

标签: sprite-kit skphysicscontact

非常感谢任何帮助。我对此比较陌生,只是觉得我开始理解编码。

我的问题-----

我很难通过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))
        }
    }
}

}

1 个答案:

答案 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,看看是否能阻止多重接触问题。