具有线条和区域的程序性地形纹理

时间:2013-12-29 21:28:59

标签: java bufferedimage procedural

我目前正在制作一个程序,用程序生成2d地形图,在尺寸定义的图像上使用不同的技术,如perlin噪声,单形,voronoi,分形噪声等,以便能够在我需要的游戏中使用它2d地形。

我遇到http://paulbourke.net/fractals/noise的“建模假行星”部分,我需要在2d纹理上制作它,而不是像解释的那样在3D世界上。

现在我正在尝试

  1. 从点“X”到“Y”
  2. 创建一条线
  3. 该行将定义一个区域,其左侧或右侧的布尔值为“较暗”。
  4. 进行多次迭代以创建纹理。
  5. 使用最终图像的RGB值来改变森林,湖泊等物品。
  6. 这会以这种方式运作:

    使用以下方法覆盖,

    http://img35.imageshack.us/img35/24/islf.png

    我利用我的高中数学能力来创建代码示例,但它并没有真正起作用......

    问题:

    1. 我应该如何更改它以使其有效而不仅仅是失败?
    2. 有没有比使用我正在使用的方式更简单的方法?
    3. Java文件: 如果我需要一个关于我将如何进行的例子,这里是:

      package Generator;
      
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.Graphics;
      import java.awt.image.BufferedImage;
      import java.util.Random;
      
      import VectorialStuffs.Vector2;
      
      public class Linear
      {
          public static BufferedImage generateImage(Dimension dim, int iterations)
          {
              BufferedImage image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
      
              //point X and point Y
              Vector2 pointX;
              Vector2 pointY;
      
              //difference between those
              Vector2 diff;
              Vector2 side;
              double slope;
      
              //random
              Random rand = new Random();
              boolean direction;              //the orientation of the dark zone. (left/right)
      
              for (int i = 0; i < iterations; ++i)
              {
                  pointX = new Vector2(0, 0);
                  pointY = new Vector2(0, 0);
                  direction = rand.nextBoolean();
                  System.out.println(direction);
      
                  side = new Vector2(0, 0);   //there are 4 sides of the image.
                  while (side.x == side.y)
                  {
                      side.x = rand.nextInt(3);   //0 - 1 - 2 - 3
                      side.y = rand.nextInt(3);
                  }
      
                  switch(side.x)  //not the x coord, the X point! ;D
                  {
                      //x = random and y = 0
                      case 0:
                          pointX.x = rand.nextInt(dim.width);
                          pointX.y = 0;
                      break;
                      //x = max and y = random
                      case 2:
                          pointX.x = dim.width;
                          pointX.y = rand.nextInt(dim.height);
                      break;
                      //x = random and y = max
                      case 1:
                          pointX.x = rand.nextInt(dim.width);
                          pointX.y = dim.height;
                      break;
                      //x = 0 and y = random
                      case 3:
                          pointX.x = 0;
                          pointX.y = rand.nextInt(dim.height);
                      break;
                  }
      
                  switch(side.y)  //not the y coord, the Y point! ;D
                  {
                      //x = random and y = 0
                      case 0:
                          pointY.x = rand.nextInt(dim.width);
                          pointY.y = 0;
                      break;
                      //x = max and y = random
                      case 2:
                          pointY.x = dim.width;
                          pointY.y = rand.nextInt(dim.height);
                      break;
                      //x = random and y = max
                      case 1:
                          pointY.x = rand.nextInt(dim.width);
                          pointY.y = dim.height;
                      break;
                      //x = 0 and y = random
                      case 3:
                          pointY.x = 0;
                          pointY.y = rand.nextInt(dim.height);
                      break;
                  }
      
                  diff = new Vector2((pointY.x - pointX.x), (pointY.y - pointX.y));
                  slope = diff.y / diff.x;
      
                  Graphics graph = image.getGraphics();
      
                  if (direction)  //true = right | false = left
                  {
                      int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                      int end = dim.width;
      
                      graph.setColor(Color.red);
                      graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                      graph.setColor(Color.yellow);
                      graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
      
                      for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                      {
                          System.out.println(times);
                          start = (int)((times-diff.y)/slope + diff.y);   //this is where it goes wrong?
                          for (int value = start; value < end; ++value)
                          {
                              graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                              graph.fillRect(value, times, 1, 1);
                          }
                      }
                      graph.dispose();
                  }
                  else
                  {
                      int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                      int end = dim.width;
      
                      graph.setColor(Color.red);
                      graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                      graph.setColor(Color.yellow);
                      graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
      
                      for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                      {
                          System.out.println(times);
                          start = (int)((times-diff.y)/slope);
                          for (int value = end; value < start; --value)
                          {
                              graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                              graph.fillRect(value, times, 1, 1);
                          }
                      }
                      graph.dispose();
                  }
              }
      
              return image;
          }
      }
      

      注意: 在这种情况下,vector2只是一个带有X和Y的类,可以访问它(这可能是暂时的)。

      启动部分,以避免您浪费时间:

      terrainImage = Linear.generateImage(size, 1);   //size being a Dimension. -> "new Dimension(256, 256)"
      if (terrainImage != null)
      {
          Icon wIcon = new ImageIcon(terrainImage);
          JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.OK_OPTION, wIcon);
      }
      

      //修改 这是需要改进的代码:

      if (direction)  //true = right | false = left
                      {
                          int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                          int end = dim.width;
      
                          graph.setColor(Color.red);
                          graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                          graph.setColor(Color.yellow);
                          graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
      
                          for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                          {
                              System.out.println(times);
                              start = (int)((times-diff.y)/slope + diff.y);   //this is where it goes wrong?
                              for (int value = start; value < end; ++value)
                              {
                                  graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                                  graph.fillRect(value, times, 1, 1);
                              }
                          }
                          graph.dispose();
                      }
                      else
                      {
                          int start;  //the start x coordinate, on the line then increases until reaching the end of the image
                          int end = dim.width;
      
                          graph.setColor(Color.red);
                          graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
                          graph.setColor(Color.yellow);
                          graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
      
                          for (int times = 0; times < dim.height; ++times)    //horizontal drawer
                          {
                              System.out.println(times);
                              start = (int)((times-diff.y)/slope);
                              for (int value = end; value < start; --value)
                              {
                                  graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
                                  graph.fillRect(value, times, 1, 1);
                              }
                          }
                          graph.dispose();
                      }
      

      我不能像上面的图片中所示那样工作,它所做的一切都是没有,或偏离2点。 此外,有时它会无缘无故地冻结,所以如果我对此进行更多迭代会发生什么:/

2 个答案:

答案 0 :(得分:1)

代码的模式生成元素应该只占用大约3行,包括旋转,颜色模式调制以及所有迭代的函数。

我会尽力明白:

你不需要一个条形图/直线来生成地图,你需要在一个/两个轴上的任何图案,这些图案从地图的一半周期开始,并且得到的地图越来越小或者更小而且时间较短。

图案:

一条线是圆的(x);或圆形(x + y)或圆形(sin(x + y +平移条)+条形宽度)&lt; - 中间不仅仅是侧面的真实条形// 你可以使用X和Y函数的加法和乘法来制作曲线和曲折线以及2D线。该函数基本上只是一行,您可以将其更改为X值以便旋转。

旋转:

而不是每次产生垂直线时的功能X,你需要使用正弦和共窦函数来产生X和Y值。

4例30;旋转是:圆形(X * 0.866+ Y * 0.5)

获取随机值的正弦和余弦,它将为您提供模式的随机旋转,方便的是您只需对循环迭代进行随机值并将其发送到符号余弦。

好的我会用伪代码写这个会更简单:


var pattern = 0; // black canvas

for(var i=1; i=100; i++)
{
   pattern += round((sin   (X*sin(pseudorand(i))  + Y*cos(pseudorand(i)) + translation) + roundshift )*strength;
}

上述循环将通过添加不同旋转的条形图来生成数千个地图模式。

Round =量化你的sin(XY)函数,因此它只是黑色和白色/红色灰色。

Sin(XY)=用作模式的变量函数,通过舍入到0/1值进行量化...乘以并将该值钳制在同一行中,使其不超过1或0

roundshift =圆形(sin)模式内的值,它将sin在圆值内向下或向上移动,从而导致每次迭代的黑/白比例更小或更大。它是i的倍数,因此它是i的函数,每个循环都会变小。

xsin(rnd i)ycos(rnd i)=旋转你的模式rnd's必须是相同的数字。

翻译值=当你+/-一个数字到一个Sin(x +翻译)。它向后/向前移动

最后你的模式值将等于maxiumum 100,所以偏差为100,因此对于256来说它是0-1或者多为2.56,并且使用颜色随机函数来生成模式值的RGB随机倍数。

对于每个像素x y,上面的循环显然需要运行一次。

我不知道如何在JS中使用canvas数组/纹理插件像素,应该很容易。

上面的代码会给你很好的模式和你的错误的视觉反馈,所以你应该能够很好地完善它,只考虑我错过了钳位到sin(-1 1)+轮回结果的0-1值。

所以一个圆形是圆形的(sin(xy)+平移),你可以使用许多xy添加的muptiplied sins的函数来将其他所有东西加在一起,而不是条形图形,图形圆形,正方形,摆动,椭圆形,矩形等。 / p>

有一个网站都是关于这种类型的模式,除了有序角度和说5-6次迭代,使用点条三角形等,他是加拿大人和异常艺术品,如果没有那么多TD模式生成我可以找到他的网站!

答案 1 :(得分:0)

这是一个网站,解释了“模式打桩”的过程,它在越来越小的迭代中覆盖了许多形状。

唯一的区别是他使用有序旋转来创建对称性,并且您希望随机旋转来创建混沌贴图。

在2d看到所有堆积模式的照片,他有许多关于异常艺术及其网站的例子,我从这个人那里学到了很多:

http://algorithmic-worlds.net/info/info.php?page=pilpat 这里是对称旋转中叠加越来越小的模式的更多工作: https://www.google.com/search?q=Samuel+Monnier&espv=210&es_sm=93&source=lnms&tbm=isch&sa=X&ei=It0AU9uTCOn20gXXv4G4Cw&ved=0CAkQ_AUoAQ&biw=1365&bih=911

与使用随机sin cos旋转相同。

enter image description here