Trying to make a lives counter using Global variables

I need help with making a counter for the number of lives my player character has in my game. This is the code I’m trying to make work:

I’ve made the “Lives” Global variable a Number, so this should work to reset my game once my character’s lives run out (become less than one). The problem is that when I tried to deduct one life from the “Lives” Global variable whenever my player character runs out of health points, that Global variable automatically becomes a negative number for some reason, which means that my game always restarts the whole game instead of just the current level. Below is a screenshot showing what I believe to be the problematic area:

My idea was to deduct one from the “Lives” Global variable each time my player character runs out of health points and then restart the entire game only when the “Lives” Global variable is less than one, but it always just goes straight to a negative number instead of just deducting one from the “Health” variable.

What am I doing wrong here? I would like to know since I still need to make more use of Global variables in my game, such as making the “Health” variable into one, or deducting one life when the ingame timer runs out, or making the “Score” variable a Global one, etc.

Any help here would be much appreciated.

2 Likes

The problem here is in the first picture. You are connecting a once to the “set” instead of the “get” of the number. Set will set the value to whatever was inputted - in this case it would be one. However, setting a number doesn’t output anything, so the global hasn’t even been setted once, and remains at zero lives.

Just change it to “get” and I’m pretty sure it’ll work fine.

That didn’t resolve the problem, unfortunately. I did as you instructed, but now the game always sets the “Lives” global variable to “3” even after the player character runs out of health points. I have noticed, however, that the Lives counter does briefly display a “2” instead of “3” when the player character loses all of its health points, but once the current level is restarted, the Lives counter is set to"3" again. So now the “RestartGame” function never triggers, whereas before adding what you told me, it triggered every time after the player character lost a life.


Whhhhattt is this…

Should be like this, why are you using another number for health when you already have a global???

@WYTam

This is because I wanted to have both a health meter and a lives counter (the player character for the purposes of the Flowlab lesson I’m making needs both). I’ll need help afterwards to make the health meter its own Global variable later on.

Can you think of anything else that might solve the problems I’m having with making a lives counter a Global variable?

2 Likes

just use the global like a normal number, it acts the same

1 Like

I was trying to do that. But as my game currently is, I’m still having the problem of the “Lives” Global variable not changing like it should.

Ohhh I see what you want. You want the lives to keep AFTER the level is reloaded.

The problem is, I’m not sure if you can keep the global after the level is reset.

You might have to use save blocks.

So it’s not possible to keep the number of lives after a level is restarted by a LoadLevel block using the RestartCurrent function? I thought that Global variables would be kept that way.

What should I do instead if I want the number of lives to be saved and decreased each time the current level restarts due to player death? If the only solution is to use Save blocks, how do I use them?

1 Like

use a save

Input through save to save a number to this name (the text at the bottom is the name of the save, if you type the same name in a different save block, the values will be the same), it will output the saved value through “done”

Input through read to read the number of this name, it will output the current saved number.

This number will be saved, through level reload and even closing/reopening the tab.

I think some confusion must have happened here, Globals do save when the level is restarted, the Save behavior isn’t required.

Then why is it not working…?

Coding / user error.
From the original screenshot the Global is set at the beginning of the game, so any alterations won’t matter because it’s being set at the start.
There is absolutely no reason why a Global would function any different between restarting the same level and just moving to a new level

1 Like

It’s good that an expert like you is here. Could you please tell me what I’m doing wrong and what I should be doing instead if I want both health points and a Global variable for lives? I’m at my wit’s end right now.

Where exactly should I set a Global variable’s value so that it’s changed in the manner I originally intended? You seem to be implying that my use of the Once function at the beginning to set the “Lives” Global variable is incorrect. Is that because the value of that Global variable needs to be set somewhere else? I was under the impression that a Global variable’s value needs to be set at the start so it can have a value before that value can be properly decreased (by losing lives).

I’d appreciate it greatly if you could help me over this coding hurdle.

3 Likes

How you have the player take damage seems to work fine (maybe consider using Parent objects so you don’t need so many Collision behaviors), it’s only the Lives system that needs to be altered.

The problem other people encountered is they thought the deduction of lives was the system to reset the game. However if the player was on the 2nd level it would be more apparent. You want to restart level 2 when you die, but if you die 3 times it takes you back to level 1.

{"data":{"behavior":{"v":"2","nodes":[{"inputCount":0,"outputCount":0,"name":"Set Lives","behaviorType":"logic.NodeGroup","x":-450,"y":696,"group":"","id":"5abc5ab29f863146","isMenuItem":false},{"inputCount":3,"outputCount":1,"name":"Number","behaviorType":"logic.logic.Value","x":90,"y":696,"group":"5abc5ab29f863146","id":"120b79e32de7704c","startVal":3,"tag":"Lives","roundMode":1},{"inputCount":3,"outputCount":1,"name":"Global","behaviorType":"logic.logic.Global","x":-270,"y":696,"group":"5abc5ab29f863146","id":"120baec45b21634f","tag":"Lives:Number","version":2,"dataType":2},{"inputCount":1,"outputCount":1,"name":"RestartGame","behaviorType":"logic.gameflow.RestartGame","x":270,"y":608,"group":"5abc5ab29f863146","id":"1210d49b618acf4b"},{"inputCount":4,"outputCount":4,"name":"Label","behaviorType":"logic.hud.Label2","x":90,"y":784,"group":"5abc5ab29f863146","id":"12150e40e2896940","text":"0","textColor":16038674,"fontName":"oduda","scale":10,"textAlign":"left","maxWidth":0,"xO":1060,"yO":29,"pin":false,"alpha":100,"kerning":0},{"inputCount":0,"outputCount":1,"name":"Once","behaviorType":"logic.triggers.Once","x":-450,"y":696,"group":"5abc5ab29f863146","id":"120ceac13ec4c544","resetOnLevelStart":false},{"gateVal":0,"mode":"equal to","inputCount":2,"outputCount":2,"name":"Filter","behaviorType":"logic.logic.Filter2","x":-90,"y":696,"group":"5abc5ab29f863146","id":"5abcef2cd14fa74b"},{"inputCount":3,"outputCount":1,"name":"Switch","behaviorType":"logic.logic.Switch","x":90,"y":608,"group":"5abc5ab29f863146","id":"5ac71a44aba4db4f","_startVal":0,"dataType":2}],"links":[{"input_id":"120baec45b21634fi0","output_id":"120b79e32de7704co0"},{"input_id":"5abcef2cd14fa74bi1","output_id":"120baec45b21634fo0"},{"input_id":"120baec45b21634fi1","output_id":"120ceac13ec4c544o0"},{"input_id":"5ac71a44aba4db4fi2","output_id":"5abcef2cd14fa74bo0"},{"input_id":"120b79e32de7704ci1","output_id":"5abcef2cd14fa74bo0"},{"input_id":"5ac71a44aba4db4fi1","output_id":"5abcef2cd14fa74bo1"},{"input_id":"12150e40e2896940i0","output_id":"5abcef2cd14fa74bo1"},{"input_id":"1210d49b618acf4bi0","output_id":"5ac71a44aba4db4fo0"}]}}}

What this does:
First, it gets the Lives value, if it’s equal to 0, it sets it to 3. This allows the game to set the lives, but not set it if there is already a value there.
The Switch is there to prevent the game from restarting when it’s not supposed to. To output from the Switch, it requires a value greater than 0 to turn On. So 0 → 3 won’t cause it to output because it needs a value greater than 0 first
However, 1 → 0 will work because it first gives a value greater than 0.

3 Likes

XD how did I overlook that I am so dumb

1 Like

Thank you so very much for solving this for me. I’m still not used to thinking in terms of Flowlab coding. I had no idea that using a Switch block in the way you described would solve things for me.

Could you please verify that the following screenshot is the most efficient way to make the ingame timer deduct one life from the player once it runs out of time? It appears to work from my testing, but I’d like to know if I’m on the right track here.

How would I go about using “Parent objects”? This Flowlab blog entry outlines the procedure, but doesn’t go into detail about how you would actually set the code for the Parent object, in this case a damaging enemy or hazard. Do I set up a sprite block, label it “Enemy,” then code it to deduct one health point upon collision with the player, then just select the “Enemy” block as the Parent for the enemies in my game that damage the player? Do I then delete the block from all levels (but keep it in my sprite library)?

Speaking of that, what do I do about hazards (stationary dangers) or enemies that deduct more than one health point from the player character upon collision with the player character? Or projectiles emitted from enemies that damage the player on contact as well? Do those get separate Parent objects? Or would a projectile that deducts just one Health point from the player on contact be lumped into the “Enemy” parent object mentioned by the blog entry?

I have some other questions regarding Global variables as well. If I want to make the Health points value a Global variable (so if the player gets more than 3 Health points at the end of a level, the Health points will be retained if the player has more than 3 after progressing to the next level), do I duplicate your code regarding the “Lives” Global variable, including the Switch block, in case the Health points value is less than three?

It appears to be all good :+1:

Parent objects do copy code, but I was thinking more of their other property of being considered the same collision type.

So you’d created a parent object, let’s call it “Parent Enemy”.
Then, set this object as the parent for the things that damage the player.
Now inside the player, you have several Collision behaviors set to different dangerous stuff, instead you can now set it to the “Parent Enemy” object. If “Bat” has “Parent Enemy” as it’s Parent, then it will activate any Collision behaviors looking for the “Parent Enemy” object.

Yeah that should work for being able to keep health increases between levels. However if the player only has 2 health when moving on, that will be kept as well.
So to fix this, you’d want to set the Filter to “Less than 3”. Then, after the new Health Global it should connect to a Switch, and that Switch is what connects to the Filter. This *Switch will then turn itself off.
What this will do is check if the player health is below 3, in which case it will set it to 3. The new Switch in front of the Global is so that when the player takes damage and falls below 3 Hp, the health won’t once again be set to 3.

How would I do something similar with globals, but for rewards/gaining currency?