Hey everyone,
I am pretty new to Codea and I wanted to make a mini game to test my skills, but I have some difficulties with making a Zelda-like health bar made out of 10 hearts. This means that everytime something hits my Hero, the heart on the far right becomes a “half-heart” and if it happens again the heart becomes empty. Then it continues with the heart on its left, again and again until all the hearts are empty. I’ve already drawn the 3 stages a heart can have and made them into sprites, but I am struggling with making the code to make the health diminish. I thought of having a table Hearts= {full, full,full, full,full, full,full, full,full, full} and a variable Health = 20 and everytimes the Health decreases by one, the first heart on the far right to be not empty, becomes either a Half-heart or empty depending on its previous state. Do you have any suggestions or ideas on how I could make it? I am sorry if it is a little complicated and not well explained, I’m not a native speaker in english
Thank you very much for taking the time to help me. Have a nice day
ColourCoder
@ColourCoder Here’s a start. You’ll probably have to change this to fit your needs.
displayMode(FULLSCREEN)
function setup()
h=readImage("Planet Cute:Heart")
-- create half a heart sprite
setContext(h)
fill(0)
rect(h.width/2,0,h.width/2,h.height)
setContext()
-- number of hearts
nbr=10
end
function draw()
background(0)
fill(255)
text("tap screen",WIDTH/2,HEIGHT/2)
-- draw full hearts
for z=1,nbr do
sprite("Planet Cute:Heart",200+40*z,300,40)
end
-- draw half heart
if nbr>0 and nbr%1~=0 then
sprite(h,200+40*(nbr+1-nbr%1),300,40)
end
end
function touched(t)
if t.state==BEGAN then
nbr=nbr-.5
end
end
Here’s a heart health bar in a class, just replace the images with the ones you are going to use. I just used a green gem for a full heart and a yellow gem for a half heart (which, now that I think of it, is kind of funny since your name is ColourCoder and the gem changes color).
EDIT: changed something in the code that caused an error
--# Main
-- Health
function setup()
print("tap the screen to lose health")
fullHeart = readImage("Planet Cute:Gem Green")
halfHeart = readImage("Planet Cute:Gem Orange")
h = HeartHealthBar(WIDTH/2, HEIGHT/2, 400)
end
function draw()
background(0, 0, 0, 255)
h:draw()
end
function touched(touch)
if touch.state==BEGAN then
h:loseHealth()
end
end
--# HeartHealthBar
HeartHealthBar = class()
function HeartHealthBar:init(x, y, w)
self.x = x
self.y = y
self.w = w
self.health = {}
for i=1, 10 do
table.insert(self.health, {num=i, typ="full"})
end
end
function HeartHealthBar:draw()
translate(self.x-self.w/2, self.y)
for a,b in pairs(self.health) do
if b.typ == "full" then
sprite(fullHeart, b.num*self.w/10, 0, self.w/10)
elseif b.typ == "half" then
sprite(halfHeart, b.num*self.w/10, 0, self.w/10)
end
end
end
function HeartHealthBar:loseHealth()
if self.health[#self.health] then
if self.health[#self.health].typ=="full" then
self.health[#self.health].typ="half"
else
self.health[#self.health]=nil
end
end
end
@ColourCoder If you’re after a class, here’s my above code written as a class. You give it the x,y position, the number of hearts to start with, and the size of the hearts.
displayMode(FULLSCREEN)
function setup()
-- x pos, y pos, nbr of hearts, size of hearts
hb=healthBar(0,300,10,70)
end
function draw()
background(0)
fill(255)
text("tap screen",WIDTH/2,HEIGHT/2)
hb:draw()
end
function touched(t)
if t.state==BEGAN then
hb:touched(t)
end
end
healthBar = class()
function healthBar:init(x,y,nbr,size)
self.x=x
self.y=y
self.nbr=nbr
self.size=size
self.h=readImage("Planet Cute:Heart")
setContext(self.h)
fill(0)
rect(self.h.width/2,0,self.h.width/2,self.h.height)
setContext()
end
function healthBar:draw()
for z=1,self.nbr do
sprite("Planet Cute:Heart",self.x+self.size*z,self.y,self.size)
end
if self.nbr>0 and self.nbr%1~=0 then
sprite(self.h,self.x+self.size*(self.nbr+1-self.nbr%1),self.y,self.size)
end
end
function healthBar:touched(t)
if t.state==BEGAN then
self.nbr=self.nbr-.5
end
end
I updated my code using @dave1707’s method for making a half heart, with a slight variation. I changed the blendmode so that instead of just adding a black rectangle to the heart image, it makes that part of the image transparent.
--# Main
-- HeartHealthBar
function setup()
values={bgc=0}
tween(2.0, values, {bgc=75}, {loop=tween.loop.pingpong})
-- these two lines change the background color so that you know that the half hearts are transparent
print("tap the screen to lose health")
fullHeart = readImage("Planet Cute:Heart")
halfHeart = readImage("Planet Cute:Heart")
setContext(halfHeart)
fill(0, 0, 0, 255)
blendMode(ZERO, ONE_MINUS_SRC_ALPHA)
rect(halfHeart.width/2, 0, halfHeart.width/2, halfHeart.height)
setContext()
blendMode(NORMAL)
h = HeartHealthBar(WIDTH/2, HEIGHT/2, 400)
end
function draw()
background(math.floor(values.bgc))
h:draw()
end
function touched(touch)
if touch.state==BEGAN then
h:loseHealth()
end
end
--# HeartHealthBar
HeartHealthBar = class()
function HeartHealthBar:init(x, y, w)
self.x = x
self.y = y
self.w = w
self.health = {}
for i=1, 10 do
table.insert(self.health, {num=i, typ="full"})
end
end
function HeartHealthBar:draw()
translate(self.x-self.w/2, self.y)
for a,b in pairs(self.health) do
if b.typ == "full" then
sprite(fullHeart, b.num*self.w/10, 0, self.w/10)
elseif b.typ == "half" then
sprite(halfHeart, b.num*self.w/10, 0, self.w/10)
end
end
end
function HeartHealthBar:loseHealth()
if self.health[#self.health] then
if self.health[#self.health].typ=="full" then
self.health[#self.health].typ="half"
else
self.health[#self.health]=nil
end
end
end
Thank you very much guys!!!
@Saturn031000 I tried to change your codes a little bit so that you can actually see empty hearts. However I’ve come across a weird problem: the hearts do not empty in a “continuous flow”. I’ve spend hours trying to fix it but in vain. Is there anyway you could help me out on this? Here’s my code:
-- Test
function setup()
Grid:init()
parameter.integer("Health",0,20,20)
Hearts = {3,3,3,3,3,3,3,3,3,3}
Hearts[0] = 3
end
function draw()
background(0, 0, 0, 255) --black
Grid:draw()
for i=0,19 do
if Health<=i then
Hearts[math.floor(i/2)+1] = 2
end
if Health>=i then
Hearts[math.floor(i/2)+1] = 3
end
for j=1,10 do
if Hearts[j-1] == 2 or Hearts[j-1] == 1 then
Hearts [j] = 1
end
if Health == 0 then
Hearts[1] = 1
end
if Hearts[j] == 3 then
sprite("Documents:FullHeart",j*10,100,10)
end
if Hearts[j] == 2 then
sprite("Documents:HalfHeart",j*10,100,10)
end
if Hearts[j] == 1 then
sprite("Documents:heartempty",j*10,100,10)
end
end
end
end
Whoops I used the wrong button. Here’s my code:
-- Test
function setup()
Grid:init()
parameter.integer("Health",0,20,20)
Hearts = {3,3,3,3,3,3,3,3,3,3}
Hearts[0] = 3
end
function draw()
background(0, 0, 0, 255) --black
Grid:draw()
for i=0,19 do
if Health<=i then
Hearts[math.floor(i/2)+1] = 2
end
if Health>=i then
Hearts[math.floor(i/2)+1] = 3
end
for j=1,10 do
if Hearts[j-1] == 2 or Hearts[j-1] == 1 then
Hearts [j] = 1
end
if Health == 0 then
Hearts[1] = 1
end
if Hearts[j] == 3 then
sprite("Documents:FullHeart",j*10,100,10)
end
if Hearts[j] == 2 then
sprite("Documents:HalfHeart",j*10,100,10)
end
if Hearts[j] == 1 then
sprite("Documents:heartempty",j*10,100,10)
end
end
end
end
@ColourCoder, try putting your code between three ~'s, it’ll make it easier to copy your code. (The mods should fix it for you if you don’t know what I mean)
The ~~~ should be on a line by themselves.
Try pressing return after the tildes and put the second set on their own line. Your code should be ‘sandwiched’ between the tildes @ColourCoder
Thanks! So here is my code if anybody can help me out:
-- Test
function setup()
Grid:init()
parameter.integer("Health",0,20,20)
Hearts = {3,3,3,3,3,3,3,3,3,3}
Hearts[0] = 3
end
function draw()
background(0, 0, 0, 255) --black
Grid:draw()
for i=0,19 do
if Health<=i then
Hearts[math.floor(i/2)+1] = 2
end
if Health>=i then
Hearts[math.floor(i/2)+1] = 3
end
for j=1,10 do
if Hearts[j-1] == 2 or Hearts[j-1] == 1 then
Hearts [j] = 1
end
if Health == 0 then
Hearts[1] = 1
end
if Hearts[j] == 3 then
sprite("Documents:FullHeart",j*10,100,10)
end
if Hearts[j] == 2 then
sprite("Documents:HalfHeart",j*10,100,10)
end
if Hearts[j] == 1 then
sprite("Documents:heartempty",j*10,100,10)
end
end
end
end
We dont have the Grid class
@ColourCoder Any sprite you use from your Documents folder isn’t available to anyone on the forum. It’s only useable by you.