动态更改或销毁Texture2D以进行绘图和碰撞检测

时间:2009-04-27 23:21:29

标签: xna textures sprite

我正在使用XNA进行2D项目。我有一个问题,我不知道解决它的方法。我有一个绘制到屏幕的纹理(图像),例如:

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

现在我希望能够破坏部分结构/图像,使其看起来像:

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

这样碰撞现在也适用于新图像。

哪种方式可以更好地解决这个问题:

  1. 将整个纹理与另一个纹理交换,该纹理在其被销毁的地方是透明的。
  2. 对spriteBatch.Draw(sourceRectangle,destinationRectangle)使用一些技巧来获取所需的矩形,并以某种方式进行碰撞检查。
  3. 将纹理分割成4个较小的纹理,每个纹理将负责它自己的绘图/碰撞检测。
  4. 使用其他一些我不知道的智能方式。
  5. 任何帮助将不胜感激。如果您需要更多说明/示例,请与我们联系。

    编辑:澄清我将提供一个使用示例。 想象一下4x4的墙壁,当它射击时,它的一小部分被破坏。

4 个答案:

答案 0 :(得分:1)

我会选择第三个选项:

  

3 - 将纹理分割成4个较小的纹理   纹理每个都将是   对它自己负责   绘图/碰撞检测。

这并不难。基本上它与TileSet结构相同。但是,您需要更改代码以适应此方法。 阅读关于Tiles的一点内容:http://www-cs-students.stanford.edu/~amitp/gameprog.html#tiles 许多网站和书籍都谈到了Tiles以及如何使用它来构建游戏世界。但是你可以将这个逻辑用于从小部分整体堆肥的所有东西。

让我快速说明其他选项:

  

1 - 用整个纹理交换   另一种纹理,即透明的   在它被摧毁的地方。

不..每个不同的位置都有不同的图像是不好的。如果你需要改变纹理?你会再次重拍每张图片吗?

  

2 - 使用一些技巧   spriteBatch.Draw(sourceRectangle,   destinationRectangle)获取   绘制所需的矩形,也可以   以某种方式与此进行碰撞检查。

不幸的是它不起作用,因为spriteBatch.Draw仅适用于矩形:(

  

4 使用其他智能方法我不这样做   知道。

我无法想象这有什么魔力。也许,您可以使用其他图像制作面具。但它的处理成本非常高。

答案 1 :(得分:0)

在Ziggyware上查看这篇文章。它大概是Deformable Terrain,可能就是你要找的东西。从本质上讲,该技术涉及将要隐藏的像素设置为透明。

答案 2 :(得分:0)

选项#3将起作用。

更强大的系统(如果您不希望限于框)将使用逐像素冲突检测。该过程基本上如下:

  1. 计算每个对象的边界框(或圆圈)
  2. 检查两个对象是否重叠
  3. 对于每个重叠,将精灵blit到隐藏的表面上,随时比较像素值。如果在尝试从第二个精灵中绘制像素时已经设置了像素,则会发生碰撞。
  4. 这是一个很好的XNA示例(实际上是另一篇Ziggyware文章):2D Per Pixel Collision Detection

    更多链接:

    Can someone explain per-pixel collision detection

    XNA 2-d per-pixel collision

答案 3 :(得分:0)

我最终选择了选项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来“破坏”某些子类,以及如何检查整个区块是否被破坏。 通过这种技术,子弹将具有相同的纹理。到目前为止,我无法想到一个更简单的解决方案。