Score saved and loaded on death

Hi, so i’ve managed to get a super basic game up and running by following the tutorials on here. But i can’t seem to figure out how to have it that when you die, a new collection is opened which is the death menu and on that it shows your high score…and then what would i save this data as so that a public leaderboard(Facebook instant) could read it? Thanks in advance to any hero who helps :slight_smile:

Adding multiple screens to your game is usually done by loading and unloading connections via what we call collection proxy components. There’s an example here:

Online high score lists can be created using PlayFab, Steam and many others. Are your doing a mobile game?

thanks! i’ve managed to get a loading screen proxy which has buttons for New Game, Exit Game and then when the player dies the proxy loads an end game menu with New Game/Exit Game also…but i don’t understand how to post the score to some sort of high score…in unity i would save the players score with playerprefs (which could then be called from Facebook leaderboard)…what would be the equivalent in defold?

You need to store the highscore data somewhere that won’t get destroyed when the player dies and the level ends. Either you always track highscores from outside of your game collection, or when the player dies you send it outside the collection at that time.

The simplest way would be with a lua module. Store your highscore info in the module when the player dies, and any other script can require the module to access it (for displaying a highscore menu, or sending to an online leaderboard, etc.), and it won’t go away until you close the game.

If you want to save highscores to disk, use sys.get_save_file() to get a filepath that you can save to, and sys.save() with the path and a lua table, and you are done! Load it again next time with sys.load().

1 Like

There’s a manual that describes different ways to work with files, for instance when saving high scores to an application specific folder: https://defold.com/manuals/file-access/

2 Likes

thanks, though that link seems to not work, i tried googling Defold File Access and it seems like defold have removed that page :confused:

Here’s a updated link to that manual: https://defold.com/manuals/file-access/

If you put your code between triple backticks ``` then it will be formatted correctly.

```
like this
```

"You can also use "Details" tags to collapse large chunks of stuff...

Click the gear icon in the editing toolbar and choose “Hide Details” (or type the tags in yourself).

I’ve read about the DevSave dependency, so figured if i put a save score function into the hero script when they die… and then a load function into the main menu script where their score will be saved and loaded/displayed??

Hero Script:

if self.lives == 0 then
						
						------------ would this save score? ??
						local save_state = {
							scores =  self.scores
						}

						local success = sys.save(sys.get_save_file("TestGame", "save_state"), save_state)
					

Main Menu Script:

local text_nodes = {"score", "score_text"}

function init(self)
	msg.post(".", "acquire_input_focus")

	-- would this load the saved score????
	
	local save_state = sys.load(sys.get_save_file("TestGame", "save_state"))
	if not next(save_state) then
		self.scores = 0
	else
		self.scores = save_state.scores	
	end
	
	
	--- would this write score into the score text area???
	
	local s = gui.get_node("score")
	gui.set_text(s, message.score)
	
end

This is what i get when i try to run the game:
(not sure if this is even related to it trying to save and load the score…as i don’t know if this would even work)
(anyone willing to do a tutorial or break it down into plain english an example of a save score on death and load score to be displayed on a score text component on a GUI then be happy to pay top dollar! or at least give massive praise :smiley: )

ERROR:SCRIPT: /Assets/mainmenu/mainmenu.gui_script:19: attempt to index global 'message' (a nil value)
stack traceback:
	/Assets/mainmenu/mainmenu.gui_script:19: in function </Assets/mainmenu/mainmenu.gui_script:3>
ERROR:GAMESYS: Error when initializing gui component: -2.

You just need to fix the issue that the error message is about and it should work. It looks like you just copy-pasted the code from somewhere else and forgot to change everything over completely. You use 'message.score', which should be 'self.scores' I think?

Hey thanks for that spot! i glazed over that! i’ve changed it and the errors have gone, but however when the player dies and it then launches the main menu , the score there isn’t loading the supposedly saved score?

Main Menu Script:

local text_nodes = {"score", "score_text"}

function init(self)
	msg.post(".", "acquire_input_focus")

	-- load saved score??
	
	local save_state = sys.load(sys.get_save_file("TestGame", "save_state"))
	if not next(save_state) then
		self.score = 0
	else
		self.score = save_state.score	
	end
	
	
	--- write score into the score text area?
	
	local s = gui.get_node("score")
	gui.set_text(s, self.score) --- your fix you pointed out :) 
	
end

Debug it step-by-step. Before you save it, pprint() the table to make sure it contains what you think it does. Then put in another print to make sure it saved correctly. Then do the same when you load it. Figure it which step is failing.

1 Like

So add in

pprint(self.score)

?.. if so the response i’ve got is DEBUG:SCRIPT: nil DEBUG:SCRIPT: 0
[ sorry if i sound dense, it’s been a bit of a nightmare changing over from unity which i managed to program my head around and it seemed a bit more user-friendly (dummy friendly)

And an example as well: https://defold.com/examples/file/sys_save_load/

Well after using Defold for a while I tried a bit of Unity, and it seemed very user-unfriendly to me! So I guess we’re even, haha.

OK, I think you’ve still got issues with things named incorrectly or trying to access them from the wrong place.

In one of your posts you’re using “scores” and in the other you’re using “score”. Make sure those are consistent.

Next, you’re trying to get the loaded score from “self”, which is not right. Self properties are what you would call “Instance Variables” in Unity/C# I believe? They are specific to each instance of the script that exists when your game is running. The “self” of your main menu script is totally separate from the “self” of your hero script. You’re loading the save score from the main menu script, and you never set 'self.score' to anything in that script, so of course it’s going to be nil.

-- You're loading it into the local variable "save_state". 
local save_state = sys.load(sys.get_save_file("TestGame", "save_state"))

-- So you would access it like this:
print(save_state.score)

pprint(save_state) -- doing this...
-- ...should give you something like this:

DEBUG:SCRIPT: 
{ --[[00000000020DADD0]]
 score = 1
}

Make sure you read the “Lua Programming in Defold” manual (again). Defold will definitely not be user-friendly if you don’t know the basics.

3 Likes

ah ok I get what you mean, this is going to take a lot of re-thinking processes. I figured “self” was like the player prefs… i’ll have to attempt some more reading of the the lua programming… in regards to the place where to save the score, could I maybe make a collection called score manager with a gui in there which saves the score? but then would that have to go in the loader proxy or would that never be loaded in the first place? or would I load it but just not have it visible on screen?.. thank you so much by the way - when (if) I figure this all out I totally need to make a tutorial and quote all you guys

You want a Lua module for that.

1 Like

Riiiight! gotcha! and does it matter where that module is saved/folder structure or is it just directly within the project folder? and does it matter what it’s called? something like ScoreModule? …. just managed to find this… is it pretty much this?

Yeah, you can store it anywhere, but mind you that you need to write out this path when you’re requiring it in a script.

For what you need (though I admit I only skimmed the full thread) just this would suffice:

local M = {score = 0}
return M

Then you can require the module in any script that needs access to the score value:

local m = require("main/modules/ScoreModule")

This is the only place where the name and path of the module matters.

Once you do this, you can access the score value as m.score

2 Likes

thank you so much, my lord ! the shroud has cleared and I can see clearly now the rain has gone! lol feeling hopeful! I cant wait to actually get the main framework of the game sorted so I can start on the fun bit which is the designing :smiley: … one last question… would I need to amend this in any way for facebook leaderboard to read this or would this module be enough for facebook to read the players score and post it to their leaderboard? (need to add in the competitive nature of a leaderboard )