A friend of mine and I are always talking about our current progress in learning game development. Recently, saving the game (data persistence) came up, and when I summarized how I tackled that for my project, he thought I should post a question here and see if anyone else had input on the scenario.
A little bit of background: I'm working on a top down 2d rpg and experimenting with different gameplay concepts here and there. I am using cocos2d for Python, and may eventually move to Kivy. Most importantly for the save portion, I'm using Tiled TMX files for my maps / levels, and sqlalchemy.
So, I wanted all the different objects in each map to maintain their states and positions when the player leaves the map, and when the players come back, everything is at or near where he left off...unless a great deal of time has passed or something. Now, I hadn't considered at all what to do to allow this at first. ...Another friend of mine decided to just 'pickle' his map objects to a file. I tried to do this but ran into a lot of problems – I was attempting to pickle an entire sprite entity instead of just the data bits, so I ran into issues of threading... it was a mess.
Then I went with a sqlite db for storing all the various data. The reason I had this trouble at all is because a tmx map file is just xml underneath – and I wouldn't want to have to make copies of the original map files and then commit the map objects' locations back to a separate xml file – that sounded messy.
My final plan was to create a tmx map object to db map object converter. The logic is, if the player hasn't been to this map yet, initialize the objects from tmx to the db, and mirror all their properties and value pairs as well... then get the actual map from tmx xml as usual, then load map objects from the db. On map exit, commit all the map objects back to db.
TL;DR: what would have been a better way to store persistent map object data if I'm using Tiled TMX maps? Was doing a db overkill? What's an example of best practice for map save data like this, where you want the objects on the map to remain as they were when you were last on the map?
Thanks, I hope that's clear enough!
Here's the objectgroup of a tmx file I'm using
<objectgroup name="objects" width="30" height="30"> <object name="Entrance1" type="start" x="159" y="326" width="32" height="32"> <properties> <property name="start_name" value="Entrance1"/> </properties> </object> <object name="To hello1" type="portal" x="160" y="256" width="32" height="64"> <properties> <property name="map_name" value="hello.tmx"/> <property name="portal_name" value="Entrance2"/> </properties> </object> <object name="Item1" type="item" x="480" y="288" width="29" height="30"> <properties> <property name="image" value="ironbarstack.png"/> <property name="item" value="ironbar"/> <property name="quantity" value="3"/> <property name="requirements" value="0"/> </properties> </object> <object name="Item2" type="item" x="449" y="351" width="29" height="30"> <properties> <property name="image" value="rope.png"/> <property name="item" value="rope"/> <property name="quantity" value="1"/> <property name="requirements" value="0"/> </properties> </object> </objectgroup>
If I'm working on a level in Tiled (adding another item on the floor for instance) and then playtesting it, I need to check for updates each time I load up the map right now. So, I check to see if that tmx map name exists in the maps table of the save game db being used. If it exists, create a list of tmx objects and db objects, and iterate through the tmx objects, update/add the db counterparts with the key being their name value. Then, at the end if there are any db objects remaining from the db object list, remove them from the db. If the map doesn't exist in the db yet, then it's a straight conversion from tmx object to db object, no checks done.
At first when I went the db route, I was storing each type of map object in its own table with properties I expected to be required for each. That proved difficult, time consuming and rather unnecessary. I ended up just doing a one to one conversion from tmx map to db map, tmx object to db object, and tmx object properties to db object properties.
After the game content is completed, I plan on removing all of the tmx files and these sync checks, and just having a master db that the game content is copied from. As a bonus question, does this make sense, or am I making a lot of work by attempting to avoid the building of a proprietary map editor by using Tiled?