lưu trữ thế giới roguelike tạo thủ tục vào khu vực


7

Tôi hiện đang phát triển một trò chơi roguelike 3D sẽ diễn ra trong một thế giới rất rộng lớn. Thế giới được tạo ra bởi thuật toán thủ tục được cung cấp bởi tập lệnh bên ngoài trong thời gian chạy. Để tăng tốc độ kết xuất và tối thiểu hóa các yêu cầu về bộ nhớ, tôi đang chia thế giới thành các khu vực. Một vùng là một hình chữ nhật 2D có kích thước tối đa 1024 x 1024 (không cần phải là một hình vuông), chứa newmảng được phân bổ động (thông qua một ) của Tile's. Tileđược định nghĩa là càng nhỏ càng tốt, để tối thiểu hóa việc sử dụng bộ nhớ. Chỉ các vùng hiển thị trên màn hình hoặc trong vùng lân cận ngay lập tức nằm trong bộ nhớ, phần còn lại được tải từ tệp đĩa cứng theo nhu cầu.

Vấn đề tôi gặp phải là trình tạo bản đồ không cần biết về bố cục vùng logic, do đó, nó có thể tạo ra loại bản đồ này (đặc biệt đối với các cấp Z cao hơn, như lofts trong thành phố): Bản đồ được tạo qua máy phát điện

Đây sẽ là quá nhiều lãng phí bộ nhớ để gửi nó trong 1024 x 1024, vì vậy, tốt hơn là đặt nó vào các phần nhỏ hơn như thế này:

Khu cuối cùng

Vì vậy, cuối cùng câu hỏi: làm thế nào tôi có thể chuyển đổi dữ liệu được cung cấp bởi tập lệnh trình tạo thế giới thành cấu trúc thế giới thực trong bộ nhớ?

Những gì tôi đã nghĩ về cho đến nay:

  1. Script có một phương thức SetTile(x, y, tileType)và thế giới sẽ tự động tính toán lại sau mỗi giả sử 100 ô, vì vậy các vùng được đặt hiệu quả nhất có thể. Điều này sẽ yêu cầu RẤT NHIỀU sao chép vùng, di chuyển, thay đổi kích thước, v.v. - đó là một hoạt động rất chậm, nhưng nó sẽ giữ bố cục thế giới theo thứ tự hợp lý, vì vậy, ví dụ sẽ dễ thực hiện các phương thức như GetTile(x, y)trong tập lệnh
  2. Script có một phương thức SetTile(x, y, tileType)tạm thời chỉ lưu trữ một Ngói vào std :: vector và sau khi mọi thứ hoàn thành, thế giới sẽ chạy một lượt thứ hai tính toán các vùng. Cách này nhanh hơn, nhưng có một nhược điểm - vì Ngói được đặt không theo thứ tự cụ thể, nên thực sự khó có GetTile(x, y)phương pháp trong tập lệnh. Có lẽ có một giải pháp cho nhược điểm đó, tôi chỉ không có bất kỳ ý tưởng nào - std::maplà quá chậm để được sử dụng ở đây.
  3. Nếu không thể thực hiện tắt màn hình, có thể giải pháp sẽ là hiển thị các vùng thành tập lệnh và được tạo rõ ràng (ý tôi là đưa vào CreateZone()chức năng API tập lệnh và tương tự) - Tôi không muốn điều này, vì tập lệnh sẽ được hiển thị cho người dùng cuối và Tôi muốn làm cho họ mạnh mẽ nhất có thể.
  4. Có lẽ có giải pháp nào khác? Có lẽ tôi có thể tổ chức thế hệ theo một cách khác (tôi vẫn cần các tập lệnh, nhưng nó có thể là một tập lệnh chỉ tạo ra một phần của thế giới và sau đó kết nối)?

Những điều bổ sung tôi vừa nghĩ ra: toàn bộ thế giới có thể quá lớn để có thể đưa vào bộ nhớ cùng một lúc. Vì vậy, nó xoay vấn đề hơn nữa - tôi phải chia phần thế hệ (theo kịch bản) thành các giai đoạn. Bất kỳ đề xuất?

Về công nghệ: Tôi đang sử dụng C ++ 03 'mà không có Boost và AngelScript làm ngôn ngữ kịch bản


3D như trong 3D được xem hoặc 3D như Pháo đài lùn?
DampeS8N

@ DampeS8N 3D như trong Pháo đài Lùn
PiotrK

Câu trả lời:


4

Cách mà Pháo đài Lùn và nhiều roguelike tương tự khác xử lý các bản đồ thế giới khổng lồ là phá vỡ bản đồ thành nhiều phần. Thông thường, đây là những lát cắt dọc của bản đồ thế giới, dễ dàng phát trực tiếp khi đang bay. Đó là cách Minecraft và Pháo đài lùn trong Chế độ Phiêu lưu hoạt động.

Trong Chế độ Pháo đài, Pháo đài Lùn cho phép bạn chọn một khối các khối để chơi. Nhiều khối hơn có nghĩa là chơi chậm hơn.

Điều này thường giải quyết các vấn đề về hiệu suất tổng thể và sự cố khi tải toàn bộ bản đồ cùng một lúc, ngay cả đối với các bản đồ nhỏ hơn. Tôi sẽ giữ các giải pháp phức tạp cho đến khi bạn thực sự có vấn đề. Tuy nhiên, đây là một số tùy chọn. Có vẻ như từ các ví dụ của bạn rằng bạn sẽ tham gia một trò chơi đô thị. Nếu điều đó có nghĩa là các tòa nhà chọc trời cao tới hàng trăm tầng trở lên, điều đó chắc chắn có thể bắt đầu gây ra các vấn đề về hiệu suất, đặc biệt là nếu các tầng đó trải rộng trên nhiều cấp Z với không gian bảo trì giữa các tầng như nhiều tòa nhà cao tầng có.

Trong trường hợp này, không có lý do nào để không phá vỡ bản đồ thành các phần theo chiều ngang. Bạn có thể loại bỏ những cái hoàn toàn trống rỗng khỏi bản đồ. Hoặc nếu trò chơi của bạn cho phép xây dựng, chỉ cần để trống (hoặc chứa đầy không khí, hoặc bất cứ điều gì trò chơi của bạn cần.)

Digression: Trên thực tế, một roguelike đặt trong các tòa nhà cao lớn, mô hình áp suất không khí có thể thực sự tuyệt vời ...


Chạch ngang! Tôi đã không nghĩ về họ và họ dường như làm việc rất tốt trong trường hợp của tôi. Cảm ơn!
PiotrK

3

Nếu tôi hiểu chính xác câu hỏi của bạn, mối quan tâm chính của bạn là lưu trữ / truy cập vào các ô được tạo. Tin tốt: bạn không phải dành chỗ trống cho tất cả các ô chưa được tạo. Có nhiều cách lưu trữ cấu trúc dữ liệu 'có hình dạng bất thường'.

Ví dụ: một giải pháp khả thi là xây dựng danh sách các con trỏ tới các ô bạn đã tạo.

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

Danh sách (hộp màu xám) có kích thước động, bắt đầu từ 0 và tăng dần theo từng con trỏ (vòng tròn màu đỏ) mà bạn đặt trong đó. Vì vậy, nếu bạn chỉ tạo 3 gạch cho đến nay, bạn sẽ có một danh sách 3 con trỏ. Bằng cách này, bạn sẽ không phải đặt trước bộ nhớ cho hàng triệu ô xếp trước.

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

Khi tìm kiếm một ô cụ thể, bạn lặp lại trên danh sách con trỏ và kiểm tra các thuộc tính của ô mà con trỏ hiện tại đang trỏ tới. Trong C #, với một đại diện Danh sách chẳng hạn, một tìm kiếm sẽ như thế này:

Tile GetTile(int x, int y)
{
   foreach (var tile in tileList)
   {
      if (tile.X == x && tile.Y == y) return tile;
   }
   return null;
}

Không nên có một kịch bản, trong đó tất cả các ô được tạo và tải vào bộ nhớ cùng một lúc. Khi người chơi di chuyển, chỉ cần xóa các con trỏ mà bạn không còn cần trong danh sách (và các ô tương ứng của chúng khỏi bộ nhớ). Hãy chắc chắn rằng bạn có một độ trễ nhỏ, nếu không, các thao tác bộ nhớ có thể gây ra độ trễ khi người chơi di chuyển nhanh vào và ra khỏi một khu vực hoặ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.