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 - örnek proje

Düzenleyiciden açabileceğiniz veya GitHub üzerinden indirebileceğiniz bu örnek projede, oyun içi bilgi göstergesinde (HUD) puan sayımı için kullanılan efektleri gösteriyoruz. Puanlar ekranda rastgele belirerek oyuncunun farklı konumlarda puan kazandığı bir oyunu simüle eder.

Puanlar belirdikten sonra bir süre süzülür. Bunu sağlamak için puanları saydam hale getirir, ardından renklerini kademeli olarak görünür kılarız. Ayrıca yukarı doğru hareket etmeleri için animasyon uygularız. Bu işlemler aşağıdaki on_message() işlevinde yapılır.

Ardından ekranın üst kısmındaki toplam puana doğru hareket eder ve orada toplanırlar. Yukarı doğru hareket ederken hafifçe soluklaşırlar. Bu işlem float_done() işlevinde yapılır.

Üstteki puana ulaştıklarında değerleri, toplam puanın kademeli olarak ulaşacağı bir hedef puana eklenir. Bu işlem swoosh_done() işlevinde yapılır.

Betik (script) güncellendiğinde hedef puanın artırılıp artırılmadığını ve toplam puanın artırılması gerekip gerekmediğini denetler. Bu koşul sağlandığında toplam puan daha küçük bir adımla artırılır. Ardından, zıplama efekti vermek için toplam puanın ölçeğine animasyon uygulanır. Bu işlem update() işlevinde yapılır.

Toplam puan her artırıldığında belirli sayıda daha küçük yıldız oluşturur ve toplam puandan dışarı doğru hareket etmeleri için onlara animasyon uygularız. Yıldızların oluşturulması, canlandırılması ve silinmesi spawn_stars(), fade_out_star() ve delete_star() işlevlerinde yapılır.

-- file: hud.gui_script
-- how fast the score counts up per second
local score_inc_speed = 1000

function init(self)
    -- the target score is the current score in the game
    self.target_score = 0
    -- the current score being counted up towards the target score
    self.current_score = 0
    -- the score as displayed in the hud
    self.displayed_score = 0
    -- keep a reference to the node displaying the score for later use below
    self.score_node = gui.get_node("score")
end

local function delete_star(self, star)
    -- star has finished animation, delete it
    gui.delete_node(star)
end

local function fade_out_star(self, star)
    -- fade out the star before deletion
    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)
    -- position of the score node, to be used for placing the stars
    local p = gui.get_position(self.score_node)
    -- distance from the position where the star is spawned
    local start_distance = 0
    -- distance where the star stops
    local end_distance = 240
    -- angle distance between each star in the star circle
    local angle_step = 2 * math.pi / amount
    -- randomize start angle
    local angle = angle_step * math.random()
    for i=1,amount do
        -- increment the angle by the step to get an even distribution of stars
        angle = angle + angle_step
        -- direction of the star movement
        local dir = vmath.vector3(math.cos(angle), math.sin(angle), 0)
        -- start/end positions of the star
        local start_p = p + dir * start_distance
        local end_p = p + dir * end_distance
        -- create the star node
        local star = gui.new_box_node(vmath.vector3(start_p.x, start_p.y, 0), vmath.vector3(30, 30, 0))
        -- set its texture
        gui.set_texture(star, "star")
        -- set to transparent
        gui.set_color(star, vmath.vector4(1, 1, 1, 0))
        -- fade in
        gui.animate(star, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_OUT, 0.2, 0.0, fade_out_star)
        -- animate position
        gui.animate(star, gui.PROP_POSITION, end_p, gui.EASING_NONE, 0.55)
    end
end

function update(self, dt)
    -- check if the score needs to be updated
    if self.current_score < self.target_score then
        -- increment the score for this timestep to grow towards the target score
        self.current_score = self.current_score + score_inc_speed * dt
        -- clamp the score so it doesn't grow past the target score
        self.current_score = math.min(self.current_score, self.target_score)
        -- floor the score so it can be displayed without decimals
        local floored_score = math.floor(self.current_score)
        -- check if the displayed score should be updated
        if self.displayed_score ~= floored_score then
            -- update displayed score
            self.displayed_score = floored_score
            -- update the text of the score node
            gui.set_text(self.score_node, string.format("%d p", self.displayed_score))
            -- set the scale of the score node to be slightly bigger than normal
            local s = 1.3
            gui.set_scale(self.score_node, vmath.vector3(s, s, s))
            -- then animate the scale back to the original value
            s = 1.0
            gui.animate(self.score_node, gui.PROP_SCALE, vmath.vector3(s, s, s), gui.EASING_OUT, 0.2)
            -- spawn stars
            spawn_stars(self, 4)
        end
    end
end

-- this function stores the added score so that the displayed score can be counted up in the update function
local function swoosh_done(self, node)
    -- retrieve score from node
    local amount = tonumber(gui.get_text(node))
    -- increase the target score, see the update function for how the score is updated to match the target score
    self.target_score = self.target_score + amount
    -- remove the temp score
    gui.delete_node(node)
end

-- this function animates the node from having floated first to swoosh away towards the displayed total score
local function float_done(self, node)
    local duration = 0.2
    -- swoosh away towards the displayed score
    gui.animate(node, gui.PROP_POSITION, gui.get_position(self.score_node), gui.EASING_IN, duration, 0.0, swoosh_done)
    -- also fade out partially during the swoosh
    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)
    -- register added score, this message could be sent by anyone wanting to increment the score
    if message_id == hash("add_score") then
        -- create a new temporary score node
        local node = gui.new_text_node(message.position, tostring(message.amount))
        -- use the small font for it
        gui.set_font(node, "small_score")
        -- initially transparent
        gui.set_color(node, vmath.vector4(1, 1, 1, 0))
        gui.set_outline(node, vmath.vector4(0, 0, 0, 0))
        -- fade in
        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)
        -- float
        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

main.script dosyasında dokunma/fare girdisini alır, ardından dokunma konumunu kullanarak yeni puanlar oluşturmak için GUI betiğine bir ileti (message) göndeririz.

-- On click/touch get touch position and send it via message to hud gui script as well as the scored point amount.

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) -- use input action.x & action.y as x & y positions of touch
    if action_id == hash("touch") then
        if action.pressed then
            msg.post("main:/hud#hud", "add_score" , { position = pos, amount = 1500})
        end
    end
end