1

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

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

现在我正在尝试

  1. 创建一条从点“X”到点“Y”的线
  2. 该线将定义一个区域,该区域具有布尔值,该线的左侧或右侧“较暗”。
  3. 这样做进行多次迭代以创建纹理。
  4. 使用最终图像的 RGB 值来更改森林、湖泊等内容。

这会这样工作:

用下面的这个方法覆盖,

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

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

问题:

  1. 我应该如何更改它以使其正常工作而不仅仅是失败?
  2. 有没有比使用我正在使用的更简单的方法?

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 点偏移。此外,有时它会无缘无故地冻结,所以如果我对此进行更多迭代会发生什么:/

4

2 回答 2

1

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

我会尽量清楚:

您不需要条形图/线来生成地图,您需要 1/2 轴上的任何图案,该图案从地图周期的一半开始,并且地图的比例越来越小或周期越来越小.

图案:

一条线是round(x);或圆形 (x+y) 或圆形(sin(x+y +translatebar)+barwidth)<-- 中间的真实条形而不仅仅是侧面 // 您可以稍后使用曲线和锯齿线以及使用加法和乘法的 2D 线X 和 Y 函数。该函数本质上只是一条线,您可以在其中更改它的 X 值以便旋转。

回转:

您需要使用 sinus 和 co sinus 函数来生成 X 和 Y 值,而不是每次生成一条垂直线的函数 X。

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 = value inside round(sin) 模式,在轮值内向下或向上移动 sin,导致每次迭代的黑色/白色比例更小或更大。它是 i 的倍数,所以它是 i 的函数,每个循环都会变小。

xsin(rnd i) ycos(rnd i) = 旋转你的模式,两个 rnd 都必然是相同的数字。

转换值 = 当您将数字 +/- 转换为 Sin(x+translate) 时。它向后/向前移动条

最后,您的模式值将等于最大 100,因此除以 100 即为 0-1 或乘以 2.56 为 256,并使用颜色随机器使 RGB 随机倍数您的模式值。

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

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

上面的代码会给你很好的模式和你的错误的视觉反馈,所以你应该能够很好地改进它,只是认为我错过了将 sin (-1 1) + roundshift 结果的 0-1 值。

所以条形图是圆形的(sin(xy)+translate),您可以使用 xy 的许多函数添加倍增的 sins 来将其他所有内容相加,而不是条形图、圆形、正方形、摆动、椭圆形、矩形等。

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

于 2014-02-12T08:02:53.300 回答
0

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

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

看到所有二维堆积图案的图片,他有很多关于异常艺术和他的网站的例子,我从这个人那里学到了很多:

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 旋转相同。

在此处输入图像描述

于 2014-02-16T15:42:02.133 回答