Динамически изменять или уничтожать Texture2D для рисования и обнаружения столкновений - PullRequest
4 голосов
/ 28 апреля 2009

Я использую XNA для 2D-проекта. У меня есть проблема, и я не знаю, как ее решить. У меня есть текстура (изображение), которая рисуется на экране, например:

|+++|+++|
|---|---|
|+++|+++|

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

|+++|
|---|---|
|+++|+++|

так что теперь столкновение будет работать и для нового изображения.

Каким путем было бы лучше решить эту проблему:

  1. Поменяйте местами всю текстуру другой текстурой, которая прозрачна в местах, где она уничтожена.
  2. Используйте некоторую хитрость с spriteBatch.Draw (sourceRectangle, destinationRectangle), чтобы получить желаемые нарисованные прямоугольники, а также каким-то образом выполните проверку столкновения.
  3. Разделите текстуру на 4 меньшие текстуры, каждая из которых будет отвечать за собственное обнаружение рисования / столкновения.
  4. Используйте какой-нибудь другой умный способ, о котором я не знаю.

Любая помощь будет оценена. Дайте мне знать, если вам нужно больше разъяснений / примеров.

РЕДАКТИРОВАТЬ: Чтобы уточнить, я приведу пример использования для этого. Представьте себе кусок стены 4х4, который при стрельбе уничтожает небольшую часть 1х1.

Ответы [ 4 ]

1 голос
/ 30 апреля 2009

Я возьму третий вариант:

3 - Разделить текстуру на 4 меньших текстуры каждая из которых будет ответственность за свое рисование / обнаружение столкновений.

Это не сложно сделать. По сути, это то же самое, что и структура TileSet. Тем не менее, вам нужно изменить код, чтобы соответствовать этому подходу. Прочитайте немного о Tiles на: http://www -cs-students.stanford.edu / ~ amitp / gameprog.html # плитки Многие сайты и книги рассказывают о Tiles и о том, как использовать его для построения игровых миров. Но вы можете использовать эту логику для всего, что представляет собой компост из маленьких частей.

Позвольте мне быстро отметить другие варианты:

1 - Поменять всю текстуру на другая текстура, которая прозрачна в местах, где он разрушен.

нет .. иметь разные образы на разные позиции плохо. Если вам нужно изменить де текстуры? Будете ли вы переделывать каждое изображение снова?

2 - Используйте некоторые хитрости с spriteBatch.Draw (sourceRectangle, destinationRectangle), чтобы получить желаемые прямоугольники нарисованы, а также сделать проверка столкновения с этим как-то.

К сожалению, это не работает, потому что spriteBatch.Draw работает только с прямоугольниками: (

4 Используйте какой-нибудь другой умный способ, которым я не знать о.

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

0 голосов
/ 04 мая 2009

В итоге я выбрал вариант 3. В основном у меня есть класс Tile, который содержит текстуру и размеры. Размер n означает, что внутри этой плитки есть n * n субтилей. У меня также есть массив, который отслеживает, какие плитки разрушены или нет. Мой класс выглядит так в псевдокоде:

 class Tile
     texture
     dimention
     int [,] subtiles; //0 or 1 for each subtile

     public Tile() // constructor
         subtiles = new int[dimention, dimention];
         intialize_subtiles_to(1);

     public Draw() // this is how we know which one to draw
        //iterate over subtiles
        for(int i..
          for(int j ...)
             if(subtiles[i,j] == 1)
                Vector2 draw_pos = Vector2(i*tilewidth,
                                      j*tileheight)                       
                spritebatch.Draw(texture, draw_pos)

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

   public bool collides(Rectangle rect)
       //iterate over subtiles 
       for i...
          for j..
              if(subtiles[i,j]==0) continue;

              subtile_rect = //figure out the rect for this subtile
              if(subtile_rect.intersects(rect))
                   return true;

       return false;

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

0 голосов
/ 30 апреля 2009

Вариант № 3 будет работать.

Более надежная система (если вы не хотите ограничиваться блоками) будет использовать обнаружение столкновений на пиксель. Процесс в основном работает следующим образом:

  1. Рассчитать ограничивающую рамку (или круг) для каждого объекта
  2. Проверьте, не перекрываются ли два объекта
  3. Для каждого перекрытия спрайты сбрасывают на скрытую поверхность, сравнивая значения пикселей по мере движения. Если пиксель уже установлен, когда вы пытаетесь нарисовать пиксель из второго спрайта, у вас есть столкновение.

Вот хороший пример XNA (фактически, другая статья о Ziggyware): Обнаружение столкновений 2D на пиксель

Еще несколько ссылок:

Может ли кто-нибудь объяснить обнаружение столкновений на пиксель

XNA 2-х пиксельное столкновение

0 голосов
/ 30 апреля 2009

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

...