Save to lua rather than JSON?

I’m using the save/load method for JSON detailed here https://docs.coronalabs.com/tutorial/data/jsonSaveLoad/index.html which is working great although due to [topic=‘72318’]another problem[/topic] I want to save the game objects. However, when I save to JSON format, upon reload a print of one of the objects reports  <type ‘function’ is not supported by JSON.> and more importantly _proxy  <type ‘userdata’ is not supported by JSON.>.

Is it possible to save in a similar way to this method but to a lua file or is there another way to solve this…or even the other problem?

Hi,

JSON only supports the String, Number, and Boolean types (which can be within Tables).

There really shouldn’t be a need to store a function in your JSON, so I would manage your data that you need to save for your game objects differently. There is no way around your issue.

If you are using special game objects then you need to reinitialize those objects using the JSON data when the game is reloaded.

-dev

Agreed.  You cannot directly serialize display object.  You need to save just the info need to re-create or re-initialize the object.

So maybe we need to store in json only list of properties of an object (table) without storing functions. How to list them?

This totally depends on your needs.  I’ll look through my code, but I’m sure I have an example of saving and restoring objects via custom-serialization.

… Here is a demo game with built-in editor that allows save and restore:

https://github.com/roaminggamer/CoronaGeek/raw/master/Hangouts/ICanMakeThat/Ichi%20Mechanics.zip

This screen with these parts in the editor:

ichi.png

produces this save file:

[{"y":-100,"pieceType":"bumper1","rotation":90,"x":-100},{"y":-20,"pieceType":"ball","rotation":0,"x":-100},{"y":140,"pieceType":"goal","rotation":0,"x":-20},{"y":-100,"pieceType":"bumper1","rotation":180,"x":100},{"y":20,"pieceType":"bumper1","rotation":0,"x":100},{"y":20,"pieceType":"bumper1","rotation":180,"x":180},{"y":140,"pieceType":"bumper2","rotation":270,"x":180}]

It was the _proxy information being lost when the objects were removed that was causing the issue. I’m saving move data in a solitaire card game and it doesn’t seem to work if the objects are removed. So I tried to save the objects but that doesn’t seem to work with json. Not sure what the best way to save the game is really.

** UPDATED **

@hasen6,

We addressed this above. You need to come up with your own custom save system that saves the data will later need, in order to restore the state of your game. 

There is no single-solution to this.

Trying to restore a solitaire game that was stopped and destroyed mid-game would probably include these steps:

  1. Initialize base game.

  2. Load state of game logic: score, remaining unused cards.

  3. Restore cards the player had showing in their stacks, placing them where they were before.

  4. Attach all touch listeners, etc. you need to move cards, drag-and-drop, etc.

This implies you’d need to save all this data.

There is no “save my game state, restore my game state, keep playing” library.

PS - Also, we said clearly you cannot save display objects as JSON encoded objects directly then ‘restore’ them directly.  It just won’t work.  So, don’t try to do that.  Your last post seems like you’re ignoring the information you were given.  Believe me it absolutely will not work.  The json.enccode() function cannot crawl all the fields of the display objects in coroana.  It will probably skip most fields and wont’ get stuff like fill color, etc.

If you get really stuck on this, you might consider hiring someone out of the community to make you a starter module that plays, saves, and restores the game. 

Then, you can use the module and make changes as needed to make your game.

@hasen6,

I forgot to ask.  Is this a learning experiment or a making money experiment?

If it is for learning, I suggest changing the game.  Solitaire seems like a simple game at first look, but implementing it is actually pretty hard. 

It is made hard by the way you can drag cards around both singly and as groups.  Then there is stacking cards, detecting drops, … The large numbers of ways you interact with cards in Solitaire and the rule checks needed to do this correctly are pretty challenging.

Poker or Blackjack are both much easier games to learn Programming and Corona (or any engine for that matter) with.

That’s weird, last night when I replied there weren’t this many replies. Yes I see now, your example code looks interesting, so you mean I can save the _proxy data and then add it back into the game objects or something?

Saving score, number of moves etc is simple, I’ve already implemented that. Saving the move data is simple enough too but it seems they won’t move properly without all the other data contained in the objects. I didn’t realise they would be separated from the saved move data when the objects were removed.

Actually the game already has everything except this. It plays great with animations, unlimited undo and redo, auto move on click, auto complete on win etc. All that’s missing is the resume game which I hadn’t anticipated would be this fiddly. 

Part of the difficulty is it needs to resume the game and also remember all the moves so that the unlimited undo will still function. So the shuffle has to be remembered as well as the deal out and then all moves afterwards. They have to be stored so that the moves can be undid back to the start just after the deal was made. Upon resuming the game, all these stored shuffle, deal and moves are remade albeit too fast for the eye to see. This was my idea for how to approach resume game anyway.

I did all of this and even solved the problem by storing the game objects in a table, but then I got stuck again because the game objects can’t actually be saved to json.

It’s for making money although it is my first game. I just started learning game programming in these last couple of months (before that I did web programming) and Solitaire is certainly hard, you’re right. I made a platform game in Love2d already which was much easier than this.

When the object is removed it’s missing _proxy and _class which holds things like the x and y position but also breaks the toFront() function but I’m not sure why that is.

What RG is suggesting is you save all the relevant information for each display object, such as its type, position, filename, scale etc, and then use this when loading to create brand new display objects with the appropriate listeners and custom parameters added.

Then all the hidden fields and functions which Corona needs will be restored too.

Yes that’s what I said above.

Sounds like it might work anyway. I’ll try it.

I think it’s not so bad and I have some thoughts about this.

Lets look what we CAN READ (to save) from existing object directly or measure them indirectly, anyway:

  1. Positions, dimenstions and number of layer (and etc.) of an object.

  2. We CAN get all physics settings, including gravity of environment, gravity scale, friction, bouncing, also we can GET and SET angular and linear velocities, dampings (and etc.) of an object

  3. General variables and custom object variables since in Lua they can be generated «on the fly» (such as healh, score, damage multipliers, current weapon, gold, inventory)

  4. for listeners and function you need to create standalone libraries for each enemy or card or hero (or else) and just save and restore information about all instances and after loading your game just recreate these instances with their own settings. I mean you don’t need to save listeners and functions they already ARE in your classes and they already prepared to work with new options you give them by reading from file.

In other words I think you need to break your statements to «need to save» and «not need to save». You can see how this is realized in «sticker knight platformer» free game example. There are main «classes» mean «libraries» for every game object. Each object’s options (or settings or parameters, how do you prefer) are loaded from json map file, I mean for each INSTANCE they all are loaded from file. Each coin is exactly at it’s place, each enemy is on it’s place. It’s good idea to create a «template» for each game object and then just create one more instance of this with it’s own settings, finally you can save these settings once again.

Just break this big job to few smaller things and see what you can do. I’m very far from finishing my game so I can’t give you any example. 

Ok thanks. It seems to be coming together now, the save game is almost working. So you are also making a solitaire game or you mean you’re also making your first game?

I just want to add some additional thoughts to this. You don’t want to save the display objects. They include the texture data for the image and a bunch of overhead that is destroyed when the app is closed (or potentially on suspend on Android) If we did save this, it would make your saved data huge and take up more space on the user’s device than you need to.  As suggested above, copy the important values (.x, .y. .rotation, .cardName, or other fields you ad, what stack they are in, the order of the cards in the stack) as it’s own independent Lua table of just text and numbers and JSON encode that and save it.  When reloading, read that back in and recreated the display objects and move them, add them to groups, etc. as necessary based on the data. 

Your users will be happy with save files that are maybe a couple of Kbytes in size instead of multiple megabytes.  Besides Corona won’t let you do that anyway since we don’t let you get to that texture memory.

Rob

Yes, in the end it was sufficient for me to just save numbers for various things since the advice in this thread enabled me to figure out where in the code my saved moves were not getting the data added to them that they needed during the game loop. I figured it all out and now have a working resume game function that saves and reloads just fine. :slight_smile:

Hi,

JSON only supports the String, Number, and Boolean types (which can be within Tables).

There really shouldn’t be a need to store a function in your JSON, so I would manage your data that you need to save for your game objects differently. There is no way around your issue.

If you are using special game objects then you need to reinitialize those objects using the JSON data when the game is reloaded.

-dev

Agreed.  You cannot directly serialize display object.  You need to save just the info need to re-create or re-initialize the object.