Выбор мыши XNA 2D

Я работаю над простой 2D-стратегией в реальном времени с использованием XNA. Прямо сейчас я достиг точки, когда мне нужно иметь возможность щелкнуть спрайт для единицы или здания и иметь возможность ссылаться на объект, связанный с этим спрайтом. Из исследований, которые я провел за последние три дня, я нашел много ссылок на то, как делать «Выбор мыши» в 3D, которые, похоже, не применимы к моей ситуации. Я понимаю, что еще один способ сделать это - просто иметь массив всех «выбираемых» объектов в мире, и когда игрок нажимает на спрайт, он проверяет местоположение мыши по отношению к местоположениям всех объектов в массиве. проблема, с которой я столкнулся при таком подходе, заключается в том, что он станет довольно медленным, если количество юнитов и зданий вырастет до больших чисел. (это также не кажется очень элегантным), так что я мог бы сделать это другими способами. (Обратите внимание, что я также работал над идеями использования хэш-таблицы для связывания объекта с местоположением спрайта и использования двумерного массива, где каждое местоположение в массиве представляет один пиксель в мире. неуклюжие способы делать вещи.)


person APalmer    schedule 24.12.2010    source источник


Ответы (3)


Для сотен единиц достаточно просто выполнить линейный поиск O(n) по всем единицам в мире, если области щелчка представляют собой круги или прямоугольники. Тем более, что это будет один раз за клик, а не один раз за кадр.

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

Для более подробного ответа вот мой ответ на аналогичный вопрос о разделении пространства. Там я упоминаю сетки с сегментами и деревья квадрантов как потенциальные структуры для оптимизации производительности.

Но вы никогда не должны оптимизировать производительность, пока не протестируете и на самом деле не столкнетесь с проблемой производительности!

person Andrew Russell    schedule 24.12.2010
comment
Я ценю ваш вклад. Думаю, я буду следовать тому, что вы сказали. Я полагаю, я не знаю, понадобится ли мне еще какая-либо серьезная оптимизация производительности. Один уточняющий вопрос. Существуют ли какие-либо действительно хорошие методы программирования, которым следует следовать, чтобы упростить реализацию полурадикальных изменений (таких как изменение структуры данных, которую вы используете для тестирования кликов и хранения объектов). Глядя на то, как я сейчас программирую, я полагаю, что оптимизация моего кода с использованием некоторых из этих методов и тех, о которых вы говорите в другом посте, на который вы ссылаетесь, будет довольно сложным процессом. - person APalmer; 26.12.2010
comment
@Corndog: Используете ли вы какой-либо контроль версий? Google Subversion и Subversion Book — хорошая бесплатная отправная точка. После того, как у вас есть контроль версий, вы можете начать вносить радикальные изменения в свой код без страха (это похоже на огромную волшебную кнопку отмены). Вы также можете поискать модульное тестирование — если вы хотите быть абсолютно уверены, что не нарушите свой алгоритм (честно говоря, вам, вероятно, не нужно выполнять автоматизированное модульное тестирование в этот конкретный случай - должно быть довольно просто проверить код выбора вручную). - person Andrew Russell; 27.12.2010

Если у вас есть класс, который управляет объектами drawabel, у вас может быть статический int, который вы увеличиваете каждый раз, когда создаете новый объект, и сохраняете старый как локальный экземпляр Color в объекте drawabel. Затем вы можете использовать преобразователь типов .Net, чтобы преобразовать его в массивы до свидания и обратно, не помню его имени, и я разговариваю по телефону в поезде, поэтому не могу проверить вас, я боюсь.

Когда вы строите цвет из массива байтов, просто не забудьте максимизировать альфа-канал, и если вы получите слишком много объектов, вы можете выйти за пределы индексов, которые вы можете использовать. снова потребуйте новые цвета с 0:0:0:255, так как, надеюсь, некоторые старые больше не используются: P

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

person Tomas    schedule 30.12.2010

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

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

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

Color[] pixel = new Color[1];
texture.GetData(pixel, mousePosition.Y * texture.Width + mousePosition.x, 1);
//pixel[0] == colour of the item the mouse is over. You can now look this up in a dictionary<Color, item>

Вы должны быть осторожны, чтобы не остановить конвейер, делая это (заставляя ЦП ждать, пока ГП отобразит что-то). Лучший способ сделать это — переключиться между двумя целями рендеринга и всегда получать данные из цели рендеринга, которую вы использовали в последнем кадре, это означает, что данные устарели на один кадр, но ни у одного человека нет достаточно быстрой реакции, чтобы это заметить.

Дополнение в ответ на ваш комментарий.

Чтобы присвоить уникальный цвет каждому объекту, просто увеличьте байт для каждого объекта. Когда этот байт переполняется, увеличьте другой, а когда этот байт переполняется, увеличьте другой; Затем вы можете использовать эти три байта как красный, зеленый и синий. Помните, чтобы поддерживать альфу на максимальном значении, вы не хотите видеть сквозь объекты!

Чтобы решить проблему, задний буфер немного изменен в XNA4. Теперь вы должны отрендерить в rendertarget и разрешить это. Сделать это довольно просто, и это описано Шоном Харгривзом здесь

person Martin    schedule 24.12.2010
comment
Я очень заинтересован в этом маршруте, но, честно говоря, я понятия не имею, как вы будете назначать уникальный цвет для каждого объекта (вы бы просто увеличивали шестнадцатеричное значение каждый раз, когда вы создаете новый объект?) и после выяснения цветов, как вы бы преобразовали задний буфер в текстуру? есть ли веб-сайт, статья или учебник, на который вы могли бы указать мне, что говорит об этом? (Я также пойду осмотреться и посмотреть, что я могу найти, но любая помощь ускорит этот процесс.) Спасибо за вашу помощь и вклад. - person APalmer; 26.12.2010