java - 带有线条和区域的程序地形纹理

标签 java bufferedimage procedural

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

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

现在我正在努力

  1. 创建从点“X”到点“Y”的直线
  2. 该线将定义一个带有 boolean 值的区域,该线的左侧或右侧“较暗”。
  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();
                }

我无法让它像上图所示那样工作,它所做的只是什么都没有,或者偏离了两个点。 另外,有时它会无缘无故地卡住,所以我不知道如果我对此进行更多迭代会发生什么:/

最佳答案

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

我会尽力说清楚:

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

模式:

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

旋转:

您需要使用正弦和余弦函数来生成 X 和 Y 值,而不是每次都使用函数 X 来生成垂直线。

4 示例 30;旋转为:round( 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;
}

上面的循环将通过添加不同旋转的条形来生成数千个 map 图案。

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

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

roundshift = round(sin) 模式内的值,该模式在舍入值内向下或向上移动 sin,从而导致每次迭代的黑/白比例更小或更大。它是 i 的倍数,所以它是 i 的函数,每次循环都会变小。

xsin(rnd i) ycos(rnd i) = 旋转您的图案,两个 rnd 的数字必须相同。

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

最终您的图案值将等于最大值 100,因此除以 100,得到 0-1 或乘以 2.56 得到 256,并使用颜色随机化器使 RGB 随机为您的图案值的倍数。

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

我不知道如何在 JS 中执行 Canvas 数组/纹理插件像素,它应该很容易。

上面的代码将为您提供出色的模式和错误的视觉反馈,因此您应该能够很好地改进它,只是认为我错过了将 sin (-1 1)+ roundshift 结果的 0-1 值钳位。

因此,条形图是圆形的(sin(xy)+平移),您可以使用 xy 相乘的许多函数将其他所有内容加在一起,而不是条形图、图形圆形、正方形、 Swing 、椭圆形、矩形等。

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

关于java - 带有线条和区域的程序地形纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20830256/

相关文章:

Java stdin 不提示程序运行

java - 当图像的 HSB 值更改时,BufferedImage 不会保持透明度

php - 从过程函数到 OOP 类(一种特定情况)

java - 如何将 "Player image"添加到 Java 中?

java - 增加 BufferedImage 的 PPI

sql - 如何将此用于生成菜单层次结构的过程 SQL 代码转换为基于 SET 的方法?

php - 函数中来自不同文件的变量而不使用全局变量

java - dbunit 数据集没有将 boolean 字段放入数据库

java - 外部资源与@Before/@After

java - logback 行号未显示在日志中