Làm thế nào bạn có thể đặt tất cả hình ảnh từ một trò chơi vào 1 tập tin?


67

Tôi vừa hoàn thành một trò chơi RPG cơ bản được viết bằng C ++ SFML, tôi đã nỗ lực rất nhiều cho trò chơi và tôi muốn phân phối nó, tuy nhiên tôi đã gặp phải một vấn đề nhỏ.

Vấn đề là, tôi có hơn 200 tệp hình ảnh và bản đồ (chúng là các tệp .txt chứa mã bản đồ) tất cả trong cùng một thư mục có thể thực thi được, khi tôi nhìn vào thư mục, nó khiến tôi muốn khóc một chút rất nhiều tài nguyên, tôi chưa bao giờ thấy một trò chơi cho bạn thấy tất cả các tài nguyên trực tiếp, thay vào đó tôi tin rằng họ đóng gói các tài nguyên trong một tệp nhất định.

Chà, đó là những gì tôi đang cố gắng đạt được: Tôi hy vọng sẽ đóng gói tất cả các hình ảnh trong 1 tệp (Có thể là các tệp .txt) sau đó có thể đọc từ tệp đó hoặc dễ dàng thêm vào tệp đó.



Tôi đã thấy mã trong đó tất cả các hình ảnh được đóng gói thành một chuỗi trong mã. Nhưng điều đó đã được thực hiện do yêu cầu. (Đó là một cuộc thi Java 64KB)
Omar Kooheji

Xin lỗi đó là một cuộc thi java 4Kb. Không phải là 64Kb.
Omar Kooheji

Câu trả lời:


62

Các lập trình viên trò chơi đã dựa vào một trong hai phương pháp lưu trữ dữ liệu chính:

  • lưu trữ mỗi tệp dữ liệu dưới dạng một tệp riêng biệt
  • lưu trữ mỗi tệp dữ liệu trong một định dạng lưu trữ tùy chỉnh

Hạn chế của giải pháp đầu tiên là vấn đề dung lượng ổ đĩa bị lãng phí, cũng như vấn đề cài đặt chậm hơn.

Giải pháp thứ hai cung cấp những cạm bẫy của riêng nó, đầu tiên là bạn phải viết tất cả hình ảnh / âm thanh / vv của riêng bạn. tải các thói quen sử dụng API tùy chỉnh để truy cập dữ liệu lưu trữ. Một nhược điểm nữa là bạn phải viết tiện ích lưu trữ của riêng mình để xây dựng kho lưu trữ ở nơi đầu tiên.

Trừ khi bạn sẽ luôn tải tất cả các tệp từ kho lưu trữ, TAR / GZ có thể không phải là một ý tưởng hay, bởi vì bạn không thể trích xuất các tệp cụ thể khi bạn cần chúng. Đây là lý do nhiều trò chơi sử dụng kho lưu trữ ZIP, cho phép bạn trích xuất các tệp riêng lẻ theo yêu cầu (một ví dụ điển hình là Quake 3, có tệp PK3 không có gì ngoài các tệp ZIP có phần mở rộng khác nhau).

EDIT: "Ẩn" cấu trúc thư mục trò chơi và "Chỉ giữ" các tệp thực thi

Một giải pháp khác thường được sử dụng để "ẩn" các tệp trò chơi trong cấu trúc thư mục. Chỉ giữ các tệp thực thi của bạn và có thể một tệp readme trong thư mục chính và di chuyển các tệp trò chơi vào một thư mục phụ có tên "dữ liệu" hoặc liên quan khác.

EDIT: Gamedev Tuts Plus có một tài nguyên tốt

EDIT: vô chính phủ

Một giải pháp tiềm năng libarchive, đó là một thư viện lưu trữ sẽ xử lý việc trích xuất các tệp từ một kho lưu trữ, chẳng hạn như tệp ZIP. Nó thậm chí còn cho phép bạn gán tệp được trích xuất cho một con trỏ FILE tiêu chuẩn, điều này sẽ khiến việc giao tiếp với bất kỳ thư viện nào khác có khả năng đơn giản hơn.

EDIT: Tệp định dạng ZIP với phần mở rộng thay thế

Ở đây, tôi thích Bình luận của @Joachimererer

Sử dụng các tệp định dạng ZIP với các tiện ích mở rộng thay thế cũng có một truyền thống tuyệt vời bên ngoài các trò chơi: Java cũng vậy , Định dạng OpenDocument (còn gọi là định dạng OpenOffice / LibreScript) , thậm chí cả Office Open XML (còn gọi là định dạng Microsoft Office "mới") thực hiện nó .


2
Vâng, Thief / SystemShock2 đã sử dụng các tệp .zip đổi tên thành cái khác. Trong Java, bạn có thể sử dụng một cái gì đó như TrueZip để truy cập các tệp trong các khóa như thể chúng là các tệp trong các thư mục, tôi tưởng tượng có các thư viện tương tự cho C ++.
Nick

18
Sử dụng các tệp định dạng ZIP với các tiện ích mở rộng thay thế cũng có một truyền thống tuyệt vời bên ngoài các trò chơi: Java cũng vậy , Định dạng OpenDocument (còn gọi là định dạng OpenOffice / LibreScript) , thậm chí cả Office Open XML (còn gọi là định dạng Microsoft Office "mới") phải không , ...
Joachim Sauer

5
@Sishish. Tùy thuộc vào nền tảng, lượng không gian đĩa được chiếm bởi rất nhiều tệp nhỏ có thể lớn hơn đáng kể so với lượng được chiếm bởi một tệp lớn, ngay cả khi tệp lớn đó không bị nén ( .tarví dụ). Đó là cách thức lưu trữ dữ liệu trên đĩa.
TRiG

1
Ah, đó là sự thật. Không nên nhiều mặc dù, trừ khi có rất nhiều , nhưng trong trường hợp đó nó thực sự có thể tích tụ. Tôi có thể tưởng tượng việc cài đặt và gỡ cài đặt cũng gây ấn tượng với nhiều tệp nhỏ.
Svish

2
Hơi liên quan đến bình luận của Kylotan, đây là một bài đăng của Jonathan Blow trên blog của Nhân chứng về việc sử dụng tài liệu lưu trữ và cách họ tương tác với cơ chế vá của Steam. "Nhân chứng gói hầu hết dữ liệu của nó vào một tệp 2 gigabyte được lưu trữ ở định dạng .zip. Trước khi tải phiên bản ban đầu lên Steam, tôi đã thực hiện một biện pháp bảo vệ để giảm thiểu kích thước bản vá, hoặc vì vậy tôi nghĩ [...] (Hãy tưởng tượng các tệp đó được lưu trữ theo thứ tự ngẫu nhiên: có thể mọi bản vá liên quan đến mọi người chơi tải xuống lại toàn bộ trò chơi!) "
Eric

39

Một giải pháp khác thường được sử dụng để "ẩn" các tệp trò chơi là cấu trúc thư mục. Chỉ giữ các tệp thực thi của bạn và có thể là một readme trong thư mục chính và di chuyển các tệp trò chơi vào một "dữ liệu" thư mục phụ. Tôi không nghĩ rằng nó là rất hiếm khi làm như vậy. Nhiều trò chơi tôi biết lưu trữ nội dung của họ theo cách như vậy.


8
+1 Nếu không gian đĩa hoặc bảo vệ không phải là vấn đề, đó là cách khắc phục dễ dàng nhất.
Laurent Couvidou

1
+1 vì anh chàng kia nói +1. Không thể sai được hả? (Đùa qua một bên, câu trả lời tuyệt vời.)
jcora

Điều này, theo tôi, là sự lựa chọn lý tưởng. Nếu hệ thống tập tin không thể xử lý hiệu quả thì hệ thống tập tin bị hỏng và bạn nên dựa vào nhà sản xuất hệ điều hành để cải thiện nó.
Omnifarious

3
@Omnifarious Điều đó không phải lúc nào cũng đúng, ví dụ như khi đọc từ đĩa quang, ngay cả với một hệ thống tệp hoàn hảo, việc đóng gói các tệp để tải tìm kiếm quá mức (việc tăng tốc độ thực sự có thể khá đáng ngạc nhiên). Nhưng đây là một câu chuyện hoàn toàn khác đối với các đĩa cứng và tôi có xu hướng nghĩ rằng OP nằm trong trường hợp này.
Laurent Couvidou

3
@ Mr.Beast Bạn đã bỏ lỡ quan điểm của tôi. Tôi đang nói về đĩa quang. Tôi đã làm việc cho một studio nơi đó là công việc toàn thời gian của một lập trình viên để đảm bảo các tệp sẽ được đóng gói hiệu quả nhất có thể trên DVD, để có thời gian tải tốt nhất có thể. Tôi chắc rằng anh ấy sẽ rất vui khi biết rằng anh ấy có thể đã dựa vào hệ thống tệp DVD;)
Laurent Couvidou

22

Tôi thực sự thích PhysFS cho điều này. Nó cho phép bạn truy cập vào các thư mục hoặc kho lưu trữ zip với cùng một mã. Nó hoạt động tốt cho tất cả các giai đoạn của một đời trò chơi.

  1. Trong quá trình phát triển : truy cập tài nguyên trực tiếp từ hệ thống phân cấp thư mục. Cách này lưu trữ nén không theo cách và bạn có thể nhanh chóng lặp lại.
  2. Triển khai ban đầu : nén tài nguyên của bạn để dễ dàng triển khai / cài đặt nhanh. Không cần mã để thay đổi. Chỉ cần trỏ PhysFS vào zip thay vì thư mục.
  3. Cập nhật / Modding : PhysFS có thể tải nhiều kho lưu trữ zip trong đó các tài nguyên từ cái này ghi đè lên cái kia. Các bản cập nhật có thể đơn giản như một zip mới chỉ với các tệp đã thay đổi. Tương tự cho modding.

cập nhật:

Tôi đã sử dụng hướng dẫn đi kèm với nguồn và tài liệu doxygen để học PhysFS. API thực sự khá đơn giản, bạn sẽ dành nhiều thời gian hơn để tìm hiểu cách tải hình ảnh vào SFML thông qua bộ đệm thay vì theo đường dẫn tệp.


4
Tôi đang sử dụng PhysFS cho dự án hiện tại của mình và tôi thích nó. Tôi không luôn cần phải tạo lại tệp lưu trữ nội dung của mình; Tôi chỉ có thể thả một phiên bản cập nhật trong đường dẫn tìm kiếm và BAM! Nó hoạt động.
Zack The Human

Sau một số câu trả lời tôi quyết định tôi sẽ đi với PhysFS. Bạn có quan tâm để giới thiệu một hướng dẫn tốt đẹp? :)
Bugster

12

Tôi khuyên bạn nên sử dụng tệp ZIP. Đây là một định dạng phổ biến và bạn sẽ tìm thấy các thư viện được tạo sẵn cho phép bạn tải các tệp từ trong tệp ZIP. Một tìm kiếm nhanh của Google thậm chí còn tiết lộ trình tải zip cho sfml .


3

Chà, bạn có thể gian lận như họ đã đề cập :) Bạn có thể tạo một tấm sprite từ hình ảnh, ngày nay không cần phải nén nó trừ khi nó tiết kiệm được rất nhiều không gian. Sau khi bạn tạo một tấm sprite hoặc một vài tấm sprite từ hình ảnh, bạn có thể chỉ cần đổi tên các tiện ích mở rộng của chúng. Hầu hết các Game thủ sẽ không bận tâm kiểm tra và tại sao không để tùy chọn đó cho các Nghệ sĩ có thể muốn sửa đổi trò chơi của bạn trong tương lai? Bằng cách đó, họ cũng có thể tạo ra một tấm sprite, đổi tên phần mở rộng của nó và bắt đầu cuộn.

Với các tệp văn bản, tôi sẽ khiêm tốn đề nghị bạn chuyển đổi dữ liệu đó thành dạng nhị phân. Tôi khá chắc chắn rằng bạn sẽ tìm thấy một cách đơn giản để làm điều đó .. Ví dụ, nếu bạn chỉ sử dụng AZ, az và 0-9, bạn có thể sử dụng 6 bit để thể hiện mỗi ký tự, điều đó sẽ phần nào bảo vệ tài liệu có bản quyền của bạn, nó cũng sẽ ngăn người khác chỉnh sửa bản đồ .. Bạn luôn có thể thêm trình chuyển đổi bản đồ nếu muốn. Nén là hoàn toàn hợp lý cho văn bản mặc dù.


Chuyển đổi sang nhị phân là lời khuyên tốt nhưng không phải để bảo vệ - nó sẽ dễ dàng phân tích cú pháp hơn và tải nhanh hơn. Sẽ đề nghị nó như một bước xử lý trước, nhưng điều đó sẽ lạc đề đối với câu hỏi.
Maximus Minimus

Chà, tôi đoán, nếu anh ta muốn bảo vệ nó hiệu quả hơn, anh ta có thể thử mã hóa nó trong RSA hoặc một thuật toán tương tự (không cần thiết). Tôi nghi ngờ bất cứ ai cũng sẽ sử dụng trái phép các tệp bản đồ từ một trò chơi độc lập nếu nó nằm trong tệp nhị phân. Có vẻ như không đáng để đầu tư thời gian vào việc phân tích cú pháp của chúng tôi. Các tệp văn bản hoàn toàn dễ bị tổn thương và như bạn đã đề xuất một cái gì đó không hiệu quả để lưu trữ dữ liệu.
sói

3
Trên ổ cứng, tải một tệp zip nhanh hơn rất nhiều tệp nhỏ vì có ít tìm kiếm ngẫu nhiên ít tốn kém hơn vào đĩa vật lý. Một nhị phân cho một trò chơi nhỏ có thể được ánh xạ vào bộ nhớ và hoạt động "kỳ diệu", hầu như không cần phân tích cú pháp.
Liosan

@Liosan Bạn có thể hiểu sai ý tôi hoặc tôi hiểu nhầm bạn .. Tôi đã nói nhị phân là tốt hơn để lưu trữ dữ liệu và các nhà thiết kế trò chơi khác không muốn học cách phân tích mã bản đồ nhị phân của bạn, trừ khi nó được ghi lại và khuyến khích sửa đổi mục đích. Do đó, nó cung cấp một số bảo vệ thô sơ đối với các tệp văn bản.
sói

2

Nó không chỉ là về số lượng tài nguyên hoặc dung lượng đĩa.
Với rất nhiều tệp kết cấu khác nhau, như bạn đang sử dụng SFML, kết xuất với OpenGL, mỗi lần bạn định kết xuất một kết cấu, OpenGL cần liên kết kết cấu tiếp theo với thẻ video (kiểm tra glBindTexture ()) và đó là một nhiệm vụ thực sự tốn kém.
Với ý nghĩ đó, bạn có thể nhận ra lý do tại sao các trò chơi thường đặt một số họa tiết trong cùng một kết cấu, cái gọi là spritesheets, theo menu / cấp độ / bản đồ của trò chơi.
Kết quả là một hiệu suất rất lớn, vì bạn đang kết xuất rất nhiều họa tiết với cùng một lệnh gọi kết cấu liên kết.


Sau khi nhận được một số tài liệu tham khảo để thực hiện một spritesheet, tôi đã xem xét một số tái cấu trúc để giảm số lượng hình ảnh. Cảm ơn
Bugster

2

Cá nhân tôi sẽ đi xuống tuyến đường tệp nhị phân tùy chỉnh cho việc này. Đây là điều mà tôi tự làm mọi lúc, nó không khó như âm thanh và nó cũng cung cấp một mức độ khó hiểu cho các tệp tài nguyên trò chơi của bạn. Tôi đã viết một bài viết giới thiệu nhỏ về Gamedev về điều này cách đây không lâu nếu bạn quan tâm:

http://gamedev.tutsplus.com/tutorials/imcellenceation/create-custom-binary-file-formats-for-your-games-data/

Sprite-sheet hoàn toàn là một chủ đề khác nhau nhưng chúng là tiêu chuẩn cho hầu hết các trò chơi :)


1

Một phương pháp khác bạn có thể sử dụng:

Phiên bản miễn phí của XnView cung cấp một tính năng gọi là " Strip of Images" (SHIFT + A), cho phép bạn tạo sprite-collections.

Điều này giảm thiểu truy cập tệp và đặc biệt quan trọng đối với các ứng dụng / trò chơi web để giảm thiểu số lượng HTTP-roundtrips.

Truy cập vào các hình ảnh riêng lẻ sau đó được cấp thông qua các bản đồ tọa độ (ví dụ: định nghĩa css).


0

Trước tiên, bạn phải viết tất cả hình ảnh / âm thanh / vv của riêng bạn. tải các thói quen sử dụng API tùy chỉnh để truy cập dữ liệu lưu trữ. Một nhược điểm nữa là bạn phải viết tiện ích lưu trữ của riêng mình để xây dựng kho lưu trữ ở nơi đầu tiên. Trừ khi bạn sẽ luôn tải tất cả các tệp từ kho lưu trữ, TAR / GZ có thể không phải là một ý tưởng hay, bởi vì bạn không thể trích xuất các tệp cụ thể khi bạn cần chúng. Đây là lý do nhiều trò chơi sử dụng kho lưu trữ ZIP, cho phép bạn trích xuất các tệp riêng lẻ theo yêu cầu (một ví dụ điển hình là Quake 3, có tệp PK3 không có gì ngoài các tệp ZIP có phần mở rộng khác nhau). http: // zpp-l Library.sourceforge.net/

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.