Plans for save/load game functionality in Phaser
The next big thing to work on is the save/load game functionality. I want to get this done ASAP because after that I can release a demo of the map editor for people to mess around with. They can contribute to the game by uploading their own art assets and creating ladder maps. I have a tentative plan for achieving the save/load game functionality in-browser and I'll outline it here.
The meta-data for all my game objects (things like unit type, tree type, etc) are neatly organized in a JSON file. The most important data I need to save for game objects (trees, units, buildings, etc) are x/y coordinates and the key for the JSON file which will tell me everything I need to know about the game object. I can recreate game object attributes by looking up their keyed values in the JSON file. There's also player data like which team the unit belongs to and stuff specific to different game objects types, such as the health of units, and their currently facing direction but I won't worry about that right now.
The second big part of this is saving the terrain (grass, snow, dirt, basically anything you draw onto the canvas using the brush tool) which is in an entirely separate layer from game objects. My plan is to utilize the toDataURL method to save the entire canvas (minus game objects i.e. objects placed on top of terrain) in a string format. Then I can recreate the canvas with my base64 string.
So, in summary, I can recreate the static aspect of the map with the base64 string and the dynamic aspect (units, buildings, trees, etc) with my JSON. Users will be able to download the current game state in a text file (likely, a JSON) and upload it to load the map.
- I'm not sure if the toDataURL method encodes the entire canvas into a base64 or if it encodes only the visible portion of the canvas. Or, it could be that Phaser is incapable of drawing an image to the entire canvas using image data. My experience in trying to draw the entire canvas has led me to believe that at least one of those is true or needs to be worked around. I know that if you try to draw the entire game canvas into a Phaser.BitmapData object, you only get the visible portion if you try adding it to the game as a Phaser.Image or sprite. I've worked around this in the past by relying on the BitmapData.drawGroup method, which miraculously draws the entire group into a bmd, regardless of wether or not the entire group is visible. I don't have that option now because, when loading maps, I need to draw a base64 instead of an existing Phaser.Group.
- Because my canvas is in webgl mode, I'll need to use preserveDrawingBuffer for toDataURL to even work. This has performance implications. An alternative is to draw my webgl canvas onto a canvas with 2d context, and save the base64 of the 2d context instead of the original webgl context. Something like this: context2d.drawImage( webglCanvas, 0, 0 ).
- If that map size is huge (and my game will have huge maps), the base64 string will be huge. Experimenting with a 2000 x 2000 pixel map, my base64 was 3MB ... that's 3MB of pure text. Probably a lot smaller than if I were to save the canvas as a PNG, but it's still a problematic file size. 3MB is big enough to crash notepad and the file size will only increase exponentially as the map size increases. Games like aoe2 didn't have to worry about this problem. Because texture placement was tile-based, they could procedurally recreate the map with a simple 2D matrix. But I need to save an entire image of the static layer of the map.
So, basically all my problems are related to the fact that I just had to have non-tiled based texture placement. I foresee many long and sleepless nights trying to figure out all the workarounds. Lots of sighing and grunting and hair-pulling... I guess that's the price of innovation!