Implementing a Health Status Bar in Corona SDK
Implementing a Health Status Bar in Corona SDK
Many games need a way to show the players how well they are doing. It could be a simple counter to show the number of lives left or a bar that decreases and increases as a players energy goes up and down.
![]()
There are as many different ways to do this as there are games but lets look at a couple of different ways.
The simplest may be simply using text to display the health status:
|
1 2 3 4 5 |
local lives = 5 local livesLabel = display.newText("Lives: ", 10, 30, native.systemFont, 16) local livesValue = display.newText(string.format("%d", lives), livesLabel.contentWidth+20,30,native.systemFontBold, 16) livesLabel:setTextColor(225,225,225) livesValue:setTextColor(255,255,255) |
Then later in your code when a player looses a life (or gains one back) simply change the text value of “livesValue” and Corona will magically update the value for you:
|
1 2 3 4 |
if lives > 0 then lives = lives - 1 end livesValue.text = string.format("%d", lives) |
Of course you might want to drop a graphic behind the text, set the colors accordingly, and possibly drop a duplicate text string underneath offset by a pixel to give a little stroke/shadow to the text.
But our players expect more from games and a simple text display won’t be accepted as high quality. Traditional arcade games have shown your lives as small versions of your player’s graphic. If your game involves a ship, perhaps you see a display of 5 little ships to show your life count.
With a display of say 5 small rockets, you will need one image and you will replicate it several times.
|
1 2 3 4 5 6 7 8 9 |
local lifeIcons = {} local lives = 5 local maxLives = 5 local i for i = 1, maxLives do lifeIcons[i] = display.newImage("lifeicon.png") lifeIcons[i].x = 10 + (lifeIcons[i].contentWidth * (i - 1)) lifeIcons[i].y = 30 -- start at 10,10 end |
This will create a display of 5 little icons that shows your full life status. Later in your code when you need to change the display:
|
1 2 3 4 |
if lives > 0 then lifeIcons[lives].isVisible = false lives = lives - 1 end |
Later when you need to give a life back:
|
1 2 3 4 5 |
lives = lives + 1 if lives > maxLives then lives = maxLives end lifeIcons[lives].isVisible = true |
But what if you want more of a bar-graph display. As long as you’re using discrete values, you can continue to use a similar method using different graphics for each value, in this example, there are 5 lives, so you can create 5 different graphics for each of the 5 life states.
![]()
Instead of using a loop to load in the same graphic, you would need to load in each of the separate five graphics in and position them all at the same location:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
local lifeIcons = {} local lives = 5 local maxLives = 5 lifeBar[0] = display.newImage("lifeicon0.png") lifeBar[1] = display.newImage("lifeicon1.png") lifeBar[2] = display.newImage("lifeicon2.png") lifeBar[3] = display.newImage("lifeicon3.png") lifeBar[4] = display.newImage("lifeicon4.png") lifeBar[5] = display.newImage("lifeicon5.png") local i for i = 1, maxLives do lifeBar[i].x = 10 lifeBar[i].y = 30 lifeBar[i].isVisible = false end lifeBar[lives].isVisible = true |
Then to change the graphic:
|
1 2 3 4 5 |
if lives > 0 then lifeBar[lives].isVisible = false lives = lives - 1 lifeBar[lives].isVisible = true end |
This same concept can be done with MovieClips.
|
1 2 3 4 |
healthSprites = movieclip.newAnim{"lifeicon1.png", "lifeicon2.png", "lifeicon3.png", "lifeicon4.png", "lifeicon5.png", "lifeicon0.png"} healthSprites.x = 50 healthSprites.y = 10 healthSprites:play{startFrame=1, endFrame=lives, loop=1, remove=false} |
Then to show the current health level:
[/crayon]
lives = lives – 1
if lives < 0 then
lives = 0
end
if lives == 0 then
healthSprites:play{startGrame=6, endFrame=6, loop=1, remove=false}
else
healthSprites:play{startFrame=1, endFrame=lives, loop=1, remove=false}
end
[/crayon]
This gives you the benefit of a little animation as well. Unlike the example above, we load in the “No life left” graphic in frame 6, because movieclip starts at frame 1. We could have put frame 0 first, and just done a “lives + 1″ to get the right offset.
Hope this is helpful!


just wondering how i would implement the health bar into storybaord. i tried accessing in another scene but nothing happens. heres my code
main.lua
-----------------------------------------------------------------------------------------
-- main.lua
-----------------------------------------------------------------------------------------
display.setStatusBar( display.HiddenStatusBar )
-- require controller module
local storyboard = require "storyboard"
local widget = require "widget"
storyboard.health = 100
-- comment out below four lines to remove FPS status
--local fps = require("fps")
--local performance = fps.PerformanceOutput.new();
--performance.group.x, performance.group.y = 50, 0;
--performance.alpha = 0.2; -- So it doesn't get in the way of the rest of the scene
-- load first screen
storyboard.gotoScene( "scene1", "fade", 400 )
storyboard.healthLabel = display.newText("Health: ", 10, 295, native.systemFont, 16)
storyboard.healthValue = display.newText(string.format("%d", storyboard.health), storyboard.healthLabel.contentWidth+20,295,native.systemFontBold, 16)
storyboard.healthLabel:setTextColor(225,225,225)
storyboard.healthValue:setTextColor(255,255,255)
scene2.lua
---------------------------------------------------------------------------------
-- ROOM 2
---------------------------------------------------------------------------------
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local lastScene = storyboard.getPrevious()
print(storyboard.health) -- should print 100.
---------------------------------------------------------------------------------
-- BEGINNING OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
local background, room3, room5, room7
-- Touch event listener for background image
local function gotoRoom3( self, event )
if event.phase == "began" then
storyboard.gotoScene( "scene3", "fade", 400 )
storyboard.health = storyboard.health + 75
return true
end
end
local function gotoRoom5( self, event )
if event.phase == "began" then
storyboard.gotoScene( "scene5", "fade", 400 )
return true
end
end
local function gotoRoom7( self, event )
if event.phase == "began" then
storyboard.gotoScene( "scene7", "fade", 400 )
return true
end
end
-- Called when the scene's view does not exist:
function scene:createScene( event )
local screenGroup = self.view
background = display.newImage( "assets/graphics/Room2.png", 0, 0 )
screenGroup:insert( background )
room3 = display.newImage( "assets/graphics/gotoRoom3.png", 5, 130 )
screenGroup:insert( room3 )
room3.touch = gotoRoom3
room5 = display.newImage( "assets/graphics/gotoRoom5.png", 175, 5 )
screenGroup:insert( room5 )
room5.touch = gotoRoom5
room7 = display.newImage( "assets/graphics/gotoRoom7.png", 350, 130 )
screenGroup:insert( room7 )
room7.touch = gotoRoom7
print( "\n2: createScene event")
end
-- Called immediately after scene has moved onscreen:
function scene:enterScene( event )
print( "2: enterScene event" )
-- remove previous scene's view
-- storyboard.purgeScene( lastScene )
print( "last scene was:", lastScene ) -- output: last scene name
-- Update Lua memory text display
room3:addEventListener( "touch", room3 )
room5:addEventListener( "touch", room5 )
room7:addEventListener( "touch", room7 )
end
-- Called when scene is about to move offscreen:
function scene:exitScene( event )
print( "2: exitScene event" )
-- remove touch listener for image
room3:removeEventListener( "touch", room3 )
room5:removeEventListener( "touch", room5 )
room7:removeEventListener( "touch", room7 )
end
-- Called prior to the removal of scene's "view" (display group)
function scene:destroyScene( event )
print( "((destroying scene 2's view))" )
end
---------------------------------------------------------------------------------
-- END OF YOUR IMPLEMENTATION
---------------------------------------------------------------------------------
-- "createScene" event is dispatched if scene's view does not exist
scene:addEventListener( "createScene", scene )
-- "enterScene" event is dispatched whenever scene transition has finished
scene:addEventListener( "enterScene", scene )
-- "exitScene" event is dispatched before next scene's transition begins
scene:addEventListener( "exitScene", scene )
-- "destroyScene" event is dispatched before view is unloaded, which can be
-- automatically unloaded in low memory situations, or explicitly via a call to
-- storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( "destroyScene", scene )
---------------------------------------------------------------------------------
return scene
I don’t have time right now to dig into your code. Perhaps this would be better asked on the Corona SDK Forums where more eyes will see it.
But in general terms, any display objects that you DO NOT put into the storyboard “group” group will sit above the storyboard groups as they switch in and out. You could create this in your main.lua, create a group called “controlPanel”, i.e.
controlPanel = display.newGroup()
and put your health bar there and then hide it using either controlPanel.alpha = 0 or controlPanel.isVisible = false and then when you get to a scene where you want it to show just set it the other way. It should then stay above your scene’s display group.
Rob, thanks for the info. ill start asking on the corona SDKforum. how would i update the health bar in other scenes. I’m not to fimilar with how to pass data back and forth between scenes.