Придание физики тайлам SKTileMapNode в Xcode 8

Я изучаю Swift, и в качестве проекта я работаю над 2D-игрой, основанной на плитках, похожей на супер Марио, где мой персонаж будет ходить и прыгать по плиткам.

Последняя версия Xcode и Sprite Kit дает возможность создавать Tile Map непосредственно в Xcode.

В презентации нового набора Xcode и Sprite парень демонстрирует игру, похожую на то, над чем я работаю.

https://developer.apple.com/videos/play/wwdc2016/610/ (около 20-й минуты).

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

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

если кто-нибудь знает это, я был бы очень признателен за помощь.

Если вопрос неясен, дайте мне знать, потому что я также новичок в переполнении стека.


person MJ1986    schedule 04.10.2016    source источник


Ответы (4)


Сотрудник Apple Бобит говорит здесь, что "правильный подход" заключается в добавлении пользовательских данных в ваш SKTileDefinition объектов и используйте их для идентификации и добавления физических тел на плитки.

Таким образом, вы можете добавить значение пользовательских данных в определение плитки либо программно, либо в редакторе, например:

введите описание изображения здесь

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

self.tileMap = self.childNode(withName: "Tile Map") as? SKTileMapNode  
guard let tileMap = self.tileMap else { fatalError("Missing tile map for the level") }  

let tileSize = tileMap.tileSize  
let halfWidth = CGFloat(tileMap.numberOfColumns) / 2.0 * tileSize.width  
let halfHeight = CGFloat(tileMap.numberOfRows) / 2.0 * tileSize.height  

for col in 0..<tileMap.numberOfColumns {  
    for row in 0..<tileMap.numberOfRows {  
        let tileDefinition = tileMap.tileDefinition(atColumn: col, row: row)  
        let isEdgeTile = tileDefinition?.userData?["edgeTile"] as? Bool  
        if (isEdgeTile ?? false) {  
            let x = CGFloat(col) * tileSize.width - halfWidth  
            let y = CGFloat(row) * tileSize.height - halfHeight  
            let rect = CGRect(x: 0, y: 0, width: tileSize.width, height: tileSize.height)  
            let tileNode = SKShapeNode(rect: rect)  
            tileNode.position = CGPoint(x: x, y: y)  
            tileNode.physicsBody = SKPhysicsBody.init(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2.0, y: tileSize.height / 2.0))  
            tileNode.physicsBody?.isDynamic = false  
            tileNode.physicsBody?.collisionBitMask = playerCollisionMask | wallCollisionMask  
            tileNode.physicsBody?.categoryBitMask = wallCollisionMask  
            tileMap.addChild(tileNode)  
        }  
    }  
}  

Лично я считаю такой подход слишком суетливым. Я собираюсь попробовать другой подход в своей игре, и если он сработает, я опубликую его здесь. Чего бы я действительно хотел, так это того, чтобы Apple улучшила API карты тайлов, чтобы мы могли добавлять физические тела непосредственно в отдельные тайлы. Возможно, в процессе они могли бы оптимизировать движок, чтобы физические тела на отдельных тайлах автоматически объединялись, образуя более крупные и оптимальные формы для повышения производительности системы.

Обновление: я отправил запрос в Apple по поводу этой проблемы, что бы из этого ни вышло.

person peacetype    schedule 15.03.2018
comment
ОТЛИЧНАЯ РАБОТА!!! Отличное исследование, поздравляю с получением информации от инсайдера Apple. Я не могу отблагодарить вас достаточно. Отсутствие прозрачности в направлениях мышления и дизайна игровых комплектов невероятно отталкивает. Как и отсутствие значимых усилий по исправлению ошибок и привнесению какого-либо чувства сплоченности, простоты использования и элегантности в процессы и парадигмы этих вещей. Они должны быть источником постоянного смущения для компании с такой степенью власти и ресурсов. - person Confused; 15.03.2018
comment
Удачи вам в ваших испытаниях и невзгодах на пути к созданию еще большего количества обходных путей для clusterfark, которым является SK. - person Confused; 15.03.2018
comment
@Confused Спасибо за похвалу и добрые пожелания! :) Я обязательно опубликую лучшее решение, если найду его. - person peacetype; 15.03.2018

В качестве альтернативы вы можете применить алгоритм линейной развертки к плиткам, которым вы хотите присвоить SKPhysicsBody.

Вы можете сделать это в четыре шага;

  1. Повторите положение плиток в вашем SKTileMap.

  2. Найдите плитки, которые находятся рядом друг с другом.

  3. Для каждой группы смежных плиток соберите:

    • a down-left corner coordinate and
    • координата правого верхнего угла.
  4. Нарисуйте квадрат и переходите к следующей группе плиток, пока не закончатся координаты плитки.

Снимок экрана без изображений для сравнения

Снимок экрана без изображений, показывающий физические тела

См. мой ответ в аналогичном сообщении о том, как это реализовать.

person Ramon123    schedule 14.06.2019

Я не уверен, что есть верный способ сделать это... но вот два способа подумать о том, как попробовать применить физику к тайловой карте.

Вариант 1. Примените SKNodes к каждой позиции каждой плитки на карте и примените соответствующее физическое тело к этому SKNode на основе содержимого и состояния этой плитки.

Вариант 2: Используйте информацию о положении каждой плитки, чтобы добавить массив физических тел в SKTileMapNode и разместить каждое из них соответствующим образом.

Я представляю гравитационный платформер в стиле Марио, с такой местностью, которая нуждается в физических телах для земли:

введите здесь описание изображения

Поднятая стенограмма с WWDC Apple о тайлах и физике:

И вы заметите, что здесь я сталкиваюсь с плитками.

И я достигаю этого, используя пользовательские данные, которые мы можем поместить на каждую из наших плиток.

Здесь я покажу вам наш набор плиток.

Выберите один из вариантов здесь.

И вы можете видеть, что у нас есть некоторые пользовательские данные здесь.

И у меня просто есть значение с именем edgeTile, которое является логическим значением, и я установил его равным 1.

Итак, в коде я просматриваю карту тайлов в нашей демонстрации платформы здесь и ищу все эти краевые тайлы.

И всякий раз, когда я его нахожу, я создаю некоторые физические данные, чтобы игрок мог столкнуться с ним.

И так как это только на нашей тайловой карте, скажем, я хотел преодолеть вот эту большую стену.

Когда я запущу игру, вы увидите, что мой парень на самом деле не может прыгнуть достаточно высоко, чтобы справиться с этим.

И он действительно этого хочет, потому что вон та красная кнопка выглядит очень заманчиво.

Я действительно хочу подтолкнуть эту штуку.

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

Плитки больше нет, и теперь мы можем пройти через них.

И нам не пришлось менять код или что-то еще.

Мы просто использовали данные, которые мы извлекли из карты тайлов, для настройки нашего тайла.

Это так просто.


Звучит очень просто, но требуется гораздо больший ум, чем мой, чтобы понять, что делается и как это делается.

person Confused    schedule 04.10.2016
comment
Я собираюсь прокомментировать здесь вместо того, чтобы отвечать: предоставление физических тел отдельным плиткам не имеет большого смысла, в конечном итоге вы добавляете больше тел, чем необходимо, что действительно вредит движку. В приведенном здесь примере вам потребуется проверить 11 тел, 4 из которых являются пустой тратой времени из-за их местоположения. Я полагаю, что спикер (я этого еще не видел) пытался сказать, что нужно использовать пользовательские данные для создания ваших собственных физических тел там, где это необходимо, вроде того, что делает этот человек. forums.developer.apple.com/thread/50043 - person Knight0fDragon; 04.10.2016
comment
Для персонажа Марио такие физические накладные расходы являются проблемой? - person Confused; 05.10.2016
comment
абсолютно, у вас будут плитки повсюду в зависимости от того, насколько велик уровень - person Knight0fDragon; 05.10.2016
comment
так что добавлять и удалять узлы физики на основе тайлов на экране в любое время? - person Confused; 05.10.2016
comment
нет, вы хотите, чтобы это было автоматически, это не может работать таким образом, идея состоит в том, чтобы делиться ресурсами. Так снимаешь тело с 1 кирпича, снимаешь со всех - person Knight0fDragon; 05.10.2016
comment
Какой? Это плитки. Каждая из них адресуется индивидуально благодаря userData, верно? И у каждого есть уникальное местоположение, которое можно обнаружить/установить. - person Confused; 05.10.2016
comment
в качестве альтернативы, измените битовые маски .... для тех, что за кадром, чтобы они не вычислялись, но я пока не совсем понимаю эту маскировку категории. - person Confused; 05.10.2016
comment
userData — это просто NSMutableDictionary, мы рассмотрели это в другом вопросе. Идея состоит в том, чтобы просто дать ему идентификаторы, я не уверен на 100%, но я не думаю, что пользовательские данные нацелены на отдельную ячейку, я думал, что это для общего SKNode, который используется на карте - person Knight0fDragon; 05.10.2016
comment
Если у меня есть 1 плитка травы, расположенная в 2 ячейках, могу ли я дать им 2 разных набора пользовательских данных? - person Knight0fDragon; 05.10.2016
comment
Да... Я также не уверен, может ли каждая индексируемая позиция плитки иметь свои собственные данные/идентификацию. - person Confused; 05.10.2016
comment
да, если это так, тело для 1 - это тело для всех - person Knight0fDragon; 05.10.2016
comment
Единственный способ, которым я могу это сделать, — это использование итерации по местоположениям: developer.apple.com/reference/spritekit/sktilemapnode/ - person Confused; 05.10.2016
comment
В любой момент времени можно определить, какие столбцы и строки SKTileMapNode находятся на экране. Для тех, кто нет, физическое тело можно удалить. Для тех, которые появляются на экране, в зависимости от направления движения и т. д., необходимо получить определение SKTile и добавить/активировать соответствующее физическое тело. - person Confused; 05.10.2016
comment
Довольно необычно, что Apple не разработала и не создала механизм для такого рода обработки физики как часть SKTileMapNode. Я думаю. - person Confused; 05.10.2016
comment
Эх, я бы подумал, что геймплей должен делать такие вещи в любом случае - person Knight0fDragon; 05.10.2016
comment
Смотрите дополнительный контент в моем ответе выше... @Knight0fDragon - person Confused; 05.10.2016
comment
он начинает свой пост, говоря, что он также хотел бы знать, как это было сделано, вероятно, имея в виду, что он не думает, что его код в любом случае похож на то, что он видел в демонстрации Apple WWDC. Как вы думаете, это одно и то же? - person Confused; 05.10.2016
comment
Что-то очень похожее на это - person Knight0fDragon; 05.10.2016
comment
ого, нет возможности перечислить все определения, это хромает - person Knight0fDragon; 05.10.2016
comment
Это тоже. Я в шоке, что у каждой позиции плитки нет какого-то уникального идентификатора. Я имею в виду... я полагаю, что можно создать 2D-массив для каждой позиции плитки, но кажется странным, что это не часть SKTileMapNode. - person Confused; 05.10.2016
comment
Все это кажется наполовину испеченным. Например, давайте сделаем отображение плитки, потому что это круто, верно? Верно! - person Confused; 05.10.2016
comment
вы могли бы подумать, что это можно использовать с .map, пройтись по вашей Tilegroup (я предполагаю, что это индекс на карте тайлов) и установить функции на основе пользовательских данных (я предполагаю, что TileDefinition — это взломанный SKNode) - person Knight0fDragon; 05.10.2016
comment
Глядя на него, я пока не вижу в этом ничего особенного. Они делают почти то же, что и я с тайловыми движками, мне просто любопытно, могут ли они менять текстуру быстрее, чем я (из-за отсутствия низкоуровневого доступа) - person Knight0fDragon; 05.10.2016
comment
Нет, это странно, нет идентификатора местоположения плитки, кроме столбца/строки. TileGroup является держателем TileDefinitions, которые определяют только то, что возможно с точки зрения текстуры для любой данной плитки, и не имеют ничего общего с местоположением. Итак, это TileNode›TileSet›TileGroup›TileDefinition, в котором TileGroup может содержать несколько TileDefinition. - person Confused; 05.10.2016
comment
Как будто они ждут, пока кто-нибудь покажет им, как лучше всего адресовать отдельные местоположения плитки в SKTileMapNode, после чего они скопируют эту идею и выпустят ее в версии 2, вероятно, для iOS 11. - person Confused; 05.10.2016
comment
пытаясь понять, что такое набор плиток - person Knight0fDragon; 05.10.2016
comment
Хорошо, я думаю, я понял, tileSet Я думаю, это данные текстуры тайлов, tileDefinition — это данные SKNode тайлов, а tileGroup — это индекс местоположения карты. Имеет смысл, что группа тайлов содержит несколько определений для анимации. - person Knight0fDragon; 05.10.2016
comment
tileGroup, похоже, не имеет никакой информации о местоположении на карте. Отдельные tileDefinitions применяются к местоположениям на карте. tileGroup — это только контейнер для определений. Мне не удалось найти функцию, подобную индексу, которая знает, какое tileDefinition находится в любом месте карты. - person Confused; 05.10.2016
comment
с чего бы это, это индекс, а не ячейка - person Knight0fDragon; 05.10.2016
comment
Я имею в виду, что было бы логично, что где-то должен быть какой-то индекс всех ячеек... но, похоже, его нет... - person Confused; 05.10.2016
comment
ха, это не имеет смысла - person Knight0fDragon; 05.10.2016
comment
Ok. Подумайте об этом... как вы обращаетесь к тайлу в любом заданном месте на тайловой карте? Как вы думаете, как это лучше сделать? Как узнать, какое tileDefinition в данный момент находится в этом месте, чтобы можно было добавить соответствующее физическое тело? - person Confused; 05.10.2016
comment
если бы мы делали это как массив [1,2,3,3,2,1], вы опрашиваете карту для ячейки (2,0), которая говорит вам проверить группу 2. В группе 2 происходит волшебство я бы подумал - person Knight0fDragon; 05.10.2016
comment
Нет, именно в tileDefinition вы найдете то, что вам нужно, то есть используемую текстуру в этом месте. строка/столбец, спросите tileDefinition, какую текстуру он показывает. tileDefinition может отображать более одной текстуры, а также может вращать ее. - person Confused; 05.10.2016
comment
Вы получаете определение плитки из группы - person Knight0fDragon; 05.10.2016
comment
если вы измените определения внутри группы, то в моем примере должны измениться ОБА 3 - person Knight0fDragon; 05.10.2016
comment
Вы получаете определение тайла от группы, которое вы получаете от набора, которое вы получаете от узла... да... но более важный вопрос, как вы получаете текстуру, которая отображается в любом заданном месте? - person Confused; 05.10.2016
comment
mySKTileMapNode.mySKTileSet.mySKTileGroup.mySKTileDefinition.texture(at: столбец/строка) или что-то в этом роде... - person Confused; 05.10.2016
comment
Текстура доступна из определения, так же, как вы получаете ее из спрайтенода, с той лишь разницей, что анимация дается вам автоматически, поэтому это должны быть текстуры, а не текстуры. - person Knight0fDragon; 05.10.2016
comment
ааа, кажется, я понял... tileDefinition действительно имеет только одну возможную текстуру, а не несколько. Меня смутило множество документов. Это не несколько текстур, это несколько кадров возможной одной текстуры, которые будут иметь скорость воспроизведения, но все равно будут составлять одну единую текстуру, только с несколькими кадрами, как в анимации. Хотите другую текстуру? Нужен другой tileDefinition. Таким образом, любое отдельное tileDefinition имеет только одну известную текстуру, но это может быть анимация с последовательностью кадров, а не просто неподвижное изображение. - person Confused; 05.10.2016
comment
Я быстро забуду это. Вышесказанное, но хорошая новость заключается в том, что если вы знаете, что такое tileDefinition в каком-либо месте, то вы знаете, какая текстура используется в этом месте, но, возможно, еще не знаете, какой кадр, если это анимированная текстура с последовательностью кадров. - person Confused; 05.10.2016
comment
именно поэтому группа позволяет несколько - person Knight0fDragon; 05.10.2016
comment
Я собираюсь изменить свое имя пользователя на медленно-запутанный-забывчивый-невежественный - person Confused; 05.10.2016
comment
Я предполагаю, что набор тайлов похож на атлас текстур, но обрабатывается как кешированная видеопамять, которую они постоянно записывают во время этапов анимации, и именно так анимируются ВСЕ узлы, вместо того, чтобы менять ссылку на все узлы. Раньше так делал, когда занимался разработкой Nintendo DS. - person Knight0fDragon; 05.10.2016
comment
Я думаю, что понимаю тебя. Это делает оптимальным, возможно, запуск большого количества последовательностей кадров в разное время. Я думаю. Может быть. Можно ли сделать что-то подобное с точки зрения оптимизации репликации физических тел вокруг сцены? - person Confused; 05.10.2016
comment
конечно, но я думаю, что мы попадаем на сложную территорию, которую они, возможно, не захотят потакать, и это только уменьшит пространство в памяти, а не скорость выполнения - person Knight0fDragon; 05.10.2016
comment
ага, ок. Я забыл, что SKPhysicsBodies, вероятно, уже довольно легкие. - person Confused; 05.10.2016
comment
Проблема с физическими телами заключается в том, что 1 физическое тело всегда должно сверяться со всеми другими физическими телами, если только битовая маска не означает, что у нас есть 32 различных стека, которые могут содержать ссылку на тело (я хочу сказать нет), так что это означает, что мы нужно устранить. Сейчас большая часть этого делается быстро, но как бы быстро это ни было, если у вас много тел, то будет медленно. Представьте себе 32001 тело на экране. это 32000(32000+1)/2 или что-то в этом роде, то есть 512 016 000 вызовов - person Knight0fDragon; 05.10.2016
comment
Итак, если бы все физические тела были настроены так, чтобы не проверяться друг с другом на предмет столкновений или контактов, установив для всех их масок категорий значение «нет, не проверять, они не проверяются»? Если это так, изменение маски категории/маски столкновения/контакта может быть намного легче/проще/быстрее/проще. - person Confused; 05.10.2016
comment
другими словами, включите проверку физики только для физических тел, которые представляют плитки, находящиеся в данный момент на экране, и ни для одного из тех, что находятся за пределами экрана. - person Confused; 05.10.2016
comment
это не поможет, потому что вам нужно проверить ВСЕ узлы, если они на экране или нет, лол - person Knight0fDragon; 05.10.2016
comment
Почему так? Наверняка все физические расчеты отключены, так что это все 512 миллионов проверок. Только около дюжины тел на экране включены, и формула может подготовиться к включению любых битовых масок, необходимых для соответствия следующему положению камеры ??? - person Confused; 05.10.2016
comment
Я знаю, что трудно думать как компьютер, лол, как вы ожидаете, что система будет знать, что включать и выключать, она должна пройти через каждое тело и сказать, вы на экране? ой, да ладно, включи физику и давай проверим поподробнее - person Knight0fDragon; 05.10.2016
comment
это ничем не отличается от категории BitMasks, вопрос в том, вы входите в группу 1? ок, сделайте более тщательную проверку - person Knight0fDragon; 05.10.2016
comment
Единственный способ, которым я знаю, как сократить проверку всего, - это иметь списки. Тогда вам нужно сравнивать только то, что находится в списке, а не весь мир физических тел. - person Knight0fDragon; 05.10.2016
comment
Я думаю, у нас разное видение масштаба. Я думаю об игре типа марио. Скажем... 8x экранов по 128 тайлов каждый (16x8) = 1024 тайла. - person Confused; 05.10.2016
comment
Нет необходимости искать тайлы, чтобы появиться на экране, вы можете просто сохранить их все в массиве и знать, когда включать/выключать их (их физику) в зависимости от положения камеры. - person Confused; 05.10.2016
comment
вы все еще выполняете проверку, может быть, ВЫ физически не выполняете проверку, но компьютер должен, иначе вы говорите при каждом обновлении хватать каждый узел на экране и бросать его в кучу, и это еще более безумно, лол - person Knight0fDragon; 05.10.2016
comment
Положение камеры = плитки видны на экране. Это математика. Для позиции x (камера прокручивается только влево ‹--› вправо) должны быть включены physicsNodes, связанные с диапазоном видимых в данный момент столбцов tileMap. Эти столбцы представляют собой числа, непосредственно относящиеся к текущей позиции камеры в формате .x. - person Confused; 05.10.2016
comment
Я не могу объяснить вам эти низкоуровневые вещи, вы просто не понимаете, и я начинаю злиться. Я знаю, это звучит просто, просто так не работает, что бы вы ни делали, вам нужно каким-то образом коснуться каждого физического тела. - person Knight0fDragon; 05.10.2016
comment
Успойкойся. Подумайте об этом логически. Я, наверное, плохо объясняю. ТОЛЬКО карты mapTiles, видимые на экране, нуждаются в физике. Эти позиции mapTile можно рассчитать. Это означает, что все положения mapTile НЕ на экране можно считать выключенными с точки зрения связанных с ними физических тел. Вы предполагаете, что мне нужен урок основ информатики, когда это не так. Я пытаюсь показать тебе отношения, которые ты упустил. - person Confused; 05.10.2016
comment
Существует прямая связь между столбцами tileMapLocations и текущим положением камеры. Если только когда-либо включать связанные физические тела для плиток на экране, нет необходимости пробивать всю карту плиток, чтобы определить, что на экране. Это известено. - person Confused; 05.10.2016
comment
это так не работает, вам все равно нужно проверить, ЕСТЬ ли это на экране, нет ничего бесплатного, что отфильтровывало бы на экране и за его пределами - person Knight0fDragon; 05.10.2016
comment
Да, есть. Положение камеры НЕПОСРЕДСТВЕННО относится к столбцам карты тайлов. - person Confused; 05.10.2016
comment
положение камеры означает дерьмо, которое просто говорит, где делать оценку, оценка все равно должна произойти - person Knight0fDragon; 05.10.2016
comment
вы не двигаете камеру, и все категории данных физического тела BitMasks волшебным образом сбиваются до 0 - person Knight0fDragon; 05.10.2016
comment
Я знаю, что вам все еще нужно делать физические расчеты на экране. Так никогда не бывает. Я говорю о включении и выключении узлов, что не очень дорого: В примитивном английском: для столбцов плюс и минус 8 единиц из camera.position.x (при условии, что 16 плиток помещаются на экране по горизонтали) = physicsNodeON. Для столбцов на 9 единиц меньше текущего положения камеры и больше текущего положения камеры отключите физику. Остальные все выключены. - person Confused; 05.10.2016
comment
Таким образом, это очень эффективный процесс включения и выключения, основанный на физике, в зависимости от положения камеры ... нет необходимости перебирать все плитки, чтобы определить, какие из них на экране, а какие нет, в каждом кадре. - person Confused; 05.10.2016
comment
Больше предварительных проверок не бывает, моя точка зрения ни при чем, каждое физическое тело нужно трогать, есть способы уменьшить скорость, но нам все равно нужно трогать каждое тело - person Knight0fDragon; 05.10.2016
comment
выключение и включение узлов означает, что вы касаетесь каждого узла, затем каждого тела в узле и нажимаете на переключатель. это означает постоянное перестроение массива, потому что вам нужно перебирать все известные тела. Это намного медленнее, чем создание массива один раз и сравнение с целым числом. - person Knight0fDragon; 06.10.2016
comment
Я достаточно уверен, что вы понимаете, что я предлагаю, но намеренно избегаете этого. - person Confused; 06.10.2016
comment
нет, я не избегаю этого, вам нужно думать на более низком уровне, за кулисами - person Knight0fDragon; 06.10.2016
comment
вы хотите использовать только то, что находится на экране, ну, у вас есть 3 варианта, вы можете создавать новый список физических тел при каждом обновлении, каждый раз используя то, что отображается на экране, вы можете создавать список того, что находится на экране, и добавлять и удалить то, что находится на экране, что включает сравнение со старым и новым, или вы можете поместить все узлы в список и просмотреть каждый узел, чтобы определить, находится ли он на экране или нет. Как еще можно построить этот список - person Knight0fDragon; 06.10.2016
comment
Они все там, все время, уже там. Физическое воссоздание эстетики тайловой карты существует постоянно. Но включение и выключение, о которых я говорил все это время, связано с маскировкой. Включение и выключение маскировки. - person Confused; 06.10.2016
comment
У меня нет подходящего лексикона, чтобы говорить о маскировке физических категорий. Я еще не до конца понимаю, как это работает, и как даже использовать его терминологию. Но я знаю вот что: когда категории совпадают, они обнаруживают друг друга на предмет контактов и/или столкновений. Верно? Таким образом, можно отключить это поведение, то есть 1000 физических тел просто находятся в сцене и ничего не делают. - person Confused; 06.10.2016
comment
Отразите лексикон столбца/строки Tilemap в двумерном массиве, содержащем все физические тела, и это просто вопрос точного определения того, какие physicsTiles включать и выключать, в зависимости от положения камеры. Я почти уверен, что SKTileMapNode делает то же самое с текстурами тайлов. - person Confused; 06.10.2016
comment
да я знаю, как вы рассчитываете включать и выключать маскировку не трогая каждый узел, нужно знать что попало на экран, а что попало с экрана - person Knight0fDragon; 06.10.2016
comment
Как я уже сказал: положение камеры.x всегда относится (точно) к набору столбцов в tileMap. Если этот набор столбцов зеркально отражается в 2D-массиве, содержащем PhysicsBodies, то нет даже никакой математики. Для любой заданной позиции x вы точно знаете, какие тела активировать. - person Confused; 06.10.2016
comment
нет, вам нужно физически сказать памяти измениться, чтобы сделать это, вам нужно коснуться переменной - person Knight0fDragon; 06.10.2016
comment
Вы действительно слишком много думаете об этом. Представьте себе двумерный массив, который отражает столбцы и строки карты тайлов. В этом массиве есть физическое тело для каждой плитки. Эстетическое представление любой данной плитки соответствует форме ее физического тела в этом зеркальном массиве. Всякий раз, когда плитка появляется на экране, вы переходите в точно такое же место в массиве physicsBodies и меняете ее категорию битовой маски с of на on, аналогичным образом, для тех, которые выходят за пределы экрана с другой стороны, вы отключаете их. - person Confused; 06.10.2016
comment
Доступные переменные зависят от количества строк в вашей тайловой карте, умноженное на 2, потому что одна сторона уходит с экрана, а другая появляется на экране. - person Confused; 06.10.2016
comment
Думайте об этом как о конвейерной ленте физических тел, движущихся под камерой. - person Confused; 06.10.2016
comment
Приятно поболтать, ребята :) Кто-то из сотрудников Apple наконец-то откликнулся на ссылку, опубликованную @Knight0fDragon. Они указали некоторый код как правильный подход, поэтому я разместил его здесь. Кажется, что добавление физических тел к плиткам путем поиска по их пользовательским данным на данный момент настолько хорошо, насколько это возможно. - person peacetype; 15.03.2018

Я провел два дня, пробуя разные идеи, но не нашел ничего лучше того, что я разместил в другом моем ответе. Как упоминалось там, это способ, рекомендованный сотрудником Apple, и, насколько я знаю, это самый эффективный способ, чтобы SpriteKit автоматически добавлял физические тела ко всем вашим тайлам. Я протестировал его, и он работает. (Хотя я все еще жду, когда Apple добавит простой способ размещения физических тел на тайлах).

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

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

Альтернативный подход № 1 — использование меньшего количества физических тел

Создайте свою тайловую карту в редакторе. Затем продолжайте работать в редакторе, перетаскивая цветные спрайты (SKSpriteNodes) по частям вашей карты, которым требуется физическое тело. Сформируйте узлы так, чтобы получился максимально большой прямоугольник для областей, которым нужны физические тела. Это лучше всего работает для больших плоских поверхностей, таких как стены, полы, потолки, платформы, ящики и т. д. Это утомительно, но в итоге вы получите гораздо меньше физических тел в вашей симуляции, чем если бы вы использовали автоматический подход, упомянутый выше.

Альтернативный подход № 2 — не использовать физические тела

Эта идея, вероятно, потребует еще большей работы, но потенциально вы можете вообще избежать использования физических тел. Сначала создайте свою тайловую карту в редакторе. Проанализируйте свою карту, чтобы определить, какие плитки обозначают барьер, за который игрок не должен переходить. Назначьте идентификатор пользовательских данных для этого типа плитки. Вам потребуются разные категории идентификаторов для разных типов барьеров, и вам также может понадобиться разработать дизайн, соответствующий этому подходу.

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

person peacetype    schedule 16.03.2018
comment
Я не думаю, что Apple в ближайшее время добавит физику к плиткам. Разве цель плиток не в том, чтобы быть высокооптимизированными и сохранять мощность для того, что впереди? - person Moose; 18.03.2018
comment
Вы, вероятно, правы насчет Apple, но можно надеяться :) Я просто предположил, но кажется, что добавление физических тел может быть сделано таким образом, чтобы не добавлять слишком много накладных расходов. Я понимаю, что SKPhysicsBody довольно хорошо оптимизирован. - person peacetype; 19.03.2018