Is it possible for the hearts and magic bar used in ZSDX to be instead shown as red and blue orbs like in Diablo? I tried to simply use the code and custom graphics but I'm not exactly sure how to compile the graphics to create a HUD.
You can do whatever you want. Try inspiring you with the magic meter from ZSDX , it's more or less the same thing I think. I'm not good enough to help you with the programmation of it, but it's clearly possible (and probably more easy to do than using hearts ^^)
I finally started working on the code for this...
-- DIABLO STYLE HEALTH ORB
local life_bar = {}
function life_bar:new(game)
local object = {}
setmetatable(object, self)
self.__index = self
object:initialize(game)
return object
end
function life_bar:initialize(game)
self.game = game
self.surface = sol.surface.create(48, 48)
self.life_bar_img = sol.surface.create("hud/health_orb.png")
self.container_img = sol.surface.create("hud/health_orb.png")
self.life_displayed = game:get_life()
self.max_life_displayed = 0
self:check()
self:rebuild_surface()
end
-- Checks whether the view displays the correct info
-- and updates it if necessary.
function life_bar:check()
local need_rebuild = false
local max_life = self.game:get_max_life()
local life = self.game:get_life()
-- Maximum health
if max_life ~= self.max_life_displayed then
need_rebuild = true
if self.life_displayed > max_life then
self.life_displayed = max_life
end
self.max_life_displayed = max_life
end
-- Current health
if life ~= self.life_displayed then
need_rebuild = true
local increment
if life < self.life_displayed then
increment = -1
elseif life > self.life_displayed then
increment = 1
end
if increment ~= 0 then
self.life_displayed = self.life_displayed + increment
if (life - self.life_displayed) % 10 == 1 then
--sol.audio.play_sound("magic_bar")
end
end
end
-- Redraw the surface only if something has changed.
if need_rebuild then
self:rebuild_surface()
end
-- Schedule the next check.
sol.timer.start(self.game, 20, function()
self:check()
end)
end
function life_bar:rebuild_surface()
self.surface:clear()
-- Max health
self.container_img:draw(self.surface)
-- Current health
self.life_bar_img:draw_region(0, 0, 2 + self.life_displayed, 8, self.surface)
end
function life_bar:set_dst_position(x, y)
self.dst_x = x
self.dst_y = y
end
function life_bar:on_draw(dst_surface)
if self.max_life_displayed > 0 then
local x, y = self.dst_x, self.dst_y
local width, height = dst_surface:get_size()
if x < 0 then
x = width + x
end
if y < 0 then
y = height + y
end
self.surface:draw(dst_surface, x, y)
end
end
return life_bar
It displays the graphic of the orb but I'm not sure how to make the bar go down vertically since the code was taken from the horizontal magic bar.. :-\
http://imgur.com/Rnxd22S
You just have to draw the rctangle corresponding to the life you have. That seems to be done in the function life_bar:rebuild_surface(), in the last paragraph inside that function. Of course you need to use the coordinates of the region of the picture to draw, so I cannot help you more.
I made the "bar" for the health on the top left corner which is why i set the region coordinates for the code at 0,0 and the orb size is about 48x48. I'm not too sure what change I should make...
The 4 first parameters of the built-in function draw_region allow to draw only a rectangle of the image, to draw only the part of the bar you need to display (which dependends on the life). That's the part you have to modify. All of this is inside the function rebuild_surface().
+1 Diarandor.
Then Starlock must find a solution, for example with a cross-multiplication, to compare one life to the max life. 1 pixel is equal to 1 life if you have max_life = 39 (the height of the health orb), but if max life is different, 1 pixel will not represent 1 life. You should reorganize the sprites of the picture in a 48x48 grid like this (http://forum.solarus-games.org/index.php?action=dlattach;topic=396.0;attach=169;image), it will help you to draw region and also to create animation.
The idea of this orb is very interesting for an old-school game. ;)
EDIT: So interesting that I'm trying to fix and improve your script. :P I will give you the result tomorrow.
EDIT 2: Not exactly, tomorrow...
SEE ATTACHMENT. (http://forum.solarus-games.org/index.php?action=dlattach;topic=396.0;attach=170)
-- DIABLO STYLE HEALTH ORB
-- Script by Starlock from an another script (magic_bar.lua) written by Christopho.
-- Modified by froGgy.
-- v 1.0:
-- First version posted by Starlock. It was named 'life_bar'
-- v 2.0:
-- Tested with SOLARUS version 1.5
-- Script renamed to 'health_orb'. So need changes in ../data/scripts/hud/hud.lua
-- Correction of problems to draw surfaces.
-- Adding get_pixel(l, m). See explanation below.
-- Adding animations (container_surface replaced by container_sprite), so need ../data/sprites/hud/health_orb.dat
-- and need this line 'sprite{ id = "hud/health_orb", description = "HUD: Health Orb" }' in ../data/project_db.dat
-- Adding calls to the sounds.
-- Sprites reorganized in the image. Need new ../data/sprites/hud/health_orb.png
local health_orb = {}
-- Explanation of this local function named 'get_pixel(l, m)'
-- 39 is orb height. So if you change the orb size, replace 39 and 38 by your own values. Idem in rebuild_surface()
-- 1 pixel is equal to 1 life if you have max_life = 39, but if max_life is different, 1 pixel will not represent anymore 1 life,
-- that's why this function is useful.
-- Parameters: l is life and m is max_life.
local function get_pixel(l, m)
local result = (39 * l)/m
local e, d = math.modf(result)
if e == 0 or d >= 0.5 and e ~= 38 then
e = math.ceil(result)
end
return e
end
function health_orb:new(game)
local object = {}
setmetatable(object, self)
self.__index = self
object:initialize(game)
return object
end
function health_orb:initialize(game)
self.game = game
self.surface = sol.surface.create(48, 48)
self.health_orb_img = sol.surface.create("hud/health_orb.png")
self.container_sprite = sol.sprite.create("hud/health_orb")
self.container_sprite:set_animation("normal")
self.life_displayed = self.game:get_life()
self.life_pixel_displayed = 0
self.max_life_displayed = 0
self:check()
self:rebuild_surface()
end
function health_orb:on_started()
-- This function is called when the HUD starts or
-- was disabled and gets enabled again.
-- Unlike other HUD elements, the timers were canceled because they
-- are attached to the menu and not to the game
-- (this is because the hearts are also used in the savegame menu).
self.danger_sound_timer = nil
self:check()
self:rebuild_surface()
end
-- Checks whether the view displays the correct info
-- and updates it if necessary.
function health_orb:check()
local need_rebuild = false
local max_life = self.game:get_max_life()
local life = self.game:get_life()
-- Maximum health
if max_life ~= self.max_life_displayed then
need_rebuild = true
self.max_life_displayed = max_life
self.life_pixel_displayed = get_pixel(self.life_displayed, self.max_life_displayed)
end
-- Current health
if life ~= self.life_displayed then
need_rebuild = true
local increment
if life < self.life_displayed then
increment = -1
elseif life > self.life_displayed then
increment = 1
if self.game:is_started()
and self.life_displayed % 4 == 0 then
sol.audio.play_sound("heart")
end
end
self.life_displayed = self.life_displayed + increment
for i = 1, get_pixel(1, self.max_life_displayed) do
self.life_pixel_displayed = get_pixel(self.life_displayed , self.max_life_displayed)
end
end
-- If we are in-game, play animations and a sound if the life is low.
if self.game:is_started() then
if self.game:get_life() <= self.game:get_max_life() / 4
and not self.game:is_suspended() then
-- Show animations "danger..." of the empty container sprite if not already done.
need_rebuild = true
if self.container_sprite:get_animation() ~= "danger" then
self.container_sprite:set_animation("danger")
end
if self.danger_sound_timer == nil then
self.danger_sound_timer = sol.timer.start(self, 250, function()
self:repeat_danger_sound()
end)
self.danger_sound_timer:set_suspended_with_map(true)
end
else
if self.container_sprite:get_animation() ~= "normal" then
self.container_sprite:set_animation("normal")
need_rebuild = true
end
end
end
-- Redraw the surface only if something has changed.
if need_rebuild then
self:rebuild_surface()
end
-- Schedule the next check.
sol.timer.start(self.game, 50, function()
self:check()
end)
end
function health_orb:repeat_danger_sound()
if self.game:get_life() <= self.game:get_max_life() / 4 then
sol.audio.play_sound("danger")
self.danger_sound_timer = sol.timer.start(self, 750, function()
self:repeat_danger_sound()
end)
self.danger_sound_timer:set_suspended_with_map(true)
else
self.danger_sound_timer = nil
end
end
function health_orb:rebuild_surface()
self.surface:clear()
-- Empty container
self.container_sprite:draw(self.surface)
-- Current health
self.health_orb_img:draw_region(3, (42 - self.life_pixel_displayed), 42, self.life_pixel_displayed, self.surface, 3, (42 - self.life_pixel_displayed))
end
function health_orb:set_dst_position(x, y)
self.dst_x = x
self.dst_y = y
end
function health_orb:on_draw(dst_surface)
if self.max_life_displayed > 0 then
local x, y = self.dst_x, self.dst_y
local width, height = dst_surface:get_size()
if x < 0 then
x = width + x
end
if y < 0 then
y = height + y
end
self.surface:draw(dst_surface, x, y)
end
end
return health_orb
________________________
In ../data/scripts/hud/hud.lua with other elements:
-- blablabla
local health_orb_builder = require("scripts/hud/health_orb")
-- blablabla
-- Then, example of position!
menu = health_orb_builder:new(game)
menu:set_dst_position(-104, 6)
hud.elements[#hud.elements + 1] = menu
________________________
In ../data/project_db.dat:
sprite{ id = "hud/health_orb", description = "HUD: Health Orb" }
________________________
In a ../data/sprites/hud/health_orb.dat (http://forum.solarus-games.org/index.php?action=dlattach;topic=396.0;attach=171) with the health_orb.png (http://forum.solarus-games.org/index.php?action=dlattach;topic=396.0;attach=169;image):
animation{
name = "danger",
src_image = "hud/health_orb.png",
frame_delay = 200,
frame_to_loop_on = 0,
directions = {
{ x = 0, y = 48, frame_width = 48, frame_height = 45, origin_x = 0, origin_y = 0, num_frames = 4 },
},
}
animation{
name = "normal",
src_image = "hud/health_orb.png",
directions = {
{ x = 48, y = 0, frame_width = 48, frame_height = 45, origin_x = 0, origin_y = 0 },
},
}