掌握 xge_camera_t 结构体与正交投影相机,实现平移、缩放、旋转的 2D 世界视图。
XGE 的相机定义了"世界坐标 → 屏幕坐标"的映射关系。正交投影(Orthographic)是 2D 游戏的标准选择——物体不因距离而缩小,保持像素精确。
相机支持三个自由度:平移(Position)、缩放(Scale)、旋转(Rotation)。
typedef struct xge_camera_t {
xge_vec2_t tPosition; // 相机中心(世界坐标)
xge_vec2_t tScale; // 缩放因子 (1,1)=原始
float fRotation; // 旋转角度(弧度)
xge_rect_t tViewport; // 视口矩形(像素)
int iCoordinateMode; // XGE_COORD_Y_DOWN / XGE_COORD_CENTER
int iProjectionMode; // XGE_CAMERA_ORTHO / XGE_CAMERA_PERSPECTIVE
float fFovY; // 透视 FOV(正交时忽略)
float fNearZ; // 近裁剪面
float fFarZ; // 远裁剪面
float fPerspectiveDistance; // 透视距离
} xge_camera_t;| 函数 | 说明 |
|---|---|
xge_camera_t xgeCameraDefault(float fWidth, float fHeight) | 创建默认正交相机(原点在左上角) |
void xgeCameraSet(const xge_camera_t* pCamera) | 设置当前相机 |
xge_camera_t xgeCameraGet(void) | 获取当前相机 |
gcc -O2 -I. -o ch14.exe ch14_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch14.exe
| 常量 | 值 | 说明 |
|---|---|---|
XGE_COORD_Y_DOWN | 0 | 原点在左上角,Y 轴向下(默认,适合 UI) |
XGE_COORD_CENTER | 1 | 原点在中心,Y 轴向上(适合游戏世界) |
static int onFrame(void* pUser) {
xgeClear(0x081114FF);
// 创建默认正交相机(800×600 视口)
xge_camera_t cam = xgeCameraDefault(800.0f, 600.0f);
xgeCameraSet(&cam);
// 此时 (0,0) 在左上角,(800,600) 在右下角
xgeShapeRectFill(100, 100, 200, 150, 0x4FD8C2FF);
return XGE_OK;
}static float g_fPlayerX = 400, g_fPlayerY = 300;
static int onFrame(void* pUser) {
xgeClear(0x081114FF);
// 相机中心跟随玩家
xge_camera_t cam = xgeCameraDefault(800.0f, 600.0f);
cam.tPosition.fX = g_fPlayerX;
cam.tPosition.fY = g_fPlayerY;
xgeCameraSet(&cam);
// 世界中的物体用世界坐标绘制
xgeShapeCircleFill(g_fPlayerX, g_fPlayerY, 20, 0xFFB454FF);
xgeShapeRectFill(0, 0, 2000, 50, 0x2A4A3FFF); // 地面
return XGE_OK;
}xge_camera_t cam = xgeCameraDefault(800.0f, 600.0f);
// 放大 2 倍(值越大越放大)
cam.tScale.fX = 2.0f;
cam.tScale.fY = 2.0f;
// 旋转 15 度
cam.fRotation = 15.0f * 3.14159265f / 180.0f;
// 使用中心坐标模式
cam.iCoordinateMode = XGE_COORD_CENTER;
xgeCameraSet(&cam);static float g_fZoom = 1.0f;
static int onFrame(void* pUser) {
// 读取滚轮增量
float wheel = xgeMouseGetWheel().fY;
g_fZoom += wheel * 0.1f;
// 限制缩放范围
if (g_fZoom < 0.25f) g_fZoom = 0.25f;
if (g_fZoom > 4.0f) g_fZoom = 4.0f;
xge_camera_t cam = xgeCameraDefault(800.0f, 600.0f);
cam.tScale.fX = g_fZoom;
cam.tScale.fY = g_fZoom;
xgeCameraSet(&cam);
xgeClear(0x081114FF);
// ... 绘制世界 ...
return XGE_OK;
}将以下代码保存为 ch14_main.c,编译后运行即可体验相机平移与滚轮缩放:
#include "xge.h"
static float g_fZoom = 1.0f;
static float g_fCamX = 400.0f, g_fCamY = 300.0f;
static int onFrame(void* pUser) {
(void)pUser;
// 滚轮缩放
xge_vec2_t wheel = xgeMouseGetWheel();
g_fZoom += wheel.fY * 0.1f;
if (g_fZoom < 0.25f) g_fZoom = 0.25f;
if (g_fZoom > 4.0f) g_fZoom = 4.0f;
// 方向键平移相机
float spd = 5.0f / g_fZoom;
if (xgeKeyDown(XGE_KEY_LEFT)) g_fCamX -= spd;
if (xgeKeyDown(XGE_KEY_RIGHT)) g_fCamX += spd;
if (xgeKeyDown(XGE_KEY_UP)) g_fCamY -= spd;
if (xgeKeyDown(XGE_KEY_DOWN)) g_fCamY += spd;
// 设置相机
xge_camera_t cam = xgeCameraDefault(800.0f, 600.0f);
cam.tPosition.fX = g_fCamX;
cam.tPosition.fY = g_fCamY;
cam.tScale.fX = g_fZoom;
cam.tScale.fY = g_fZoom;
xgeCameraSet(&cam);
xgeClear(0x081114FF);
// 绘制世界中的物体
xgeShapeRectFill(0, 0, 2000, 50, 0x2A4A3FFF);
xgeShapeCircleFill(400, 300, 30, 0xFFB454FF);
xgeShapeRectFill(100, 100, 120, 80, 0x4FD8C2FF);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch14 - Ortho Camera";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeRun(onFrame, NULL);
xgeUnit();
return 0;
}xgeCameraDefault(800, 600) 创建默认正交相机,原点在左上角。tPosition 是相机中心看向的世界坐标,方向键平移相机即改变此值。tScale 控制缩放,滚轮增量乘以 0.1 使缩放平滑。xgeCameraSet。xgeBegin 后重置为默认。如需自定义相机,每帧都要调用 xgeCameraSet。