Tạo địa hình thủ tục 2D - Đảm bảo kết nối?


7

Tôi đang làm việc trên một nền tảng 2D trong XNA. Một trong những điều tôi muốn trở thành một đặc điểm thiết kế chính là tạo nội dung theo thủ tục. Bước đầu tiên là tạo thủ tục địa hình. Vì vậy, tôi đã thực hiện vô số nghiên cứu về cách tạo ra tiếng ồn Perlin, làm dịu nó, chơi với các thông số và tất cả những gì jazz. Tôi cũng đã dành nhiều thời gian tại pcg.wikidot.com. Vấn đề tôi có là tạo ra một mức độ được kết nối 100%. Có nghĩa là, nhân vật có thể đi từ phần bên trái của cấp độ cho đến phần bên phải.

Ngay bây giờ, tôi sử dụng nhiễu perlin để tạo ra một sprite khi giá trị nhiễu tại thời điểm đó là <0.

Đây là video về vấn đề tôi gặp phải (xin vui lòng loại trừ các vấn đề bối cảnh điên rồ và thực tế nhân vật của tôi bị kẹt khi tôi tạo một cấp độ mới).

http://screencast.com/t/uWJsIGLoih

Như bạn có thể thấy trong video, địa hình có vẻ đủ thú vị, nhưng bạn không thể làm được gì nhiều vì tiếng ồn Perlin ngăn cách mức độ thành các buồng nhỏ, ngẫu nhiên.

Tôi đã cố gắng thực hiện một bước đi ngẫu nhiên và che phủ tiếng ồn perlin trên nó, vì vậy tôi đảm bảo một con đường từ trái sang phải. Vấn đề với điều đó được minh họa dưới đây: http://screencast.com/t/ilLvxdp3

Vì vậy, câu hỏi của tôi là: Tôi có thể làm những điều gì để đảm bảo người chơi có thể nhận được từ phần bên trái của cấp độ sang phần bên phải của cấp độ?

Câu trả lời:


13

Khi sử dụng tính kết nối từ , bạn sẽ sử dụng công cụ phù hợp nhất để xác định giải pháp: lý thuyết đồ thị.

Kết nối là một thuộc tính của đồ thị. Các biểu đồ có thể được kết nối hoặc ngắt kết nối (như bạn đang gặp phải, AKA là một hình đa sắc). Bất kỳ cấp độ trò chơi nào, ở bất kỳ số lượng kích thước nào, đều có thể được biểu diễn dưới dạng biểu đồ và theo logic, đây thường là cách tốt nhất để thao tác chúng. Thế giới trò chơi của bạn là một biểu đồ về sự phụ thuộc giữa các khối xây dựng riêng lẻ trong thế giới của bạn; và cũng ở mức độ kết nối giữa các lĩnh vực khác nhau của bạn. Bạn có thể sử dụng cái trước để lấy cái sau.

Có một điểm rất quan trọng để xem xét khi làm việc với các mức (2D) dưới dạng biểu đồ, và đó là tính phẳng . Tùy thuộc vào yêu cầu của bạn, tính đồng nhất có thể hoặc không phải là mối quan tâm. Với việc bạn sử dụng tiếng ồn, tôi mong đợi điều sau, tuy nhiên tôi phác thảo các tùy chọn ở đây để bạn biết chúng là gì.

Đồ thị phẳng - ví dụ đơn giản nhất là một mê cung. Một mê cung khác với một mê cung ở chỗ nó không chứa các nhánh - nó là một con kỳ lân . Nếu bạn định lấy một khối cây bụi (!) Vững chắc và tạo ra một mê cung xuyên qua nó, thì không có lúc nào có thể rẽ vào mê cung, chạy vào một con đường hiện có. Nó thực sự giống như một trò chơi của Snake, thực sự - nếu con đường là cơ thể của con rắn, nó không thể được phép cắn / giao nhau. Hơn nữa , bạn có thể có một mê cung phẳng; điều này sẽ phân nhánh, nhưng không có lúc nào các nhánh có thể được phép giao nhau các phần hiện có của mê cung đã được tạo ra, giống như với một mê cung.

Biểu đồ không phẳng - Ví dụ đơn giản nhất là bản đồ đường phố thành phố. Một thành phố về cơ bản là một mê cung. Tuy nhiên, nó là một mê cung được kết nối cao ở chỗ có nhiều tuyến đường riêng lẻ để đi từ nơi này đến nơi khác. Hơn nữa, việc nhúng đồ thị không phẳng cho phép giao cắt, đó chính xác là giao điểm. Và như chúng ta đã biết, một thành phố không phải là một thành phố không có giao lộ. Chúng là không thể thiếu cho lưu lượng giao thông. Trong các trò chơi, điều này có thể tốt hoặc xấu, tùy thuộc vào mục tiêu của bạn. Dòng chảy tốt cho phép AI hành động dễ dàng hơn và khám phá được tự do hơn; mặt khác, nó cũng cho phép người chơi đi từ điểm bắt đầu đến mục tiêu một cách nhanh chóng - có khả năng quá nhanh.

Điều này đưa chúng tôi đến phương pháp của bạn, đó là sử dụng tiếng ồn. Tùy thuộc vào đầu ra nhiễu Perlin được diễn giải, nó có thể có một số mức độ kết nối như thang đo vĩ mô, nhưng nó không được thiết kế cho kết nối 1 (một biểu đồ duy nhất). Điều này để lại cho bạn một vài lựa chọn.

  1. Bỏ việc sử dụng tiếng ồn Perlin và thay vào đó tạo ra một biểu đồ được kết nối ngẫu nhiên, không chéo (không giao nhau). Điều này cung cấp kiểm soát lưu lượng tối đa. Tuy nhiên, cách tiếp cận này không tầm thường, bởi vì tính phẳng của đồ thị đòi hỏi phải xác định và loại bỏ các sơ đồ con Kuratowski K3,3 và K5; cũng như sản xuất một mặt phẳng nhúng tiếp theo; cả hai đều là vấn đề NP-đầy đủ. Đây chắc chắn là cách tiếp cận khó nhất, nhưng nó phải được đề cập trước tiên để biết bạn đang đứng ở đâu. Tất cả các phương pháp khác là một lối tắt của một số loại, xung quanh phương pháp này, đó là toán học cơ bản đằng sau việc tạo mê cung.

  2. Bỏ việc sử dụng tiếng ồn Perlin và thay vào đó tạo ra một đồ thị phi phẳng ngẫu nhiên được nhúng trong bề mặt phẳng (AKA một mặt phẳng nhúng) - đây là cách các trò chơi như Diablo và roguelike có thể hoạt động dễ dàng, vì cả hai đều sử dụng lưới cấu trúc để chia nhỏ một không gian phẳng (trên thực tế, phần lớn các cấp độ trong roguelike DO cho phép giao cắt, hiển nhiên trong số lượng giao lộ bốn chiều). Các thuật toán tạo ra sự kết nối giữa các ô hoặc phòng mẫu thường được gọi là "thợ khắc" hoặc "người điều chỉnh", bởi vì chúng tăng không gian trống ra khỏi một khối đá rắn, tăng dần.

  3. Làm như tùy chọn (2), nhưng tránh giao nhau. Do đó, cả hai nhúng (hình học mức) là phẳng, và cấu trúc liên kết (dòng chảy cấp) cũng là phẳng. Bạn sẽ phải cẩn thận để không tự biến mình vào ngõ cụt, nếu bạn muốn tránh giao cắt.

  4. Tạo bản đồ của bạn bằng cách sử dụng tiếng ồn. Sau đó, bằng cách sử dụng thuật toán lấp đầy trên mọi ô ở cấp độ không được kết nối của bạn (là biểu đồ, mặc dù đa bội và dựa trên lưới), bạn có thể suy ra tất cả các sơ đồ con không liên kết, rời rạc trong đa lớp lớn hơn đó. Tiếp theo, hãy xem xét cách bạn muốn kết nối từng sơ đồ con riêng lẻ. Nếu bạn muốn tránh giao cắt, tôi đề nghị một kết nối tuần tự của những điều này. Nếu không, bạn có thể kết nối chúng theo bất kỳ cách nào bạn muốn. Để thực hiện việc này một cách hữu cơ, thay vì tạo ra các đoạn cứng, thẳng, tôi sẽ sử dụng một số loại hàm kết hợp để trộn các điểm gần nhất của mỗi cặp đồ thị con (nếu liên kết tuần tự). Điều này sẽ làm cho phép nối trở nên "lỏng" hơn, phù hợp với đầu ra Perlin điển hình. Một cách khác mà bạn có thể tham gia các khu vực sẽ là đẩy họ lại gần nhau hơn,

  5. Tạo một bản đồ quá lớn sử dụng tiếng ồn. Cô lập tất cả các sơ đồ con như được mô tả trong tùy chọn 3. Xác định cái nào là thú vị nhất, theo các tiêu chí nhất định (có thể là kích thước, hoặc một cái gì đó khác, nhưng kích thước sẽ dễ nhất). Chọn ra và chỉ sử dụng sơ đồ con đó, nó đã hoàn toàn tự kết nối. Khó khăn với cách tiếp cận này là bạn có thể khó kiểm soát kích thước của đồ thị kết quả của mình, trừ khi bạn vũ phu tạo ra một bản đồ thực sự lớn, hoặc nhiều bản đồ nhỏ hơn, để chọn sơ đồ con hoàn hảo của bạn. Điều này là do kích thước của các sơ đồ con thực sự phụ thuộc vào các tham số Perlin được sử dụng và cách bạn diễn giải kết quả.

Ngoài hai phần cuối, một điều tôi chắc chắn bạn đã làm, nhưng chỉ trong trường hợp không: Tạo trường hợp kiểm tra tiếng ồn Perlin tối thiểu trong Flash. Chơi xung quanh với các tham số cho đến khi bạn có được mức độ kết nối cao hơn giữa các khu vực "đảo" của bạn. Tôi không nghĩ rằng điều này có thể giải quyết vấn đề của bạn 100% qua tất cả các thế hệ, vì tiếng ồn Perlin không có sự đảm bảo vốn có của sự kết nối. Nhưng nó có thể cải thiện kết nối.

Bất cứ điều gì bạn không hiểu, hãy hỏi và tôi sẽ làm rõ.


Đây là một câu trả lời tuyệt vời.
tenpn

1
Sau đó, bạn phải chặt cây mạnh nhất ở khu vực phía trước ... bằng ... một con cá trích!
Jonathan Connell

Hahaha ... vâng.
Kỹ sư

Tôi chưa thực hiện bất kỳ giải pháp nào trong số này, nhưng thông tin được cung cấp khiến tôi suy nghĩ lại một số điều và tôi nghĩ rằng nó đã trả lời câu hỏi của tôi tốt nhất. Vì vậy, tôi đánh dấu nó là câu trả lời. Cảm ơn tất cả.
SpaDusA

5

Cách tiếp cận chung cho vấn đề này:

  1. Xây dựng bản đồ theo cách đảm bảo tính kết nối ngay từ đầu. Nhiều trình tạo dungeon trên PCG wiki hoạt động theo cách này.
  2. Tạo một bản đồ có khả năng bị ngắt kết nối, sau đó viết một cái gì đó (có thể là một đường dẫn) để kiểm tra sự kết nối. Vứt bỏ các bản đồ không hoạt động.
  3. Tạo bản đồ có khả năng bị ngắt kết nối, sau đó sửa nó bất cứ khi nào nó không được kết nối. Bất cứ khi nào các thuật toán kiểm tra của bạn tìm thấy một khu vực không thể xuyên thủng, các đường hầm nổ, xây dựng cầu, thêm dịch chuyển tức thời, v.v.
  4. Tạo bản đồ có khả năng bị ngắt kết nối, sau đó cung cấp cho các công cụ người chơi để kết nối mọi thứ khi cần. Biến lỗi bản đồ bị ngắt kết nối thành một tính năng. Terraria, Minecraft, vv làm điều này.
  5. Tạo bản đồ có khả năng bị ngắt kết nối, sau đó làm cho người chơi khởi động lại hoặc chuyển sang một cấp độ khác nếu không thể hoàn thành cấp độ. Tôi tin rằng một số roguelike làm điều này.

Tôi đồng ý với Kylotan rằng chức năng tiếng ồn có thể không lý tưởng, nhưng chức năng tiếng ồn có thể làm được rất nhiều và bạn có thể sửa nó theo một cách nào đó. Xem bài viết này cho một số ý tưởng.


2

Video đó thật khó hiểu và tôi không thể hiểu được những gì bạn đang cố gắng thể hiện với nó thành thật. Nhưng tôi sẽ đề nghị tiếng ồn Perlin có lẽ là thuật toán sai cho công việc. Nó được thiết kế để thực hiện trơn tru các thực thể liên tục, trong khi bạn đang cố gắng tạo các thực thể phân tán và rời rạc. Những gì có thể hoạt động tốt hơn là sử dụng các giá trị ngẫu nhiên để sắp xếp lại và điều chỉnh các sắp xếp được thiết kế bằng tay của các nền tảng để đảm bảo rằng khu vực kết quả có thể chơi được.

Có một số thông tin về cách Spelunky đã làm điều này tại đây: http://tinysubversions.com/2009/09/spelunkys-procedural-space/


0

Hãy thử sửa đổi giá trị perlin dựa trên chiều cao, tức là ở dưới cùng thêm 1 vào giá trị nhiễu, ở đầu trừ 1 từ giá trị nhiễu và ở giữa nội suy tuyến tính giữa 1 và -1. Bằng cách này, ở phía dưới, bạn gần như sẽ được đảm bảo nhận được giá trị> = 0 và ở đầu bạn sẽ gần như được đảm bảo để có được giá trị <= 0.

Đây là giả sử giá trị <0 được coi là không khí. Nếu tôi hiểu mô tả của bạn chính xác, bạn sẽ phải chuyển nó.

Chúc mừng.


1
Vì vậy, tôi đã thử phương pháp của bạn và tôi đã nhận được kết quả như sau: screencast.com/t/vxnc0LHbLGPQ Tôi không thực sự chắc chắn rằng điều đó đã giúp tôi giải quyết vấn đề. Tôi vẫn phải xử lý hậu kỳ để đảm bảo kết nối.
SpaDusA

0

Một cách tiếp cận đơn giản mà bạn dễ dàng chấp nhận với mã hiện tại của mình là tiếp tục tạo các bản đồ ngẫu nhiên cho đến khi một bản đồ đáp ứng ràng buộc kết nối của bạn.

Bạn có thể nhanh chóng kiểm tra ràng buộc kết nối của mình bằng cách sử dụng vùng lấp từ vị trí bắt đầu. Liệu nó có lấp đầy tất cả các điểm đến một điểm cuối hợp pháp?

Bạn có thể thực hiện hàng ngàn kiểm tra như vậy mỗi giây, vì vậy đây có thể là một vụ hack hoàn toàn chấp nhận được.

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.