统一 Image 和 Sprite 语义到目前的 Image/Sprite 结构体而非之前的类定义
This commit is contained in:
parent
56eec9e9d2
commit
feb088a854
|
|
@ -212,7 +212,7 @@ cmake --build build-win --config Release --target GenerateTomAtlasHeader
|
||||||
src/Apps/Game/generated/tom_atlas.h
|
src/Apps/Game/generated/tom_atlas.h
|
||||||
```
|
```
|
||||||
|
|
||||||
该头文件包含 `tom_atlas_pixels` 和每张图的 `RenderData::SpriteRegion`,因此板端运行 Tom 游戏时不需要额外部署图片资源文件。尺寸规则、region 名称和 PNG 文件名统一记录在 `src/Apps/Game/tools/asset_pipeline/SpriteAssetTool.cpp` 顶部的 `Sources` 表里;CMake 不再重复维护每张 PNG 的路径。
|
该头文件包含 `tom_atlas_pixels` 和每张图的 `RenderData::Sprite`,因此板端运行 Tom 游戏时不需要额外部署图片资源文件。尺寸规则、region 名称和 PNG 文件名统一记录在 `src/Apps/Game/tools/asset_pipeline/SpriteAssetTool.cpp` 顶部的 `Sources` 表里;CMake 不再重复维护每张 PNG 的路径。
|
||||||
|
|
||||||
`src/Apps/Game/assets/sprites/` 属于旧的 `.sprite` 文件部署流程,Tom 主游戏现在不再依赖它。只有旧的手动测试或未迁移工具还可能引用该目录;清理这些旧入口后可以删除这个目录。
|
`src/Apps/Game/assets/sprites/` 属于旧的 `.sprite` 文件部署流程,Tom 主游戏现在不再依赖它。只有旧的手动测试或未迁移工具还可能引用该目录;清理这些旧入口后可以删除这个目录。
|
||||||
|
|
||||||
|
|
@ -307,8 +307,8 @@ IMX6U-Game/
|
||||||
## 模块说明
|
## 模块说明
|
||||||
|
|
||||||
### Draw2D
|
### Draw2D
|
||||||
- **DrawContext**:统一绘制入口,封装 FrameBuffer、DepthBuffer、Rasterizer、TriangleRasterizer,对外提供 `clear`、`draw_line`、`draw_triangle`、`draw_sprite`、`draw_sprite_region`、`draw_text`、`draw_tilemap`、`present` 接口
|
- **DrawContext**:统一绘制入口,封装 FrameBuffer、DepthBuffer、Rasterizer、TriangleRasterizer,对外提供 `clear`、`draw_line`、`draw_triangle`、`draw_sprite`、`draw_text`、`draw_tilemap`、`present` 接口
|
||||||
- **SpriteRegion**:描述 atlas 中的子区域,`draw_sprite_region` / `draw_sprite_region_ex` 可直接绘制子图,底层复用 `draw_sprite_ex`
|
- **Sprite**:描述 atlas 中的子区域,是对外 sprite 绘制单位;`draw_sprite` / `draw_sprite_ex` 读取其 atlas 子区域并写入 RGB565 framebuffer
|
||||||
- **Tilemap**:使用 `uint16_t` tile id 引用 atlas 中的固定大小 tile,`draw_tilemap` 按视口可见范围遍历 tile,并在视口边缘做像素级裁剪
|
- **Tilemap**:使用 `uint16_t` tile id 引用 atlas 中的固定大小 tile,`draw_tilemap` 按视口可见范围遍历 tile,并在视口边缘做像素级裁剪
|
||||||
|
|
||||||
### Core
|
### Core
|
||||||
|
|
@ -351,7 +351,7 @@ IMX6U-Game/
|
||||||
- 可旋转立方体的 3D 渲染(MVP 变换、背面剔除、扫描线填充、深度测试)
|
- 可旋转立方体的 3D 渲染(MVP 变换、背面剔除、扫描线填充、深度测试)
|
||||||
- 双平台显示后端(SDL2 / Framebuffer)
|
- 双平台显示后端(SDL2 / Framebuffer)
|
||||||
- 离线资源转换工具:PNG sprite -> RGBA5551 C++ 头文件,像素字体 -> bitmap atlas/header
|
- 离线资源转换工具:PNG sprite -> RGBA5551 C++ 头文件,像素字体 -> bitmap atlas/header
|
||||||
- 基础 2D sprite、SpriteRegion、bitmap font 文本绘制和 tilemap 视口绘制,当前 demo 显示 FPS 文本、测试 sprite 和小型滚动 tilemap
|
- 基础 2D sprite、atlas 子图 sprite、bitmap font 文本绘制和 tilemap 视口绘制,当前 demo 显示 FPS 文本、测试 sprite 和小型滚动 tilemap
|
||||||
- Core 目录规范化,代码收敛到 `src/Core/`
|
- Core 目录规范化,代码收敛到 `src/Core/`
|
||||||
- `Core::DrawContext` 统一绘制入口,封装现有绘制能力
|
- `Core::DrawContext` 统一绘制入口,封装现有绘制能力
|
||||||
- C++11 兼容代码
|
- C++11 兼容代码
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ IMX6U-Game/
|
||||||
职责:
|
职责:
|
||||||
|
|
||||||
- 管理 framebuffer、depthbuffer、渲染上下文。
|
- 管理 framebuffer、depthbuffer、渲染上下文。
|
||||||
- 提供基础绘制接口:点、线、矩形、四边形、三角形、sprite、SpriteRegion、tilemap、简单文本等。
|
- 提供基础绘制接口:点、线、矩形、四边形、三角形、sprite、atlas 子图 sprite、tilemap、简单文本等。
|
||||||
- 提供颜色、矩形、定点数、纹理、裁剪区域等基础数据结构。
|
- 提供颜色、矩形、定点数、纹理、裁剪区域等基础数据结构。
|
||||||
- 封装 SDL2 / framebuffer 显示提交、输入轮询,并通过独立 `ITimeSource` 提供单调整数毫秒时间。
|
- 封装 SDL2 / framebuffer 显示提交、输入轮询,并通过独立 `ITimeSource` 提供单调整数毫秒时间。
|
||||||
- 提供音频输入、音频输出和按键输入的抽象接口。
|
- 提供音频输入、音频输出和按键输入的抽象接口。
|
||||||
|
|
@ -231,7 +231,7 @@ ALSA、evdev、SDL2、`/dev/fb0` 等平台细节只能出现在 `src/Core/Platfo
|
||||||
```cpp
|
```cpp
|
||||||
Core::DrawContext ctx(width, height);
|
Core::DrawContext ctx(width, height);
|
||||||
ctx.clear(RenderData::Color(18, 18, 24, 255));
|
ctx.clear(RenderData::Color(18, 18, 24, 255));
|
||||||
ctx.draw_sprite(x, y, image);
|
ctx.draw_sprite(x, y, sprite);
|
||||||
ctx.draw_text(font, x, y, color, "text");
|
ctx.draw_text(font, x, y, color, "text");
|
||||||
ctx.present(display);
|
ctx.present(display);
|
||||||
```
|
```
|
||||||
|
|
@ -281,7 +281,7 @@ poll input -> update current app -> render current app -> present framebuffer
|
||||||
|
|
||||||
1. ~~先抽出统一 `IApp` 和 `AppManager`,让当前 demo 成为一个 app。~~ 未实现,当前直接写主循环。
|
1. ~~先抽出统一 `IApp` 和 `AppManager`,让当前 demo 成为一个 app。~~ 未实现,当前直接写主循环。
|
||||||
2. ~~把 SDL2 初始化、输入、present 固定在平台层,应用层不直接碰 SDL。~~ **已完成**
|
2. ~~把 SDL2 初始化、输入、present 固定在平台层,应用层不直接碰 SDL。~~ **已完成**
|
||||||
3. ~~建立 `Core::DrawContext`,先封装 clear、pixel、line、rect、quad。~~ **已完成**(`Core::DrawContext` 封装了 clear、draw_line、draw_triangle、draw_sprite、draw_sprite_region、draw_text、draw_tilemap、present)
|
3. ~~建立 `Core::DrawContext`,先封装 clear、pixel、line、rect、quad。~~ **已完成**(`Core::DrawContext` 封装了 clear、draw_line、draw_triangle、draw_sprite、draw_text、draw_tilemap、present)
|
||||||
4. ~~底层代码统一放在 `src/Core/`,Demo 入口迁移到 `src/Apps/Demo/`。~~ **已完成**
|
4. ~~底层代码统一放在 `src/Core/`,Demo 入口迁移到 `src/Apps/Demo/`。~~ **已完成**
|
||||||
5. 新增 Launcher app,只做最小菜单和应用切换。
|
5. 新增 Launcher app,只做最小菜单和应用切换。
|
||||||
6. 新增 GameA/GameB 空壳,验证三应用切换。
|
6. 新增 GameA/GameB 空壳,验证三应用切换。
|
||||||
|
|
@ -309,10 +309,10 @@ poll input -> update current app -> render current app -> present framebuffer
|
||||||
- 生成头文件、源 PNG/TTF 和转换脚本应一起纳入仓库,保证资源可追溯、可再生成。
|
- 生成头文件、源 PNG/TTF 和转换脚本应一起纳入仓库,保证资源可追溯、可再生成。
|
||||||
- 生成数据目前面向简单直接的调试/小型游戏资源;后续如果资源体积增长,应继续评估 1-bit mask、RLE 或自定义资源包格式。
|
- 生成数据目前面向简单直接的调试/小型游戏资源;后续如果资源体积增长,应继续评估 1-bit mask、RLE 或自定义资源包格式。
|
||||||
|
|
||||||
## 12. SpriteRegion 与 Tilemap 约定
|
## 12. Sprite 与 Tilemap 约定
|
||||||
|
|
||||||
- `RenderData::SpriteRegion` 只描述某张 atlas 中的子区域,不拥有像素数据;它通过 `const Image* atlas` 引用源图。
|
- `RenderData::Sprite` 只描述某张 atlas 中的子区域,不拥有像素数据;它通过 `const Image* atlas` 引用源图。
|
||||||
- `DrawContext::draw_sprite_ex` 是底层 sprite 绘制入口,负责源区域检查、目标屏幕裁剪、scale 和 flip;`draw_sprite_region` 系列只是对 atlas 子区域的语义包装。
|
- `DrawContext::draw_sprite` 是对外 sprite 绘制入口;`draw_sprite_ex` 只在需要 scale / flip 时使用。两者都以 `RenderData::Sprite` 为渲染单位,内部再按 atlas 子区域读取像素。
|
||||||
- `RenderData::Tilemap` 使用 `uint16_t` tile id 保存地图网格,`Tilemap::EmptyTile` (`0xFFFF`) 表示空 tile。
|
- `RenderData::Tilemap` 使用 `uint16_t` tile id 保存地图网格,`Tilemap::EmptyTile` (`0xFFFF`) 表示空 tile。
|
||||||
- `Tilemap` 当前只支持一个 atlas、固定 tile 宽高和固定 `atlas_columns`;tile id 通过 `tile_id % atlas_columns` / `tile_id / atlas_columns` 映射到 atlas 中的源区域。
|
- `Tilemap` 当前只支持一个 atlas、固定 tile 宽高和固定 `atlas_columns`;tile id 通过 `tile_id % atlas_columns` / `tile_id / atlas_columns` 映射到 atlas 中的源区域。
|
||||||
- `DrawContext::draw_tilemap` 的裁剪分两层:
|
- `DrawContext::draw_tilemap` 的裁剪分两层:
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ int main(int argc, char* argv[])
|
||||||
test_sprite_width,
|
test_sprite_width,
|
||||||
test_sprite_height,
|
test_sprite_height,
|
||||||
RenderData::PixelFormat::RGBA5551);
|
RenderData::PixelFormat::RGBA5551);
|
||||||
RenderData::SpriteRegion sprite_region(&sprite_img, 0, 0, sprite_img.width, sprite_img.height);
|
RenderData::Sprite sprite(&sprite_img, 0, 0, sprite_img.width, sprite_img.height);
|
||||||
|
|
||||||
const std::array<uint16_t, 8 * 4> tileIds = {
|
const std::array<uint16_t, 8 * 4> tileIds = {
|
||||||
0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile,
|
0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile,
|
||||||
|
|
@ -179,9 +179,9 @@ int main(int argc, char* argv[])
|
||||||
ctx.clear_color(clearColor);
|
ctx.clear_color(clearColor);
|
||||||
|
|
||||||
// sprite 测试
|
// sprite 测试
|
||||||
ctx.draw_sprite(10, 10, sprite_img);
|
ctx.draw_sprite(10, 10, sprite);
|
||||||
ctx.draw_sprite_region_ex(30, 10, sprite_region, 2, false, false);
|
ctx.draw_sprite_ex(30, 10, sprite, 2, false, false);
|
||||||
ctx.draw_sprite_region_ex(10, 30, sprite_region, 3, true, false);
|
ctx.draw_sprite_ex(10, 30, sprite, 3, true, false);
|
||||||
ctx.draw_tilemap(testTilemap, 650, 500, 96, 48, static_cast<int32_t>(frame_start_ms / 20u) % 32, 0);
|
ctx.draw_tilemap(testTilemap, 650, 500, 96, 48, static_cast<int32_t>(frame_start_ms / 20u) % 32, 0);
|
||||||
|
|
||||||
// FPS 计数
|
// FPS 计数
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "SpriteRegion.h"
|
#include "Sprite.h"
|
||||||
|
|
||||||
namespace TomAtlas
|
namespace TomAtlas
|
||||||
{
|
{
|
||||||
|
|
@ -166665,23 +166665,23 @@ namespace TomAtlas
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||||
};
|
};
|
||||||
|
|
||||||
static const RenderData::Image image(tom_atlas_pixels, tom_atlas_width, tom_atlas_height, 0x0000, RenderData::PixelFormat::RGBA5551);
|
static const RenderData::Image image(tom_atlas_pixels, tom_atlas_width, tom_atlas_height, 0x0000, RenderData::PixelFormat::RGBA5551);
|
||||||
|
|
||||||
static const RenderData::SpriteRegion background(&image, 0, 0, 1024, 600);
|
static const RenderData::Sprite background(&image, 0, 0, 1024, 600);
|
||||||
static const RenderData::SpriteRegion tom_listhen(&image, 0, 601, 290, 450);
|
static const RenderData::Sprite tom_listhen(&image, 0, 601, 290, 450);
|
||||||
static const RenderData::SpriteRegion tom_openmouse1(&image, 291, 601, 298, 450);
|
static const RenderData::Sprite tom_openmouse1(&image, 291, 601, 298, 450);
|
||||||
static const RenderData::SpriteRegion tom_openmouse2(&image, 590, 601, 297, 450);
|
static const RenderData::Sprite tom_openmouse2(&image, 590, 601, 297, 450);
|
||||||
static const RenderData::SpriteRegion tom_say1(&image, 0, 1052, 305, 450);
|
static const RenderData::Sprite tom_say1(&image, 0, 1052, 305, 450);
|
||||||
static const RenderData::SpriteRegion tom_say2(&image, 306, 1052, 304, 450);
|
static const RenderData::Sprite tom_say2(&image, 306, 1052, 304, 450);
|
||||||
static const RenderData::SpriteRegion tom_say3(&image, 611, 1052, 304, 450);
|
static const RenderData::Sprite tom_say3(&image, 611, 1052, 304, 450);
|
||||||
static const RenderData::SpriteRegion tom_say4(&image, 0, 1503, 304, 450);
|
static const RenderData::Sprite tom_say4(&image, 0, 1503, 304, 450);
|
||||||
static const RenderData::SpriteRegion tom_stand(&image, 305, 1503, 274, 450);
|
static const RenderData::Sprite tom_stand(&image, 305, 1503, 274, 450);
|
||||||
static const RenderData::SpriteRegion ui_fat(&image, 580, 1503, 90, 90);
|
static const RenderData::Sprite ui_fat(&image, 580, 1503, 90, 90);
|
||||||
static const RenderData::SpriteRegion ui_hand(&image, 671, 1503, 89, 90);
|
static const RenderData::Sprite ui_hand(&image, 671, 1503, 89, 90);
|
||||||
static const RenderData::SpriteRegion ui_i(&image, 761, 1503, 89, 90);
|
static const RenderData::Sprite ui_i(&image, 761, 1503, 89, 90);
|
||||||
static const RenderData::SpriteRegion ui_record(&image, 851, 1503, 86, 90);
|
static const RenderData::Sprite ui_record(&image, 851, 1503, 86, 90);
|
||||||
static const RenderData::SpriteRegion ui_tom(&image, 938, 1503, 85, 90);
|
static const RenderData::Sprite ui_tom(&image, 938, 1503, 85, 90);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
#include "DrawContext.h"
|
#include "DrawContext.h"
|
||||||
#include "PointerInput.h"
|
#include "PointerInput.h"
|
||||||
#include "SpriteRegion.h"
|
#include "Sprite.h"
|
||||||
#include "tom_atlas.h"
|
#include "tom_atlas.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
@ -19,7 +19,7 @@ namespace
|
||||||
const int32_t TomBottomPadding = 72;
|
const int32_t TomBottomPadding = 72;
|
||||||
const int32_t ButtonBottomPadding = 16;
|
const int32_t ButtonBottomPadding = 16;
|
||||||
|
|
||||||
const RenderData::SpriteRegion* const SpeakingFrames[] = {
|
const RenderData::Sprite* const SpeakingFrames[] = {
|
||||||
&TomAtlas::tom_say1,
|
&TomAtlas::tom_say1,
|
||||||
&TomAtlas::tom_say2,
|
&TomAtlas::tom_say2,
|
||||||
&TomAtlas::tom_say3,
|
&TomAtlas::tom_say3,
|
||||||
|
|
@ -28,7 +28,7 @@ namespace
|
||||||
&TomAtlas::tom_say2
|
&TomAtlas::tom_say2
|
||||||
};
|
};
|
||||||
|
|
||||||
static const RenderData::SpriteRegion& SelectSpeakingFrame(uint32_t animationMs)
|
static const RenderData::Sprite& SelectSpeakingFrame(uint32_t animationMs)
|
||||||
{
|
{
|
||||||
const size_t frameCount = sizeof(SpeakingFrames) / sizeof(SpeakingFrames[0]);
|
const size_t frameCount = sizeof(SpeakingFrames) / sizeof(SpeakingFrames[0]);
|
||||||
const size_t frameIndex = (animationMs / SpeakingFrameMs) % frameCount;
|
const size_t frameIndex = (animationMs / SpeakingFrameMs) % frameCount;
|
||||||
|
|
@ -113,9 +113,9 @@ namespace Game
|
||||||
void TomGameApp::draw(Core::DrawContext& ctx)
|
void TomGameApp::draw(Core::DrawContext& ctx)
|
||||||
{
|
{
|
||||||
ctx.clear_color(RenderData::Color(18, 18, 24, 255));
|
ctx.clear_color(RenderData::Color(18, 18, 24, 255));
|
||||||
ctx.draw_sprite_region(0, 0, TomAtlas::background);
|
ctx.draw_sprite(0, 0, TomAtlas::background);
|
||||||
|
|
||||||
const RenderData::SpriteRegion* tom = &TomAtlas::tom_stand;
|
const RenderData::Sprite* tom = &TomAtlas::tom_stand;
|
||||||
if (state == TomGameState::Recording)
|
if (state == TomGameState::Recording)
|
||||||
{
|
{
|
||||||
tom = &TomAtlas::tom_listhen;
|
tom = &TomAtlas::tom_listhen;
|
||||||
|
|
@ -132,8 +132,8 @@ namespace Game
|
||||||
tomY = 0;
|
tomY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.draw_sprite_region(tomX, tomY, *tom);
|
ctx.draw_sprite(tomX, tomY, *tom);
|
||||||
ctx.draw_sprite_region(buttonX, buttonY, TomAtlas::ui_record);
|
ctx.draw_sprite(buttonX, buttonY, TomAtlas::ui_record);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TomGameApp::update_input(bool& recordTrigger)
|
void TomGameApp::update_input(bool& recordTrigger)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "AnimationSystem.h"
|
#include "AnimationSystem.h"
|
||||||
#include "SpriteRasterizer.h"
|
#include "DrawContext.h"
|
||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Game
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationSystem::draw(Rasterizer::SpriteRasterizer& spriteRasterizer) const
|
void AnimationSystem::draw(Core::DrawContext& drawContext) const
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < objects.size(); ++i)
|
for (size_t i = 0; i < objects.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -48,7 +48,7 @@ namespace Game
|
||||||
const RenderData::Sprite* sprite = object.animator->get_current_sprite();
|
const RenderData::Sprite* sprite = object.animator->get_current_sprite();
|
||||||
if (sprite != nullptr)
|
if (sprite != nullptr)
|
||||||
{
|
{
|
||||||
spriteRasterizer.DrawSprite(*sprite, object.x, object.y);
|
drawContext.draw_sprite(object.x, object.y, *sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../components/SpriteAnimator.h"
|
#include "../components/SpriteAnimator.h"
|
||||||
|
|
||||||
namespace Rasterizer
|
namespace Core
|
||||||
{
|
{
|
||||||
class SpriteRasterizer;
|
class DrawContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Game
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
void draw(Rasterizer::SpriteRasterizer& spriteRasterizer) const;
|
void draw(Core::DrawContext& drawContext) const;
|
||||||
|
|
||||||
void set_position(size_t index, int32_t x, int32_t y);
|
void set_position(size_t index, int32_t x, int32_t y);
|
||||||
void set_visible(size_t index, bool visible);
|
void set_visible(size_t index, bool visible);
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ namespace
|
||||||
const std::vector<uint16_t>& atlas_pixels,
|
const std::vector<uint16_t>& atlas_pixels,
|
||||||
int32_t atlas_height)
|
int32_t atlas_height)
|
||||||
{
|
{
|
||||||
std::ofstream file(OutputHeaderPath);
|
std::ofstream file(OutputHeaderPath, std::ios::binary);
|
||||||
if (!file.good())
|
if (!file.good())
|
||||||
{
|
{
|
||||||
std::cerr << "Open output header failed: " << OutputHeaderPath << std::endl;
|
std::cerr << "Open output header failed: " << OutputHeaderPath << std::endl;
|
||||||
|
|
@ -342,7 +342,7 @@ namespace
|
||||||
file << "#pragma once\n";
|
file << "#pragma once\n";
|
||||||
file << "#include <cstdint>\n";
|
file << "#include <cstdint>\n";
|
||||||
file << "#include \"Image.h\"\n";
|
file << "#include \"Image.h\"\n";
|
||||||
file << "#include \"SpriteRegion.h\"\n\n";
|
file << "#include \"Sprite.h\"\n\n";
|
||||||
file << "namespace TomAtlas\n";
|
file << "namespace TomAtlas\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << "\tstatic const int32_t tom_atlas_width = " << AtlasWidth << ";\n";
|
file << "\tstatic const int32_t tom_atlas_width = " << AtlasWidth << ";\n";
|
||||||
|
|
@ -355,8 +355,15 @@ namespace
|
||||||
const size_t end = std::min(i + 12, atlas_pixels.size());
|
const size_t end = std::min(i + 12, atlas_pixels.size());
|
||||||
for (size_t j = i; j < end; ++j)
|
for (size_t j = i; j < end; ++j)
|
||||||
{
|
{
|
||||||
|
if (j > i)
|
||||||
|
{
|
||||||
|
file << " ";
|
||||||
|
}
|
||||||
WritePixel5551(file, atlas_pixels[j]);
|
WritePixel5551(file, atlas_pixels[j]);
|
||||||
file << ", ";
|
if (j + 1 < atlas_pixels.size())
|
||||||
|
{
|
||||||
|
file << ",";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
file << "\n";
|
file << "\n";
|
||||||
}
|
}
|
||||||
|
|
@ -369,7 +376,7 @@ namespace
|
||||||
for (size_t i = 0; i < regions.size(); ++i)
|
for (size_t i = 0; i < regions.size(); ++i)
|
||||||
{
|
{
|
||||||
const AtlasRegion& region = regions[i];
|
const AtlasRegion& region = regions[i];
|
||||||
file << "\tstatic const RenderData::SpriteRegion "
|
file << "\tstatic const RenderData::Sprite "
|
||||||
<< region.source->region_name
|
<< region.source->region_name
|
||||||
<< "(&image, "
|
<< "(&image, "
|
||||||
<< region.x << ", "
|
<< region.x << ", "
|
||||||
|
|
|
||||||
|
|
@ -60,53 +60,39 @@ namespace Core
|
||||||
triangleRasterizer->DrawTriangle2D(triangle, color);
|
triangleRasterizer->DrawTriangle2D(triangle, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::draw_sprite(int32_t dst_x, int32_t dst_y, const RenderData::Image& img)
|
void DrawContext::draw_sprite(int32_t dst_x, int32_t dst_y, const RenderData::Sprite& sprite)
|
||||||
{
|
{
|
||||||
draw_sprite_region(dst_x, dst_y, img, 0, 0, img.width, img.height);
|
draw_sprite_ex(dst_x, dst_y, sprite, 1, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::draw_sprite(int32_t dst_x, int32_t dst_y, const RenderData::SpriteRegion& region)
|
void DrawContext::draw_sprite_ex(int32_t dst_x, int32_t dst_y, const RenderData::Sprite& sprite,
|
||||||
|
int32_t scale, bool flip_h, bool flip_v)
|
||||||
{
|
{
|
||||||
draw_sprite_region(dst_x, dst_y, region);
|
if (!sprite.atlas) return;
|
||||||
}
|
|
||||||
|
|
||||||
void DrawContext::draw_sprite_region(int32_t dst_x, int32_t dst_y, const RenderData::Image& img,
|
blit_sprite_pixels(
|
||||||
int32_t src_x, int32_t src_y, int32_t src_w, int32_t src_h)
|
|
||||||
{
|
|
||||||
draw_sprite_ex(dst_x, dst_y, img, src_x, src_y, src_w, src_h, 1, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawContext::draw_sprite_region(int32_t dst_x, int32_t dst_y, const RenderData::SpriteRegion& region)
|
|
||||||
{
|
|
||||||
draw_sprite_region_ex(dst_x, dst_y, region, 1, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawContext::draw_sprite_region_ex(int32_t dst_x, int32_t dst_y, const RenderData::SpriteRegion& region,
|
|
||||||
int32_t scale, bool flip_h, bool flip_v)
|
|
||||||
{
|
|
||||||
if (!region.atlas) return;
|
|
||||||
|
|
||||||
draw_sprite_ex(
|
|
||||||
dst_x,
|
dst_x,
|
||||||
dst_y,
|
dst_y,
|
||||||
*region.atlas,
|
*sprite.atlas,
|
||||||
region.x,
|
sprite.x,
|
||||||
region.y,
|
sprite.y,
|
||||||
region.width,
|
sprite.width,
|
||||||
region.height,
|
sprite.height,
|
||||||
scale,
|
scale,
|
||||||
flip_h,
|
flip_h,
|
||||||
flip_v);
|
flip_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::draw_sprite_ex(int32_t dst_x, int32_t dst_y, const RenderData::Image& img,
|
void DrawContext::blit_sprite_pixels(int32_t dst_x, int32_t dst_y,
|
||||||
int32_t src_x, int32_t src_y, int32_t src_w, int32_t src_h,
|
const RenderData::Image& image,
|
||||||
int32_t scale, bool flip_h, bool flip_v)
|
int32_t src_x, int32_t src_y,
|
||||||
|
int32_t src_w, int32_t src_h,
|
||||||
|
int32_t scale, bool flip_h, bool flip_v)
|
||||||
{
|
{
|
||||||
if (scale < 1 || !img.pixels || src_w <= 0 || src_h <= 0) return;
|
if (scale < 1 || !image.pixels || src_w <= 0 || src_h <= 0) return;
|
||||||
if (src_x < 0 || src_y < 0 || src_x + src_w > img.width || src_y + src_h > img.height) return;
|
if (src_x < 0 || src_y < 0 || src_x + src_w > image.width || src_y + src_h > image.height) return;
|
||||||
|
|
||||||
const int32_t img_w = img.width;
|
const int32_t img_w = image.width;
|
||||||
const int32_t screen_w = frameBuffer->get_width();
|
const int32_t screen_w = frameBuffer->get_width();
|
||||||
const int32_t screen_h = frameBuffer->get_height();
|
const int32_t screen_h = frameBuffer->get_height();
|
||||||
const int32_t draw_w = src_w * scale;
|
const int32_t draw_w = src_w * scale;
|
||||||
|
|
@ -126,7 +112,7 @@ namespace Core
|
||||||
|
|
||||||
Core::FramePixel* dst = static_cast<Core::FramePixel*>(frameBuffer->get_buffer());
|
Core::FramePixel* dst = static_cast<Core::FramePixel*>(frameBuffer->get_buffer());
|
||||||
const int32_t fb_w = frameBuffer->get_width();
|
const int32_t fb_w = frameBuffer->get_width();
|
||||||
const uint16_t* src = static_cast<const uint16_t*>(img.pixels);
|
const uint16_t* src = static_cast<const uint16_t*>(image.pixels);
|
||||||
|
|
||||||
if (scale == 1)
|
if (scale == 1)
|
||||||
{
|
{
|
||||||
|
|
@ -249,9 +235,9 @@ namespace Core
|
||||||
const int32_t clipped_w = clipped_right - clipped_left;
|
const int32_t clipped_w = clipped_right - clipped_left;
|
||||||
const int32_t clipped_h = clipped_bottom - clipped_top;
|
const int32_t clipped_h = clipped_bottom - clipped_top;
|
||||||
|
|
||||||
draw_sprite_ex(clipped_left, clipped_top, *tilemap.atlas,
|
blit_sprite_pixels(clipped_left, clipped_top, *tilemap.atlas,
|
||||||
clipped_src_x, clipped_src_y, clipped_w, clipped_h,
|
clipped_src_x, clipped_src_y, clipped_w, clipped_h,
|
||||||
1, false, false);
|
1, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "Vector2.h"
|
#include "Vector2.h"
|
||||||
#include "Triangle.h"
|
#include "Triangle.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "SpriteRegion.h"
|
#include "Sprite.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
#include "BitmapFont.h"
|
#include "BitmapFont.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
@ -41,6 +41,12 @@ namespace Core
|
||||||
int32_t dst_x, int32_t dst_y,
|
int32_t dst_x, int32_t dst_y,
|
||||||
uint16_t pixel);
|
uint16_t pixel);
|
||||||
|
|
||||||
|
void blit_sprite_pixels(int32_t dst_x, int32_t dst_y,
|
||||||
|
const RenderData::Image& image,
|
||||||
|
int32_t src_x, int32_t src_y,
|
||||||
|
int32_t src_w, int32_t src_h,
|
||||||
|
int32_t scale, bool flip_h, bool flip_v);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DrawContext(int32_t width, int32_t height);
|
DrawContext(int32_t width, int32_t height);
|
||||||
~DrawContext();
|
~DrawContext();
|
||||||
|
|
@ -58,15 +64,8 @@ namespace Core
|
||||||
void draw_line(const Math::Vector2Int& from, const Math::Vector2Int& to, const RenderData::Color& color);
|
void draw_line(const Math::Vector2Int& from, const Math::Vector2Int& to, const RenderData::Color& color);
|
||||||
void draw_triangle(const RenderData::Triangle& triangle, const RenderData::Color& color);
|
void draw_triangle(const RenderData::Triangle& triangle, const RenderData::Color& color);
|
||||||
|
|
||||||
void draw_sprite(int32_t dst_x, int32_t dst_y, const RenderData::Image& img);
|
void draw_sprite(int32_t dst_x, int32_t dst_y, const RenderData::Sprite& sprite);
|
||||||
void draw_sprite(int32_t dst_x, int32_t dst_y, const RenderData::SpriteRegion& region);
|
void draw_sprite_ex(int32_t dst_x, int32_t dst_y, const RenderData::Sprite& sprite,
|
||||||
void draw_sprite_region(int32_t dst_x, int32_t dst_y, const RenderData::Image& img,
|
|
||||||
int32_t src_x, int32_t src_y, int32_t src_w, int32_t src_h);
|
|
||||||
void draw_sprite_region(int32_t dst_x, int32_t dst_y, const RenderData::SpriteRegion& region);
|
|
||||||
void draw_sprite_region_ex(int32_t dst_x, int32_t dst_y, const RenderData::SpriteRegion& region,
|
|
||||||
int32_t scale, bool flip_h, bool flip_v);
|
|
||||||
void draw_sprite_ex(int32_t dst_x, int32_t dst_y, const RenderData::Image& img,
|
|
||||||
int32_t src_x, int32_t src_y, int32_t src_w, int32_t src_h,
|
|
||||||
int32_t scale, bool flip_h, bool flip_v);
|
int32_t scale, bool flip_h, bool flip_v);
|
||||||
void draw_tilemap(const RenderData::Tilemap& tilemap,
|
void draw_tilemap(const RenderData::Tilemap& tilemap,
|
||||||
int32_t screen_x, int32_t screen_y,
|
int32_t screen_x, int32_t screen_y,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace RenderData
|
namespace RenderData
|
||||||
{
|
{
|
||||||
struct SpriteRegion
|
struct Sprite
|
||||||
{
|
{
|
||||||
const Image* atlas;
|
const Image* atlas;
|
||||||
int32_t x;
|
int32_t x;
|
||||||
|
|
@ -12,10 +12,10 @@ namespace RenderData
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
|
|
||||||
SpriteRegion()
|
Sprite()
|
||||||
: atlas(nullptr), x(0), y(0), width(0), height(0) {}
|
: atlas(nullptr), x(0), y(0), width(0), height(0) {}
|
||||||
|
|
||||||
SpriteRegion(const Image* atlas, int32_t x, int32_t y, int32_t width, int32_t height)
|
Sprite(const Image* atlas, int32_t x, int32_t y, int32_t width, int32_t height)
|
||||||
: atlas(atlas), x(x), y(y), width(width), height(height) {}
|
: atlas(atlas), x(x), y(y), width(width), height(height) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
#include "SpriteRasterizer.h"
|
|
||||||
#include "FrameBuffer.h"
|
|
||||||
#include "../RenderData/Image.h"
|
|
||||||
#include "../RenderData/Sprite.h"
|
|
||||||
|
|
||||||
namespace Rasterizer
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
inline uint16_t rgba5551_to_rgb565(uint16_t c)
|
|
||||||
{
|
|
||||||
const uint16_t r = static_cast<uint16_t>((c >> 11) & 0x1Fu);
|
|
||||||
const uint16_t g = static_cast<uint16_t>((c >> 6) & 0x1Fu);
|
|
||||||
const uint16_t b = static_cast<uint16_t>((c >> 1) & 0x1Fu);
|
|
||||||
const uint16_t g6 = static_cast<uint16_t>((g << 1) | (g >> 4));
|
|
||||||
return static_cast<uint16_t>((r << 11) | (g6 << 5) | b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool rgba5551_is_opaque(uint16_t c)
|
|
||||||
{
|
|
||||||
return (c & 0x1u) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteRasterizer::DrawImage(const RenderData::Image& image, int32_t x, int32_t y)
|
|
||||||
{
|
|
||||||
DrawSprite(RenderData::Sprite(&image), x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteRasterizer::DrawSprite(const RenderData::Sprite& sprite, int32_t x, int32_t y)
|
|
||||||
{
|
|
||||||
if (frameBuffer == nullptr || !sprite.is_valid())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int32_t minX = x < 0 ? -x : 0;
|
|
||||||
const int32_t minY = y < 0 ? -y : 0;
|
|
||||||
const int32_t maxX = x + sprite.width > frameBuffer->get_width() ? frameBuffer->get_width() - x : sprite.width;
|
|
||||||
const int32_t maxY = y + sprite.height > frameBuffer->get_height() ? frameBuffer->get_height() - y : sprite.height;
|
|
||||||
|
|
||||||
if (minX >= maxX || minY >= maxY)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::FramePixel* dst = static_cast<Core::FramePixel*>(frameBuffer->get_buffer());
|
|
||||||
const int32_t fb_w = frameBuffer->get_width();
|
|
||||||
|
|
||||||
for (int32_t sy = minY; sy < maxY; ++sy)
|
|
||||||
{
|
|
||||||
Core::FramePixel* dst_row = dst + (y + sy) * fb_w;
|
|
||||||
for (int32_t sx = minX; sx < maxX; ++sx)
|
|
||||||
{
|
|
||||||
const uint16_t color = sprite.get_pixel_fast(sx, sy);
|
|
||||||
if (!rgba5551_is_opaque(color))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst_row[x + sx] = rgba5551_to_rgb565(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace Core
|
|
||||||
{
|
|
||||||
class FrameBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace RenderData
|
|
||||||
{
|
|
||||||
class Image;
|
|
||||||
struct Sprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Rasterizer
|
|
||||||
{
|
|
||||||
class SpriteRasterizer
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
Core::FrameBuffer* frameBuffer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SpriteRasterizer(Core::FrameBuffer* frameBuffer) : frameBuffer(frameBuffer) {}
|
|
||||||
|
|
||||||
void DrawImage(const RenderData::Image& image, int32_t x, int32_t y);
|
|
||||||
void DrawSprite(const RenderData::Sprite& sprite, int32_t x, int32_t y);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace RenderData
|
|
||||||
{
|
|
||||||
class Image
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
std::vector<uint16_t> pixels;
|
|
||||||
|
|
||||||
static bool calculate_pixel_count(int32_t width, int32_t height, size_t& count)
|
|
||||||
{
|
|
||||||
if (width <= 0 || height <= 0)
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t safeWidth = static_cast<size_t>(width);
|
|
||||||
const size_t safeHeight = static_cast<size_t>(height);
|
|
||||||
if (safeWidth > std::numeric_limits<size_t>::max() / safeHeight)
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
count = safeWidth * safeHeight;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Image() : width(0), height(0) {}
|
|
||||||
|
|
||||||
Image(int32_t width, int32_t height) : width(0), height(0)
|
|
||||||
{
|
|
||||||
size_t pixelCount = 0;
|
|
||||||
if (calculate_pixel_count(width, height, pixelCount))
|
|
||||||
{
|
|
||||||
this->width = width;
|
|
||||||
this->height = height;
|
|
||||||
pixels.assign(pixelCount, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image(int32_t width, int32_t height, const std::vector<uint16_t>& pixels) : width(0), height(0)
|
|
||||||
{
|
|
||||||
size_t pixelCount = 0;
|
|
||||||
if (calculate_pixel_count(width, height, pixelCount) && pixels.size() == pixelCount)
|
|
||||||
{
|
|
||||||
this->width = width;
|
|
||||||
this->height = height;
|
|
||||||
this->pixels = pixels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t get_width() const { return width; }
|
|
||||||
|
|
||||||
int32_t get_height() const { return height; }
|
|
||||||
|
|
||||||
size_t total_pixels() const { return pixels.size(); }
|
|
||||||
|
|
||||||
const uint16_t* data() const { return pixels.data(); }
|
|
||||||
|
|
||||||
uint16_t* data() { return pixels.data(); }
|
|
||||||
|
|
||||||
bool is_valid() const
|
|
||||||
{
|
|
||||||
size_t pixelCount = 0;
|
|
||||||
return calculate_pixel_count(width, height, pixelCount) && pixels.size() == pixelCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t get_pixel(int32_t x, int32_t y) const
|
|
||||||
{
|
|
||||||
if (x < 0 || x >= width || y < 0 || y >= height)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(y) * width + x;
|
|
||||||
return pixels[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t get_pixel_fast(int32_t x, int32_t y) const
|
|
||||||
{
|
|
||||||
size_t index = static_cast<size_t>(y) * width + x;
|
|
||||||
return pixels[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_pixel(int32_t x, int32_t y, uint16_t color)
|
|
||||||
{
|
|
||||||
if (x < 0 || x >= width || y < 0 || y >= height)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(y) * width + x;
|
|
||||||
pixels.at(index) = color;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
#include "Image.h"
|
|
||||||
|
|
||||||
namespace RenderData
|
|
||||||
{
|
|
||||||
struct Sprite
|
|
||||||
{
|
|
||||||
const Image* image;
|
|
||||||
int32_t x;
|
|
||||||
int32_t y;
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
|
|
||||||
Sprite() : image(nullptr), x(0), y(0), width(0), height(0) {}
|
|
||||||
|
|
||||||
Sprite(const Image* image) :
|
|
||||||
image(image),
|
|
||||||
x(0),
|
|
||||||
y(0),
|
|
||||||
width(image ? image->get_width() : 0),
|
|
||||||
height(image ? image->get_height() : 0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Sprite(const Image* image, int32_t x, int32_t y, int32_t width, int32_t height) :
|
|
||||||
image(image),
|
|
||||||
x(x),
|
|
||||||
y(y),
|
|
||||||
width(width),
|
|
||||||
height(height)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool is_valid() const
|
|
||||||
{
|
|
||||||
if (image == nullptr || !image->is_valid())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x < 0 || y < 0 || width <= 0 || height <= 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x + width <= image->get_width() && y + height <= image->get_height();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t get_pixel(int32_t localX, int32_t localY) const
|
|
||||||
{
|
|
||||||
if (!is_valid() || localX < 0 || localX >= width || localY < 0 || localY >= height)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return image->get_pixel(x + localX, y + localY);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t get_pixel_fast(int32_t localX, int32_t localY) const
|
|
||||||
{
|
|
||||||
return image->get_pixel_fast(x + localX, y + localY);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -78,11 +78,12 @@ namespace
|
||||||
Core::DrawContext ctx(2, 1);
|
Core::DrawContext ctx(2, 1);
|
||||||
ctx.clear_color(RenderData::Color(0, 0, 255, 255));
|
ctx.clear_color(RenderData::Color(0, 0, 255, 255));
|
||||||
|
|
||||||
RenderData::Image sprite(
|
RenderData::Image image(
|
||||||
sprite_pixels,
|
sprite_pixels,
|
||||||
2,
|
2,
|
||||||
1,
|
1,
|
||||||
RenderData::PixelFormat::RGBA5551);
|
RenderData::PixelFormat::RGBA5551);
|
||||||
|
RenderData::Sprite sprite(&image, 0, 0, image.width, image.height);
|
||||||
ctx.draw_sprite(0, 0, sprite);
|
ctx.draw_sprite(0, 0, sprite);
|
||||||
|
|
||||||
CaptureDisplay display;
|
CaptureDisplay display;
|
||||||
|
|
@ -95,6 +96,29 @@ namespace
|
||||||
assert(pixels[1] == 0x07E0u);
|
assert(pixels[1] == 0x07E0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestDrawSpriteUsesAtlasSubrect()
|
||||||
|
{
|
||||||
|
const uint16_t atlas_pixels[] = {
|
||||||
|
0xF801u,
|
||||||
|
0x07C1u
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderData::Image atlas(
|
||||||
|
atlas_pixels,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
RenderData::PixelFormat::RGBA5551);
|
||||||
|
RenderData::Sprite sprite(&atlas, 1, 0, 1, 1);
|
||||||
|
|
||||||
|
Core::DrawContext ctx(1, 1);
|
||||||
|
ctx.clear_color(RenderData::Color::Blue());
|
||||||
|
ctx.draw_sprite(0, 0, sprite);
|
||||||
|
|
||||||
|
CaptureDisplay display;
|
||||||
|
const Core::FramePixel* pixels = PresentPixels(ctx, display);
|
||||||
|
assert(pixels[0] == 0x07E0u);
|
||||||
|
}
|
||||||
|
|
||||||
void TestSpriteAssetLoaderRoundTripsRgba5551()
|
void TestSpriteAssetLoaderRoundTripsRgba5551()
|
||||||
{
|
{
|
||||||
const std::string path = "render_pipeline_test.sprite";
|
const std::string path = "render_pipeline_test.sprite";
|
||||||
|
|
@ -216,6 +240,7 @@ int main()
|
||||||
TestFrameBufferStoresRgb565();
|
TestFrameBufferStoresRgb565();
|
||||||
TestImageDefaultsToRgba5551AndReturnsRawPixels();
|
TestImageDefaultsToRgba5551AndReturnsRawPixels();
|
||||||
TestDrawSpriteUsesOneBitAlpha();
|
TestDrawSpriteUsesOneBitAlpha();
|
||||||
|
TestDrawSpriteUsesAtlasSubrect();
|
||||||
TestSpriteAssetLoaderRoundTripsRgba5551();
|
TestSpriteAssetLoaderRoundTripsRgba5551();
|
||||||
TestDrawTextUsesBitMaskAndColor();
|
TestDrawTextUsesBitMaskAndColor();
|
||||||
TestDrawTextColorChangesPerCallAndBackgroundFill();
|
TestDrawTextColorChangesPerCallAndBackgroundFill();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue