Tutorials
Tutorials

This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this tutorial in English

HUD - projeto de exemplo

Neste projeto de exemplo, que você pode abrir pelo editor ou baixar do GitHub, demonstramos efeitos para contagem de pontuação. As pontuações aparecem aleatoriamente pela tela, simulando um jogo em que o jogador obtém pontos em posições diferentes.

As pontuações flutuam por um tempo depois de aparecerem. Para conseguir isso, definimos as pontuações como transparentes e depois fazemos a cor aparecer gradualmente. Também as animamos para cima. Isso é feito em on_message() abaixo.

Depois, elas se movem para a pontuação total no topo da tela, onde são somadas. Elas também desaparecem levemente enquanto se movem para cima. Isso é feito em float_done().

Quando chegam à pontuação no topo, seus valores são adicionados a uma pontuação-alvo, em direção à qual a pontuação total faz a contagem. Isso é feito em swoosh_done().

Quando o script é atualizado, ele verifica se a pontuação-alvo aumentou e se a pontuação total precisa ser contada para cima. Quando isso é verdadeiro, a pontuação total é incrementada em um passo menor. A escala da pontuação total é então animada para criar um efeito de quique. Isso é feito em update().

Cada vez que o total é incrementado, criamos uma quantidade de estrelas menores e as animamos para fora da pontuação total. As estrelas são criadas, animadas e removidas em spawn_stars(), fade_out_star() e delete_star().

-- file: hud.gui_script
-- velocidade com que a pontuacao aumenta por segundo
local score_inc_speed = 1000

function init(self)
    -- a pontuacao-alvo e a pontuacao atual no jogo
    self.target_score = 0
    -- a pontuacao atual sendo contada ate a pontuacao-alvo
    self.current_score = 0
    -- a pontuacao como exibida no hud
    self.displayed_score = 0
    -- mantem uma referencia ao node que exibe a pontuacao para uso posterior abaixo
    self.score_node = gui.get_node("score")
end

local function delete_star(self, star)
    -- a estrela terminou a animacao, remova-a
    gui.delete_node(star)
end

local function fade_out_star(self, star)
    -- faz a estrela desaparecer antes da remocao
    gui.animate(star, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 0), gui.EASING_INOUT, 0.2, 0.0, delete_star)
end

local function spawn_stars(self, amount)
    -- posicao do node de pontuacao, usada para posicionar as estrelas
    local p = gui.get_position(self.score_node)
    -- distancia da posicao onde a estrela e criada
    local start_distance = 0
    -- distancia onde a estrela para
    local end_distance = 240
    -- distancia angular entre cada estrela no circulo de estrelas
    local angle_step = 2 * math.pi / amount
    -- randomiza o angulo inicial
    local angle = angle_step * math.random()
    for i=1,amount do
        -- incrementa o angulo pelo passo para obter uma distribuicao uniforme de estrelas
        angle = angle + angle_step
        -- direcao do movimento da estrela
        local dir = vmath.vector3(math.cos(angle), math.sin(angle), 0)
        -- posicoes inicial/final da estrela
        local start_p = p + dir * start_distance
        local end_p = p + dir * end_distance
        -- cria o node da estrela
        local star = gui.new_box_node(vmath.vector3(start_p.x, start_p.y, 0), vmath.vector3(30, 30, 0))
        -- define sua textura
        gui.set_texture(star, "star")
        -- define como transparente
        gui.set_color(star, vmath.vector4(1, 1, 1, 0))
        -- aparece gradualmente
        gui.animate(star, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_OUT, 0.2, 0.0, fade_out_star)
        -- anima a posicao
        gui.animate(star, gui.PROP_POSITION, end_p, gui.EASING_NONE, 0.55)
    end
end

function update(self, dt)
    -- verifica se a pontuacao precisa ser atualizada
    if self.current_score < self.target_score then
        -- incrementa a pontuacao para este passo de tempo ate alcancar a pontuacao-alvo
        self.current_score = self.current_score + score_inc_speed * dt
        -- limita a pontuacao para que ela nao passe da pontuacao-alvo
        self.current_score = math.min(self.current_score, self.target_score)
        -- arredonda a pontuacao para baixo para exibi-la sem decimais
        local floored_score = math.floor(self.current_score)
        -- verifica se a pontuacao exibida deve ser atualizada
        if self.displayed_score ~= floored_score then
            -- atualiza a pontuacao exibida
            self.displayed_score = floored_score
            -- atualiza o texto do node de pontuacao
            gui.set_text(self.score_node, string.format("%d p", self.displayed_score))
            -- define a escala do node de pontuacao um pouco maior que o normal
            local s = 1.3
            gui.set_scale(self.score_node, vmath.vector3(s, s, s))
            -- entao anima a escala de volta para o valor original
            s = 1.0
            gui.animate(self.score_node, gui.PROP_SCALE, vmath.vector3(s, s, s), gui.EASING_OUT, 0.2)
            -- cria estrelas
            spawn_stars(self, 4)
        end
    end
end

-- esta funcao armazena a pontuacao adicionada para que a pontuacao exibida possa ser contada na funcao update
local function swoosh_done(self, node)
    -- recupera a pontuacao do node
    local amount = tonumber(gui.get_text(node))
    -- aumenta a pontuacao-alvo; veja a funcao update para saber como a pontuacao e atualizada para corresponder a ela
    self.target_score = self.target_score + amount
    -- remove a pontuacao temporaria
    gui.delete_node(node)
end

-- esta funcao anima o node depois que ele flutuou, fazendo-o partir rapidamente em direcao a pontuacao total exibida
local function float_done(self, node)
    local duration = 0.2
    -- parte rapidamente em direcao a pontuacao exibida
    gui.animate(node, gui.PROP_POSITION, gui.get_position(self.score_node), gui.EASING_IN, duration, 0.0, swoosh_done)
    -- tambem desaparece parcialmente durante esse movimento
    gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 0.6), gui.EASING_IN, duration)
end

function on_message(self, message_id, message, sender)
    -- registra a pontuacao adicionada; esta mensagem poderia ser enviada por qualquer um que queira incrementar a pontuacao
    if message_id == hash("add_score") then
        -- cria um novo node de pontuacao temporario
        local node = gui.new_text_node(message.position, tostring(message.amount))
        -- usa a fonte pequena para ele
        gui.set_font(node, "small_score")
        -- inicialmente transparente
        gui.set_color(node, vmath.vector4(1, 1, 1, 0))
        gui.set_outline(node, vmath.vector4(0, 0, 0, 0))
        -- aparece gradualmente
        gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_OUT, 0.3)
        gui.animate(node, gui.PROP_OUTLINE, vmath.vector4(0, 0, 0, 1), gui.EASING_OUT, 0.3)
        -- flutua
        local offset = vmath.vector3(0, 20, 0)
        gui.animate(node, gui.PROP_POSITION, gui.get_position(node) + offset, gui.EASING_NONE, 0.5, 0.0, float_done)
    end
end

No main.script, recebemos entrada de toque/mouse e então enviamos uma mensagem ao script de GUI para criar novas pontuações usando a posição do toque.

-- Ao clicar/tocar, obtem a posicao do toque e a envia por mensagem ao script de GUI hud, junto com a quantidade de pontos.

function init(self)
    msg.post(".", "acquire_input_focus")
end

function on_input(self, action_id, action)
    local pos = vmath.vector3(action.x, action.y, 0) -- usa input action.x e action.y como posicoes x e y do toque
    if action_id == hash("touch") then
        if action.pressed then
            msg.post("main:/hud#hud", "add_score" , { position = pos, amount = 1500})
        end
    end
end