跳转至

Sprite (离屏画布)

类: LGFX_Sprite / M5Canvas(来自 M5GFX)
头文件: M5GFX.h(自动包含 LGFX_Sprite)

Sprite 是一个离屏绘图缓冲区。你可以使用与 M5Cardputer.Display 相同的 API 向其中绘制内容,然后一次性将其传送到屏幕上。这可以实现双缓冲渲染,消除闪烁,打造流畅 UI。

M5CanvasLGFX_Sprite 的便捷子类,默认使用 PSRAM 分配。


M5Canvas vs LGFX_Sprite

M5Canvas sprite(&M5Cardputer.Display);  // 自动 PSRAM,绑定父显示
LGFX_Sprite sprite;                     // 无父显示,手动 PSRAM

大多数情况下用 M5Canvas。仅在需要通过 setPsram() 显式控制 PSRAM 时才用 LGFX_Sprite


生命周期

void* createSprite(int32_t w, int32_t h);  // 分配离屏缓冲区
void deleteSprite();                       // 释放缓冲区
M5Canvas sprite(&M5Cardputer.Display);
sprite.setColorDepth(16);                // 必须在 createSprite 之前调用
sprite.createSprite(320, 240);

// ... 在 sprite 上绘图 ...

sprite.deleteSprite();                   // 完成后清理

缓冲区管理

void setPsram(bool enabled);                       // 下次 createSprite 时使用 PSRAM
void* setColorDepth(color_depth_t depth);          // 更改色深(会重建缓冲区)
void setBuffer(void* buffer, int32_t w, int32_t h, uint8_t bpp = 0);  // 封装外部内存
void* getBuffer();                                 // 原始缓冲区指针
uint32_t bufferLength();                           // 缓冲区大小(字节)

色深选项: 1, 4, 8, 16, 24, 32(每像素位数)。M5Cardputer 推荐 16

Warning

setColorDepth()setPsram() 必须在 createSprite() 之前调用。创建后更改色深会销毁并重建缓冲区。


传送到显示

void pushSprite(int32_t x, int32_t y);                              // 传送到父显示
void pushSprite(LovyanGFX* dst, int32_t x, int32_t y);             // 传送到任意显示
void pushSprite(int32_t x, int32_t y, uint16_t transparent);        // 带透明色
sprite.pushSprite(0, 0);                 // 完整画面传送到父显示 (0,0)
sprite.pushSprite(&M5Cardputer.Display, 10, 20);  // 传送到 (10,20)
sprite.pushSprite(0, 0, TFT_BLACK);      // TFT_BLACK 像素为透明

旋转/缩放传送

void pushRotated(float angle);                                     // 旋转传送
void pushRotated(float angle, uint16_t transparent);               // 带透明
void pushRotateZoom(float angle, float zoom_x, float zoom_y);     // 旋转 + 缩放
void pushAffine(const float matrix[6]);                            // 仿射变换

继承的绘图方法

LGFX_Sprite 继承了 LGFXBase所有绘图方法,因此 显示屏 (M5GFX) 中的所有方法在 Sprite 上同样适用:

sprite.fillScreen(TFT_BLACK);
sprite.fillRect(10, 10, 100, 50, TFT_RED);
sprite.drawCircle(160, 120, 60, TFT_GREEN);
sprite.drawString("你好", 10, 10);

双缓冲渲染

M5Canvas backBuffer(&M5Cardputer.Display);

void setup() {
    M5Cardputer.begin();
    backBuffer.setColorDepth(16);
    backBuffer.createSprite(320, 240);
}

void loop() {
    M5Cardputer.update();

    // 在后台缓冲区绘制所有内容
    backBuffer.fillScreen(TFT_BLACK);
    backBuffer.drawString("FPS 计数器", 10, 10);
    // ... 更多绘图 ...

    // 一次性传送 — 无闪烁
    backBuffer.pushSprite(0, 0);
}

低色深精灵与调色板

内存紧张时,可使用 8 位(或更低)色深配合调色板:

M5Canvas sprite(&M5Cardputer.Display);
sprite.setColorDepth(8);
sprite.createSprite(320, 240);

sprite.createPalette();
sprite.setPaletteColor(0, TFT_BLACK);
sprite.setPaletteColor(1, TFT_WHITE);
sprite.setPaletteColor(2, TFT_RED);

sprite.fillScreen(0);              // 使用调色板索引 0
sprite.drawString("Hi", 10, 10);   // 文字颜色使用调色板
sprite.pushSprite(0, 0);

从 BMP 加载精灵

bool createFromBmpFile(const char* path);     // 从 SD 卡加载
bool createFromBmp(const uint8_t* data, uint32_t len);  // 从内存加载
sprite.createFromBmpFile("/logo.bmp");
sprite.pushSprite(0, 0);

这将用 BMP 内容替换精灵缓冲区(无需先调用 createSprite)。


快速示例:简单游戏循环

M5Canvas canvas(&M5Cardputer.Display);

void setup() {
    M5Cardputer.begin();
    canvas.setColorDepth(16);
    canvas.createSprite(320, 240);
}

int x = 100, y = 100;

void loop() {
    M5Cardputer.update();

    // 清空后台缓冲区
    canvas.fillScreen(TFT_BLACK);

    // 移动玩家
    auto& keys = M5Cardputer.Keyboard.keysState();
    if (M5Cardputer.Keyboard.isKeyPressed('w')) y--;
    if (M5Cardputer.Keyboard.isKeyPressed('s')) y++;
    if (M5Cardputer.Keyboard.isKeyPressed('a')) x--;
    if (M5Cardputer.Keyboard.isKeyPressed('d')) x++;

    // 绘制游戏对象
    canvas.fillRect(x, y, 16, 16, TFT_GREEN);

    // 翻转到屏幕
    canvas.pushSprite(0, 0);
}

void cleanup() {
    canvas.deleteSprite();
}