Skip to content

Lập trình UI ​

UI thuộc về từng người chơi, nên được điều khiển bằng ClientScript. Bạn có thể dựng UI trong KHIM Engine (Thiết kế UI) rồi lập trình, hoặc dựng hoàn toàn bằng code.

Gọi tới UI dựng trong KHIM Engine ​

Mỗi người chơi nhận một bản của mọi thứ dưới UI khi vào game. ClientScript nằm bên trong một đối tượng UI có đối tượng đó là script.parent:

lua
-- ClientScript bên trong Canvas "Shop"
local shop = script.parent
local buy = shop.Panel.BuyButton

buy.clicked:connect(function()
    net.send("buy", "Sword")
end)

ClientScript khác tìm nó trong gui của người chơi:

lua
local shop = players.me.gui:waitFor("Shop")
shop.visible = false

Dựng UI bằng code ​

lua
-- ClientScript: bộ đếm xu ở đầu màn hình
local canvas = new("Canvas", players.me.gui)

local label = new("Label", canvas)
label.anchor = vec2(0.5, 0)
label.position = dim(0.5, 0, 0, 80)    -- giữa màn hình, cách mép trên 80 điểm
label.size = dim.px(200, 40)
label.text = "Xu: 0"
label.textSize = 22
label.textColor = rgb(255, 255, 255)
label.backgroundColor = rgb(20, 20, 20)
label.backgroundTransparency = 0.3
new("Corner", label).radius = 12

net.on("coinCollected", function(total)
    label.text = "Xu: " .. total
end)

Kích thước và vị trí: dim ​

UI được dàn bằng giá trị dim - một scale (tỉ lệ của cha) và một offset (điểm UI) cho X và Y:

lua
dim(xScale, xOffset, yScale, yOffset)
dim(0.5, 0, 0, 40)    -- rộng nửa cha, cao 40 điểm
dim.scale(1, 1)       -- bằng cả cha
dim.px(200, 50)       -- 200 x 50 điểm

anchor (một vec2, 0 tới 1) là điểm của đối tượng mà position đặt vào: vec2(0.5, 0.5) là canh giữa.

Điểm UI to lên theo tỉ lệ HUD của người chơi, nên bố cục trông như nhau trên màn hình lớn. camera.viewportSize cho kích thước màn hình tính bằng điểm UI.

Thuộc tính chung ​

Mọi đối tượng UI (Panel, Label, Button, TextInput, Image, ImageButton...):

Thành viên
position, sizedim
anchorvec2
backgroundColor, backgroundTransparencyHộp nền
visibleHiện hay ẩn
zIndexVẽ đè lên cái thấp hơn (không bao giờ nằm dưới cha)
layoutOrderThứ tự trong ListLayout hay GridLayout sắp theo LayoutOrder

Đối tượng chữ (Label, Button, TextInput) có thêm text, textColor, textSize, textAlign ("Left", "Center", "Right"), textWrapped, textScaled và font ("Default", "Bold", "Display").

Hình ảnh có thêm image (tên hình - "coin", "icon-star"... - hoặc "asset:123"), imageColor, imageTransparency.

Nút bấm và ô nhập ​

lua
button.clicked:connect(function() print("đã bấm") end)            -- Button, ImageButton

box.focusLost:connect(function(enterPressed)                       -- TextInput
    if enterPressed then print("đã gõ: " .. box.text) end
end)
box.placeholder = "Nhập mã"

Các điều khiển riêng của KHIM:

lua
local bar = new("ProgressBar", canvas)       -- máu, kinh nghiệm, đang tải
bar.min, bar.max, bar.value = 0, 100, 75
bar.fillColor = rgb(80, 220, 120)

local slider = new("SliderInput", canvas)    -- người chơi kéo
slider.min, slider.max, slider.step = 0, 1, 0.05
slider.changed:connect(function(value) print("âm lượng", value) end)

local toggle = new("Toggle", canvas)         -- bật/tắt
toggle.text = "Nhạc"
toggle.changed:connect(function(on) print("nhạc", on) end)

Đối tượng bố cục ​

Đặt chúng bên trong một đối tượng UI để sắp xếp hay trang trí:

lua
local list = new("ListLayout", panel)
list.direction = "Vertical"        -- hoặc "Horizontal"
list.padding = 8                   -- số điểm giữa các con
list.alignX = "Center"
list.sortOrder = "LayoutOrder"     -- hoặc "Name"

local grid = new("GridLayout", panel)
grid.cellSize = dim.px(80, 80)
grid.cellPadding = dim.px(6, 6)

local pad = new("Padding", panel)
pad.top, pad.bottom, pad.left, pad.right = 10, 10, 12, 12

new("Corner", panel).radius = 10

local border = new("Border", panel)
border.color = rgb(255, 255, 255)
border.thickness = 2
border.transparency = 0.6

local grad = new("Gradient", panel)
grad.color0 = rgb(40, 40, 60)
grad.color1 = rgb(10, 10, 20)
grad.rotation = 90                 -- từ trên xuống
Bổ trợThành viên
AspectRatioaspectRatio, aspectType ("FitWithinMaxSize", "ScaleWithParentSize"), dominantAxis
Scalescale - vẽ nó và nội dung to hay nhỏ hơn (tween để làm hiệu ứng rê chuột)
SizeLimitminSize, maxSize (vec2, điểm)
TextSizeLimitminTextSize, maxTextSize
BorderapplyTo = "Text" viền quanh chữ thay vì quanh hộp
GradientcolorMid, midpoint - màu thứ ba ở giữa

Danh sách cuộn ​

ScrollPanel cuộn nội dung bằng con lăn chuột hoặc kéo:

lua
local scroller = new("ScrollPanel", canvas)
scroller.size = dim.px(300, 400)
scroller.automaticCanvasSize = "Y"     -- tự lớn ra cho vừa nội dung
new("ListLayout", scroller).padding = 6

for i = 1, 20 do
    local row = new("Button", scroller)
    row.size = dim(1, 0, 0, 40)
    row.text = "Món " .. i
end

Nút trong ScrollPanel chỉ được bấm khi thả tay mà không kéo, nên lướt cửa hàng bằng ngón tay sẽ không mua nhầm.

Hiệu ứng chuyển động cho UI ​

Đối tượng UI tween như part:

lua
panel.position = dim(0.5, 0, 1.2, 0)                        -- nằm ngoài mép dưới
panel:tween({position = dim(0.5, 0, 0.5, 0)}, {time = 0.4, style = "Back", direction = "Out"})

local grow = new("Scale", button)
-- khi rê chuột, script có thể tween grow.scale từ 1 lên 1.1

Hiện menu trong game góc nhìn thứ nhất ​

Ở góc nhìn thứ nhất hoặc khoá camera, con trỏ bị giữ ở giữa. Thả nó ra khi menu mở:

lua
input.onKey("B", function()
    shop.visible = not shop.visible
    input.mouseFree = shop.visible
end)

Chữ trong world ​

Với chữ gắn vào một part - tên, giá, thanh máu trên đầu quái - dùng Billboard trên part thay vì UI màn hình.