Passer au contenu principal
Version: bleeding-edge 🩸

Basic HUD (Canvas)

Comment ajouter un HUD de base en utilisant les fonctionnalités de Render's Canvas pour afficher la santé et les munitions du personnage.

tip

Vous pouvez également créer des interfaces utilisateur complètes et complexes en utilisant HTML + JavaScript + CSS, vérifiez : HUD de base (HTML).

A Canvas is a painting fabric which can be drawn to. The following code shows how to add a basic UI using Canvas:

Client/Index.lua
-- Spawns the Canvas
HUDCanvas = Canvas(true, Color.TRANSPARENT, 0, true)

-- Subscribes for Update event, we can only draw inside this event
HUDCanvas:Subscribe("Update", function(self, width, height)
-- Gets the Local Player
local local_player = Client.GetLocalPlayer()
if (not local_player) then return end

-- Gets the Local Character (possessed by the Local Player)
local local_character = local_player:GetControlledCharacter()
if (not local_character) then return end

-- Draws the Health
self:DrawText(tostring(local_character:GetHealth()), Vector2D(100, height - 100), FontType.PoiretOne, 25, Color.WHITE)

-- Gets the Local Weapon
local character_weapon = local_character:GetPicked()
if (character_weapon and character_weapon:GetType() == "Weapon") then
-- Draws the Ammo Clip
self:DrawText(tostring(character_weapon:GetAmmoClip()), Vector2D(width - 200, height - 100), FontType.PoiretOne, 25, Color.WHITE)

-- Draws the Ammo Bag
self:DrawText("/ " .. tostring(character_weapon:GetAmmoBag()), Vector2D(width - 140, height - 87), FontType.PoiretOne, 15, Color.WHITE)
end
end)

The example above re-renders and updates all health/ammo information ever tick, which could be bad for performance. Gladly we can fast improve it by limiting the auto repaint rate by changing it in the constructor:

-- Instead of 0 in the auto_repaint_rate parameter
HUDCanvas = Canvas(true, Color.TRANSPARENT, 0, true)

-- Use 0.033, so it only updates every 0.033ms (i.e. at 30 fps)
// highlight-next-line
HUDCanvas = Canvas(true, Color.TRANSPARENT, 0.033, true)

Another further optimization is to only update when needed, for this case we will need to implement some additional code. In this case, we set auto_repaint_rate to -1 to disable it from being auto repainted:

-- We set -1 to never auto repaint
HUDCanvas = Canvas(true, Color.TRANSPARENT, -1, true)

-- Subscribes for Update event, we can only draw inside this event (as usual)
HUDCanvas:Subscribe("Update", function(self, width, height)
-- Gets the Local Player
local local_player = Client.GetLocalPlayer()
if (not local_player) then return end

-- Gets the Local Character (possessed by the Local Player)
local local_character = local_player:GetControlledCharacter()
if (not local_character) then return end

-- Draws the Health
self:DrawText(tostring(local_character:GetHealth()), Vector2D(100, height - 100), FontType.PoiretOne, 25, Color.WHITE)

-- Gets the Local Weapon
local character_weapon = local_character:GetPicked()
if (character_weapon and character_weapon:GetType() == "Weapon") then
-- Draws the Ammo Clip
self:DrawText(tostring(character_weapon:GetAmmoClip()), Vector2D(width - 200, height - 100), FontType.PoiretOne, 25, Color.WHITE)

-- Draws the Ammo Bag
self:DrawText("/ " .. tostring(character_weapon:GetAmmoBag()), Vector2D(width - 140, height - 87), FontType.PoiretOne, 15, Color.WHITE)
end
end)


-- Now we subscribe for when we want it to be updated:

-- When LocalPlayer spawns, sets an event on it to trigger when we possesses a new character, to store the local controlled character locally. This event is only called once, see Package.Subscribe("Load") to load it when reloading a package
Client.Subscribe("SpawnLocalPlayer", function(local_player)
local_player:Subscribe("Possess", function(player, character)
UpdateLocalCharacter(character)
end)
end)

-- When package loads, verify if LocalPlayer already exists (eg. when reloading the package), then try to get and store it's controlled character
Package.Subscribe("Load", function()
local local_player = Client.GetLocalPlayer()
if (local_player ~= nil) then
UpdateLocalCharacter(local_player:GetControlledCharacter())
end
end)

-- Function to set all needed events on local character (to update the UI when it takes damage or dies)
function UpdateLocalCharacter(character)
-- Verifies if character is not nil (eg. when GetControllerCharacter() doesn't return a character)
if (character == nil) then return end

-- Sets on character an event to update the health's UI after it takes damage
character:Subscribe("TakeDamage", function(charac, damage, type, bone, from_direction, instigator, causer)
HUDCanvas:Repaint()
end)

-- Sets on character an event to update the health's UI after it dies
character:Subscribe("Death", function(charac)
HUDCanvas:Repaint()
end)

-- Sets on character an event to update his grabbing weapon (to show ammo on UI)
character:Subscribe("PickUp", function(charac, object)
if (object:GetType() == "Weapon") then
HUDCanvas:Repaint()
end
end)

-- Sets on character an event to remove the ammo ui when he drops it's weapon
character:Subscribe("Drop", function(charac, object)
HUDCanvas:Repaint()
end)

-- Sets on character an event to update the UI when he fires
character:Subscribe("Fire", function(charac, weapon)
HUDCanvas:Repaint()
end)

-- Sets on character an event to update the UI when he reloads the weapon
character:Subscribe("Reload", function(charac, weapon, ammo_to_reload)
HUDCanvas:Repaint()
end)

-- Updates the UI immeditelly
HUDCanvas:Repaint()
end

-- Updates the UI positions when the Viewport (screen) is resized
Client.Subscribe("ViewportResized", function(NewSize)
HUDCanvas:Repaint()
end)