# Help: Using tile graphics to represent health value. How do I make it scalable, as opposed to hardcoding values?

I'm trying to make a Zelda-styled health system with hearts and half hearts representing the amount of health the player has.

My initial implementation looks like this:

``````on load do

// set starting health and max health
hearts = 6
heartsMax = 6
heartPieces = 0

end

on draw do

// Hearts UI
if hearts==6 then
tell 0,0 to
swap "heart_full"
end
tell 1,0 to
swap "heart_full"
end
tell 2,0 to
swap "heart_full"
end
end

if hearts==5 then
tell 0,0 to
swap "heart_full"
end
tell 1,0 to
swap "heart_full"
end
tell 2,0 to
swap "heart_half"
end
end

if hearts==4 then
tell 0,0 to
swap "heart_full"
end
tell 1,0 to
swap "heart_full"
end
tell 2,0 to
swap "heart_empty"
end
end

if hearts==3 then
tell 0,0 to
swap "heart_full"
end
tell 1,0 to
swap "heart_half"
end
tell 2,0 to
swap "heart_empty"
end
end

if hearts==2 then
tell 0,0 to
swap "heart_full"
end
tell 1,0 to
swap "heart_empty"
end
tell 2,0 to
swap "heart_empty"
end
end

if hearts==1 then
tell 0,0 to
swap "heart_half"
end
tell 1,0 to
swap "heart_empty"
end
tell 2,0 to
swap "heart_empty"
end
end
end
``````

This is working as intended, and I can gain and lose health as expected.

My question then, is how would I make this scalable to allow for increasing the max health? Is it possible without hardcoding every swap for every possible value of health? I'm trying to avoid a game where the player could theoretically gain up to 20 hearts, which means I would need to hard code 40 (because there are hearts and half hearts) blocks of swaps for every possible value of health.

If hardcoding it is my only option then just knowing that is helpful, but I was hoping there was some math solution of using variable values in the swap coordinates to sort of dynamically draw the hearts depending on any health value the character might have.

Thanks!
DMCA Quest.zip (5.3 KB)

You could try using the `label` function with embed commands. If you set your font size to half width then you should be able to embed as many hearts as you need

do you mean editing the font to replace some of the symbols with hearts? I hadn't thought of using `label`

Oh you could do that, but I meant using the special embed syntax, like follows:

``````label "{embed:heartLeft}{embed:heartRight}" at 0,0
``````

Where `heartLeft` and `heartRight` are tiles in your room. You just need to note that when using a half width font, only the left half of the tile will be printed

Alternatively if you don't want to use a half width font project-wide, you could just make a tile that is a whole heart, and another that is just the left half, and use that with embed, as the half heart will only ever be at the end of the string

I see. would there be a way to tell it how many hearts to embed based on the value of `hearts` variable?

Otherwise, I would still be creating a conditional `label` command for every variation of possible heart values, but that does still look to be less total code if I went that route.

You could use division and modulo to tell you both how many hearts as well as whether or not you need a half.

1 Like

Well that's above my current knowledge as a "literally just started programming when Pulp released" newbie, but I will try to learn how to use modulo and implement this. Thanks!

Yeah I think you could do that like this:

``````hearts = 3

heartCounter = hearts
if hearts>0 then
heartString = "{embed:heart}"
heartCounter--
end

while heartCounter>0 do
heartString = "{heartString}{embed:heart}"
end

if heartString!=0 then
label "{heartString}" at 0,0
end
``````

Note that this doesn't take into account the half hearts, but it should get you started!

On its own, my above post isn't very clear, so here's a working player script showing what I mean. The a button increases the heart halves and the b button decreases them.

``````on load do
halves = 15
heartString = ""
call "updateHearts"
end

on cancel do
if halves>0 then
halves--
call "updateHearts"
end
end

on confirm do
if halves<20 then
halves++
call "updateHearts"
end
end

on updateHearts do
log "halves: {halves}"

hearts = halves
x = hearts
y = 2
call "modulo"

heartString = ""
if mod!=0 then
hearts--
end

hearts /= 2
while hearts>0 do
heartString = "{heartString}{embed:heart}"
hearts--
end

if mod!= 0 then
heartString = "{heartString}{embed:half}"
end
end

on draw do
if heartString!="" then
label "{heartString}" at 0,0
end
end

on modulo do
mod = x
mod /= y
mod -= floor mod
mod *= y
end
``````
5 Likes

Wow, that looks great! I'll have to take some time to study this since it's currently above my skill level, but it definitely seems like it solves my problem so I'll mark it as the solution.

Thanks for the help and providing a working example!

2 Likes

modulo in this case might be overkill, since you're always only dividing by 2. You just need to compare the value of hearts after dividing by 2 to the floor of hearts.

``````heartString = ""
hearts = halves
hearts /= 2

half = hearts
hearts = floor hearts
half -= hearts

while hearts > 0 do
heartString = "{heartString}{embed:heart}"
hearts--
end
if half != 0 then
heartString = "{heartString}{embed:half}"
end

``````

edit: I realize this isn't much of a contribution to the answer, it might be just a little easier for a new programmer to follow.

2 Likes

True, modulo would be more useful for something like 4 pieces per heart or if you wanted to split the hearts onto multiple rows.

I've been using your example code in a separate project to try and tweak it to my needs and it's working! Based off your example I was also able to make it draw the "empty" hearts as well so that the player always knows what their maximum health is, and it's all scalable!

Now you've essentially solved my problem, which I am grateful for, but if you're able could you offer some more insight into one part of your code that I don't quite understand?

I actually think I grasp the whole `modulo` function now and how it's determining whether to draw a half or whole heart, but I still don't actually understand how the `while` loop is working?

``````while hearts>0 do
heartString = "{heartString}{embed:heart}"
hearts--
end
``````

I understand that it's decrementing `hearts` each loop until it reaches 0, but I'm just not understanding the syntax of how `embed` works. How is it drawing multiple hearts? Is the value of `heartString` telling it how many `heart` tiles to embed? Is it embeding an extra tile every loop until it reaches 0?

I guess just an overhead view of the logic would help, but again, you've already solved my problem so thank you for that!

(Here's my modified project in case anyone wants to check it out)
hearts test.zip (2.7 KB)

4 Likes

That's awesome! Well done on extending it to support empty hearts!

Maybe simplifying the code a bit might help. Here's an example without the embedding which might make it clearer:

``````s = "It goes on"
num = 3
while num>0 do
s = "{s} and on"
num--
end

log "{s}" // "It goes on and on and on and on"
``````

It's worth noting that in many other programming languages, `"{s} and on"` could just as easily be written as `s + " and on"`. The idea being that the string `s`, in this case, has " and on" appended to it each iteration.

So, in our hearts code, each iteration of the while loop will append a new heart to the end of the current `heartString` variable (which starts empty) so that we end up with the number of hearts we are expecting. Also, as above, the `heartString = "{heartString}{embed:heart}"` code can be thought of just as equivalent to `heartString = heartString + heartTile`.

Regarding the embed syntax, it just replaces the `{embed:heart}` with a single heart tile at that point in the string.

2 Likes