重构SpriteAssertTool.cpp,减少中间文件产生;重构TomGame文件夹,删去不必要的文件;修改CMakeLists,PC重构Game自动重新构建资源头文件;修改文档
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
+138957
-81101
File diff suppressed because it is too large
Load Diff
-1
@@ -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 +0,0 @@
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user