Lưu trữ trạng thái trò chơi khi thoát trên iPhone bằng Objective-C


10

Làm thế nào bạn sẽ lưu trữ trạng thái trò chơi của bạn ở lối ra cho một trò chơi iPhone được viết bằng Objective-C?

Câu trả lời:


7

Đây là phương pháp tôi đã sử dụng trong các trò chơi của mình.

Đầu tiên, mọi đối tượng cần được duy trì phải thực hiện giao thức NSCoding. Bạn muốn chỉ lưu trữ dữ liệu mô hình của bạn và không có gì cụ thể cho quy trình hiện tại. Điều này có nghĩa là bạn không thể duy trì các con trỏ hoặc bất kỳ id tài nguyên nào mà HĐH cung cấp cho bạn khi chạy. Đối với các con trỏ, bạn có thể khắc phục điều này một cách dễ dàng bằng cách chỉ cần đảm bảo rằng bạn mã hóa các đối tượng mà chúng trỏ đến thay vì chính các con trỏ. Đối với các tài nguyên khác, bạn sẽ cần một cách để kết nối đối tượng của bạn với tài nguyên mới khi chạy.

Thứ hai, đảm bảo rằng tất cả các đối tượng trò chơi của bạn có thể được truy cập thông qua một đối tượng gốc. Ví dụ, đối tượng này có thể là một đối tượng chính cho toàn bộ trạng thái trò chơi. Một khả năng khác là bạn có thể lưu trữ chúng trong một trong các lớp tập hợp Foundation (NSMutableArray, NSMutableset, NSMutableDipedia).

Khi bạn nhận được thông báo rằng ứng dụng của bạn đang di chuyển vào nền (applicationDid EntryBackground), bạn sẽ cần sử dụng NSKeyedArchiver để lưu toàn bộ trạng thái vào một tệp. Tập tin đó nên có trong thư mục tài liệu cho ứng dụng của bạn. Đây là một chút mã để chỉ ra cách thực hiện:

NSArray *docDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [docDirectories objectAtIndex:0];
NSString *saveFile = [docsPath stringByAppendingPathComponent:SAVE_STATE_FILENAME];
[NSKeyedArchiver archiveRootObject:gameState toFile:saveFile;

Khi bạn phát hiện ra rằng bạn đã quay trở lại nền trước, bạn nên xóa tệp lưu để tránh mọi sự nhầm lẫn vào lần tiếp theo ứng dụng của bạn được khởi chạy.

Khi khởi động ứng dụng, bạn cần kiểm tra sự tồn tại của tệp lưu. Nếu bạn có một cái, bạn tải nó lên như thế này:

NSArray *docDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [docDirectories objectAtIndex:0];
NSString *saveFile = [docsPath stringByAppendingPathComponent:SAVE_STATE_FILENAME];
[gameState release];
gameState = [[NSKeyedArchiver unarchiveObjectWithFile:saveFile] retain];

Tùy thuộc vào thiết kế của bạn, bạn có thể cần phải đi qua trạng thái trò chơi và kết nối lại bất kỳ tài nguyên nào mà bạn không thể duy trì. Điều này thực sự phụ thuộc vào mức độ tách biệt mã mô hình của bạn với mã kết xuất.

Tại thời điểm này, bạn có thể muốn đưa trò chơi của mình vào trạng thái tạm dừng, tùy thuộc vào loại trò chơi bạn đang thực hiện.

Hy vọng rằng điều này sẽ giúp những người khác đang cố gắng thực hiện tiết kiệm trò chơi trên iPhone.


2

Làm thế nào để lưu trữ trạng thái trò chơi là một câu hỏi phức tạp phụ thuộc nhiều vào cách bạn thiết lập trò chơi của mình.

Trên iPhone cụ thể, bạn sẽ chỉ phải móc vào -(void)applicationWillTerminate:trong của bạn UIApplicationDelegateđể bắt khi ứng dụng sẽ thoát ra, từ hành động sử dụng hay không. Tuy nhiên, bạn có một khoảng thời gian ngắn để thực hiện công việc của mình trước khi HĐH sẽ giết quá trình của bạn.


2
applicationWillTerminate chỉ hoạt động cho các ứng dụng không hỗ trợ đa nhiệm hoặc cho SDK trước 4.0. Tốt hơn là sử dụng applicationDid EntryBackground với mã sau 4.0.
Dennis Munsie

1

Điều đó phần lớn phụ thuộc vào cách trò chơi của bạn được mã hóa. Bạn đang theo dõi một vài ngà hoặc một cái gì đó quan trọng hơn?

Nếu nó chỉ là một vài chiếc ngà, có lẽ tôi sẽ viết chúng cho một bản vẽ trên nền và tải nó khi khởi động.

Nếu có nhiều ngà hơn, bạn có thể tốt hơn với CoreData (và / hoặc lưu giá trị của chúng khi chúng thay đổi thay vì cố gắng khớp mọi thứ vào cửa sổ đóng).


Bạn thực sự có thể làm được rất nhiều việc với thời gian HĐH cho bạn tắt. Tôi đã có thể duy trì khá nhiều đối tượng trò chơi (ít nhất vài trăm) bằng cách sử dụng phương pháp mà tôi đã mô tả trong câu trả lời của mình trong thời gian đó. Ngay cả trên iPod touch 1G chậm. Tùy thuộc vào loại trò chơi bạn đang thực hiện, giải pháp CoreData có thể hoạt động tốt hơn khi ứng dụng thoát, nhưng với chi phí chơi trò chơi chậm hơn.
Dennis Munsie

1

Giống như cách bạn lưu nó khi người dùng va vào trò chơi lưu mà không thoát.

Đây có phải là câu hỏi về làm thế nào để lưu trạng thái trò chơi? Hoặc làm thế nào để làm một cái gì đó tại thoát ứng dụng?

Đối với câu hỏi sau, câu trả lời là: appWillTerminate (hoặc appWillResignActive.) Trong iOS4 trở lên, bạn có thể yêu cầu thêm thời gian (Google "iOS-4 yêu cầu thêm thời gian") nếu trò chơi tiết kiệm của bạn mất một thời gian.

Nếu bạn đang hỏi làm thế nào để lưu trạng thái trò chơi, tôi sẽ là một fan hâm mộ lớn của NSDipedia để lưu trữ các giá trị dễ dàng được đọc lại bởi công cụ trò chơi.

NSMutableDictionary *saveDict = [NSMutableDictionary dictionary];
[saveDict setValue: [NSNumber numberWithInt: currentScore] forKey: @"currentScore"];
// etc...
[saveDict writeToFile: saveFilePath atomically: YES];

Nếu bạn muốn, bạn có thể thêm "chữ ký" ( ví dụ như md5 hoặc tương tự) để xác minh trên trò chơi tiếp tục để đảm bảo rằng ai đó đã không bị lừa với tệp để cố gắng gian lận.


1

Tôi sẽ nói không. Lưu nó khi nó có ý nghĩa cho trò chơi, không phải khi ứng dụng đang thoát. Ví dụ: nếu đây là trò chơi theo lượt, thì hãy lưu vào cuối mỗi lượt. Nếu đó là một trò chơi dựa trên cấp độ, hãy lưu ở cuối mỗi cấp độ. Có một vài lý do cho việc này:

  • Sử dụng điện thoại di động là rất khó lường. Có, bạn nhận được thông báo bởi SDK iPhone khi ứng dụng đang đóng, nhưng nó có thể ở giữa mọi thứ và quá trình chuyển đổi không chỉ là "thoát" mà còn nhận được cuộc gọi, nhận văn bản, v.v.
  • Bạn có rất ít thời gian và nguồn lực để tắt trò chơi của mình khi thoát ứng dụng. Hầu hết trong số đó có thể sẽ được tiêu thụ chỉ bằng cách tạm dừng trò chơi của bạn và dọn dẹp bộ nhớ. Không cần thêm vào tải đó bằng cách lưu trạng thái trò chơi.
  • Hầu hết các trò chơi có tạm dừng tự nhiên có ý nghĩa cho việc tiết kiệm. Bạn có thể tận dụng các tạm dừng này để lưu trữ liên tục trạng thái trò chơi và người dùng sẽ không bao giờ nhận thấy rằng bạn đang tiêu thụ thêm tài nguyên.
  • Bằng cách lưu tăng dần trong khi chơi trò chơi, lượng dữ liệu sẽ được lưu sẽ nhỏ hơn trên mỗi lần lưu.

1

Dưới đây là ví dụ về cách triển khai giao thức NSCoding cho một số lớp "bản đồ" và "trình phát" ví dụ:

http://deadpanic.com/howtosave

Sau đó, bạn có thể lưu các đối tượng bằng phương pháp Dennis 'NSKeyedArchiver.

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.