Sử dụng L-Systems để tạo thành phố theo thủ tục


10

Tôi hiện đang làm một ứng dụng tập trung rất nhiều vào nội dung được tạo theo thủ tục. Cho đến nay, tôi đã thực hiện thành công thế hệ thủ tục về địa hình và hình dạng của bản đồ bằng cách sử dụng nhiễu đơn giản. Tôi thực sự hài lòng với vẻ ngoài của nó. Bây giờ tôi đang cố gắng làm điều tương tự cho các thành phố. Tôi chỉ cần tạo ra một bố cục 2D của đường phố và các tòa nhà. Tôi đã xem xét nó và có vẻ như hầu hết mọi người đề nghị sử dụng L-Systems. Tuy nhiên tôi dường như không thể quấn đầu quanh họ. Tôi có được khái niệm, nhưng không thực hiện thành mã. Có ai có bất kỳ ví dụ mã nào của L-Systems cho các thành phố được tạo theo thủ tục hoặc đề xuất về các cách khác để xử lý các thành phố không?



+1 Hurrah cho L-Systems !
luser droog

Một cách tôi đã làm một cái gì đó tương tự là tạo ra một lưới các nút đại diện cho các giao điểm, sau đó kết nối ngẫu nhiên các nút liền kề. Làm cho bố cục giống như mê cung, nhưng đường phố không được kết nối với nhau, vì vậy thực sự điều hướng nó là không thể.
dùng137

Sự vô lý thường được trích dẫn cho các hệ thống L tạo thành phố là giấy của Giáo xứ và Müller: Mô hình hóa thủ tục của các thành phố . Tôi cũng tìm thấy một ví dụ tuyệt vời về việc thực hiện . Đó là một nơi tốt để bắt đầu, nhưng tùy thuộc vào yêu cầu chính xác của bạn, bạn có thể phải thay đổi một số thứ xung quanh.
Anders Ryndel

Câu trả lời:


20

L-Systems , từ những gì tôi có thể nói *, là một tập hợp các quy tắc thay thế giống như ngữ pháp mà bạn có thể áp dụng đệ quy để có được kết quả "hữu cơ" thú vị.

Thực vật là nơi L-Systems thường được sử dụng, vì chúng cho thấy rất nhiều sự tăng trưởng đệ quy (tức là nhánh tách ra thành nhiều nhánh hơn). Ví dụ đơn giản, tôi sẽ hiển thị cây "kẹo mút" được tạo bằng Hệ thống L:

variables : | o              (these are the things that will grow)
start  : o
         |                   (this is what we start with)
rules  : (o  o   o)         (these are the substitution rules that we apply
               \ /            one step at a time)

Vì vậy, ở thế hệ 1, chúng ta chỉ có sự khởi đầu:

o
|

Ở thế hệ 2, chúng tôi tuân theo từng quy tắc và thay thế các phần hiện có theo quy tắc. Chúng tôi thay thế "quả bóng" bằng "hai gậy và bóng":

o   o
 \ /
  |

Thế hệ 3:

o o   o o
 \|   |/
   \ /
    |

Chẳng mấy chốc chúng ta sẽ có một cái cây to (crappy)!

Để thực hiện điều này trong mã, bạn có thể thực hiện điều này một cách đệ quy (ví dụ DFS), liên tục áp dụng các quy tắc trên cùng các phần cho đến khi bạn đạt được một kết thúc tùy ý hoặc bạn có thể thực hiện điều này lặp đi lặp lại (ví dụ BFS) như chúng ta đã làm trong ví dụ này , thực hiện một quy tắc "vượt qua" trên tất cả các yếu tố và lặp lại một số bước. Đó là:

Đệ quy:

tree = start
grow(tree, start)

func grow(tree, part)
    if this part of the tree is big enough
        stop
    if part is 'o'
        replace part with 'o\/o'
        grow(tree, the left 'o')
        grow(tree, the right 'o')

Lặp lại:

tree = start
for a number of iterations
    for each part in tree
        if part is 'o':
            replace with 'o\/o'

Rất nhiều việc sử dụng L-Systems thực hiện bước "phát triển" bằng cách sử dụng phân ngành - nghĩa là các bộ phận tiếp tục nhỏ hơn khi chúng được "phát triển", các phần lớn hơn chỉ bị chia. Nếu không, hệ thống đang phát triển của bạn có thể bắt đầu chồng chéo lên nhau. Bạn sẽ thấy trong ví dụ về cây kẹo mút của mình, tôi đã bảo đảm một cách kỳ diệu hai nhánh không trùng nhau ở giữa bằng cách thay đổi hình dạng của các nhánh mới. Hãy làm ví dụ thành phố bằng cách sử dụng phân khu:

variables: block_vertical block_horizontal road_vertical road_horizontal
start: block_vertical
rules: (block_vertical  block_horizontal road_vertical block_horizontal)
       (block_horizontal  block_vertical road_horizontal block_vertical)

Điều này sẽ có ý nghĩa trong một phút.

Thế hệ 1:

+--------------------+
|                    |
|                    |
|                    |
|        V           |
|                    |
|                    |
|                    |
+--------------------+

Một khối dọc đơn, nhàm chán. (Chữ V là viết tắt của dọc.)

Thế hệ 2: chúng tôi thay thế khối dọc bằng khối ngang bằng đường dọc ở giữa

+--------------------+
|       r            |
|       r            |
|       r            |
|   H   r      H     |
|       r            |
|       r            |
|       r            |
+--------------------+

Các r là viết tắt của đường! Tôi đã ngẫu nhiên tách ra, chúng tôi không muốn các phần thông thường nhàm chán trong PCG.

Thế hệ 3: chúng tôi thay thế các khối ngang bằng các khối dọc tách ra bằng các đường ngang. Những con đường hiện có ở lại; không có quy tắc cho họ.

+--------------------+
|   V   r            |
|       r            |
|rrrrrrrr            |
|       r      V     |
|   V   r            |
|       rrrrrrrrrrrrr|
|       r      V     |
+--------------------+

Chú ý cách các con đường kết nối với nhau, điều này thật tuyệt. Lặp lại đủ số lần này và bạn sẽ kết thúc với một cái gì đó như thế này (ngang nhiên gạt ra một câu trả lời liên quan ):

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

Lưu ý rằng có rất nhiều chi tiết tôi chưa đề cập và kết quả này trông "rõ ràng" được tạo ra - các thành phố thực sự trông hơi khác. Đó là những gì làm cho PCG vui / khó. Có vô số điều bạn có thể làm để điều chỉnh và cải thiện kết quả của mình, nhưng không liên quan đến L-Systems, tôi sẽ để lại câu trả lời này tại đây; hy vọng điều này sẽ giúp bạn bắt đầu.

* - Tôi chưa nghiên cứu chính thức về L-Systems, mặc dù tôi đã gặp các loại cụ thể như ngữ pháp và thảm thực vật PCG; vui lòng sửa cho tôi nếu tôi nhận được bất kỳ định nghĩa hoặc khái niệm sai


1

@congusbongus câu trả lời là tuyệt vời, hãy để tôi thêm một vài điều.

Các khối cần phải được chia thành các khu vực xây dựng theo tất cả các con đường giáp với chúng. Khi bạn có đường xung quanh, mô hình tổng thể là một vòng tròn. Xem liên kết này để biết ví dụ: http://oldurbanist.blogspot.fr/2012/01/city-blocks-spaces-in-b between.html

(Tùy thuộc vào mật độ, có thể không có không gian trong tâm vòng, xem kowloon).

Một khi bạn đã thực hiện các khối, bạn cần tạo các tòa nhà. Họ là một chút khó khăn và đòi hỏi một thế hệ hai vượt qua. Chúng phụ thuộc một phần: máy phát điện của bạn không nên tạo một cửa sổ ở phía trước bức tường bên cạnh tòa nhà tiếp theo.

Và để thêm sức sống cho điều này, bạn có thể muốn tác động đến thế hệ bằng các môi trường như địa hình hoặc bản đồ kinh tế: Đường (trừ ở San Francisco) có xu hướng đi quanh những ngọn đồi lớn, thay vì đi thẳng và các loại nhà rất nặng chịu ảnh hưởng của một phần của thành phố họ đang ở.

chúc vui vẻ.

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.