Tạo bản đồ gạch


25

Tôi đang lập trình một trò chơi dựa trên gạch và tôi có một số ô cơ bản (cỏ, bụi bẩn, v.v.), nhưng tôi không thể tìm ra cách tạo bản đồ ngẫu nhiên tốt, bởi vì khi tôi thực hiện một số lựa chọn thực sự ngẫu nhiên, nếu lát nên là cỏ / bụi bẩn, tôi nhận được điều này:

Hình ảnh trong trò chơi

Tôi hiểu tại sao điều này xảy ra, nhưng điều tôi muốn là tạo ra một số khu vực cỏ hoặc bụi bẩn liên tục ngẫu nhiên. Một cái gì đó sẽ có ý nghĩa hơn, như thế này:

Kết quả như ý


1
Ngoài các câu trả lời được đề xuất, bạn có thể viết công cụ tự động di động của riêng bạn để tạo ra các bản đồ như vậy. Sửa đổi các quy tắc của máy tự động, bạn có thể tạo ra các hành vi rất khác nhau, dẫn đến các loại bản đồ rất khác nhau. Ví dụ: gievn một máy tự động 2d tương tự như Cuộc sống, các quy tắc ngập lụt có thể dẫn đến "đại dương và hòn đảo" (Giống như hình ảnh của bạn ở trên), và một quy tắc như 1267/17 có thể dẫn đến lao động tuyệt đẹp.
Manu343726

Câu trả lời:


19

Những gì bạn có thể làm là tạo ngẫu nhiên một bản đồ Voronoi như thế này:

  1. Chọn ngẫu nhiên center points(xem các chấm đen) và quyết định ngẫu nhiên nếu chúng là cỏ hoặc bụi bẩn.
  2. Sau đó, trên tất cả các gạch, kiểm tra xem nó gần nhất với center pointbụi bẩn hoặc cỏ.
  3. Làm xong!

Nếu những gì bạn đã làm trước đây là "lật một đồng xu" cho mỗi ô (tiếng ồn), thì việc tạo sơ đồ Voronoi sẽ mang lại kết quả tốt hơn nhiều.

Bạn có thể cải thiện điều này bằng cách chia center pointsthành islandsmột thuật toán:

  1. Chọn một nhóm nhỏ centers pointsvà chỉ định chúng là leaders.
  2. Lặp lại thêm một điểm trung tâm không quyết định liền kề ngẫu nhiên mỗi lượt.
  3. Làm xong!

nhập mô tả hình ảnh ở đây


1
Cảm ơn, nhưng có vẻ như là một giải pháp rất khó khăn.
Vilda

2
Đây không phải là một giải pháp rất khó khăn. Đầu tiên chọn ngẫu nhiên center points. Sau đó quyết định nếu chúng là cỏ hoặc bụi bẩn. Bây giờ lặp qua mảng và quyết định xem mỗi ô gần nhất với điểm bẩn hay điểm cỏ. Có lẽ cho tôi biết phần nào thách thức?
sói

Đo khoảng cách. Dù sao, tôi sẽ cố gắng và cho bạn biết.
Vilda

Ok, vì vậy tôi đã thành công một số điểm. ( dropbox.com/s/dlx9uxz8kkid3kc/random_tile_map2.png ) và vì vậy cả lớp tôi tạo ra trông như thế này: dropbox.com/s/pxhn902xqrhtli4/gen.java . Nhưng nó vẫn không hoạt động.
Vilda

3
@ViliX các liên kết của bạn bị hỏng
Artur Czajka

24

Bạn có thể sử dụng nhiễu perlin, được sử dụng để tạo sơ đồ chiều cao. Tiếng ồn Perlin trong các trò chơi

Sau đó, bạn có thể sử dụng độ cao như một cố vấn, khả năng cỏ / bụi bẩn xuất hiện ở một khu vực trên bản đồ là bao nhiêu.

Ví dụ (giá trị nhiễu Perlin từ 0-256): Nếu giá trị lớn hơn 200 thì khả năng cỏ được đặt là 80% (bụi bẩn 20%). Nếu giá trị nằm trong khoảng từ 100 đến 200 thì khả năng cỏ được đặt là 50% (bụi bẩn cũng 50%). Nếu giá trị dưới 100 thì khả năng cỏ được đặt là 20% (bụi bẩn 80%).


Ok, giả sử rằng tôi có một mảng [] [] float (0-1 xác suất) và tôi có thể sử dụng nó để sinh ra các ô với xác suất. Nhưng làm thế nào để tôi điền vào mảng xác suất này? Mảng là (giả sử) 400x200, làm thế nào để điền nó với các giá trị xác suất?
Vilda

Ông đang đề nghị lấp đầy nó bằng tiếng ồn perlin (thay vì tiếng ồn trắng như lật đồng xu).
sói

Có, nhưng làm thế nào tôi có thể đạt được điều đó?
Vilda

Liên kết tôi đã đăng có thể xóa câu hỏi này. Đầu tiên tạo ra tiếng ồn và sau đó làm giảm tiếng ồn này. Kết quả sẽ là một mảng 2 chiều mà bạn có thể sử dụng để tạo ra tilemap tiếp theo. liên kết
Klitz

Đó là một câu trả lời thực sự tốt nhưng nó sẽ hiếm khi nhận được kết quả tương tự như những gì bạn đã trình bày.
sói

8

nhập mô tả hình ảnh ở đây

http://gamedevelopment.tutsplus.com/tutorials/generate-random-cave-levels-USE-cellular-automata--gamedev-9664

đây là phiên bản của tôi về phương thức automata di động bắt đầu bằng cách điền vào lưới một cách ngẫu nhiên sau đó chạy các quy tắc automata cullular này trên nó một vài lần

  • Nếu một tế bào sống có ít hơn hai hàng xóm sống, nó sẽ chết.
  • Nếu một tế bào sống có hai hoặc ba hàng xóm sống, nó vẫn sống.
  • Nếu một tế bào sống có nhiều hơn ba hàng xóm sống, nó sẽ chết.
  • Nếu một tế bào chết có chính xác ba hàng xóm sống, nó sẽ trở nên sống động.

và nó trông giống như một cái hang

chỉ mục có thể được chuyển đổi sang vị trí x & y và quay lại với mã này

public int TileIndex(int x, int y)
{
    return y * Generator.Instance.Width + x;
}
public Vector2 TilePosition(int index)
{
    float y = index / Generator.Instance.Width;
    float x = index - Generator.Instance.Width * y;
    return new Vector2(x, y);
}

Tôi chỉ trả về một danh sách các bool vì tôi sử dụng danh sách này cho nhiều thứ: hang, cây, hoa, cỏ, sương mù, nước thậm chí bạn có thể kết hợp nhiều danh sách theo nhiều cách khác nhau ở đây trước tiên tôi loại bỏ tất cả các hang nhỏ hơn sau đó kết hợp hai danh sách ngẫu nhiên

nhập mô tả hình ảnh ở đây

private int GetAdjacentCount(List<bool> list, Vector2 p)
{
    int count = 0;
    for (int y = -1; y <= 1; y++)
    {
        for (int x = -1; x <= 1; x++)
        {
            if (!((x == 0) && (y == 0)))
            {
                Vector2 point = new Vector2(p.x + x, p.y + y);
                if (PathFinder.Instance.InsideMap(point))
                {
                    int index = PathFinder.Instance.TileIndex(point);
                    if (list[index])
                    {
                        count++;
                    }
                }
                else
                {
                    count++;
                }
            }
        }
    }
    return count;
}
private List<bool> GetCellularList(int steps, float chance, int birth, int death)
{
    int count = _width * _height;
    List<bool> list = Enumerable.Repeat(false, count).ToList();
    for (int y = 0; y < _height; y++)
    {
        for (int x = 0; x < _width; x++)
        {
            Vector2 p = new Vector2(x, y);
            int index = PathFinder.Instance.TileIndex(p);
            list[index] = Utility.RandomPercent(chance);
        }
    }
    for (int i = 0; i < steps; i++)
    {
        var temp = Enumerable.Repeat(false, count).ToList();
        for (int y = 0; y < _height; y++)
        {
            for (int x = 0; x < _width; x++)
            {
                Vector2 p = new Vector2(x, y);
                int index = PathFinder.Instance.TileIndex(p);
                if (index == -1) Debug.Log(index);
                int adjacent = GetAdjacentCount(list, p);
                bool set = list[index];
                if (set)
                {
                    if (adjacent < death)
                        set = false;
                }
                else
                {
                    if (adjacent > birth)
                        set = true;
                }
                temp[index] = set;
            }
        }
        list = temp;
    }
    if ((steps > 0) && Utility.RandomBool())
        RemoveSmall(list);
    return list;
}

2
Vui lòng giải thích những gì mã của bạn làm, thay vì đăng một mẫu về những gì nó làm, một liên kết và chính mã. Câu trả lời của bạn nên được khép kín, để ngay cả khi các liên kết bị hỏng, nó vẫn có thể sử dụng được.
Vụ kiện của Quỹ Monica

6

Chọn một điểm trên bản đồ. Đặt loại gạch mong muốn với giá trị cơ bản như 40. Theo dõi nơi bạn đã đặt gạch mới mong muốn. Thêm điểm bắt đầu vào một danh sách.

Đối với mỗi điểm trong danh sách này, bạn ghé thăm tất cả hàng xóm. Trong khi bạn có đủ năng lượng còn lại (bắt đầu từ 40), hãy thêm một ô mong muốn và thêm nó vào danh sách sẽ được truy cập. Cung cấp cho gạch mới ít năng lượng hơn, được xác định bởi bạn. Dễ nhất = hạ thấp ngẫu nhiên. Sau khi bạn truy cập vào ô từ danh sách, loại bỏ nó. Bắt đầu lại bằng cách truy cập bất kỳ gạch không mong muốn nhưng được tạo ra.

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.