thuật toán hình vuông nhỏ kim cương


12

Thuật toán hình vuông kim cương là thuật toán tạo địa hình fractal (heightmap). Bạn có thể tìm thấy một mô tả hay về cách thức hoạt động ở đây:

http://www.gameprogrammer.com/fractal.html (Được sử dụng làm tài liệu tham khảo.)

http://www.playfuljs.com/realistic-terrain-in-130-lines/ (Triển khai JS tuyệt vời, có lẽ bạn có thể muốn đánh cắp trình kết xuất của anh ấy. Hãy xem ở đây thuật toán này có khả năng http: // demos. playfuljs.com/terrain/ .)

Ý tưởng chung là bạn có 4 góc là hạt (a) và tính chiều cao của điểm trung tâm bằng cách lấy trung bình bốn góc đó và thêm một giá trị ngẫu nhiên, ví dụ từ -0,5 đến 0,5 (b). Nếu bạn áp dụng điều này cho lưới, bạn sẽ nhận được một lưới kim cương (hình vuông turend 45 °) và bạn lặp lại tương tự (c, d), nhưng phạm vi ngẫu nhiên sẽ nhỏ hơn, ví dụ -0.125 đến 0.125, v.v. nhập mô tả hình ảnh ở đây

Chương trình của bạn phải chấp nhận một số đầu vào:

  • Một số nguyên l=1,2,3,...xác định kích thước của lưới vuông với chiều dài cạnh 2^l+1. Tại l=10bạn sẽ phải lưu trữ khoảng một triệu số.
  • Bốn hạt (điểm nổi) cho mỗi góc
  • Một tham số 0<h<1xác định độ nhám ( Htrong liên kết) có nghĩa là phạm vi ngẫu nhiên ban đầu lớn như thế nào
  • Các tham số a,bđại diện cho giới hạn dưới và trên ban đầu cho phạm vi ngẫu nhiên và được nhân với hmỗi bước tinh chỉnh. (Số ngẫu nhiên được chọn thống nhất giữa ab.

Đầu ra phải bao gồm lưới 2d đã hoàn thành.

Vì vậy, thuật toán thô sẽ trông như thế này:

Create a square grid with sidelength 2^l+1
Place seed values in the corners
Repeat:
  |  Perform square steps
  |  Refine Range: a = a*h; b=b*h;
  |  Perform diamond steps
  |  Refine Range

Có một chi tiết bạn cần lưu ý: Tại ranh giới của lưới, bạn sẽ chỉ có ba đỉnh của viên kim cương , vì vậy bạn cũng chỉ nên tính trung bình của ba điểm đó.

Một hình ảnh trực quan của một số ví dụ (vui lòng cho chúng tôi biết các tham số bạn đã sử dụng) là tùy chọn nhưng được đánh giá cao và tất nhiên không thêm vào số byte.

Một triển khai thay đổi nhỏ của thuật toán này có thể được tìm thấy ở đây: Trình tạo địa hình voxel được chiếu song song

Tôi đã tạo một hàm vẽ nhỏ trong javascript để thay thế các chiều cao trong 2d dưới dạng ảnh thang độ xám. http://jsfiddle.net/flawr/oy9kxpsx/

Nếu bất kỳ ai trong số bạn thích 3d và có thể tạo tập lệnh để xem bản đồ trong 3d hãy cho tôi biết! =)

Câu trả lời:


8

Java, 1017 byte

Đầu vào là một danh sách được phân tách bằng dấu cách như vậy : l s1 s2 s3 s4 h a b.

Đầu ra là một mảng 2d chứa các số.

Chương trình:

import java.util.*;import static java.lang.Math.*;class C{public static void main(String[]a){int b=a.length,d=0;float[]c=new float[b];for(;d<b;){c[d]=Float.parseFloat(a[d++]);}e=(int)(pow(2,c[0])+1);f=new float[e][e];f[0][0]=c[1];f[0][e-1]=c[2];f[e-1][0]=c[3];f[e-1][e-1]=c[4];g=c[5];float h=c[6],i=c[7];s(0,0,e-1,e-1,h,i);System.out.print(Arrays.deepToString(f));}static int e;static float[][]f;static float g;static void s(int q,int r,int s,int t,float h,float i){if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)return;float o,p;int m=(q+s)/2,n=(r+t)/2;f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i-h)-h);d(m,r,m-q,o=h*g,p=i*g);d(q,n,m-q,o,p);d(m,t,m-q,o,p);d(s,n,m-q,o,p);}static void d(int x,int y,int e,float h,float i){float o,p;f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)-h);s(x-e,y-e,x,y,o=h*g,p=i*g);s(x,y-e,x+e,y,o,p);s(x-e,y,x,y+e,o,p);s(x,y,x+e,y+e,o,p);}static float a(int...j){float k=0,l=0;for(int d=0;d<j.length;d+=2){if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)continue;l++;k+=f[j[d]][j[d+1]];}return k/l;}}

Chương trình được thụt lề và hiển thị bản đồ:

import java.util.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.Math.*;

class D{

    public static void main(String[]a){
        int b=a.length,d=0;
        float[]c=new float[b];
        for(;d<b;){
            c[d]=Float.parseFloat(a[d++]);
        }
        e=(int)(pow(2,c[0])+1);
        f=new float[e][e];
        f[0][0]=c[1];
        f[0][e-1]=c[2];
        f[e-1][0]=c[3];
        f[e-1][e-1]=c[4];
        g=c[5];
        float h=c[6],i=c[7];
        s(0,0,e-1,e-1,h,i);
        showImage(f);
    }

    static int e;
    static float[][]f;
    static float g;

    static void s(int q,int r,int s,int t,float h,float i){
        if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)
            return;
        float o,p;
        int m=(q+s)/2,n=(r+t)/2;
        f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i+h)-h);
        d(m,r,m-q,o=h*g,p=i*g);
        d(q,n,m-q,o,p);
        d(m,t,m-q,o,p);
        d(s,n,m-q,o,p);
    }

    static void d(int x,int y,int e,float h,float i){
        float o,p;
        f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)+h);
        s(x-e,y-e,x,y,o=h*g,p=i*g);
        s(x,y-e,x+e,y,o,p);
        s(x-e,y,x,y+e,o,p);
        s(x,y,x+e,y+e,o,p);
    }

    static float a(int...j){
        float k=0,l=0;
        for(int d=0;d<j.length;d+=2){
            if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)
                continue;
            l++;
            k+=f[j[d]][j[d+1]];
        }
        return k/l;
    }

    public static void showImage(float[][] f){
        float maxHeight = Float.MIN_VALUE;
        float minHeight = Float.MAX_VALUE;
        for (float[] row : f){
            for (float height : row){
                if (height > maxHeight){
                    maxHeight = height;
                }
                if (height < minHeight){
                    minHeight = height;
                }
            }
        }
        int e = f.length;
        BufferedImage image = new BufferedImage(e, e, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < e; x++){
            for (int y = 0; y < e; y++){
                Color color = Color.getHSBColor((float)((f[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
                image.setRGB(x,y,color.getRGB());
            }
        }
        JFrame frame = new JFrame("Picture");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JComponent(){

            @Override
            public void paint(Graphics g){
                g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
            }

        });
        frame.setVisible(true);
        frame.setBounds(0,0,e,e);
    }

}

Đây là một hàm trong Java để hiển thị bản đồ:

public static void showImage(float[][] map){
    float maxHeight = Float.MIN_VALUE;
    float minHeight = Float.MAX_VALUE;
    for (float[] row : map){
        for (float height : row){
            if (height > maxHeight){
                maxHeight = height;
            }
            if (height < minHeight){
                minHeight = height;
            }
        }
    }
    int size = map.length;
    BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < size; x++){
        for (int y = 0; y < size; y++){
            Color color = Color.getHSBColor((float)((map[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
            image.setRGB(x,y,color.getRGB());
        }
    }
    JFrame frame = new JFrame("Picture");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JComponent(){

        @Override
        public void paint(Graphics g){
            g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
        }

    });
    frame.setVisible(true);
    frame.setBounds(0,0,size,size);
}

Tất cả những hình ảnh này có kích thước 7. 4 hạt 5, 10, 15, và 20.

abđược -1010tương ứng.

Độ nhám bắt đầu từ .1và tăng .1lên đến 1.

MộtHaiSố baBốnSố nămSáuBảyTámChínMười

Sắp có mã tạo địa hình !!!

Hình ảnh đến sớm !!!


Cảm ơn rât nhiều! Có lẽ bạn có thể cung cấp một lớp học xung quanh rằng với tất cả các nhập khẩu cần thiết để không cần sửa đổi lớn? Điêu đo thật tuyệt vơi!
flawr

@flawr Tôi đang làm việc trên nó.
TheNumberOne

Chỉ cần nó hoạt động, nếu bạn biết cách thực hiện, sẽ thật tuyệt nếu bạn có thể làm cho cửa sổ hiển thị 'không bị đánh cắp'. Ít nhất trên máy của tôi, bạn phải mở nó ra mỗi khi bạn khởi động nó. Đây là cách tôi hoàn thành lớp học: pastebin.com/pRAMst4d
flawr

Điều này có vẻ tuyệt vời! Tôi đặc biệt thích cách thanh lịch mà bạn đang xử lý các ranh giới nơi thiếu một
đỉnh

@flawr Cửa sổ sẽ không bị sập khi bạn mở nó bây giờ.
TheNumberOne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.