From 3beae16917d7bdb3eaddc5cc976ffaf6f02f1591 Mon Sep 17 00:00:00 2001 From: HP <2726519488@qq.com> Date: Sun, 7 Jun 2026 10:38:34 +0800 Subject: [PATCH] local changes before merge --- CMakeLists.txt | 144 ++++++++++++++++++++++++++++++++++++++------- src/main.cpp | 157 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74a7ead..70c6cc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,18 +6,49 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) option(USE_FRAMEBUFFER "Use Linux framebuffer instead of SDL2" OFF) -set(SOURCES - src/main.cpp +set(ENGINE_SOURCES src/Asset/ObjLoader.cpp + src/Asset/SpriteAssetLoader.cpp src/Core/DepthBuffer.cpp src/Core/FrameBuffer.cpp src/Core/Renderer.cpp + game/src/app/TomGameApp.cpp + game/src/components/SpriteAnimator.cpp + game/src/audio/VoiceEffect.cpp + game/src/audio/VoicePlayer.cpp + game/src/audio/VoiceRecorder.cpp + game/src/hardware/AudioInput.cpp + game/src/hardware/AudioOutput.cpp + game/src/hardware/ButtonInput.cpp + game/src/systems/AnimationSystem.cpp src/Rasterizer/Rasterizer.cpp + src/Rasterizer/SpriteRasterizer.cpp src/Rasterizer/TriangleRasterizer.cpp src/Scene/Camera.cpp src/Shading/BlinnPhongShader.cpp ) +set(ENGINE_INCLUDE_DIRS + src/Platform + src/Asset + src/Core + src/Math + src/Rasterizer + src/RenderData + src/Scene + src/Shading + game/src/app + game/src/audio + game/src/components + game/src/hardware + game/src/systems +) + +set(SOURCES + src/main.cpp + ${ENGINE_SOURCES} +) + if(USE_FRAMEBUFFER) list(APPEND SOURCES src/Platform/FBDisplay.cpp) else() @@ -26,23 +57,13 @@ endif() add_executable(IMX6U-Game ${SOURCES}) -target_include_directories(IMX6U-Game PRIVATE - src/Platform - src/Asset - src/Core - src/Math - src/Rasterizer - src/RenderData - src/Scene - src/Shading -) +target_include_directories(IMX6U-Game PRIVATE ${ENGINE_INCLUDE_DIRS}) if(USE_FRAMEBUFFER) target_compile_definitions(IMX6U-Game PRIVATE USE_FRAMEBUFFER) else() target_include_directories(IMX6U-Game PRIVATE libs/Win/SDL2/include - libs/Win/SDL_image/include ) if(WIN32) @@ -58,26 +79,109 @@ else() set(SDL2_IMAGE_DLL "${CMAKE_CURRENT_SOURCE_DIR}/libs/Win/SDL_image/lib/x86/SDL2_image.dll") endif() - target_link_directories(IMX6U-Game PRIVATE ${SDL2_LIB_DIR} ${SDL2_IMAGE_LIB_DIR}) - target_link_libraries(IMX6U-Game PRIVATE SDL2main SDL2 SDL2_image) + target_link_directories(IMX6U-Game PRIVATE ${SDL2_LIB_DIR}) + target_link_libraries(IMX6U-Game PRIVATE SDL2main SDL2) add_custom_command(TARGET IMX6U-Game POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_DLL}" "$" ) - add_custom_command(TARGET IMX6U-Game POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${SDL2_IMAGE_DLL}" - "$" - ) else() find_package(SDL2 REQUIRED) target_link_libraries(IMX6U-Game PRIVATE SDL2::SDL2) endif() + + find_package(SDL2_image QUIET) +endif() + +if(UNIX) + target_link_libraries(IMX6U-Game PRIVATE asound) endif() if(MSVC) target_compile_options(IMX6U-Game PRIVATE /utf-8 /W3) set_property(TARGET IMX6U-Game PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) endif() + +if(NOT USE_FRAMEBUFFER) + set(SPRITE_ANIMATION_TEST_SOURCES + game/tests/manual/SpriteAnimationTest.cpp + ${ENGINE_SOURCES} + src/Platform/SDLDisplay.cpp + ) + + if(WIN32) + add_executable(SpriteAnimationTest ${SPRITE_ANIMATION_TEST_SOURCES}) + target_include_directories(SpriteAnimationTest PRIVATE + ${ENGINE_INCLUDE_DIRS} + libs/Win/SDL2/include + ) + target_link_directories(SpriteAnimationTest PRIVATE ${SDL2_LIB_DIR}) + target_link_libraries(SpriteAnimationTest PRIVATE SDL2main SDL2) + + add_custom_command(TARGET SpriteAnimationTest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SDL2_DLL}" + "$" + ) + else() + add_executable(SpriteAnimationTest ${SPRITE_ANIMATION_TEST_SOURCES}) + target_include_directories(SpriteAnimationTest PRIVATE ${ENGINE_INCLUDE_DIRS}) + target_link_libraries(SpriteAnimationTest PRIVATE SDL2::SDL2 asound) + endif() + + if(MSVC AND TARGET SpriteAnimationTest) + target_compile_options(SpriteAnimationTest PRIVATE /utf-8 /W3) + endif() + + set(SPRITE_ASSET_TOOL_SOURCES + game/tools/asset_pipeline/SpriteAssetTool.cpp + src/Asset/SpriteAssetLoader.cpp + ) + + if(WIN32) + add_executable(SpriteAssetTool ${SPRITE_ASSET_TOOL_SOURCES}) + target_include_directories(SpriteAssetTool PRIVATE + src/Asset + src/RenderData + libs/Win/SDL2/include + libs/Win/SDL_image/include + ) + target_link_directories(SpriteAssetTool PRIVATE ${SDL2_LIB_DIR} ${SDL2_IMAGE_LIB_DIR}) + target_link_libraries(SpriteAssetTool PRIVATE SDL2main SDL2 SDL2_image) + + add_custom_command(TARGET SpriteAssetTool POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SDL2_DLL}" + "$" + ) + add_custom_command(TARGET SpriteAssetTool POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SDL2_IMAGE_DLL}" + "$" + ) + elseif(SDL2_image_FOUND) + add_executable(SpriteAssetTool ${SPRITE_ASSET_TOOL_SOURCES}) + target_include_directories(SpriteAssetTool PRIVATE + src/Asset + src/RenderData + ) + target_link_libraries(SpriteAssetTool PRIVATE SDL2::SDL2 SDL2_image::SDL2_image) + else() + message(STATUS "SpriteAssetTool disabled: SDL2_image was not found") + endif() + + if(TARGET SpriteAssetTool) + add_custom_target(ConvertTomSprites + COMMAND $ + --batch + "${CMAKE_CURRENT_SOURCE_DIR}/game/assets/raw" + "${CMAKE_CURRENT_SOURCE_DIR}/game/assets/sprites" + --preset tom-800x480 + DEPENDS SpriteAssetTool + COMMENT "Converting PNG assets to board-ready .sprite files" + VERBATIM + ) + endif() +endif() diff --git a/src/main.cpp b/src/main.cpp index 6dac311..e32184c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include "Vector2.h" #include "Vector3.h" #include "Vector4.h" @@ -15,6 +18,13 @@ #include #include "Vertex.h" #include "DepthBuffer.h" +#include "SpriteAssetLoader.h" +#include "SpriteRasterizer.h" +#include "Image.h" +#include "TomGameApp.h" +#include "AudioInput.h" +#include "AudioOutput.h" +#include "ButtonInput.h" #include "Display.h" #ifdef USE_FRAMEBUFFER @@ -25,6 +35,8 @@ const int32_t width = 800; const int32_t height = 600; +const int32_t tomWidth = 800; +const int32_t tomHeight = 480; struct ProjectedVertex { @@ -103,8 +115,153 @@ static bool IsTriangleVisible(const CubeTriangle &triangle, const std::array 0.0f; } +static bool HasArg(int argc, char* argv[], const std::string& expected) +{ + for (int i = 1; i < argc; ++i) + { + if (argv[i] != nullptr && expected == argv[i]) + { + return true; + } + } + + return false; +} + +static std::string FindSpriteAssetPath(const std::string& fileName) +{ + const char* roots[] = { + "game/assets/sprites/", + "../game/assets/sprites/", + "../../game/assets/sprites/", + "../../../game/assets/sprites/", + "/tmp/game/assets/sprites/", + "/usr/local/share/imx6u-game/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("game/assets/sprites/") + fileName; +} + +static bool LoadSpriteAsset(const std::string& fileName, RenderData::Image& image) +{ + const std::string path = FindSpriteAssetPath(fileName); + if (!Asset::SpriteAssetLoader::Load(path, image)) + { + std::cerr << "Load sprite asset failed: " << path << std::endl; + return false; + } + + return true; +} + +static int RunTomGame() +{ +#ifdef USE_FRAMEBUFFER + Platform::IDisplay *display = new Platform::FBDisplay(); +#else + Platform::IDisplay *display = new Platform::SDLDisplay(); +#endif + + if (!display->init(tomWidth, tomHeight)) + { + delete display; + return -1; + } + + Core::FrameBuffer frameBuffer(tomWidth, tomHeight); + Rasterizer::SpriteRasterizer spriteRasterizer(&frameBuffer); + + RenderData::Image background; + RenderData::Image tomStand; + RenderData::Image tomListen; + RenderData::Image tomSay1; + RenderData::Image tomSay2; + RenderData::Image tomSay3; + RenderData::Image tomSay4; + RenderData::Image button; + + if (!LoadSpriteAsset("background.sprite", background) || + !LoadSpriteAsset("Tom-stand.sprite", tomStand) || + !LoadSpriteAsset("Tom-listhen.sprite", tomListen) || + !LoadSpriteAsset("Tom-say1.sprite", tomSay1) || + !LoadSpriteAsset("Tom-say2.sprite", tomSay2) || + !LoadSpriteAsset("Tom-say3.sprite", tomSay3) || + !LoadSpriteAsset("Tom-say4.sprite", tomSay4) || + !LoadSpriteAsset("ui-record.sprite", button)) + { + std::cerr << "Run ConvertTomSprites before starting --tom." << std::endl; + display->shutdown(); + delete display; + return -1; + } + + Game::AudioInput audioInput; + Game::AudioOutput audioOutput; + Game::ButtonInput buttonInput; +#if defined(__linux__) + buttonInput.init(); +#endif + + Game::TomGameAssets assets; + assets.background = &background; + assets.tomStand = &tomStand; + assets.tomListen = &tomListen; + assets.tomSay1 = &tomSay1; + assets.tomSay2 = &tomSay2; + assets.tomSay3 = &tomSay3; + assets.tomSay4 = &tomSay4; + assets.button = &button; + + Game::TomGameApp app(&frameBuffer, &spriteRasterizer, &audioInput, &audioOutput, &buttonInput); + app.set_assets(assets); + if (!app.is_ready()) + { + std::cerr << "TomGameApp assets are incomplete." << std::endl; + display->shutdown(); + delete display; + return -1; + } + + bool isRunning = true; + uint32_t lastTime = display->get_time_ms(); + while (isRunning) + { + display->poll_events(isRunning); + const uint32_t currentTime = display->get_time_ms(); + const float deltaTime = static_cast(currentTime - lastTime) * 0.001f; + lastTime = currentTime; + + app.update(deltaTime); + frameBuffer.clear(RenderData::Color(18, 18, 24, 255)); + app.draw(); + display->present(&frameBuffer); + } + + buttonInput.shutdown(); + audioInput.shutdown(); + audioOutput.shutdown(); + display->shutdown(); + delete display; + return 0; +} + int main(int argc, char *argv[]) { + if (HasArg(argc, argv, "--tom")) + { + return RunTomGame(); + } + #ifdef USE_FRAMEBUFFER Platform::IDisplay *display = new Platform::FBDisplay(); #else