【问题标题】:Sprite kit player and enemy collisions精灵套件玩家和敌人的碰撞
【发布时间】:2017-04-25 16:57:47
【问题描述】:

我一直在四处寻找如何让我的玩家和敌人发生冲突。我设置了一个攻击按钮并且需要它,所以当按下按钮时,玩家面前的敌人会从屏幕上移除。我将如何设置碰撞,我如何让它只在按下按钮时发生碰撞?

我已经尝试使用此代码进行碰撞,但我认为它没有任何效果。

//physicsbody for player and enemies
func didBegin(_ contact: SKPhysicsContact) {
    var bodyA = SKPhysicsBody()
    var bodyB = SKPhysicsBody()

    if contact.bodyA.node?.name == "player" {
        bodyA = contact.bodyA
        bodyB = contact.bodyB
    } else  {
        bodyA = contact.bodyB
        bodyB = contact.bodyA
    }
    //Player hits the rocket and dies and also remove the rocket
    if bodyA.node?.name == "player" && bodyB.node?.name == "enemy" {
        bodyA.node?.removeFromParent()
        bodyB.node?.removeFromParent()


        //After player dies go to death scene
        let gameOver = GameOverScene(size:CGSize(width: 2048, height: 1536), won:  false)
        self.view?.presentScene(gameOver)

    }

}

那么这就是播放器:

 func createPlayer(_ position: CGPoint) { //This is the method that creates the player on screen. You must pass this method the position you want the sprite spawned. Or maybe you can do it somewhere else in Swift, I dunno.

    //graphic stuff
    //let playerTexture = SKTexture(imageNamed: "Ttam1") //create variable with graphic assigned to it
    let player = SKSpriteNode(texture: playerTexture) //give player the graphic
    player.size = CGSize(width: 175, height: 200) //player sprite size
    player.zPosition = 20
    player.name = "player"
    //physics stuff
    player.physicsBody = SKPhysicsBody(texture: playerTexture, size: player.size) //Set up pixel-perfect collision mesh for the player
    player.physicsBody?.isDynamic = true
    player.physicsBody!.affectedByGravity = true //Stop the player from being affected by gravity
    player.physicsBody?.allowsRotation = false
    player.physicsBody?.categoryBitMask = ColliderType.PLAYER


    //spawny stuff
    insertChild(player, at: 0) //spawn player
    player.position = position //move player to position passed into this method
    playerNode = player //Create a node where the player is, filled by the player itself... Like a D.Va ult! The call mech one, not the self-destruct one.
    /*
    let frame2 = SKTexture(imageNamed: "Ttam2")
    let frame3 = SKTexture(imageNamed: "Ttam3")
    let frame4 = SKTexture(imageNamed: "Ttam4")

    */
    let animation = SKAction.animate(with: [playerTexture, frame2, frame3, frame4], timePerFrame: 0.2)
    let runForever = SKAction.repeatForever(animation)

    player.run(runForever)

}

这就是敌人:

//Create enemy - slime
func spawnEnemy() {

    //Call the enemy variable and sprite
    let enemyTexture = SKTexture(imageNamed: "Slime1")
    let enemy = SKSpriteNode(texture: enemyTexture)
    enemy.size = CGSize(width: 175, height: 175)
    enemy.zPosition = 10
    //Collision with the enemy
    enemy.name = "enemy"
    enemyNode = enemy

    //Randomly place the enemy on screen and move
    enemy.position = CGPoint(x: 2100, y: 325)
    enemy.physicsBody? = SKPhysicsBody(texture: enemyTexture, size: enemy.size)
    enemy.physicsBody?.affectedByGravity = true
    enemy.physicsBody?.allowsRotation = false
    enemy.physicsBody?.isDynamic = true




    //Add enemy node to screen.
    addChild(enemy)

    let frame2 = SKTexture(imageNamed: "Slime2")
    let frame3 = SKTexture(imageNamed: "Slime3")
    let animation = SKAction.animate(with: [enemyTexture, frame2, frame3, frame2], timePerFrame: 0.2)
    let runForever = SKAction.repeatForever(animation)

    enemy.run(runForever)



    //Set the enemy to move in a single direction:
    let actionMove = SKAction.moveTo(x: -enemy.size.width/2, duration: 10.0)

    //Remove enemy from screen when action is complete:
    let actionRemove = SKAction.removeFromParent()
    enemy.run(SKAction.sequence([actionMove, actionRemove]))

}

【问题讨论】:

  • 让我们尝试缩小可能出现的问题。您是否首先看到了您希望在场景中看到的所有精灵?玩家和敌人看起来是否在视觉上发生碰撞?如果你在 didBegin 函数中设置了断点,你真的命中了那个断点吗?
  • 到目前为止,我已经评论了 bodyA 和 bodyB 的联系人。我有我的朋友在这里和我一起工作,我试图弄清楚这一点。起初我遇到了敌人物理框的问题(没有出现,甚至没有在游戏场景中工作),但已经解决了。他们现在在测试时都在场景中发生了碰撞,但是目前它不会为它激活任何代码
  • 更新:我们现在让玩家被粘液击中并将他从场景中移除。现在我需要一种让按钮在靠近玩家时消灭敌人的方法
  • 问题解决了,我们已经知道该怎么做了:D
  • 如果您认为您遇到的问题也可能是其他开发人员遇到的问题,则可能值得自己更新问题或添加答案。

标签: swift sprite-kit


【解决方案1】:

要让攻击按钮消灭敌人,实现touchesBegan,如果攻击按钮被按下,设置一个标志:

attacking = true

(在您的属性定义中首先定义attackingvar attacking = false

touchesEnded 中,如果对attck 按钮的触摸结束,则设置attacking = false

然后,在你的didBegin 中,只有在没有设置攻击标志的情况下才摧毁玩家。如果已设置(即玩家和史莱姆在按下攻击按钮时发生碰撞),则只销毁史莱姆,添加一些分数等。

//Player hits the rocket and dies and also remove the rocket
if bodyA.node?.name == "player" && bodyB.node?.name == "enemy" {    
    switch attacking {
    case false:
        bodyA.node?.removeFromParent()
        bodyB.node?.removeFromParent()

        //After player dies go to death scene
        let gameOver = GameOverScene(size:CGSize(width: 2048, height: 1536), won:  false)
        self.view?.presentScene(gameOver)
    case true:
        let enemy = contact.bodyA.categoryBitMask == ColliderType.ENEMY ? contact.bodyA.node : contact.bodyB.node
        enemy.removeFromParent()
        score += 1
    }
}

我假设您评论中的“火箭”是敌人节点,即粘液? :-) 我没有看到为敌人设置的categoryBitMask - 有吗?我以为是ColliderType.ENEMY

didBegin: 中的这段代码是多余的:

var bodyA = SKPhysicsBody()
var bodyB = SKPhysicsBody()
if contact.bodyA.node?.name == "player" {
    bodyA = contact.bodyA
    bodyB = contact.bodyB
} else  {
    bodyA = contact.bodyB
    bodyB = contact.bodyA
}

因为您似乎从未使用过您设置的 bodyAbodyB 变量。如果您以后确实使用它们,那么这可能更有意义:

if contact.bodyA.node?.name == "player" {
    player = contact.bodyA
    enemy = contact.bodyB
} else  {
    enemy = contact.bodyB
    player = contact.bodyA
}

然后这行代码:

        let enemy = contact.bodyA.categoryBitMask == ColliderType.ENEMY ? contact.bodyA.node : contact.bodyB.node

可以从 case true: 块中删除。

【讨论】:

    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    相关资源
    最近更新 更多