Các thuật toán tốt để tạo đường viền / khu vực trạng thái trên bản đồ sao 2d là gì?


9

Tôi đang cố gắng tạo một bản đồ sao hai chiều khá lớn hiển thị các phe / bang khác nhau, mỗi phe sở hữu một hoặc nhiều hệ thống sao. Tôi muốn tự động tạo đường viền / khu vực cho các phe phái.

Ý tưởng là về cơ bản đi từ một cái gì đó như thế này (các chấm đại diện cho các hệ sao trên mặt phẳng 2d, màu sắc là các liên kết phe)

Hệ thống sao và liên kết phe phái của họ

đến đây

Hệ thống sao với các khu vực phe phái

Tạo các bản đồ như thế này có vẻ như là một yêu cầu khá phổ biến, vì vậy câu hỏi thực tế của tôi là: Có thuật toán tiêu chuẩn để tạo các khu vực trạng thái như được hiển thị không? Nếu vậy, bạn có thể chỉ cho họ? Nếu không, bạn có thể nghĩ ra một thuật toán tốt (ý tưởng cơ bản hoặc mã giả đều ổn)?

Hiệu suất của thuật toán không phải là mối quan tâm chính đối với tôi, vì vậy tôi muốn có một bản đồ "đẹp hơn" so với bản đồ tạo nhanh hơn. Câu hỏi tương tự này đưa ra một cách tiếp cận có thể áp dụng cho vấn đề của tôi, mặc dù với một số "sự hoàn thiện" cần thiết: Cách tạo bản đồ từ biểu đồ

Hãy để tôi giải thích ý của tôi khi tôi nói xinh hơn: Ở cuối câu hỏi được liên kết, người hỏi trình bày kết quả cuối cùng của cô ấy sau khi thực hiện câu trả lời được chấp nhận. Vấn đề đầu tiên của tôi ở đây: Các khu vực cho các nút # 6, # 9 và # 12 rất nhỏ và có hình dạng kỳ lạ. Ngoài ra, thay vì các cạnh sắc nét, tôi sẽ thích một cái nhìn mượt mà hơn, cong hơn.

Ý tưởng của riêng tôi cho đến nay, bao gồm cả những hạn chế / câu hỏi tương ứng mà tôi thấy với chúng:

  • Tạo một đa giác "lồi thân" cho mỗi phe, sau đó mở rộng ra bên ngoài một chút. Vấn đề: Không có tính năng lõm. Ngoài ra, làm thế nào để bạn đối phó với chồng chéo?
  • Tạo biểu đồ voronoi cho các dấu chấm, sau đó sử dụng các cạnh đa giác voronoi giữa các hệ thống lân cận của các phe phái khác nhau làm đường viền. Vấn đề: Đa giác lớn ở các cạnh bản đồ - làm cách nào để xác định và sửa chúng?
  • Tạo một đa giác có kích thước cố định cho mỗi dấu chấm, liên kết tất cả các đa giác cho một phe duy nhất (dẫn đến một "đa giác phe" lớn, có khả năng phức tạp). Sau đó làm một cái gì đó để hòa giải các khu vực chồng chéo giữa hai phe. Vấn đề: Làm thế nào tôi có thể làm điều này chính xác? Không chính xác là một quá trình tầm thường. Điều gì xảy ra nếu có sự chồng chéo giữa hơn hai phe?

Sự giúp đỡ của bạn được đánh giá cao.


Phụ lục: Sau khi suy nghĩ về hai câu trả lời đầu tiên và cách tiếp cận tương ứng của chúng để giải quyết vấn đề, tôi nhận ra rằng các yêu cầu của tôi ở trên là không đầy đủ.

Tôi phải nói thêm rằng bản đồ có thể có các khu vực dân cư thưa thớt, nghĩa là có thể có một ngôi sao hoặc cụm sao bị cô lập. Tôi muốn hiển thị từng cụm trong đó với vùng màu tiếp giáp của riêng chúng. Một cái gì đó như thế này:

Hệ thống sao với các khu vực phe phái, các cụm khác nhau

Tôi nhận ra rằng điều này có thể cần một bước đầu tiên xác định các cụm và sau đó chạy thuật toán thực tế cho từng cụm.


(động não) Bạn có thể lấp đầy phần còn lại của không gian bằng tiếng ồn màu xanh (ví dụ: đĩa poisson) và sau đó chạy voronoi để được gán màu. Các điểm được thêm sẽ được chỉ định vùng nền trắng.
amitp

@amitp Này Amit, thật vinh dự khi bạn bình luận ở đây! Tôi đã lấy rất nhiều cảm hứng và kiến ​​thức thực tế từ việc đọc các bài viết của Red Blob Games. Thêm về chủ đề: Ý tưởng tạo ra các dấu chấm bổ sung có ý nghĩa, lý do cụ thể nào khiến bạn đề cập đến tiếng ồn màu xanh đặc biệt?
Grüse

... Tôi đoán bởi vì nó trông giống như một sự phân phối tự nhiên hơn so với các hương vị tiếng ồn khác.
Grüse

Câu trả lời:


16

Tôi nghĩ ý tưởng Voronoi là một ý tưởng hay. Mỗi ngôi sao trở thành điểm hạt giống cho Voronoi, và sau đó các vùng Voronoi hiển thị các khu vực thuộc sở hữu của mỗi phe. Tuy nhiên, có một số thay đổi sẽ giúp nó hoạt động tốt hơn:

  1. Như bạn đã đề cập, có những khu vực trống không nên được chỉ định cho một phe. Voronoi sẽ tạo ra các đa giác lớn mở rộng ra các khu vực mà phe không nên tiếp cận. Để khắc phục điều này, hãy sử dụng thuật toán nhiễu xanh như đĩa poisson để lấp đầy khoảng trống không có người ở với các ngôi sao "không thuộc sở hữu của ai". Nhiễu xanh là ngẫu nhiên nhưng phân bố đều (nó cũng có thể hữu ích để tạo các vị trí sao của bạn).
  2. Voronoi sản xuất các khu vực khối. Để tạo ra các ô tròn hơn, thay thế phép tính chu vi của Voronoi bằng phép tính centroid. Tôi đã viết một chút về điều này ở đây với một số hình ảnh so sánh.
  3. Voronoi sản xuất đa giác, nhưng bạn muốn các khu vực tròn. Ở mỗi góc, có ba đa giác. Khi cả ba cùng một phe, bạn có thể để nó một mình. Khi hai là cùng một phe, giới thiệu một đường cong bậc hai sẽ chuyển ranh giới về phía phe kia. Khi cả ba phe khác nhau, bạn có thể rời khỏi góc một mình, hoặc bạn có thể giới thiệu ba đường cong bezier để di chuyển tất cả các ranh giới ra khỏi nhau. Tôi không chắc cái nào trông đẹp hơn.

Đây là đầu ra:

Bản đồ Blobby

Tôi cũng đã viết một trang cho phép bạn vẽ các vùng để xem chúng trông như thế nào.


Điều này phù hợp với trường hợp sử dụng của tôi một cách hoàn hảo, cảm ơn bạn rất nhiều! Tôi phải nói rằng nó ấn tượng và đáng buồn không kém khi bạn có thể đưa ra một ví dụ tương tác nhanh như vậy, trong khi có thể tôi sẽ mất ít nhất vài ngày để tái tạo những gì bạn đã trình bày ở đây :) Mong bài viết hướng dẫn đó.
Grüse

4

Một trong nhiều phương pháp là bản đồ ảnh hưởng . Bạn có thể tìm kiếm các triển khai mã cụ thể, nhưng thuật toán cơ bản khá đơn giản.

Đối với mỗi đối tượng phe (ví dụ hệ thống sao), gán giá trị dương (nóng). Đối với tất cả các đối tượng của các phe phái khác, gán giá trị âm (lạnh). Độ lớn của nóng hoặc lạnh nên dựa trên mức độ ảnh hưởng mà bạn nghĩ đối tượng tác động lên môi trường xung quanh và hàng xóm. Các giá trị này không phải tỷ lệ thuận nếu cuối cùng bạn muốn giữ một "dmz" giữa các phe phái.

Sử dụng các chi tiết này để tạo lưới tạm thời (ví dụ mảng) gần bằng pixel của bản đồ. Bạn có thể xây dựng một lưới như vậy theo độ phân giải mà bạn mong muốn bao gồm 1: 1.

Tiếp theo, sử dụng phương trình truyền nhiệt / trường để lặp lại và truyền sức mạnh (sức nóng) của các đối tượng phe chống lại sức mạnh của đối tượng (lạnh) cho từng ô lân cận trong lưới.

Rửa sạch và lặp lại cho mỗi phe trên bản đồ của bạn bằng cách tạo các lưới phe riêng biệt cho mỗi phe.

Cuối cùng, nội suy các lưới phe phái với nhau để tạo ra một đường viền ảnh hưởng cho mỗi phe. Sau đó chuyển lưới đó trở lại bản đồ pixel của bạn với độ phân giải mà bạn đã sử dụng cho lưới (thêm bất kỳ màu cụ thể nào của phe, v.v.).

Nghệ thuật trong quy trình này là xác định mức độ ảnh hưởng của từng đối tượng và yếu tố trò chơi bạn sử dụng để định lượng giá trị đó.

Bên cạnh đó, các sản phẩm của phương pháp này có thể được sử dụng cho tất cả các loại khác, như quyết định ai của bạn.


Tham khảo thêm: chủ đề thảo luận về nguồn gốc của ánh xạ ảnh hưởng .


Cách tiếp cận này nên rõ ràng, nhưng nó không bao giờ xảy ra với tôi. Cám ơn bạn đã khiến tôi chú ý tới việc này! Một suy nghĩ: Bản đồ của tôi có thể thưa thớt ở một số khu vực nhất định, trong khi các khu vực khác có mật độ dày đặc với các ngôi sao thuộc các liên kết khác nhau ngay cạnh nhau. Có cách nào để sử dụng các kích thước ô lưới khác nhau cho các khu vực khác nhau không? Suy nghĩ theo dòng của một phần tư hoặc tương tự.
Grüse

2

Bạn nên nhìn vào sơ đồ Voronoi. Đây là định nghĩa trên wikipedia:

Trong toán học, sơ đồ Voronoi là phân vùng mặt phẳng thành các vùng dựa trên khoảng cách đến các điểm trong một tập hợp con cụ thể của mặt phẳng.

Các điểm cơ bản thường được tạo ngẫu nhiên và thường được gọi là các nút. Trong trường hợp của bạn, mỗi nút có thể là ngôi sao của bạn. Theo cách đó, phe liên kết với các ngôi sao có thể được liên kết với tế bào voronoi xung quanh ngôi sao và khi mọi ô được tính toán, bạn kết hợp những người có cùng phe với nhau và bạn sẽ có một đường viền khá gọn gàng xung quanh các ngôi sao của mình.

Thư viện FastNiri có hỗ trợ cho Biểu đồ Voronoi, vì vậy có lẽ bạn nên xem nó.

Làm mịn các vùng

Giữ các ngôi sao của bạn trong một «mảng an toàn» và sử dụng một bản sao của nó trong đó bạn thực sự thêm nhiều điểm hơn thông qua phép nội suy của các lân cận gần nhất và tạo sơ đồ từ các điểm đó. Nó sẽ cung cấp cho bạn các khu vực mượt mà hơn.

Những ý tưởng khác Thuật toán vận may dựa trên một đường thẳng quét mặt phẳng cartesian. Một ý tưởng thú vị sẽ là sử dụng một vòng tròn để quét máy bay từ trung tâm thiên hà / không gian của bạn, có thể điều đó cũng có thể dẫn đến một số hình dạng thú vị.

Thao tác hình học

Ý tưởng cuối cùng của bạn về việc kết hợp các đa giác nhỏ hơn thành các đa giác lớn hơn và sau đó sửa các cạnh sẽ yêu cầu các thuật toán spline tiên tiến để sửa đổi các hình dạng. Không chắc chắn nếu điều đó sẽ làm cho nó hiệu quả hoặc tìm kiếm tốt. Tôi khá chắc chắn rằng sơ đồ voronoi có thêm phần mở rộng là cách để nó tự khắc phục vấn đề cạnh và thậm chí có thể tự cung cấp một số dữ liệu bổ sung như khoảng cách từ các đường viền (có thể được sử dụng để xác định các vùng của xung đột giữa các phe phái khác nhau, xác suất gặp phải các loại tàu khác nhau, v.v.)


Lưu ý rằng OP đã đề cập đến câu trả lời bằng sơ đồ Voronoi, vì vậy họ biết về kỹ thuật này, nhưng đã yêu cầu sửa đổi cụ thể để thay đổi diện mạo của đường viền. Bạn có thể mở rộng câu trả lời của bạn để giải quyết những yêu cầu cụ thể đó không?
DMGregory

Xin lỗi, đọc sai bài đăng
BadgerBadger

Cảm ơn bạn đã sửa đổi câu trả lời của bạn! Ý tưởng làm mịn là thú vị. Tôi có hai vấn đề với cách tiếp cận Voronoi: Một: Làm cách nào để phát hiện và giới hạn các điểm "bên ngoài" để các đường viền không kéo dài hết các cạnh của màn hình (xem hình ảnh thứ hai của câu hỏi của tôi). Hai: Ở những khu vực dân cư thưa thớt, Voronoi không cho kết quả tuyệt vời vì đa giác trở nên khổng lồ. Có lẽ có một giải pháp rõ ràng cho những người mà tôi không nhìn thấy?
Grüse

Đó sẽ là một tùy chọn để thêm điểm của riêng bạn để đóng khung khu vực? Sau đó, khi bạn hiển thị biểu đồ, nếu một đường thẳng đến cạnh thực tế của hình ảnh, bạn chỉ cần không vẽ nó vì nó không phải là một phần của khu vực trò chơi. Vấn đề thứ hai nên được khắc phục với việc làm mịn. Bạn có thể thêm nhiều điểm hơn khi chúng tiếp tục xuất hiện để bạn giữ một số loại «kích thước lưới» nhất quán.
BadgerBadger

@BadgerBadger yep, tôi đang thử nghiệm thêm điểm ngay bây giờ
Grüse
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.