重构SpriteAssertTool.cpp,减少中间文件产生;重构TomGame文件夹,删去不必要的文件;修改CMakeLists,PC重构Game自动重新构建资源头文件;修改文档

This commit is contained in:
HP
2026-06-08 10:27:31 +08:00
parent 08088c8413
commit 1e34e15e04
26 changed files with 139256 additions and 82274 deletions
+41 -52
View File
@@ -1,8 +1,10 @@
set(TOM_GAME_TARGET IMX6U-Game)
set(TOM_ATLAS_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/generated/tom_atlas.h")
set_source_files_properties(${TOM_ATLAS_HEADER} PROPERTIES GENERATED TRUE)
add_executable(${TOM_GAME_TARGET}
Main.cpp
generated/tom_atlas.h
${TOM_ATLAS_HEADER}
)
target_include_directories(${TOM_GAME_TARGET} PRIVATE
@@ -11,91 +13,78 @@ target_include_directories(${TOM_GAME_TARGET} PRIVATE
imx6u_configure_app_target(${TOM_GAME_TARGET})
if(CMAKE_CROSSCOMPILING AND NOT EXISTS "${TOM_ATLAS_HEADER}")
message(FATAL_ERROR
"Tom atlas header is missing. Run GenerateTomAtlasHeader in a host build before cross compiling."
)
endif()
if(NOT USE_FRAMEBUFFER)
set(SPRITE_ASSET_TOOL_SOURCES
set(TOM_ATLAS_TOOL_SOURCES
tools/asset_pipeline/SpriteAssetTool.cpp
${PROJECT_SOURCE_DIR}/src/Core/Asset/SpriteAssetLoader.cpp
)
if(WIN32)
add_executable(TomSpriteAssetTool EXCLUDE_FROM_ALL ${SPRITE_ASSET_TOOL_SOURCES})
set_target_properties(TomSpriteAssetTool PROPERTIES OUTPUT_NAME SpriteAssetTool)
target_include_directories(TomSpriteAssetTool PRIVATE
${PROJECT_SOURCE_DIR}/src/Core/Asset
${PROJECT_SOURCE_DIR}/src/Core/RenderData
add_executable(TomAtlasTool EXCLUDE_FROM_ALL ${TOM_ATLAS_TOOL_SOURCES})
target_include_directories(TomAtlasTool PRIVATE
${PROJECT_SOURCE_DIR}/libs/Win/SDL2/include
${PROJECT_SOURCE_DIR}/libs/Win/SDL_image/include
)
target_link_directories(TomSpriteAssetTool PRIVATE
target_link_directories(TomAtlasTool PRIVATE
${SDL2_LIB_DIR}
${SDL2_IMAGE_LIB_DIR}
)
target_link_libraries(TomSpriteAssetTool PRIVATE SDL2main SDL2 SDL2_image)
target_link_libraries(TomAtlasTool PRIVATE SDL2main SDL2 SDL2_image)
add_custom_command(TARGET TomSpriteAssetTool POST_BUILD
add_custom_command(TARGET TomAtlasTool POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${SDL2_DLL}"
"$<TARGET_FILE_DIR:TomSpriteAssetTool>"
"$<TARGET_FILE_DIR:TomAtlasTool>"
)
add_custom_command(TARGET TomSpriteAssetTool POST_BUILD
add_custom_command(TARGET TomAtlasTool POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${SDL2_IMAGE_DLL}"
"$<TARGET_FILE_DIR:TomSpriteAssetTool>"
"$<TARGET_FILE_DIR:TomAtlasTool>"
)
elseif(SDL2_image_FOUND)
add_executable(TomSpriteAssetTool EXCLUDE_FROM_ALL ${SPRITE_ASSET_TOOL_SOURCES})
set_target_properties(TomSpriteAssetTool PROPERTIES OUTPUT_NAME SpriteAssetTool)
target_include_directories(TomSpriteAssetTool PRIVATE
${PROJECT_SOURCE_DIR}/src/Core/Asset
${PROJECT_SOURCE_DIR}/src/Core/RenderData
add_executable(TomAtlasTool EXCLUDE_FROM_ALL ${TOM_ATLAS_TOOL_SOURCES})
target_include_directories(TomAtlasTool PRIVATE
${SDL2_image_INCLUDE_DIRS}
${SDL2_IMAGE_INCLUDE_DIRS}
)
target_link_libraries(TomSpriteAssetTool PRIVATE SDL2::SDL2)
target_link_libraries(TomAtlasTool PRIVATE SDL2::SDL2)
if(TARGET SDL2_image::SDL2_image)
target_link_libraries(TomSpriteAssetTool PRIVATE SDL2_image::SDL2_image)
target_link_libraries(TomAtlasTool PRIVATE SDL2_image::SDL2_image)
else()
target_link_libraries(TomSpriteAssetTool PRIVATE
target_link_libraries(TomAtlasTool PRIVATE
${SDL2_image_LIBRARIES}
${SDL2_IMAGE_LIBRARIES}
)
endif()
else()
message(STATUS "SpriteAssetTool disabled: SDL2_image was not found")
message(STATUS "TomAtlasTool disabled: SDL2_image was not found")
endif()
if(TARGET TomSpriteAssetTool)
add_custom_target(ConvertTomSprites
COMMAND $<TARGET_FILE:TomSpriteAssetTool>
--batch
"src/Apps/Game/assets/raw"
"src/Apps/Game/assets/sprites"
--preset tom-800x480
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
DEPENDS TomSpriteAssetTool
COMMENT "Converting Tom PNG assets to board-ready .sprite files"
VERBATIM
)
add_custom_target(GenerateTomAtlasHeader
COMMAND $<TARGET_FILE:TomSpriteAssetTool>
--atlas-header
"src/Apps/Game/assets/raw"
"src/Apps/Game/generated/tom_atlas.h"
tom_atlas
--atlas-width
1024
--preset
tom-800x480
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
DEPENDS TomSpriteAssetTool
COMMENT "Generating Tom atlas header from PNG assets"
VERBATIM
)
if(TARGET TomAtlasTool)
if(NOT CMAKE_CROSSCOMPILING)
add_custom_target(GenerateTomAtlasHeader
COMMAND ${CMAKE_COMMAND} -E make_directory
"src/Apps/Game/generated"
COMMAND $<TARGET_FILE:TomAtlasTool>
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
DEPENDS TomAtlasTool
COMMENT "Generating Tom atlas header from PNG assets"
VERBATIM
)
add_dependencies(${TOM_GAME_TARGET} GenerateTomAtlasHeader)
else()
add_custom_target(GenerateTomAtlasHeader
COMMAND ${CMAKE_COMMAND} -E echo
"GenerateTomAtlasHeader is host-only. Run it in build-win or build-linux before cross compiling."
VERBATIM
)
endif()
endif()
endif()
View File
-1
View File
@@ -1 +0,0 @@
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
-1
View File
@@ -1 +0,0 @@
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1 +0,0 @@
@@ -1,234 +0,0 @@
#include <SDL.h>
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "FrameBuffer.h"
#include "SDLDisplay.h"
#include "SpriteAssetLoader.h"
#include "SpriteRasterizer.h"
#include "Image.h"
#include "Sprite.h"
#include "SpriteAnimator.h"
#include "AnimationSystem.h"
static std::string FindAssetPath(const std::string& fileName)
{
const char* roots[] = {
"src/Apps/Game/assets/sprites/",
"../src/Apps/Game/assets/sprites/",
"../../src/Apps/Game/assets/sprites/",
"../../../src/Apps/Game/assets/sprites/"
};
for (size_t i = 0; i < sizeof(roots) / sizeof(roots[0]); ++i)
{
const std::string path = std::string(roots[i]) + fileName;
std::ifstream file(path.c_str(), std::ios::binary);
if (file.good())
{
return path;
}
}
return std::string("src/Apps/Game/assets/sprites/") + fileName;
}
static bool LoadSpriteImage(const std::string& fileName, RenderData::Image& image)
{
const std::string path = FindAssetPath(fileName);
if (!Asset::SpriteAssetLoader::Load(path, image))
{
std::cerr << "Load sprite failed: " << path << std::endl;
return false;
}
return true;
}
static RenderData::Image ResizeImageNearest(const RenderData::Image& source, int32_t width, int32_t height)
{
if (!source.is_valid() || width <= 0 || height <= 0)
{
return RenderData::Image();
}
RenderData::Image result(width, height);
for (int32_t y = 0; y < height; ++y)
{
const int32_t sourceY = y * source.get_height() / height;
for (int32_t x = 0; x < width; ++x)
{
const int32_t sourceX = x * source.get_width() / width;
result.set_pixel(x, y, source.get_pixel_fast(sourceX, sourceY));
}
}
return result;
}
static RenderData::Image ResizeImageToFit(const RenderData::Image& source, int32_t maxWidth, int32_t maxHeight)
{
if (!source.is_valid() || maxWidth <= 0 || maxHeight <= 0)
{
return RenderData::Image();
}
const float scaleX = static_cast<float>(maxWidth) / source.get_width();
const float scaleY = static_cast<float>(maxHeight) / source.get_height();
const float scale = std::min(scaleX, scaleY);
const int32_t width = std::max(1, static_cast<int32_t>(source.get_width() * scale));
const int32_t height = std::max(1, static_cast<int32_t>(source.get_height() * scale));
return ResizeImageNearest(source, width, height);
}
static bool LoadFrames(
const std::vector<std::string>& fileNames,
std::vector<RenderData::Image>& images,
std::vector<RenderData::Sprite>& frames,
int32_t maxFrameWidth,
int32_t maxFrameHeight)
{
images.clear();
frames.clear();
images.reserve(fileNames.size());
for (size_t i = 0; i < fileNames.size(); ++i)
{
RenderData::Image image;
if (!LoadSpriteImage(fileNames[i], image))
{
return false;
}
images.push_back(ResizeImageToFit(image, maxFrameWidth, maxFrameHeight));
}
frames.reserve(images.size());
for (size_t i = 0; i < images.size(); ++i)
{
frames.push_back(RenderData::Sprite(&images[i]));
}
return !frames.empty();
}
int main(int argc, char* argv[])
{
(void)argc;
(void)argv;
const int32_t width = 800;
const int32_t height = 480;
Platform::SDLDisplay display;
if (!display.init(width, height))
{
return -1;
}
RenderData::Image originalBackground;
if (!LoadSpriteImage("background.sprite", originalBackground))
{
display.shutdown();
return -1;
}
RenderData::Image background = ResizeImageNearest(originalBackground, width, height);
std::vector<std::string> frameFiles;
frameFiles.push_back("Tom-stand.sprite");
frameFiles.push_back("Tom-listhen.sprite");
frameFiles.push_back("Tom-openmouse1.sprite");
frameFiles.push_back("Tom-openmouse2.sprite");
frameFiles.push_back("Tom-say1.sprite");
frameFiles.push_back("Tom-say2.sprite");
frameFiles.push_back("Tom-say3.sprite");
frameFiles.push_back("Tom-say4.sprite");
std::vector<RenderData::Image> frameImages;
std::vector<RenderData::Sprite> frames;
if (!LoadFrames(frameFiles, frameImages, frames, width * 7 / 10, height * 9 / 10))
{
display.shutdown();
return -1;
}
Core::FrameBuffer frameBuffer(width, height);
Rasterizer::SpriteRasterizer spriteRasterizer(&frameBuffer);
Game::SpriteAnimator tomAnimator(frames, 0.12f, true);
Game::AnimationSystem animationSystem;
const RenderData::Sprite* firstFrame = tomAnimator.get_current_sprite();
const int32_t tomX = firstFrame ? (width - firstFrame->width) / 2 : 0;
const int32_t tomY = firstFrame ? height - firstFrame->height - 20 : 0;
animationSystem.add(&tomAnimator, tomX, tomY);
std::cout << "Sprite animation test" << std::endl;
std::cout << "Space: play/pause, R: reset, Esc: quit" << std::endl;
std::cout << "Background: " << originalBackground.get_width() << "x" << originalBackground.get_height()
<< " -> " << background.get_width() << "x" << background.get_height() << std::endl;
std::cout << "Tom frame 0: " << frameImages[0].get_width() << "x" << frameImages[0].get_height() << std::endl;
bool shouldQuit = false;
uint32_t lastTime = display.get_time_ms();
while (!shouldQuit)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
shouldQuit = true;
}
else if (event.type == SDL_KEYDOWN)
{
if (event.key.repeat != 0)
{
continue;
}
if (event.key.keysym.sym == SDLK_ESCAPE)
{
shouldQuit = true;
}
else if (event.key.keysym.sym == SDLK_SPACE)
{
if (tomAnimator.is_playing())
{
tomAnimator.stop();
}
else
{
tomAnimator.play();
}
}
else if (event.key.keysym.sym == SDLK_r)
{
tomAnimator.reset();
tomAnimator.play();
}
}
}
const uint32_t currentTime = display.get_time_ms();
const float deltaTime = static_cast<float>(currentTime - lastTime) * 0.001f;
lastTime = currentTime;
animationSystem.update(deltaTime);
frameBuffer.clear(RenderData::Color(18, 18, 24, 255));
spriteRasterizer.DrawImage(background, 0, 0);
animationSystem.draw(spriteRasterizer);
display.present(&frameBuffer);
SDL_Delay(16);
}
display.shutdown();
return 0;
}
-1
View File
@@ -1 +0,0 @@
File diff suppressed because it is too large Load Diff