modified the code.
--[[
Voxel Cartoony Healthbar HUD for Roblox
Place this script as a LocalScript in StarterPlayerScripts.
The healthbar appears on the player's screen and updates in real time.
The healthbar is made of "voxel" blocks (cartoony squares) that fill/unfill as health changes.
When the player dies, the bar and all blocks turn red, then the bar tilts, falls off screen, and disappears.
]]
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local LocalPlayer = Players.LocalPlayer
-- Normal theme
local BAR_BLOCKS = 10 -- Number of voxel blocks in the healthbar
local BLOCK_SIZE = UDim2.new(0, 32, 0, 32) -- Size of each block
local BLOCK_SPACING = 8 -- Pixels between blocks
local BAR_BG_COLOR = Color3.fromRGB(30, 20, 60)
local BLOCK_FULL_COLOR = Color3.fromRGB(120, 255, 180)
local BLOCK_EMPTY_COLOR = Color3.fromRGB(255, 120, 120)
local BLOCK_OUTLINE_COLOR = Color3.fromRGB(60, 30, 120)
local BLOCK_OUTLINE_THICKNESS = 3
local BLOCK_CORNER_RADIUS = UDim.new(0, 12)
local GLOW_COLOR = Color3.fromRGB(80, 200, 255)
local GLOW_TRANSPARENCY = 0.4
local GLOW_SIZE_OFFSET = 16
local GLOW_IMAGE = "rbxassetid://5107168713" -- Soft fantasy glow (public domain, fallback to circle if not found)
local CARTOONY_SHADOW = true
-- Death theme (all red)
local DEATH_BAR_BG_COLOR = Color3.fromRGB(60, 0, 0)
local DEATH_BLOCK_FULL_COLOR = Color3.fromRGB(255, 0, 0)
local DEATH_BLOCK_EMPTY_COLOR = Color3.fromRGB(120, 0, 0)
local DEATH_BLOCK_OUTLINE_COLOR = Color3.fromRGB(180, 0, 0)
local DEATH_GLOW_COLOR = Color3.fromRGB(255, 40, 40)
local DEATH_LABEL_COLOR = Color3.fromRGB(255, 0, 0)
local DEATH_LABEL_STROKE = Color3.fromRGB(120, 0, 0)
-- Utility: Create a voxel block
local function createVoxelBlock(parent, index)
local block = Instance.new("Frame")
block.Name = "VoxelBlock"..index
block.Size = BLOCK_SIZE
block.BackgroundColor3 = BLOCK_EMPTY_COLOR
block.BorderSizePixel = 0
block.BackgroundTransparency = 0.4
block.Parent = parent
block.ZIndex = 2
-- Outline
local outline = Instance.new("UIStroke")
outline.Color = BLOCK_OUTLINE_COLOR
outline.Thickness = BLOCK_OUTLINE_THICKNESS
outline.Parent = block
-- Rounded corners
local corner = Instance.new("UICorner")
corner.CornerRadius = BLOCK_CORNER_RADIUS
corner.Parent = block
-- Glow/shadow
if CARTOONY_SHADOW then
local glow = Instance.new("ImageLabel")
glow.Name = "Glow"
glow.BackgroundTransparency = 1
glow.Image = GLOW_IMAGE
glow.ImageColor3 = GLOW_COLOR
glow.ImageTransparency = GLOW_TRANSPARENCY
glow.Size = UDim2.new(1, GLOW_SIZE_OFFSET, 1, GLOW_SIZE_OFFSET)
glow.Position = UDim2.new(0, -GLOW_SIZE_OFFSET//2, 0, -GLOW_SIZE_OFFSET//2)
glow.ZIndex = 1
glow.Parent = block
end
-- Highlight
local highlight = Instance.new("Frame")
highlight.Name = "Highlight"
highlight.Size = UDim2.new(0.5, 0, 0.2, 0)
highlight.Position = UDim2.new(0.25, 0, 0.1, 0)
highlight.BackgroundTransparency = 0.5
highlight.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
highlight.BorderSizePixel = 0
highlight.ZIndex = 3
local highlightCorner = Instance.new("UICorner")
highlightCorner.CornerRadius = UDim.new(1, 0)
highlightCorner.Parent = highlight
highlight.Parent = block
return block
end
-- Create the healthbar GUI
local function createHealthbar()
-- Remove old healthbar if exists
local old = LocalPlayer.PlayerGui:FindFirstChild("CartoonyHealthbar")
if old then old:Destroy() end
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "CartoonyHealthbar"
screenGui.ResetOnSpawn = false
screenGui.IgnoreGuiInset = true
screenGui.Parent = LocalPlayer:WaitForChild("PlayerGui")
-- Calculate bar width
local barWidth = BAR_BLOCKS * BLOCK_SIZE.X.Offset + (BAR_BLOCKS-1)*BLOCK_SPACING + 24
local barHeight = BLOCK_SIZE.Y.Offset + 32
-- Bar background
local barBg = Instance.new("Frame")
barBg.Name = "BarBackground"
barBg.Size = UDim2.new(0, barWidth, 0, barHeight)
barBg.Position = UDim2.new(0.5, -barWidth//2, 0.1, 0)
barBg.AnchorPoint = Vector2.new(0, 0)
barBg.BackgroundColor3 = BAR_BG_COLOR
barBg.BackgroundTransparency = 0.15
barBg.BorderSizePixel = 0
barBg.Parent = screenGui
barBg.ZIndex = 1
local barCorner = Instance.new("UICorner")
barCorner.CornerRadius = UDim.new(0, 18)
barCorner.Parent = barBg
-- Border glow
local borderGlow = Instance.new("ImageLabel")
borderGlow.Name = "BorderGlow"
borderGlow.BackgroundTransparency = 1
borderGlow.Image = GLOW_IMAGE
borderGlow.ImageColor3 = GLOW_COLOR
borderGlow.ImageTransparency = 0.7
borderGlow.Size = UDim2.new(1, 32, 1, 32)
borderGlow.Position = UDim2.new(0, -16, 0, -16)
borderGlow.ZIndex = 0
borderGlow.Parent = barBg
-- Voxel blocks
local blocks = {}
for i = 1, BAR_BLOCKS do
local block = createVoxelBlock(barBg, i)
block.Position = UDim2.new(0, 12 + (i-1)*(BLOCK_SIZE.X.Offset + BLOCK_SPACING), 0, 16)
blocks[i] = block
end
-- "HEALTH" label
local label = Instance.new("TextLabel")
label.Name = "HealthLabel"
label.Text = "♥ HEALTH ♥"
label.Font = Enum.Font.FredokaOne
label.TextColor3 = Color3.fromRGB(255, 255, 255)
label.TextStrokeTransparency = 0.2
label.TextStrokeColor3 = GLOW_COLOR
label.TextScaled = true
label.Size = UDim2.new(1, 0, 0, 32)
label.Position = UDim2.new(0, 0, 0, -32)
label.BackgroundTransparency = 1
label.Parent = barBg
label.ZIndex = 3
-- Label glow
local labelGlow = Instance.new("ImageLabel")
labelGlow.Name = "LabelGlow"
labelGlow.BackgroundTransparency = 1
labelGlow.Image = GLOW_IMAGE
labelGlow.ImageColor3 = GLOW_COLOR
labelGlow.ImageTransparency = 0.7
labelGlow.Size = UDim2.new(1, 24, 0, 32)
labelGlow.Position = UDim2.new(0, -12, 0, -32)
labelGlow.ZIndex = 2
labelGlow.Parent = barBg
-- Add a UIAspectRatioConstraint to keep the bar from stretching weirdly
local aspect = Instance.new("UIAspectRatioConstraint")
aspect.AspectRatio = barWidth / barHeight
aspect.Parent = barBg
return {
gui = screenGui,
blocks = blocks,
barBg = barBg,
borderGlow = borderGlow,
label = label,
labelGlow = labelGlow,
}
end
-- Update the healthbar blocks based on current health
local function updateHealthbar(blocks, health, maxHealth)
local healthPerBlock = maxHealth / BAR_BLOCKS
for i, block in ipairs(blocks) do
if health >= i * healthPerBlock then
block.BackgroundColor3 = BLOCK_FULL_COLOR
block.BackgroundTransparency = 0
if block:FindFirstChild("Glow") then
block.Glow.ImageColor3 = GLOW_COLOR
block.Glow.ImageTransparency = GLOW_TRANSPARENCY
end
elseif health > (i-1) * healthPerBlock then
-- Partial block: use a lighter color
block.BackgroundColor3 = BLOCK_FULL_COLOR:Lerp(BLOCK_EMPTY_COLOR, 0.5)
block.BackgroundTransparency = 0.15
if block:FindFirstChild("Glow") then
block.Glow.ImageColor3 = GLOW_COLOR:Lerp(BLOCK_EMPTY_COLOR, 0.5)
block.Glow.ImageTransparency = GLOW_TRANSPARENCY + 0.2
end
else
block.BackgroundColor3 = BLOCK_EMPTY_COLOR
block.BackgroundTransparency = 0.4
if block:FindFirstChild("Glow") then
block.Glow.ImageColor3 = BLOCK_EMPTY_COLOR
block.Glow.ImageTransparency = 0.7
end
end
end
end
-- Animate the healthbar when taking damage or healing
local function animateBlock(block, isHeal)
local goal = {}
if isHeal then
goal.Size = BLOCK_SIZE + UDim2.new(0, 10, 0, 10)
else
goal.Size = BLOCK_SIZE + UDim2.new(0, 4, 0, 4)
end
local tween = TweenService:Create(block, TweenInfo.new(0.18, Enum.EasingStyle.Back, Enum.EasingDirection.Out), goal)
tween:Play()
tween.Completed:Connect(function()
local resetTween = TweenService:Create(block, TweenInfo.new(0.18), {Size = BLOCK_SIZE})
resetTween:Play()
end)
-- Animate glow as well
if block:FindFirstChild("Glow") then
local glow = block.Glow
local glowGoal = {}
if isHeal then
glowGoal.ImageTransparency = 0.15
else
glowGoal.ImageTransparency = 0.5
end
local glowTween = TweenService:Create(glow, TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), glowGoal)
glowTween:Play()
glowTween.Completed:Connect(function()
local resetGlowTween = TweenService:Create(glow, TweenInfo.new(0.18), {ImageTransparency = GLOW_TRANSPARENCY})
resetGlowTween:Play()
end)
end
end
-- Animate the healthbar turning red, tilting, falling, and disappearing when dead
local function animateDeath(bar, gui)
-- Animate all colors to red
local barBg = bar.barBg
local borderGlow = bar.borderGlow
local label = bar.label
local labelGlow = bar.labelGlow
local blocks = bar.blocks
-- Animate bar background color
TweenService:Create(barBg, TweenInfo.new(0.25), {BackgroundColor3 = DEATH_BAR_BG_COLOR}):Play()
-- Animate border glow
TweenService:Create(borderGlow, TweenInfo.new(0.25), {ImageColor3 = DEATH_GLOW_COLOR}):Play()
-- Animate label color
TweenService:Create(label, TweenInfo.new(0.25), {TextColor3 = DEATH_LABEL_COLOR, TextStrokeColor3 = DEATH_LABEL_STROKE}):Play()
TweenService:Create(labelGlow, TweenInfo.new(0.25), {ImageColor3 = DEATH_GLOW_COLOR}):Play()
-- Animate all blocks to red
for _, block in ipairs(blocks) do
TweenService:Create(block, TweenInfo.new(0.25), {BackgroundColor3 = DEATH_BLOCK_EMPTY_COLOR}):Play()
if block:FindFirstChild("Glow") then
TweenService:Create(block.Glow, TweenInfo.new(0.25), {ImageColor3 = DEATH_GLOW_COLOR}):Play()
end
if block:FindFirstChildOfClass("UIStroke") then
TweenService:Create(block:FindFirstChildOfClass("UIStroke"), TweenInfo.new(0.25), {Color = DEATH_BLOCK_OUTLINE_COLOR}):Play()
end
end
-- After color change, tilt and fall off screen, then destroy
task.delay(0.28, function()
local tiltGoal = { Rotation = 30 }
local tiltTween = TweenService:Create(barBg, TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out), tiltGoal)
tiltTween:Play()
tiltTween.Completed:Connect(function()
local fallGoal = {
Position = barBg.Position + UDim2.new(0, 0, 1.2, 200),
Rotation = 80,
BackgroundTransparency = 1
}
local fallTween = TweenService:Create(barBg, TweenInfo.new(1.25, Enum.EasingStyle.Quad, Enum.EasingDirection.In), fallGoal)
fallTween:Play()
fallTween.Completed:Connect(function()
if gui and gui.Parent then
gui:Destroy()
end
end)
end)
end)
end
-- Reset the healthbar after respawn
local function resetBar(bar, origPos)
local barBg = bar.barBg
local borderGlow = bar.borderGlow
local label = bar.label
local labelGlow = bar.labelGlow
local blocks = bar.blocks
barBg.Rotation = 0
barBg.BackgroundTransparency = 0.15
barBg.Position = origPos
barBg.BackgroundColor3 = BAR_BG_COLOR
borderGlow.ImageColor3 = GLOW_COLOR
label.TextColor3 = Color3.fromRGB(255, 255, 255)
label.TextStrokeColor3 = GLOW_COLOR
labelGlow.ImageColor3 = GLOW_COLOR
for _, block in ipairs(blocks) do
block.BackgroundColor3 = BLOCK_EMPTY_COLOR
if block:FindFirstChild("Glow") then
block.Glow.ImageColor3 = GLOW_COLOR
end
if block:FindFirstChildOfClass("UIStroke") then
block:FindFirstChildOfClass("UIStroke").Color = BLOCK_OUTLINE_COLOR
end
end
end
-- Main logic
local function setupHealthbar()
local healthbar = createHealthbar()
local barBg = healthbar.barBg
local gui = healthbar.gui
local origPos = barBg.Position
local character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local humanoid = character:FindFirstChildOfClass("Humanoid") or character:WaitForChild("Humanoid")
local lastHealth = humanoid.Health
local dead = false
-- Initial update
updateHealthbar(healthbar.blocks, humanoid.Health, humanoid.MaxHealth)
-- Optional: Add a little bounce on spawn
for _, block in ipairs(healthbar.blocks) do
animateBlock(block, true)
end
-- Listen for health changes
humanoid.HealthChanged:Connect(function(newHealth)
updateHealthbar(healthbar.blocks, newHealth, humanoid.MaxHealth)
-- Animate blocks for damage/heal
if newHealth < lastHealth then
local blockIndex = math.ceil(newHealth / (humanoid.MaxHealth / BAR_BLOCKS)) + 1
if healthbar.blocks[blockIndex] then
animateBlock(healthbar.blocks[blockIndex], false)
end
elseif newHealth > lastHealth then
local blockIndex = math.ceil(newHealth / (humanoid.MaxHealth / BAR_BLOCKS))
if healthbar.blocks[blockIndex] then
animateBlock(healthbar.blocks[blockIndex], true)
end
end
lastHealth = newHealth
-- Death animation
if newHealth <= 0 and not dead then
dead = true
animateDeath(healthbar, gui)
end
end)
-- Update on respawn
LocalPlayer.CharacterAdded:Connect(function(char)
humanoid = char:WaitForChild("Humanoid")
lastHealth = humanoid.Health
dead = false
-- If the GUI was destroyed, recreate it
if not gui.Parent then
local newHealthbar = createHealthbar()
barBg = newHealthbar.barBg
gui = newHealthbar.gui
origPos = barBg.Position
for _, block in ipairs(newHealthbar.blocks) do
animateBlock(block, true)
end
updateHealthbar(newHealthbar.blocks, humanoid.Health, humanoid.MaxHealth)
healthbar = newHealthbar
else
resetBar(healthbar, origPos)
updateHealthbar(healthbar.blocks, humanoid.Health, humanoid.MaxHealth)
end
humanoid.HealthChanged:Connect(function(newHealth)
updateHealthbar(healthbar.blocks, newHealth, humanoid.MaxHealth)
if newHealth < lastHealth then
local blockIndex = math.ceil(newHealth / (humanoid.MaxHealth / BAR_BLOCKS)) + 1
if healthbar.blocks[blockIndex] then
animateBlock(healthbar.blocks[blockIndex], false)
end
elseif newHealth > lastHealth then
local blockIndex = math.ceil(newHealth / (humanoid.MaxHealth / BAR_BLOCKS))
if healthbar.blocks[blockIndex] then
animateBlock(healthbar.blocks[blockIndex], true)
end
end
lastHealth = newHealth
if newHealth <= 0 and not dead then
dead = true
animateDeath(healthbar, gui)
end
end)
end)
end
-- Run setup
setupHealthbar()
make it that the health bar slightly goes down when tilted.