Как сделать коллизию в js

Обновлено: 08.07.2024

Каков самый простой способ реализовать обнаружение столкновений в Java-игре на базе лабиринта? Это может быть барьером, но я думаю, что может быть лучший способ. Вот мой текущий код:

Поскольку вы сказали лабиринт, одна вещь, которую вы можете сделать, это определить java.awt.Rectangle для каждого сегмента стены и для перемещения вашего объекта через лабиринт.

Вы можете использовать метод пересечений, чтобы проверить, наложил ли объект на любой из сегментов стены.

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

wall.getBounds() содержит (component.getX(), component.getY())

Это будет работать, если вы используете Swing API (JComponents, JPanels и т.д.),

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

Если вы не используете Swing API и, следовательно, выполняете какую-то обычную роспись, существует множество способов обнаружения столкновения между игровыми объектами. Вы можете назначить каждому объекту либо радиус, либо поле (в зависимости от формы объекта) и написать собственную функцию столкновения. По моему личному мнению, я бы написал такую функцию, как as--

сохранить коорды игрока, если колья игрока находятся в стене, вернитесь к предыдущим мечам, иначе сохраните новые комбинации игроков

Кратко:
Как организовать выталкивание объекта во время коллизии с несколькими объектами при диагональном движении?

Более подробно:
Новичок в программировании, освоил JavaScript, пишу игру типу "Лабиринт".
Игрок - прямоугольник, стены состоят из массива прямоугольников.
Возникла проблема с коллизией. В начале все нормально - перебираю массив стен, если идет контакт с какой - обрабатываю пересечение, откидывая игрока назад, и отключая движение в соответствующею сторону. Но вот когда игрок идет по диагонали - его забрасывало к черту на кулички..
После долгих мучений прописал вот это:

JavaScript

Объекты — это ссылочные типы

Почему нельзя использовать = ? Посмотрим, что может произойти:

Оба объекта выдают одно и то же. На данный момент никаких проблем. Рассмотрим, что произойдет после редактирования второго объекта:

obj2 был изменен, однако изменения коснулись и obj . Причина заключается в том, что объекты являются ссылочными типами. Поэтому при использовании = , указатель копируется в область занимаемой памяти. Ссылочные типы не содержат значений, они являются указателем на значение в памяти.

Использование Spread

С помощью spread можно клонировать объект. Обратите внимание, что копия будет неглубокой. На момент публикации этого руководства оператор spread для клонирования объектов находился на стадии 4, соответственно официально он не указан в спецификациях. Поэтому для того, чтобы его использовать, нужно выполнить компиляцию с Babel (или чем-то подобным).

Использование Object.assign

Object.assign , выпущенный официально, также создает неглубокую копию объекта.

Использование JSON

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

Lodash DeepClone или JSON?

  • JSON.stringify/parse работает только с литералом Number, String и Object без функции или свойства Symbol.
  • deepClone работает со всеми типами, а функция и символ копируются по ссылке.

Глубокое или неглубокое клонирование?

При использовании spread для копирования объекта создается неглубокая копия. Если массив является вложенным или многомерным, этот способ не будет работать. Рассмотрим пример:

Таким образом, клонированный объект был изменен с добавлением city. В результате получаем:

Неглубокая копия предполагает копирование первого уровня и ссылается на более глубокие уровни.

Глубокая копия

Возьмем тот же пример, но применим глубокую копию с использованием JSON:

Глубокая копия является копией для вложенных объектов. Однако иногда достаточно использования неглубокой копии.

Производительность

К сожалению, на данный момент нельзя написать тестирование для spread, поскольку официально он не указан в спецификации. Однако результат показывает, что Object.assign намного быстрее, чем JSON . Тест на производительность можно найти здесь.

Object.assign и Spread

Стоит отметить, что Object.assign — это функция, которая модифицирует и возвращает целевой объект. В данном примере при использовании:

<> — это модифицируемый объект. В этой точке на целевой объект не ссылаются никакие переменные, но поскольку Object.assign возвращает целевой объект, то можно сохранить полученный присвоенный объект в переменную cloneFood . Данный пример можно изменить следующим образом:

Очевидно, что значение beef в объекте food неверно, поэтому нужно назначить правильное значение beef с помощью Object.assign . На самом деле мы не используем возвращаемое значение функции, а изменяем целевой объект, на который ссылаемся с помощью константы food .

С другой стороны, Spread — это оператор, который копирует свойства одного объекта в новый объект. При репликации приведенного выше примера с помощью spread для изменения переменной food.

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

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

HTML генерируется следующим образом. Нет ракетостроения

В скрипке, $amount установлен на 16. Как вы можете себе представить, возможное количество уникальных парных комбинаций равно:

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

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

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

Когда я увеличу $amount в 100 я получу 4950 возможная комбинация. Когда я обновляю страницу, она все еще работает нормально, но я вижу, что скорость падает. Я даже не пытался установить его на 200, потому что я не хочу, чтобы мой браузер зависал.

Вопрос — есть ли здесь еще пространство для улучшения и оптимизации? Потому что теперь я покажу, что эти квадраты будут маркерами Google Map, и мой расчет столкновений будет срабатывать для событий, когда:

  1. Плитка загружена
  2. Карта перетаскивается
  3. Масштаб изменен

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

Решение

Хорошо, посмотрел, и у тебя все сложнее. Не нужно искать пары, вы часто обращаетесь к DOM. Вы должны только коснуться DOM один раз для каждого элемента. Мусорный массив избыточен, используйте семафор. Никогда не используйте each() во времени критичный код, так как он очень медленный.

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

Массивы медленные и их следует избегать любой ценой. Повторно используйте элементы массива, если можете. Всегда спрашивайте, действительно ли вам нужен новый массив? Есть ли способ не использовать массив?

Не проверяйте, где это не нужно. У вас есть мусор, но вы тестируете эти квадраты.

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

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

Избегайте JQuery, если у вас нет четкой и обоснованной причины. JQuery ОЧЕНЬ медленный и поощряет чрезмерные манипуляции с DOM.

Думаю, что это так Ниже ваша модификация Fiddle, которая будет работать намного быстрее.

ХОРОШО. Надеюсь, это поможет. Он был запущен и работает на Chrome. Вам нужно будет взглянуть на запросы элементов к позиции и размеру, но я не считаю это важным для этого примера.

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

Другие решения

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

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

Допустим, ширина и высота вашей карты составляет 1000 пикселей, а узлы столкновения представлены в виде квадратов размером 50×50 пикселей. Вы решили реализовать сетку 100 на 100 пикселей.

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

Затем, когда вы узнаете о расположении узлов коллизий (например, извлекаемых данных из некоторого API), вы должны заполнить структуру данных ссылками на каждый из узлов коллизий в соответствии с тем, где ее центральная точка расположена в сетке.

Таким образом, квадратный узел столкновения с < x: 726, y:211, w: 50, h:50 >будет размещен так:

После того, как несколько сотен или тысяч узлов размещены в сетке (что занимает очень мало накладных расходов для каждого — всего лишь деление или два и отправка ссылки на массив), проверка на наличие коллизий для данного узла значительно сокращается, так как вам нужно только проверить наличие столкновений с узлами в ячейке текущего узла, а также с 8 соседними ячейками.

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

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

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

Я бы предложил для этого использовать простой javascript, а не jQuery, если вы действительно хотите добиться максимальной производительности, но вот решение, которое я создал, с помощью jQuery.

Читайте также: