我目前正在制作一个程序,在大小定义的图像上使用不同的技术(例如柏林噪声、单纯形、voronoi、分形噪声等)以程序方式生成 2d 地形图,以便能够在需要 2d 地形的游戏中使用它。
我发现了 http://paulbourke.net/fractals/noise 的“模拟假行星”部分我需要在 2D 纹理上制作它,而不是像所解释的那样在 3D 世界上制作。
现在我正在努力
- 创建从点“X”到点“Y”的直线
- 该线将定义一个带有 boolean 值的区域,该线的左侧或右侧“较暗”。
- 进行多次迭代以创建纹理。
- 使用最终图像的 RGB 值来更改森林、湖泊等内容。
这会这样工作:
使用下面的方法覆盖,
http://img35.imageshack.us/img35/24/islf.png
我用我的高中数学能力创建了一个代码示例,但它并没有真正起作用......
问题:
- 我应该如何更改它才能使其正常工作而不是失败?
- 有没有比使用我正在使用的更简单的方法?
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/