0
\$\begingroup\$

I am making a game and I need the world to be generated and saved. I used Perlin noise to generate the terrain (and other stuff like trees), but cannot figure out the best way to save and recall actions done by the player, e.i. if a tree is cut down or a mineshaft is used I want that entity to either be updated or deleted.

How could I accomplish this?

More info: I am making this in JavaScript and eventually want to implement Node.js to implement multiplayer features in the future. The player also has a very limited view and this is a 2D top down kind of game. I am also making this basically from scratch.

Any and all help is appreciated!

\$\endgroup\$
  • 1
    \$\begingroup\$ There's always a smallee way, than json (or any format in general). With JSON you trade the size for readability. \$\endgroup\$ – Bálint Jun 18 '17 at 21:35
  • \$\begingroup\$ I'd recommend starting with whatever's easiest (e.g. json), but encapsulate it in a separate module so that you can change the format later. Once you figure out the distribution of terrain and object types the players end up with, you can design a compact format that optimizes for that. \$\endgroup\$ – amitp Jun 18 '17 at 21:45
0
\$\begingroup\$

What technology to use for saving

When your game is single-player, you can save to the browser's localstorage. But keep in mind that the specification guarantees only 5 MB of storage per website (some browsers will give you more, but you can't rely on that). It also allows web browsers to delete old localstorage data without a warning at their discretion.

An alternative is to use the JavaScript file API to create or read savegame files which the user stores on their filesystem. This appears to the user like a web download / web upload (even though the data never leaves their device). This is less convenient for the player than localstorage, because both saving and loading require additional user interaction. That means no autosave and no one-button quicksave. But it makes it easier for players to transfer savegames between devices and frees you from the space restrictions of localstorage.

When you switch to an online game with a Node.js backend, you should consider saving to a database. If you don't want to use a database for some reason (you do want one, trust me), server-sided files are an alternative option.

What data to save

Dirty solution: Just serialize and store the whole chunk, including the procedurally generated data. This is what Minecraft does, for example. One advantage is that it is easy to do. Another is that it is good for backward compatibility. If you change your world generation algorithms, those chunks generated by the old version are unchanged. The problem is that this can amount to quite a lot of data, especially when your world is very large and/or complex.

Elegant solution: Only store the following:

  1. the seed which was used to generate the Perlin-noise for the chunk (note that the JavaScript standard RNG doesn't allow seed values, so you need to implement an own RNG. Don't be afraid, there are many well-documented PRNG algorithms around which aren't hard to implement)
  2. any changes the player made.

In order to do the latter, you need to keep a list of changes to each chunk. If the player planted a tree at 317:56, push an object { x:317, y:56, object: "Tree" } to the changes-array. When they chopped down a tree at coordinates 456:194, push an object { x:456, y:194, object: null }. If they chopped the tree at 317:56 down again (restoring the original state), remove the object with x:317, y:56.

The advantage of this method is that you minimize the amount of data you need to store when the player usually doesn't make that many changes to the game world. But keep in mind that if your player has a lot of influence on the game-world, this method can amount to even more data than just storing the whole chunk.

How to serialize data

JSON.stringify and JSON.parse are your friends here. They can turn a JavaScript object (or array) into a string and back. But keep in mind that it can not serialize functions! Any fields which contain functions will be omitted.

If the JSON code turns out to be too large for your use-case, consider running a stock compression algorithm like ZIP on it.

\$\endgroup\$
  • \$\begingroup\$ Thank you so much for that in-depth explanation. I am already using a PRNG so what you explained in your "what data to save" fits perfectly into what I already started to do right now. I was really skeptical my approach was the right one and this really reaffirms that... I was going to store things on server side with JSON initially but your suggestion of localstorage is really perfect for what I want. Once again, thank you so much. This has been great help! \$\endgroup\$ – DemonicOwl Jun 20 '17 at 3:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.