Подкласс SKSpriteNode в.sks файле

Я использую файл SpriteKit.sks Могу ли я создать спрайт в.sks в экземпляр подкласса SKSpriteNode?

Это метод init в моем подклассе:

    init(imageNamed: String) {

    let blockTexture = SKTexture(imageNamed: imageNamed)

    super.init(texture: blockTexture, color: nil, size: blockTexture.size())
}

В GameScene.swift я могу создать такой экземпляр:

var myObj = Block(imageNamed: "Block")

Мой вопрос в том, как я могу связать этот экземпляр с.sks файлом?

Я пробовал эту строку кода, но она не работает.

myObj     = childNodeWithName("block1") as Block

Любая помощь?

Благодарю.

+1
источник поделиться
1 ответ

Здесь есть несколько проблем, которые нужно решить...

Как .sks загрузка .sks

Когда вы загружаете файл .sks, SpriteKit создает экземпляр всего, используя NSKeyedUnarchiver. Это означает, что все узлы внутри загружаются как любые базовые классы, которые они .sks как Xcode, когда он создавал файл SKSpriteNode - SKSpriteNode для спрайтов с текстурным искусством, SKLabelNode для текста, SKFieldNode для физических полей и т.д. И Xcode не в настоящее время предоставляют возможность установки пользовательских классов для узлов внутри файла .sks.

(Единственное исключение для этого - изменение класса среды выполнения самой сцены - контейнера верхнего уровня для всего в файле .sks. И это только из-за пользовательской реализации SKNode.unarchiveFromFile предусмотренной для вас в шаблоне проекта. изменение классов во время загрузки работает, когда у вас есть один и только один экземпляр определенного класса в архиве - хорошо для SKScene, не так хорошо для многих узлов в сцене.)

Как работает литье

Когда вы пишете что-то вроде:

myObj = childNodeWithName("block1") as Block

Вы говорите компилятору что-то вроде: "Эй, вы знаете, что вы получили от childNodeWithName? Все, что вы знаете, это SKNode, но я знаю, что это действительно Block, поэтому, пожалуйста, позвольте мне вызвать методы Block на нем". (И компилятор говорит: "Ладно, что угодно").

Но тогда во время выполнения эта вещь, которую вы получили, действительно была действительно Block, или ваше приложение потерпит крах, потому что вы пытались сделать что-то Block y с чем-то, что не является Block. И, за бит о загрузке .sks выше, эта вещь не является и не может быть Block - Xcode не знает, как поместить Block в файл .sks. Таким образом, вы не можете получить Block из него, поэтому ваше приложение будет сбой.

обходные

Итак, если вы не можете поместить пользовательские классы в файл .sks, что вы можете сделать? Это зависит от того, что именно вы пытаетесь выполнить. Но там хороший трюк, который также может быть хорошим дизайном игры/приложения в целом: используйте файл .sks для общей компоновки и конфигурации, а также используйте второй проход для создания вещей, требующих индивидуального поведения.

Например, если вы строите уровень в 2D-платформенной игре, вы бы не захотели, чтобы файл .sks содержал экземпляр вашего класса Plumber даже если бы вы могли - у этого класса, вероятно, много подробностей о том, как высокий или толстый парень, насколько он прыгает, форму усов и т.д., и вы не хотите, чтобы каждый раз настраивать их каждый раз, когда вы делаете новый уровень, а тем более, чтобы они сохранялись снова на каждом уровне .sks файл. Вместо этого единственное, что вам действительно нужно знать в каждом файле уровня, - это позиция, в которой он начинается. Итак, перетащите "пустой узел" в Xcode и во время загрузки замените этот узел экземпляром вашего класса Plumber, например:

let spawnPoint = childNodeWithName("spawnPoint")
let player = Plumber()
player.position = spawnPoint.position
addChild(player)
spawnPoint.removeFromParent()

Если у вас больше деталей конфигурации, которые вы хотите установить в файле .sks, вы можете рассмотреть возможность автоматизации этого процесса.

  1. Создайте метод, который выполняет описанный выше узел. (Назовите это что-то вроде replaceNode(_:withNode:).)
  2. Создайте инициализатор для своего пользовательского класса, который принимает SKNode или SKSpriteNode, и установите все свои унаследованные свойства (или, по крайней мере, те, которые вам SKSpriteNode, например цвет и текстура) с этого узла.
  3. Используйте enumerateChildNodesWithName:usingBlock: с шаблоном поиска, чтобы найти все узлы в вашей сцене с определенным именем и заменить их новым узлом, созданным с помощью вашего инициализатора. Что-то вроде:

    enumerateChildNodesWithName("//brick_[0-9]*") { node, stop in
        self.replaceNode(node, withNode: BrickBlock(node))
    }
    enumerateChildNodesWithName("//question_[0-9]*") { node, stop in
        self.replaceNode(node, withNode: QuestionBlock(node))
    }
    
+16
источник

Посмотрите другие вопросы по меткам или Задайте вопрос