Chapter 61 · ShapeEx 进阶

变换:Shape 级

每个 ShapeEx 拥有独立的仿射变换矩阵,支持平移、缩放、旋转、斜切操作。

61

概念

  • Shape 变换:绘制时应用到整个 Shape(路径+填充+描边)。
  • 累积操作:Translate/Scale/Rotate/Skew 在当前矩阵上左乘。
  • Identity:重置为单位矩阵(无变换)。

API 速查

函数说明
int xgeShapeExTransformSet(xge_shape_ex pShape, const xge_shape_ex_matrix_t* pMatrix)设置完整变换矩阵
int xgeShapeExTransformIdentity(xge_shape_ex pShape)重置为单位矩阵
int xgeShapeExTransformGet(xge_shape_ex pShape, xge_shape_ex_matrix_t* pMatrix)获取当前变换
int xgeShapeExTransformTranslate(xge_shape_ex pShape, float fTX, float fTY)平移
int xgeShapeExTransformScale(xge_shape_ex pShape, float fSX, float fSY)缩放
int xgeShapeExTransformRotate(xge_shape_ex pShape, float fRadians)旋转(弧度)
int xgeShapeExTransformSkew(xge_shape_ex pShape, float fXRadians, float fYRadians)斜切(弧度)

编译本章示例

gcc -O2 -I. -o ch61.exe ch61_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch61.exe

示例 1:旋转 + 平移

xge_shape_ex shape = NULL;
xgeShapeExCreate(&shape);
xgeShapeExAppendRect(shape, -50,-50, 100,100, 8,8, 1);
xgeShapeExFillColor(shape, 0xFFB454FF);

// 先旋转 30°,再平移到屏幕中心
xgeShapeExTransformRotate(shape, 0.5236f);  // 30° in rad
xgeShapeExTransformTranslate(shape, 400, 300);
xgeShapeExDraw(shape, 0.25f);

示例 2:动态旋转动画

void OnFrame(void) {
    static float s_fAngle = 0.0f;
    s_fAngle += 0.02f;

    // 每帧重置再设置 → 避免累积
    xgeShapeExTransformIdentity(g_shape);
    xgeShapeExTransformRotate(g_shape, s_fAngle);
    xgeShapeExTransformTranslate(g_shape, 400, 300);
    xgeShapeExDraw(g_shape, 0.25f);
}

完整代码

将以下代码保存为 ch61_main.c,编译后运行即可看到 Shape 级变换动画效果:

#include "xge.h"

static float s_fAngle = 0.0f;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    s_fAngle += 0.02f;

    // 旋转方块(以原点为中心构建)
    xge_shape_ex box = NULL;
    xgeShapeExCreate(&box);
    xgeShapeExAppendRect(box, -50,-50, 100,100, 8,8, 1);
    xgeShapeExFillColor(box, 0xFFB454FF);
    xgeShapeExTransformIdentity(box);
    xgeShapeExTransformRotate(box, s_fAngle);
    xgeShapeExTransformTranslate(box, 250, 300);
    xgeShapeExDraw(box, 0.25f);
    xgeShapeExDestroy(box);

    // 缩放圆(脉动效果)
    float sc = 1.0f + 0.3f * (float)sin(s_fAngle * 2.0f);
    xge_shape_ex circle = NULL;
    xgeShapeExCreate(&circle);
    xgeShapeExAppendCircle(circle, 0, 0, 60, 60, 1);
    xgeShapeExFillColor(circle, 0x4FD8C2FF);
    xgeShapeExTransformIdentity(circle);
    xgeShapeExTransformScale(circle, sc, sc);
    xgeShapeExTransformTranslate(circle, 550, 300);
    xgeShapeExDraw(circle, 0.25f);
    xgeShapeExDestroy(circle);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch61 - Shape Transform";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • 以原点为中心:路径坐标以 (0,0) 为中心构建,旋转更自然。
  • 每帧 Identity:重置变换后再设置,避免累积。
  • 操作顺序:后调用的先应用(矩阵左乘),先 Rotate 后 Translate = 先旋转再平移。
  • 脉动缩放:用 sin 函数让 Scale 在 0.7~1.3 之间波动。

要点与陷阱

  • 操作顺序:后调用的先应用(矩阵左乘),Translate→Rotate 实际先旋转后平移。
  • 动画需重置:每帧 Identity 后再设置,否则变换会累积。
  • 路径坐标建议居中:以 (0,0) 为中心构建路径,旋转更自然。
  • 与 DrawEx pParentMatrix:父矩阵 × Shape 变换 = 最终变换。

进阶练习

  1. 实现公转+自转:Translate 公转 + Rotate 自转组合。
  2. 用 Skew 实现伪 3D 倾斜卡片效果。
变换:Shape 级效果
图:变换:Shape 级渲染效果