local changes before merge

This commit is contained in:
HP 2026-06-07 10:38:34 +08:00
parent a56bbe6f76
commit 3beae16917
2 changed files with 281 additions and 20 deletions

View File

@ -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}"
"$<TARGET_FILE_DIR:IMX6U-Game>"
)
add_custom_command(TARGET IMX6U-Game POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${SDL2_IMAGE_DLL}"
"$<TARGET_FILE_DIR:IMX6U-Game>"
)
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}"
"$<TARGET_FILE_DIR:SpriteAnimationTest>"
)
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}"
"$<TARGET_FILE_DIR:SpriteAssetTool>"
)
add_custom_command(TARGET SpriteAssetTool POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${SDL2_IMAGE_DLL}"
"$<TARGET_FILE_DIR:SpriteAssetTool>"
)
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 $<TARGET_FILE:SpriteAssetTool>
--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()

View File

@ -1,6 +1,9 @@
#include <iostream>
#include <array>
#include <cstdint>
#include <fstream>
#include <string>
#include <vector>
#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"
@ -15,6 +18,13 @@
#include <cstdlib>
#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<Mat
return faceNormal.dot(faceCenter) > 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<float>(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