InventoryGrid + VirtualJoystick + Progress:移动端游戏 HUD 界面。
构建移动端游戏 HUD:
• 虚拟摇杆:VirtualJoystick 控制角色移动
• 物品栏:InventoryGrid 底部快捷栏
• 血条/蓝条:Progress 显示 HP/MP
• 小地图:Canvas 绘制缩略地图
• 技能按钮:Button 圆形技能图标 + 冷却
| 模块 | XUI API |
|---|---|
摇杆 | xuiVirtualJoystickCreate(XY 通道) |
物品栏 | xuiInventoryGridCreate(手柄支持) |
血条 | xuiProgressCreate(水平/动画) |
小地图 | xuiCanvasCreate(自定义绘制) |
技能 | xuiButtonCreate(圆形/图标/徽章) |
gcc -O2 -I. -o ch206.exe ch206_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch206.exe
// 虚拟摇杆(左下角)
xui_virtual_joystick_desc_t tJoyDesc = { 0 };
xui_widget pJoystick;
xuiVirtualJoystickCreate(pCtx, &pJoystick, &tJoyDesc);
xuiVirtualJoystickSetMetrics(pJoystick,
60.0f, 24.0f, 0.1f);
// 摇杆回调 → 角色移动
xuiVirtualJoystickSetChange(pJoystick,
OnJoystickMove, pPlayer);
void OnJoystickMove(float fX, float fY,
void* pUser) {
player_t* p = (player_t*)pUser;
p->fVelX = fX * p->fSpeed;
p->fVelY = fY * p->fSpeed;
}
// 物品栏(底部 6 格)
xui_inventory_grid_desc_t tInvDesc = { 0 };
tInvDesc.iColumns = 6;
tInvDesc.iRows = 1;
xui_widget pHotbar;
xuiInventoryGridCreate(pCtx, &pHotbar, &tInvDesc);
// 血条
xui_progress_desc_t tHpDesc = { 0 };
tHpDesc.fMax = 100.0f;
xui_widget pHP;
xuiProgressCreate(pCtx, &pHP, &tHpDesc);
xuiProgressSetValue(pHP, 75.0f);将以下代码保存为 ch206_main.c,编译后运行即可看到游戏 HUD(摇杆 + 血条 + 物品栏)效果:
#include "xge.h"
#include "xui.h"
static xui_context g_pCtx;
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x0a0a1a);
xui_vec2_t pos;
xgeMouseGet(&pos.x, &pos.y);
xuiInputPointerMove(g_pCtx, pos.x, pos.y);
if (xgeMouseDown(XGE_MOUSE_LEFT))
xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
else
xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);
xuiUpdate(g_pCtx, xgeGetDelta());
xuiLayout(g_pCtx);
xuiRender(g_pCtx, NULL, NULL, 0);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800; d.iHeight = 500;
d.sTitle = "ch206 - Game HUD";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xuiCreate(&g_pCtx);
extern const xui_proxy_t tXgeProxy;
xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
xuiSetViewportSize(g_pCtx, 800, 500);
xui_widget pRoot;
xuiPanelCreate(g_pCtx, &pRoot, NULL);
xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 800, 500});
/* 虚拟摇杆(左下角) */
xui_virtual_joystick_desc_t tJoy = {0};
xui_widget pStick;
xuiVirtualJoystickCreate(g_pCtx, &pStick, &tJoy);
xuiWidgetSetRect(pStick, (xui_rect_t){40, 360, 120, 120});
/* 血条(左上角) */
xui_progress_desc_t tHp = {0};
tHp.fMax = 100.0f;
xui_widget pHP;
xuiProgressCreate(g_pCtx, &pHP, &tHp);
xuiWidgetSetRect(pHP, (xui_rect_t){20, 20, 200, 20});
xuiWidgetSetRect(pHP, (xui_rect_t){0, 0, 200, 20});
xuiProgressSetValue(pHP, 75.0f);
/* 物品栏(底部居中) */
xui_inventory_grid_desc_t tInv = {0};
tInv.iColumns = 6; tInv.iRows = 1;
xui_widget pBar;
xuiInventoryGridCreate(g_pCtx, &pBar, &tInv);
xuiWidgetSetRect(pBar, (xui_rect_t){250, 440, 480, 120});
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}