学习世界坐标与屏幕坐标的相互转换,实现精确的鼠标拾取、HUD 定位等功能。
XGE 中存在两套坐标:
当相机发生平移或缩放后,同一个世界坐标会映射到不同的屏幕位置。xgeWorldToScreen 和 xgeScreenToWorld 帮你在两者之间转换。
| 函数 | 说明 |
|---|---|
xge_vec2_t xgeWorldToScreen(xge_vec2_t tPoint) | 世界坐标 → 屏幕坐标 |
xge_vec2_t xgeScreenToWorld(xge_vec2_t tPoint) | 屏幕坐标 → 世界坐标 |
gcc -O2 -I. -o ch16.exe ch16_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch16.exe
static int onFrame(void* pUser) {
// 设置相机(平移 + 缩放)
xge_camera_t cam = xgeCameraDefault(800, 600);
cam.tPosition.fX = 500; // 相机看向世界 (500, 300)
cam.tPosition.fY = 300;
cam.tScale.fX = cam.tScale.fY = 2.0f; // 2x 放大
xgeCameraSet(&cam);
// 获取鼠标屏幕坐标
xge_vec2_t mouse = xgeMouseGet();
// 转换为世界坐标
xge_vec2_t world = xgeScreenToWorld(mouse);
// 判断是否点击了世界中的物体
float dx = world.fX - g_fObjX;
float dy = world.fY - g_fObjY;
if (dx*dx + dy*dy < 30*30) {
// 命中!
}
xgeClear(0x081114FF);
return XGE_OK;
}// 已知世界坐标(如 NPC 头顶)
xge_vec2_t npcPos = { .fX = 1200, .fY = 450 };
// 转换为屏幕坐标
xge_vec2_t screen = xgeWorldToScreen(npcPos);
// 在屏幕坐标处绘制名字标签(不受相机影响)
// 先重置相机为默认(屏幕坐标 = 世界坐标)
xge_camera_t hud = xgeCameraDefault(800, 600);
xgeCameraSet(&hud);
// 在 screen 位置绘制文本
// xgeTextDraw(screen.fX, screen.fY - 40, "NPC", ...);// 小地图区域:屏幕右下角 200×150
float mapX = 590, mapY = 440, mapW = 200, mapH = 150;
// 世界范围 0~4000 × 0~3000
float worldW = 4000, worldH = 3000;
// 玩家世界坐标 → 小地图屏幕坐标
xge_vec2_t player = { .fX = g_fPlayerX, .fY = g_fPlayerY };
float dotX = mapX + (player.fX / worldW) * mapW;
float dotY = mapY + (player.fY / worldH) * mapH;
xgeShapeCircleFill(dotX, dotY, 4, 0xFF6B5EFF);将以下代码保存为 ch16_main.c,编译后运行即可体验鼠标拾取世界坐标:
#include "xge.h"
static float g_fObjX = 500.0f, g_fObjY = 350.0f;
static int g_bHit = 0;
static int onFrame(void* pUser) {
(void)pUser;
// 设置 2x 放大相机
xge_camera_t cam = xgeCameraDefault(800.0f, 600.0f);
cam.tPosition.fX = 400;
cam.tPosition.fY = 300;
cam.tScale.fX = cam.tScale.fY = 2.0f;
xgeCameraSet(&cam);
// 鼠标屏幕坐标 → 世界坐标
xge_vec2_t mouse = xgeMouseGet();
xge_vec2_t world = xgeScreenToWorld(mouse);
// 判断是否悬停在物体上
float dx = world.fX - g_fObjX;
float dy = world.fY - g_fObjY;
g_bHit = (dx*dx + dy*dy < 30*30);
xgeClear(0x081114FF);
// 绘制目标物体(悬停时变色)
uint32_t color = g_bHit ? 0xFF6B5EFF : 0x4FD8C2FF;
xgeShapeCircleFill(g_fObjX, g_fObjY, 30, color);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch16 - Coordinate Transform";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeRun(onFrame, NULL);
xgeUnit();
return 0;
}xgeMouseGet() 返回鼠标的屏幕坐标(像素)。xgeScreenToWorld() 将屏幕坐标转换为当前相机下的世界坐标。xgeCameraSet 之后调用。xgeScreenToWorld 记录偏移,拖动时实时更新物体世界坐标。