Squeak.ru - шаблоны программирования

Игра «Битва за астероид» продолжает падать

Поэтому я продолжаю получать эту ошибку в случайные моменты во время игры: «фатальная ошибка: неожиданно найден ноль при развертывании необязательного значения» в моей игре о битве за астероид. Я отправлю код здесь, и если кто-нибудь может помочь понять это, я был бы признателен. Если вы не понимаете какой-либо части, вы можете спросить меня

import SpriteKit
import Darwin

struct PhysicsCatagory {
    static let Asteroids : UInt32 = 1 //00000000000000000000000000000001
    static let Bullet : UInt32 = 2 //0000000000000000000000000000010
    static let Fighter : UInt32 = 3 //0000000000000000000000000000100

    }

class GameScene: SKScene, SKPhysicsContactDelegate {

var Score = Int()
var scoreLabel = UILabel()

var Fighter = SKSpriteNode(imageNamed: "Fighter")

override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    physicsWorld.contactDelegate = self

    Fighter.position = CGPointMake(self.size.width / 2, self.size.height / 7)
    Fighter.physicsBody = SKPhysicsBody(rectangleOfSize: Fighter.size)
    Fighter.physicsBody?.affectedByGravity = false
    Fighter.physicsBody?.categoryBitMask = PhysicsCatagory.Fighter
    Fighter.physicsBody?.contactTestBitMask = PhysicsCatagory.Asteroids
    Fighter.physicsBody?.dynamic = false

    var Timer = NSTimer.scheduledTimerWithTimeInterval(0.25, target: self, selector: Selector("spawnBullets"), userInfo: nil, repeats: true)

    var asteriodsTimer = NSTimer.scheduledTimerWithTimeInterval(0.35 , target: self, selector: Selector("spawnAsteroids"), userInfo: nil, repeats: true)

    var furiousAsteriodsTimer = NSTimer.scheduledTimerWithTimeInterval(0.9 , target: self, selector: Selector("spawnFuriousAsteroids"), userInfo: nil, repeats: true)


    self.addChild(Fighter)

    scoreLabel.text = "\(Score)"
    scoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
    scoreLabel.backgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.3)
    scoreLabel.textColor = UIColor.whiteColor()

    self.view?.addSubview(scoreLabel)

}

func didBeginContact(contact: SKPhysicsContact) {

    let firstBody : SKPhysicsBody = contact.bodyA
    let secondBody : SKPhysicsBody = contact.bodyB

    if ((firstBody.categoryBitMask == PhysicsCatagory.Asteroids) && (secondBody.categoryBitMask == PhysicsCatagory.Bullet) || (firstBody.categoryBitMask == PhysicsCatagory.Bullet) && (secondBody.categoryBitMask == PhysicsCatagory.Asteroids)){

        bulletHitAsteroids(firstBody.node as! SKSpriteNode, Bullet: secondBody.node as! SKSpriteNode)

    }
}

func bulletHitAsteroids(Asteroids: SKSpriteNode, Bullet: SKSpriteNode){

    Asteroids.removeFromParent()
    Bullet.removeFromParent()

    Score++
    scoreLabel.text = "\(Score)"

}

func bulletHitFuriousAsteroids(FuriousAsteroids: SKSpriteNode, Bullet: SKSpriteNode){

    FuriousAsteroids.removeFromParent()
    Bullet.removeFromParent()

    Score = Score + 2
    scoreLabel.text = "\(Score)"
}


func spawnBullets(){

    let Bullet = SKSpriteNode(imageNamed: "Bullet")
    Bullet.zPosition = -5
    Bullet.position = CGPointMake(Fighter.position.x, Fighter.position.y)

    let action = SKAction.moveToY(self.size.height + 30, duration: 0.9)
    let actionDone = SKAction.removeFromParent()
    Bullet.runAction(SKAction.sequence([action, actionDone]))

    Bullet.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet.size)
    Bullet.physicsBody?.categoryBitMask = PhysicsCatagory.Bullet
    Bullet.physicsBody?.contactTestBitMask = PhysicsCatagory.Asteroids
    Bullet.physicsBody?.affectedByGravity = false
    Bullet.physicsBody?.dynamic = false

    self.addChild(Bullet)

}



func spawnAsteroids(){
    let Asteroids = SKSpriteNode(imageNamed: "Asteroid")
    let minValue = self.size.width / 8
    let maxValue = self.size.width - 20
    let spawnPoint = UInt32(maxValue - minValue)
    Asteroids.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)) , y: self.size.height)

    Asteroids.physicsBody = SKPhysicsBody(rectangleOfSize: Asteroids.size)
    Asteroids.physicsBody?.categoryBitMask = PhysicsCatagory.Asteroids
    Asteroids.physicsBody?.contactTestBitMask = PhysicsCatagory.Bullet
    Asteroids.physicsBody?.affectedByGravity = false
    Asteroids.physicsBody?.dynamic = true


    let action = SKAction.moveToY(-50, duration: 2.5)
    let actionDone = SKAction.removeFromParent()

    Asteroids.runAction(SKAction.sequence([action, actionDone]))

    self.addChild(Asteroids)

}

func spawnFuriousAsteroids(){
    let FuriousAsteroids = SKSpriteNode(imageNamed: "FuriousAsteroid")
    let minValue = self.size.width / 8
    let maxValue = self.size.width - 20
    let spawnPoint = UInt32(maxValue - minValue)
    FuriousAsteroids.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)) , y: self.size.height)

    FuriousAsteroids.physicsBody = SKPhysicsBody(rectangleOfSize: FuriousAsteroids.size)
    FuriousAsteroids.physicsBody?.categoryBitMask = PhysicsCatagory.Asteroids
    FuriousAsteroids.physicsBody?.contactTestBitMask = PhysicsCatagory.Bullet
    FuriousAsteroids.physicsBody?.affectedByGravity = false
    FuriousAsteroids.physicsBody?.dynamic = true


    let action = SKAction.moveToY(-50, duration: 1.5)
    let actionDone = SKAction.removeFromParent()

    FuriousAsteroids.runAction(SKAction.sequence([action, actionDone]))

    self.addChild(FuriousAsteroids)

}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

    for touch in touches {
        let location = touch.locationInNode(self)

        Fighter.position.x = location.x
    }
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    for touch in touches {
        let location = touch.locationInNode(self)

        Fighter.position.x = location.x
    }
}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
}
}
29.01.2016

  • Я предлагаю вам запустить это в отладчике, чтобы вы знали, где возникает ошибка. Это, вероятно, даст вам ответ. 29.01.2016
  • У вас должно быть несколько предупреждающих сообщений, вы можете разместить их здесь? 29.01.2016
  • Я подозреваю, что категория Fighter должна быть 4, а не 3. Безопаснее использовать 0x1 << 0, 0x1 << 1, 0x1 << 2, ... для ваших категорий. 29.01.2016
  • @RapidReverse Обратите внимание, что 0100 — это двоичное представление числа 4. Число 3 будет 0011. Вот один очень хороший пример bit-masks Одна вещь, которую вы должны учитывать, это наличие двух отдельных категорий для астероидов и яростных астероидов. Таким образом, вы могли бы легко отличить эти два типа астероидов. Есть и другие способы, но это будет самое простое решение. 31.01.2016

Ответы:


1

Он падает, потому что одно из тел не имеет своего узла. Когда произойдет сбой, попробуйте ввести что-то вроде этого в консоли отладчика:

po firstBody.node или po secondBody.node. Один из этих двух будет nil.

Это происходит, когда более двух тел соприкасаются, как в вашем примере, когда может возникнуть ситуация, когда пуля и два астероида могут соприкоснуться одновременно. Поскольку SpriteKit может одновременно проверять наличие контакта только между двумя телами, произойдет что-то вроде этого:

  • didBeginContact вызывается с двумя переданными физическими телами (пуля и первый астероид).
  • теперь вы принудительно разворачиваете узлы, связанные с этими телами, и удаляете астероид и пулю из его родителя.

затем, потому что произошло больше контактов

  • didBeginContact вызывается снова с еще двумя физическими телами, но одно из этих физических тел снова является физическим телом пули. Другое тело — это, скажем, яростный астероид.
  • теперь снова вы принудительно разворачиваете узлы, связанные с этими двумя физическими телами, но одно из них (пуля) равно нулю.

Решение будет примерно таким в вашем методе didBeginContact:

 if let firstNode = firstBody.node as? SKSpriteNode, let secondNode = secondBody.node as? SKSpriteNode {

   bulletHitAsteroids(firstNode, Bullet: secondNode)
}

Таким образом, одна пуля уничтожит только один астероид. Я думаю, это то, чего вы хотите, и в чем, в конце концов, есть смысл.

29.01.2016
  • Хорошо, сейчас он не разобьется, но мой истребитель исчезнет при астероидах, чего я и хотел, но не сейчас. 30.01.2016
  • Еще одна проблема, с которой я сталкиваюсь, заключается в том, что оценка увеличивается только на 1, а не на 2. И я не знаю, как переместить метку оценки в верхнюю середину и увеличить размер шрифта. 30.01.2016
  • @RapidReverse Сначала исправьте то, что 0x141E указал в своем комментарии (используйте 0x1 ‹‹ 0 и т. д. для установки категорий), и обработайте контакт между истребителем и астероидами. О счете. Он работает так, как вы его настроили. У вас есть Score++ в одном месте (bulletHitAsteroids) и Score+=2 в другом месте (bulletHitFuriousAsteroids). 30.01.2016
  • да, но после того, как я добавил код, который вы мне дали, каждый раз, когда астероид попадает в мой истребитель, он исчезает. И я сделал для оценки Score += 2 , но в моей метке оценки она увеличивается только по одному за раз. 31.01.2016
  • @RapidReverse Как вы ожидаете увеличить счет на 2 без запуска кода, ответственного за это действие? Из предоставленного вами кода ясно видно, что метод bulletHitFuriousAsteroids никогда не вызывается, поэтому счет не может быть увеличен на два. Также видно, что контакт истребителя с астероидом вообще не обрабатывается. В вашем коде есть еще несколько неправильных вещей, но этот вопрос был о сбоях, и это исправлено, поэтому вам следует задать еще один вопрос о дальнейших проблемах. 31.01.2016
  • Итак. Я понял, что вы сказали о подсчете очков. но когда я добавил код. если пусть firstNode = firstBody.node как? SKSpriteNode, пусть secondNode = secondBody.node как? SKSpriteNode { bulletHitAsteroids(firstNode, Bullet: secondNode) } Мой персонаж-истребитель исчезает с экрана, когда астероид касается истребителя. Больше не рухнет. но мой истребитель исчез. И я не знаю, почему. 05.02.2016
  • @RapidReverse, это странно, потому что у меня это работает (боец остается на экране), если я внесу эти изменения в код, который вы опубликовали. 05.02.2016
  • Итак, я пытаюсь вставить его в if ((firstBody.categoryBitMask == PhysicsCatagory.Asteroids) && (secondBody.categoryBitMask == PhysicsCatagory.Bullet) || (firstBody.categoryBitMask == PhysicsCatagory.Bullet) && (secondBody.categoryBitMask == PhysicsCatagory.Asteroids)) И теперь истребитель не исчезнет. Но я замечаю, что он все еще падает. И я думаю, что это из-за того, что FuriousAsteroid движется вниз быстрее, чем обычный астероид. Он врезался в обычный астероид. И если я выстрелю в астероид, который им является, игра вылетает, но я не знаю, как это исправить. 05.02.2016
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...