2016-04-15 7 views
1

Я пытаюсь сделать простую игру Space Shooter. Контакт должен происходить либо между торпедой и инопланетянином, либо челноком, и инопланетянином. Проблема в том, что этот второй контакт (шаттл и инопланетянин) происходит только после первого контакта (торпеда и инопланетянина), и еще больше они не всегда точны. Это структура создается за пределами классаEasy SpriteKit Обнаружение контакта (Space Shooter Game) Не правильно Wotking

struct PhysicsCategory { 
static let alien : UInt32 = 1 
static let torpedo : UInt32 = 2 
static let shuttle : UInt32 = 3 } 

Shuttle:

shuttle.physicsBody = SKPhysicsBody(rectangleOfSize: shuttle.size) 
shuttle.physicsBody?.categoryBitMask = PhysicsCategory.shuttle 
shuttle.physicsBody?.contactTestBitMask = PhysicsCategory.alien 
shuttle.physicsBody?.dynamic = false 
shuttle.physicsBody?.affectedByGravity = false 

Torpedo:

torpedo.physicsBody = SKPhysicsBody(rectangleOfSize: torpedo.size) 
torpedo.physicsBody?.categoryBitMask = PhysicsCategory.torpedo 
torpedo.physicsBody?.contactTestBitMask = PhysicsCategory.alien 
torpedo.physicsBody?.affectedByGravity = false 
torpedo.physicsBody?.dynamic = false 

Иностранец:

alien.physicsBody = SKPhysicsBody(rectangleOfSize: torpedo.size) 
alien.physicsBody?.categoryBitMask = PhysicsCategory.alien 
alien.physicsBody?.contactTestBitMask = PhysicsCategory.torpedo 
alien.physicsBody?.affectedByGravity = false 
alien.physicsBody?.dynamic = true 

Наконец, вот мой контактный код:

func didBeginContact(contact: SKPhysicsContact) { 
    var firstBody : SKPhysicsBody = contact.bodyA 
    var secondBody : SKPhysicsBody = contact.bodyB 

    if ((firstBody.categoryBitMask == PhysicsCategory.alien) && (secondBody.categoryBitMask == PhysicsCategory.torpedo)) || 
    ((firstBody.categoryBitMask == PhysicsCategory.torpedo) && (secondBody.categoryBitMask == PhysicsCategory.alien)) { 
     self.contactWithTorpedo(firstBody.node as! SKSpriteNode, torpedo: secondBody.node as! SKSpriteNode) 
    } else if ((firstBody.categoryBitMask == PhysicsCategory.shuttle) && (secondBody.categoryBitMask == PhysicsCategory.alien)) { 
      self.contactWithShuttle(firstBody.node as! SKSpriteNode, shuttle: secondBody.node as! SKSpriteNode) 
    } 
} 


func contactWithTorpedo (alien: SKSpriteNode, torpedo : SKSpriteNode) { 
    alien.removeFromParent() 
    torpedo.removeFromParent() 
    score++ 
    scoreLabel.text = "score: " + "\(score)" 
} 

func contactWithShuttle (alien:SKSpriteNode, shuttle:SKSpriteNode) { 
    alien.removeFromParent() 
    shuttle.removeFromParent() 

    self.view?.presentScene(EndScene()) 

} 

Я не уверен, где проблема, плюс я видел, что несколько учебников делают то же самое. Я не знаю, насколько это актуально, но это не игра iOS, а OSX. Заранее спасибо!

+0

Жюль - вы говорите, что * нет * контакты между челноком и иностранцем не признаются до тех пор, пока был контакт между торпеда и инопланетянина? –

+0

Возможная проблема с этим кодом заключается в том, что если был контакт между челноком и инопланетянином, но SKPhysicscontact, переданный в didBeginContact, имел firstBody == alien и secondBody == shuttle, ваш self.collisionWithShuttle не получил бы вызов из-за if ... then statements. –

ответ

1

Вы можете найти его менее запутанным реструктурировать свой didBeginContact следующим , так как это позволяет избежать firstBody/secondbody вещи и сложные if...then условия, чтобы увидеть, что связался с чем:

func didBeginContact(contact: SKPhysicsContact) { 
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask 

    switch contactMask { 
    case PhysicsCategory.alien | PhysicsCategory.torpedo: 
     // alien and torpedo have contacted 
     contact.bodyA.removeFromParent() 
     contact.bodyB.removeFromParent() 
     score += 1 
     scoreLabel.text = "score: " + "\(score)" 

    case PhysicsCategory.alien | PhysicsCategory.shuttle: 
     // alien and shuttle have contacted 
     contact.bodyA.removeFromParent() 
     contact.bodyB.removeFromParent() 

     self.view?.presentScene(EndScene()) 

    default : 
     //Some other contact has occurred 
     print("Some other contact") 
    } 
} 

Вы ча n просто добавьте столько случаев PhysicsCategory.enemy | PhysicsCategory.player, сколько вам нужно для всех контактов, в которых вы должны принять меры в своей игре. Кодируйте каждый потенциальный контакт индивидуально, и вы не потеряете себя, если ... тогда ... еще.

, если вам нужно ссылаться только на один из узлов, участвующих в контакте (например,чтобы удалить игрока после того, как противник бьет его), вы можете сделать это следующим образом:

let playerNode = contact.bodyA.categoryBitMask == PhysicsCategory.player ? contact.bodyA.node! : contact.bodyB.node! 
playernode.removefromParent 
+0

Я пробовал свой код, но он, похоже, не «распознает» столкновений: когда тела сталкиваются, они просто перемещают друг друга, точно так же, как не вызывала никакой функции. Во всяком случае ваш путь кажется намного чище и проще в управлении. Можете ли вы помочь? Спасибо за ответ. – Jules

+0

@Jules - Можете ли вы добавить строку печати («Контакт обнаружен») в качестве первой строки didBeginContact, чтобы увидеть, распознаются ли какие-либо контакты. –

+0

Физические тела, движущиеся друг с другом, когда они сталкиваются, не имеют ничего общего с обнаружением контакта для функций «didBeginContact»/«didEndContact». В вашей программе нет кода (кроме настройки categoryBitMask и collisionBitMask) для коллизий, только для контактов. –

0

Я бы рекомендовал вам ознакомиться с документами о SKPhysicsBody.

Каждый физический объект в сцене может быть назначен до 32 различных категорий, каждый из которых соответствует бит в битовой маске. Вы определяете значения маски, используемые в вашей игре. В сочетании со свойствами collisionBitMask и contactTestBitMask, необходимо определить, какие физики тела взаимодействуют друг с другом, и когда ваша игра уведомляется об этих взаимодействий

Прежде всего я хотел бы изменить PhysicsCategory к

struct PhysicsCategory { 
static let alien : UInt32 = 0x1 << 1 
static let torpedo : UInt32 = 0x1 << 2 
static let shuttle : UInt32 = 0x1 << 3 
} 

Тогда

alien.physicsBody?.contactTestBitMask = PhysicsCategory.torpedo | PhysicsCategory.shuttle 

Надеюсь, это поможет.

+0

Я уже прочитал документацию, но мне это не очень помогло (я только начал использовать SpriteKit только вчера). Я пробовал свой путь, но у меня по-прежнему возникает одна и та же проблема: столкновение между челноком и инопланетянином происходит только после того, как я уничтожил инопланетянина торпедой. У тебя есть другие идеи? Даже просто ссылка на учебник или другую документацию, которую вы знаете, будет потрясающей. – Jules

0

Так что мне действительно удалось решить мою проблему вчера. Я отправляю обновленный код, если он может кому-то помочь. Вне класса:

struct PhysicsCategory { 
static let player : UInt32 = 0x1 << 0 
static let bullet : UInt32 = 0x1 << 1 
static let enemy : UInt32 = 0x1 << 2} 

И затем, после применения phyics к каждому спрайта, как я уже писал, в классе:

//Contact with bullet 
func contactWithBullet(enemy : SKSpriteNode, bullet: SKSpriteNode) { 
    enemy.removeFromParent() 
    bullet.removeFromParent() 
    score += 1 
    updateLabels() 
} 

//contact with player 
func contactWithPlayer(player : SKSpriteNode, enemy : SKSpriteNode) { 
    enemy.removeFromParent() 
    lives -= 1 
    updateLabels() //another function that changes the score and lives labels 
} 
//CONTACT DETECTION 
func didBeginContact(contact: SKPhysicsContact) { 
    let firstBody : SKPhysicsBody = contact.bodyA 
    let secondBody : SKPhysicsBody = contact.bodyB 

    if (firstBody.categoryBitMask == PhysicsCategory.enemy && secondBody.categoryBitMask == PhysicsCategory.bullet || firstBody.categoryBitMask == PhysicsCategory.bullet && secondBody.categoryBitMask == PhysicsCategory.enemy) { 
     contactWithBullet(firstBody.node as! SKSpriteNode, bullet: secondBody.node as! SKSpriteNode) 
     checkScore() 
     enemiesInWave -= 1 
    } else if (firstBody.categoryBitMask == PhysicsCategory.enemy && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.enemy) { 
     contactWithPlayer(firstBody.node as! SKSpriteNode, enemy: secondBody.node as! SKSpriteNode) 
     checkLives() 
     enemiesInWave -= 1 
    } 
} 
+0

Не путайтесь между контактами и коллизиями - вы назвали свои функции, которые вызываются, когда есть контакты как «collisionWith ...», что немного запутывает. –