trò chơi tiết kiệm / tải?


12

phương pháp hoặc thuật toán được sử dụng nhiều nhất để lưu trạng thái trò chơi (hồ sơ), cơ sở dữ liệu tệp văn bản như thế nào để mã hóa đi và những thứ liên quan.

Tôi đã thấy Caesar IV sử dụng myQuery.

bất kỳ đề xuất.

Câu trả lời:


20

Tôi khá chắc chắn rằng nó thường được thực hiện ở định dạng độc quyền (nhị phân), chỉ cần viết từng biến từ bất kỳ trạng thái trò chơi nào mà bạn sử dụng vào một tệp hoặc đọc tệp đó trở lại thành một thể hiện của cấu trúc. Ví dụ, trong C ++, bạn có thể coi một đối tượng như một mảng byte và chỉ fwrite () nó vào một tệp, hoặc fread () từ tệp và chuyển nó trở lại dạng đối tượng của nó.

Nếu bạn đang sử dụng Java hoặc ngôn ngữ khác, bạn có thể chọn sử dụng tuần tự hóa để thực hiện công việc thực sự dễ dàng. Giải thích Java nằm ở cuối câu trả lời này; các ngôn ngữ khác (cấp độ cao hơn C ++) chắc chắn cũng có thư viện tuần tự hóa hoặc các hàm tích hợp riêng, bạn nên chọn sử dụng. Cho dù thói quen tuần tự hóa có hiệu quả đến đâu, không gian ổ cứng hiện nay rất rẻ, đặc biệt là khi trạng thái trò chơi không nên quá lớn và điều đó ngăn bạn viết và duy trì thói quen tuần tự hóa của riêng bạn.

Bạn tuyệt đối không nên sử dụng MySQL (chỉ cần đọc câu đầu tiên của đánh giá này ). Nếu bạn thực sự cần một cơ sở dữ liệu quan hệ vì một số lý do, hãy sử dụng SQLite ; nó là một hệ thống cơ sở dữ liệu nhẹ và tồn tại trong một tệp cơ sở dữ liệu. Nhưng đối với hầu hết các trò chơi, cơ sở dữ liệu quan hệ không phải là hướng đi và các công ty cố gắng sử dụng chúng thường kết thúc việc sử dụng chúng như một bảng tra cứu giá trị khóa thay vì cơ sở dữ liệu quan hệ thực sự.

Bất kỳ loại mã hóa nào của các tệp đĩa cục bộ chỉ là ẩn giấu ; bất kỳ hacker nào cũng sẽ đánh hơi dữ liệu ngay sau khi chương trình của bạn giải mã nó. Cá nhân tôi chống lại điều đó, ĐẶC BIỆT với các trò chơi một người chơi. Quan điểm của tôi là chủ sở hữu của trò chơi (trả tiền cho khách hàng, nhớ bạn) nên được phép hack tại trò chơi nếu họ muốn. Trong một số trường hợp, nó có thể tạo ra ý thức cộng đồng lớn hơn và "mod" có thể được phát triển cho trò chơi của bạn nhằm thu hút nhiều khách hàng đến với bạn. Ví dụ gần đây nhất xuất hiện trong tâm trí là mod Portal trong Minecraft được phát hành gần đây. Nó được xuất bản trên các trang tin tức của game thủ trên internet và bạn có thể đặt cược rằng nó đã thúc đẩy doanh số của Minecraft.


Nếu vì một lý do nào đó, bạn thực sự đủ điên rồ để sử dụng Java để phát triển trò chơi như tôi, thì đây là một lời giải thích nhanh về tuần tự hóa trong Java:

Giữ tất cả dữ liệu trạng thái trò chơi của bạn trong một lớp, tạo lớp tuần tự hóa bằng cách triển khai Serializable, sử dụng transienttừ khóa nếu bạn trộn các biến khởi tạo đặc biệt vào lớp (các đối tượng tạm thời không được tuần tự hóa) và chỉ cần sử dụng ObjectOutputStreamđể ghi vào tệp và ObjectInputStreamđọc từ tệp . Đó là nó.


2
Hehe, The Witcher không mã hóa dữ liệu của họ. Rất dễ dàng để mở tệp lưu trò chơi trong trình chỉnh sửa hex, lộn xộn một chút và nhận tất cả các thẻ gà trần ... trời ơi, tôi rất xin lỗi!
Anthony

Tôi đã sử dụng tuần tự hóa nhị phân .NET để lưu trò chơi và C # có lẽ là một nền tảng hợp lý hơn một chút so với Java để phát triển trò chơi. Tôi thích cách nó tự động lưu toàn bộ biểu đồ đối tượng tự động. Điều này đã từng rất khó khăn hơn nhiều. Tất nhiên bây giờ có thách thức loại trừ các phần không cần thiết như kết cấu, nhưng đó không phải là vấn đề lớn để thực hiện.
BlueMonkMN

Tôi không đồng ý rằng C # phổ biến hơn một chút so với Java để phát triển trò chơi. Hợp lý hơn hàm ý một số tính chủ quan và là nhà phát triển của cả XNA và Java, tôi thích Java hơn. Vui lòng liệt kê các hướng dẫn về tuần tự hóa trong C # nếu bạn muốn, tôi chưa bao giờ thực hiện nhưng tôi có thể chỉnh sửa nó thành câu trả lời của mình. Tuần tự hóa của Java sẽ lưu toàn bộ biểu đồ đối tượng và từ khóa 'thoáng qua' trên các biến loại trừ các phần không cần thiết như kết cấu; bất kỳ thành viên không nhất thời nào cũng phải được tuần tự hóa hoặc bạn có thể viết phương thức writeObject tùy chỉnh để khắc phục điều đó.
Ricket

Pickle của Python cũng sẽ lưu toàn bộ biểu đồ đối tượng cho bạn và rất dễ sử dụng. Khi nói đến thời gian để deserialize bạn đang trao đối tượng lại hoàn toàn ngậm nước, dễ dàng như chiếc bánh: docs.python.org/library/pickle.html
drhayes

Khi sử dụng trình định dạng nhị phân tích hợp, loại trừ các trường nhất định khỏi tuần tự hóa trong C # /. NET cũng đơn giản như việc tô điểm chúng bằng thuộc tính [NonSerialized]. Tuy nhiên, điều dễ bỏ qua là các sự kiện do trình biên dịch tạo ra (tức là bất kỳ sự kiện nào không có toán tử thêm / xóa tùy chỉnh) tạo ra một trường sao lưu để lưu trữ các thuê bao của họ. Do đó, thật dễ dàng để vô tình (và vô tình) bao gồm các trình xử lý sự kiện trong biểu đồ đối tượng được tuần tự hóa. Để giải quyết vấn đề này, bạn cần thêm thuộc tính NonSerialized vào khai báo sự kiện, nhưng bạn cần thêm vòng loại "trường:":[field: NonSerialized]
Mike Strobel

3

Nếu bạn đang viết mã của riêng mình, hãy nói trong C ++, bạn có thể sử dụng các tệp nhị phân. Các tệp nhị phân cung cấp cho bạn một hình thức mã hóa thông qua obfuscation. Nhưng như tài liệu trên tất cả các quốc tế, đó là một hình thức bảo mật rất yếu.

HOẶC, bạn có thể sử dụng một cái gì đó như RapidXML nếu bạn muốn một giải pháp dễ đọc cho con người.

Nếu bạn đang sử dụng một số loại khung, hãy xem xét các chức năng hỗ trợ tệp của nó. HTH


0

Hầu hết các trò chơi tôi từng thấy chỉ sử dụng mã viết tay để đọc / ghi từ các tệp nhị phân. Thông thường, định dạng trên đĩa sẽ là một bản sao chính xác của bố cục bộ nhớ của một đối tượng để tải chỉ là:

  1. Đọc tập tin vào bộ nhớ.
  2. Đúc con trỏ để đệm vào loại đối tượng.

Nó nhanh, nhưng đó là một việc vặt để duy trì, đặc thù nền tảng và không linh hoạt.

Gần đây, tôi đã thấy một vài trò chơi sử dụng SQLite. Những người tôi đã nói chuyện dường như thích nó.


0

Tuần tự hóa được đề cập trong một số câu trả lời khác, và tôi đồng ý rằng đó là một giải pháp hợp lý. Một cách nó thất bại là trong phiên bản.

Giả sử bạn phát hành trò chơi của mình và mọi người chơi nó và tạo một số trò chơi tiết kiệm. Sau đó, trong bản vá sau, bạn muốn sửa lỗi hoặc thêm một số tính năng. Nếu bạn sử dụng một phương thức tuần tự hóa nhị phân đơn giản và bạn thêm một thành viên vào các lớp của mình thì việc xê-ri hóa của bạn có thể không tương thích với các trò chơi lưu cũ khi khách hàng cài đặt bản vá của bạn.

Vì vậy, bất cứ cách tiếp cận nào bạn sử dụng, hãy chắc chắn rằng bạn nghĩ về vấn đề này trước khi bạn phát hành trò chơi lần đầu tiên! Khách hàng sẽ không hài lòng nếu họ phải bắt đầu lại sau khi áp dụng một bản vá.

Một cách để tránh điều này là sử dụng từng loại dữ liệu cơ bản thực hiện các phương thức Lưu (phiên bản) và Tải (phiên bản) đủ thông minh để biết dữ liệu nào sẽ lưu và tải cho mỗi phiên bản của trò chơi. Bằng cách đó, bạn có thể hỗ trợ khả năng tương thích ngược của trò chơi lưu của mình và không thành công nếu người dùng cố tải trò chơi lưu từ phiên bản mới hơn của trò chơi so với khi họ đang chạy.


1
Như một lưu ý nhanh: thực hiện các chức năng "lưu" và "tải" cho mỗi phiên bản của trò chơi nhanh chóng biến thành cơn ác mộng bảo trì. Tôi đã tìm thấy một giải pháp tốt hơn là nhúng số phiên bản, viết các chức năng "lưu / tải" cho phiên bản hiện tại của trò chơi và viết chức năng "chuyển đổi" từ phiên bản không hiện tại gần đây nhất sang phiên bản hiện tại. Sau đó, chỉ cần giữ tất cả các chức năng chuyển đổi của bạn xung quanh. Cố gắng tải một trò chơi mười phiên bản cũ sẽ chạy mười chức năng chuyển đổi theo chuỗi, sau đó là chức năng "tải phiên bản trò chơi hiện tại" gốc.
ZorbaTHut

Dễ dàng hơn nhiều để duy trì lâu dài - giữ một loạt các chức năng "tải mọi tệp trò chơi trước đó" xung quanh nhanh chóng biến thành một hoạt động thời gian đa thức.
ZorbaTHut

Trong các trò chơi tôi đã làm việc trên nó không phức tạp lắm - thay vì giữ nhiều bản sao của các phương thức tải / lưu, một phương thức duy nhất sử dụng số phiên bản để xác định byte nào sẽ đọc và ghi. Điều này được thực hiện dễ dàng hơn nữa nếu bạn không chỉ viết các cấu trúc, nhưng thực hiện tải và lưu dưới dạng các hoạt động ở cấp loại dữ liệu nguyên thủy (ví dụ: ReadByte / ReadFload / vv). Sau đó, nếu bạn thêm một thành viên mới, bạn có thể làm một cái gì đó như if (phiên bản> 10) {someNewByte = ReadByte (); } Thực hiện theo cách này làm cho việc hỗ trợ các nền tảng endian khác nhau cũng dễ dàng hơn.
kevin42

Một cách khác để tránh cải thiện hỗ trợ phiên bản là tránh các phương thức tuần tự hóa / giải tuần tự hóa các đối tượng của bạn ghi / đọc các giá trị riêng lẻ trực tiếp từ một luồng. Thay vào đó, các đối tượng có thể ghi dữ liệu thuộc sở hữu của họ vào túi thuộc tính bằng các cặp khóa / giá trị và sau đó ghi túi ra luồng. Trong quá trình khử lưu huỳnh, các đối tượng có thể đọc các giá trị từ túi theo tên. Nhưng thay vì kiểm tra số phiên bản cụ thể như kevin42 đã đề xuất, bạn chỉ có thể có quy tắc về cách xử lý các giá trị bị thiếu (nghĩa là sử dụng giá trị mặc định tiêu chuẩn khi giá trị bắt buộc không có trong túi).
Mike Strobel

0

Nếu bạn có thể sử dụng cùng định dạng mà bạn sử dụng để lưu trữ các cấp của mình, thì đó là một phần thưởng.

Ví dụ: một trò chơi như Peggle có thể có bố cục bảng ban đầu, số lượng bóng, điểm hiện tại (0 cho bảng ban đầu), v.v. Sau đó, một trò chơi đã lưu có thể sử dụng chính xác định dạng tương tự.

Nếu bạn sử dụng cùng định dạng thì trò chơi lưu và tải cấp có thể chia sẻ mã giúp công việc của bạn dễ dàng hơn!

Đối với một trò chơi có tệp bản đồ thực sự lớn, trò chơi lưu có thể bao gồm tệp bản đồ theo tham chiếu. Các tệp cấp độ ban đầu có thể làm điều tương tự, thậm chí, điều đó làm cho việc quay lại bản đồ đó trở nên dễ dàng hơn nếu vì lý do nào đó câu chuyện khiến nhân vật trở lại cùng một nơi, ngoại trừ một số NPC đã chết và có xác chết nằm kết thú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.