Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers AppGameKit Corner / saving data for multiple levels

Author
Message
xtremi
1
Years of Service
User Offline
Joined: 26th Aug 2018
Location:
Posted: 22nd Sep 2018 15:01
So I'm working on a little game and I need some recommendations on how to implementing saving of high scores and such.

This game has many levels, let's say 100s, and each game are very short.
For each level I want to be able to save the 5 best scores and a few other values related to each of those scores.

The binary format for the file could be something like this:

First integer in the file: <number of levels completed and saved>

5 integer holding the best scores for level 1
5 integer holding additional data for the best scores in level 1
5 integer holding additional data for the best scores in level 1
...
5 integer holding the best scores for level N
5 integer holding additional data for the best scores in level N
5 integer holding additional data for the best scores in level N

So each levels have a set of 5*3=15 integers


The initial method I wanted to implement was:

Game opens:

If save.dat file already exist:
- read file content to memory in a structure SavedData
else
- create save.dat file

Player chooses a level X, plays it, completes it:
- Compare score with corresponding best scores in the structure SavedData
-- If the score is higher than any best scores, update SavedData, BUT also write the new value to the file by:

--- open save.dat, using the level number, go to the position in the file where the score should be updated, write the value.

My problem is that in Appgamekit, when writing to file, you can either overwrite the whole file or append to the end of the file.
It is not possible (as far as I know), to open an existing file, go to a certain location and overwrite a value.
You either write to a new file, or append at end of an existing one.

One solution would be to every time I want to save a value, rewrite all the data. But that seems very inefficient. If the user gets a new high score in level 134, I should only have to rewrite one value in the file, not the complete file.

I could also just keep the new high scores in memory while the user plays, then when he exit the game write all the data to a file. But I'm not sure how this would if the game closes unexpectedly.


I'm sure there is a reasonable way of doing this, so I'm hoping for some suggestions.

Thanks in advance.















Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 24th Sep 2018 15:39
Assuming you're only concerned with saving the scores of the local player and not having to share the scores online, here's what I'd do.

Define a score type. Since you're wanting more info saved with each score than just a single number, it's easier to manage with a Type.



Then, you can either maintain a 2-dimensional array to maintain a list of levels with their 5 scores, or a 1D array of a type which contains the scores. I prefer the latter as I think it's easier to read what the data is and where it belongs.



gameScores as LevelScores[]


You can use this function to insert a score for a particular level. If it doesn't beat any of the current 5 scores, then it won't be added.


Quote: "My problem is that in Appgamekit, when writing to file, you can either overwrite the whole file or append to the end of the file.
It is not possible (as far as I know), to open an existing file, go to a certain location and overwrite a value.
You either write to a new file, or append at end of an existing one."

You are correct, there is no random access.

You would have to write out the array when the player exits the game. You can do either a binary file or just simply save the array and make it easy. If you want, rewrite the file after each level, it shouldn't be an issue. You can also trigger a flag any time a score does get updated in the array, that way you're not writing anything if nothing change. For instance, the player could play the same level for an hour and never beat a top score, therefore no reason to rewrite the scores because none changed.


If you save after each level, the overhead shouldn't affect anything and should the app crash you won't lose anything more than the last level. In the event the game crashes while writing the data, you could save the data to a temp file then once complete, delete the existing save and rename the temp. That way there's no risk of losing the save file because you're not actually overwriting it and it stays where it is until the new data is written elsewhere.

Only other alternative I can see to avoid writing 100+ levels data at a time is to store each level separately.

So if each level contains 5 scores and each score has an additional 2 integer properties associated with them, then we have 15 integers per level as you said, or 60 bytes. With 100 levels that's still only 6kb, which honestly isn't that much.
Tiled TMX Importer V.2
XML Parser V.2
Base64 Encoder/Decoder
Purple Token - Free online hi-score database
Legend of Zelda

"I like offending people, because I think people who get offended should be offended." - Linus Torvalds
Bengismo
1
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 24th Sep 2018 16:23
The easiest way is just to use the inbuilt array saving functionality



This VERY simple code shows how easy it is to use the built in functionality to write the entire score data file and re read it on startup as well as updating it. Its also very fast and adapts easily to you changing the datatype used to store the data in. The data is stored in "Scores.dat"



Another nice option is to simply put all the score info into a memblock and save that...then load that on startup in a very similar way to the above code.

Login to post a reply

Server time is: 2019-09-17 09:41:32
Your offset time is: 2019-09-17 09:41:32