Làm cách nào tôi có thể lưu trữ tất cả dữ liệu cấp độ của mình trong một tệp thay vì trải ra trên nhiều tệp?


8

Tôi hiện đang tạo dữ liệu cấp độ của mình và lưu vào đĩa để đảm bảo rằng mọi sửa đổi được thực hiện theo cấp độ đều được lưu.

Tôi đang lưu trữ "khối" 2048x2048 pixel vào một tệp. Bất cứ khi nào người chơi di chuyển qua một phần không có tệp được liên kết với vị trí, một tệp mới sẽ được tạo.

Điều này làm việc tuyệt vời, và rất nhanh. Vấn đề của tôi, là khi bạn đang chơi, số lượng tập tin ngày càng lớn hơn.

Tôi đang tự hỏi những kỹ thuật nào có thể được sử dụng để làm giảm số lượng tập tin mà không cần thực hiện một cú đánh hiệu suất. Tôi quan tâm đến cách bạn sẽ lưu trữ / tìm kiếm / cập nhật dữ liệu này trong một tệp thay vì nhiều tệp một cách hiệu quả.


5
Về cơ bản, bạn phải viết một hệ thống tệp thu nhỏ để có thể lưu trữ mọi thứ trong một tệp. Nó sẽ thêm vào sự phức tạp và có thể không đáng.
thedaian

1
Tôi thực sự không có nhiều kinh nghiệm với những điều sau đây, nhưng có lẽ một nosql db dựa trên tệp ( stackoverflow.com/questions/2403174/ trộm ) có thể là một tùy chọn.
Chris

Có bao nhiêu tập tin chúng ta đang nói về ở đây? Là người chơi tạo ra hàng chục ngàn tệp, hoặc chỉ hàng trăm? Người chơi đang thay đổi trong chunk là gì? Chunk có tạo ra một bước đắt tiền không (nghĩa là bạn có cần lưu trữ toàn bộ khối dữ liệu so với chỉ một khác biệt không?)
Lenuity

Minecraft cũng đã trải qua quá trình chuyển đổi này. Tôi tin rằng nó bắt đầu như một mod sau đó được tích hợp vào bản dựng chính. Đáng để xem xét. minecraftwiki.net/wiki/Region_file_format
MichaelHouse

1
@thedaian phức tạp hơn một chút nhưng bạn có thể thực hiện một số nội dung thú vị và thực sự cắt giảm thời gian tìm kiếm nếu bạn sẵn sàng làm thêm một số bộ nhớ để hệ thống tập tin không phải thực hiện trên đĩa.
ClassicThunder

Câu trả lời:


7

Cách nhanh nhất để làm điều này là lưu trữ mọi thứ trong một tệp và nhảy con trỏ đến đoạn bạn muốn đọc. Một khi bạn nhấn vào đĩa đọc một chuỗi từ đó điểm của anh ấy khá nhanh.

Nhiều lần truy cập vào các INodes khác nhau để tìm vị trí của tệp trên ổ đĩa vật lý, những gì nó chiếm phần lớn thời gian và cả những gì có tỷ lệ kém.

Ngoài ra, vì điều này là động, bạn cũng sẽ cần một bản đồ lưu trữ phần bù trong tệp cho mỗi đoạn.

Trên đĩa

[Chunk 1][Chunk 2][Chunk 3][Chunk 4][Chunk 5][Chunk 6][Chunk 7][Chunk 8][Chunk 9]

Có thể nhìn thấy

[7][8][9]
[6][1][2]
[5][4][3]

Sau đó, bạn chỉ cần mở một luồng đọc từ tệp nhưng không khóa các luồng / quy trình khác truy cập vào nó. Sau đó, bạn cần đọc từ phần bù chính xác cho khoảng cách chính xác. Tôi tin vào C # đó là dưới đây.

var chunk = new byte[4194304];
using (var file = new FileStream (openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (var reader = new StreamReader (file, Encoding.Unicode)) {
        reader.Read(chunk, offset * 4194304, 4194304);
    }
}

Bây giờ vì thực tế là bạn đã mở luồng ở chế độ chỉ đọc và cho phép người khác đọc / ghi vào đó, bạn có thể tiếp tục thêm các đoạn mới vào cuối. Chỉ cần theo dõi số bù của chúng và đừng cố đọc chúng trước khi chúng ở đó.

PS bạn sẽ không muốn sử dụng khối sử dụng vì bạn sẽ chỉ muốn 1 luồng đọc trong suốt vòng đời của cấp độ bạn đang sử dụng. Ngoài ra, bạn có thể phải lưu ánh xạ chunk vào một tệp khác khi thoát nhưng đó chỉ là một tải khi bạn tải cấp của mình.


Đây là cho tôi một số ý tưởng tuyệt vời. Phương pháp này có yêu cầu bạn viết mỗi đoạn có cùng số byte không? Tôi sẽ tưởng tượng, như tìm kiếm bù đắp sẽ yêu cầu nó.
jgallant

Miễn là bạn có byte đầu tiên và mỗi đoạn dài bao nhiêu thì chúng không phải có kích thước bằng nhau. Bạn chỉ cần có một cái gì đó trong bộ nhớ theo dõi hai phần dữ liệu này.
ClassicThunder

1
Tất nhiên, nếu bạn không có chúng có kích thước byte bằng nhau, bạn sẽ phải thay đổi rất nhiều nếu tăng kích thước.
MichaelHouse

1

Tùy thuộc vào thời gian cần thiết để tạo ra một đoạn, bạn chỉ có thể lưu trữ khác biệt hoặc trạng thái hiện tại (vị trí của kẻ thù, v.v.). Khi người chơi di chuyển trở lại vào một đoạn, nó sẽ tạo lại bằng cách sử dụng một hạt giống được lưu trữ, sau đó tải bất kỳ thay đổi nào được thực hiện từ tệp.

Nếu người chơi được phép thực hiện các thay đổi đáng kể, điều này có thể chậm và tệp diff sẽ vẫn khá lớn, nhưng chỉ với những thay đổi nhỏ, nên là một hoạt động không tốn kém. Nhiều khối khác nhau cũng có thể được hợp nhất thành một tệp duy nhất - một cái gì đó có kích thước hợp lý có thể được tải vào bộ nhớ.

Có lẽ bạn sẽ không muốn chuyển tất cả các khác biệt thành một tệp duy nhất - điều này sẽ mở ra một số vấn đề khác với bộ nhớ hoặc thay đổi giữa tệp.


1

Tôi biết đây là một chủ đề khá cũ - nhưng tôi chỉ muốn nói rằng tôi nghĩ rằng một kho lưu trữ ZIP có thể là cách tốt nhất để đến đây. Bạn được nén với dữ liệu của mình (đặc biệt là nếu bạn đang sử dụng bitmap thô, đặc biệt), khả năng đọc trong hệ điều hành và bạn có được tệp duy nhất như bạn muốn.


0

Điều gì về quét dir để kiểm tra dấu thời gian của các tệp trong thư mục dữ liệu cấp so với tệp đang hoạt động hiện tại và ban cho ân sủng của tệp trước đó và tệp sẽ chuyển tiếp sau mỗi 10 giây hoặc lâu hơn, và bất cứ điều gì không được sử dụng chỉ cần xóa chúng.

Trừ khi bạn yêu cầu người chơi quay trở lại. Sau đó, chỉ cần dọn sạch dữ liệu cấp độ khi hoàn thành cấp độ hoặc điểm kiểm tra? Có thể lớn lên chắc chắn, nhưng tôi không nghĩ có nhiều lựa chọn có sẵn ở đây


0

Làm thế nào về nhiều khối trên mỗi tập tin? Bạn nói khối của bạn là 2048 x 2048, làm thế nào về việc đưa 16384 x 16384 vào một tệp. Đánh dấu cái nào tồn tại bằng cách nào đó để bạn biết liệu bạn có cần tạo nó không.


0

Nếu bạn có thể tạo ra các khối đủ nhanh khi người chơi khám phá bằng mọi cách, thì bạn không cần phải lưu trữ chúng trên đĩa; tất cả những gì bạn cần làm là lưu trữ hạt giống cho các hàm nhiễu perlin bạn đang sử dụng để tạo lại nội dung thủ tục theo yêu cầu.

Chúng có thể được lưu trữ trong một tệp duy nhất và có thể được ghi tuần tự và sắp xếp trong RAM khi được tải; không cần một cấu trúc được sắp xếp phức tạp trong chính tệp trên đĩa. Bạn chỉ có thể đọc từ nó khi khởi động và viết cho nó khi bạn tạo 'trang' mới (khi chúng được gọi là) trong thế giới trò chơi.

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.