[{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/bocchi-house/","section":"Tags","summary":"","title":"Bocchi House","type":"tags"},{"content":" 项目简介 # Bocchi House 是一个运行在 HarmonyOS NEXT 平台上的游戏移植与启动平台，旨在将经典游戏（如 Paladin、Unholy Heights）移植到鸿蒙平台。\n它提供了一套从底层 Vulkan 封装到上层 2D 渲染引擎的完整图形管线：\n底层通过 platform_abstraction 封装 Vulkan 与鸿蒙原生 API（窗口、节点、SurfaceHolder） 中间层通过 graphics_adapter 提供 2D 渲染引擎（SpriteBatch、纹理管理、字体渲染） 上层游戏模块调用这些接口实现跨平台运行 技术栈：ArkTS + C++ (NAPI) + Vulkan + HarmonyOS SDK 6.1.0\n分层架构 # products (启动器) │ startAbility() ▼ game_sources (游戏) ←── 调用 ──► features/adapters (图形/音频/输入) │ │ 调用 ├── 生命周期事件 │ ▼ ▼ features/game_framework common (平台封装) │ 转发事件 │ 封装 ▼ ▼ features/adapters HarmonyOS / Vulkan 层 模块 职责 启动器 products/laptop, products/mobile 游戏列表 + startAbility() 启动游戏 游戏 game_sources/paladin, game_sources/unholy_heights 游戏核心逻辑 生命周期桥接 features/game_framework BHFrameworkCore 单例：Ability 生命周期事件 → 各 adapter；App 级窗口控制 游戏框架 features/game_framework Game 类（XNA 风格）、ScreenManager、GameScreen、GameTime 适配层 features/graphics_adapter VulkanRenderer 编排器、SpriteBatch 2D 渲染、TextureManager、SpriteFont 适配层 features/audio_adapter / input_adapter 音频接口、输入接口（框架完成，待实现） 平台封装 common/platform_abstraction Vulkan RAII 封装（12 个类）、窗口管理、节点管理、日志 移植游戏 # 游戏 原作 原始语言 移植语言 渲染方式 状态 Paladin（仙剑奇侠传） SDLPal / pal_harmony C C++ CPU 软件渲染 (320x200) 规划中 Unholy Heights（房东是魔王大人） Petit Depotto C# (XNA 4.0) C++ Vulkan GPU 2D 精灵 移植中 当前进度（2026-08-12） # ✅ game_framework 生命周期桥接：BHFrameworkCore + NapiBridge 拆分，注册 15+ NAPI 接口 ✅ 窗口控制：BHWindowManager 封装 WindowInfo，SetDecorVisible / SetResizeByDrag 已实现 ✅ Vulkan RAII 封装（12 个类）：Instance / Surface / Device / Swapchain / Command / Sync / RenderPass / Shader / Pipeline / Buffer / Image / Descriptor ✅ BHNodeContentTool 完整实现：Bind(handle, tag) → NodeContent 回调 → CreateXComponent → Surface 回调分发 ✅ graphics_adapter 结构对齐：bridge/ + GraphicsBridge、engine/ + BHGraphicsCore 编排器 ✅ Laptop 启动器 UI：Navigation + 沉浸式 + Swiper 轮播推荐 + 游戏卡片列表 🔄 BHRender 实现：SetupVKContext(window) 设备检测链已完成（CreateInstance / CreateSurface / PickPhysicalDevice / CreateLogicalDeviceAndQueue） 🔄 SpriteBatch 完整管线：着色器/顶点缓冲已建，Flush 未实现 🔄 TextureManager / SpriteFont：VkImage/View/Sampler 已建，staging upload 未实现 专栏文章 # （本栏目持续更新：项目介绍 + 架构解说 + 技术记录）\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/bocchi-house/","section":"项目","summary":"","title":"Bocchi House 移植平台","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/series/bocchi-house-%E7%A7%BB%E6%A4%8D%E5%B9%B3%E5%8F%B0/","section":"Series","summary":"","title":"Bocchi House 移植平台","type":"series"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/c++/","section":"Tags","summary":"","title":"C++","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/monogame/","section":"Tags","summary":"","title":"MonoGame","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/series/monogame-%E9%B8%BF%E8%92%99%E7%A7%BB%E6%A4%8D/","section":"Series","summary":"","title":"MonoGame 鸿蒙移植","type":"series"},{"content":" 项目简介 # 将 MonoGame 3.8.x 的运行时引擎逐行移植为 C++20，目标平台鸿蒙 HarmonyOS，渲染后端计划采用 Vulkan。\n项目定位：对源项目的完整 C++ 移植——代码结构与上游保持一致，不省略、不替代，最多以 TODO 标注待办。不是\u0026quot;做一个可用的 C++ 引擎\u0026quot;，而是逐行镜像上游。\n技术路线 # 机制 做法 平台层 partial 类 C# 前端 partial → C++ 基类（成员+属性+前端逻辑+Platform* 虚方法钩子）；平台 partial → 派生类（override） 钩子语义 C# 跨 partial 文件私有方法 → C++ 纯虚函数强制实现；构造内不调纯虚（UB），改由派生类构造后显式调用 文件结构 一文件一类型（对应 C# 源文件结构，杜绝跨文件合并；唯一豁免 MathHelper+Random 嵌套平台无关 partial） 后端 Vulkan 第一后端（参考 DirectX 实现为主、OpenGL 脏标记技巧为辅），GLES 可选第二后端 当前进度（2026-08-19） # ✅ 145+ 头文件 + 34 cpp，编译链接验证通过 ✅ 21 个平台层类全部基类化（GraphicsDevice/Texture2D/3D/Cube/RenderTarget×3/VertexBuffer/IndexBuffer/Shader/ConstantBuffer/OcclusionQuery + 4 状态类 + 2 集合类 + Adapter×3） ✅ 一文件一类型拆分（2026-08-19） ✅ 与 C# 源码逐行比对（核心逻辑一致；差异项标注 TODO） ⏳ 未移植盘点：枚举 16 个（10 个状态依赖）+ 平台无关文件约 50 个 里程碑 # 里程碑 内容 状态 M0 平台无关核心（数学/几何/Input/Audio 等） ✅ 完成 M1 状态依赖枚举 + 资源基类（全量编译零警告） ⏳ 进行中 M2 B1 窗口显示（XComponent → NativeWindow） 待启动 M3 B2 首帧：Clear + 三角形（Vulkan） 待启动 M4-M6 输入/音频/完整 Game 循环 待启动 专栏文章 # （本栏目按进度持续更新：进度报告 + 技术解说）\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/","section":"项目","summary":"","title":"MonoGame 鸿蒙移植项目","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/paladin/","section":"Tags","summary":"","title":"Paladin","type":"tags"},{"content":" 目标游戏 # Paladin（仙剑奇侠传），大宇资讯 1995 年的经典中文 RPG——对很多国内玩家来说，它是\u0026quot;国产单机 RPG 的初恋\u0026quot;。\n原作以 C 语言编写，社区里有两大参考实现：\nSDLPal：仙剑奇侠传跨平台重制引擎，用 SDL 重构了原版 pal_harmony：社区大佬做的鸿蒙版仙剑移植，为本项目提供了重要参考 移植规划 # 项 方案 原始语言 C 移植语言 C++ 渲染方式 CPU 软件渲染（320x200 原始分辨率） 参考实现 SDLPal / pal_harmony 状态 规划中 和 Unholy Heights 走 Vulkan GPU 精灵渲染不同，仙剑走的是 CPU 软件渲染 + 320x200 低分辨率路线——这恰好是 90 年代 PC 游戏的原生形态。\n软件渲染的好处是不依赖复杂的图形管线：只要有一个能往屏幕像素缓冲区写数据的路径，游戏就能跑起来。在 Vulkan 后端稳定之前，这反而是一条低风险的起步路径。\n与 Bocchi House 的关系 # Paladin 会是 Bocchi House 平台上的第二个移植游戏：\nBocchi House (启动平台) ├── Unholy Heights C# XNA → C++ / Vulkan GPU 2D 精灵 [移植中] └── Paladin (仙剑) C → C++ / CPU 软件渲染 320x200 [规划中] 两个游戏共用平台层的基础设施：game_framework 生命周期桥接、ScreenManager、输入适配器——游戏侧只需要实现自己的 Update/Draw 和资源加载。\n现状 # 目前 Paladin 模块在仓库里是骨架状态（game_sources/paladin），集成 GameScreen 还是 @Component V1 模板页，未接入渲染组件。\n后续完整移植需要适配约 27000 行 C++ 代码——这是个不小的工程，等 Unholy Heights 的渲染管线打通后，会作为第二个项目逐步推进。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/bocchi-house/paladin-port-plan/","section":"项目","summary":"","title":"Paladin（仙剑奇侠传）：Bocchi House 的下一个移植目标","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/","section":"安双的小窝","summary":"","title":"安双的小窝","type":"page"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/categories/%E6%8A%80%E6%9C%AF/","section":"Categories","summary":"","title":"技术","type":"categories"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E8%BF%9B%E5%BA%A6%E6%8A%A5%E5%91%8A/","section":"Tags","summary":"","title":"进度报告","type":"tags"},{"content":" 本日里程碑 # 完整移植审查 + 一文件一类型拆分——确立了项目标准并据此重构了文件结构。\n确立的标准 # 完整 C++ 移植（不是\u0026quot;可用的引擎版本\u0026quot;）：代码结构与上游保持一致，不省略（最多 TODO 标注待办）、不合并（每个 C# 文件对应一个 C++ 头文件，唯一豁免 MathHelper+Random 嵌套平台无关 partial）。\n一文件一类型拆分 # 盘点出 4 个跨文件合并文件，全部拆分为独立文件：\n原聚合文件 拆分结果 graphics_resources.hpp（12 类型） texture2d/texture3d/texture_cube/render_target_2d/3d/cube/vertex_buffer/index_buffer/occlusion_query 9 个独立文件 + Shader/ConstantBuffer 并入各自文件，原文件改转发头 graphics_states.hpp（6 类） blend_state/depth_stencil_state/rasterizer_state/sampler_state/texture_collection/sampler_state_collection 6 个独立文件，原文件改转发头 graphics_adapter.hpp（4 类型） graphics_adapter（仅 GraphicsAdapter）/graphics_capabilities/graphics_debug/graphics_debug_message 独立 vertex_element.hpp 拆出 vertex_element_format.hpp 独立枚举（C# 12 值 = C++ 12 值） 与 C# 源码逐行比对 # ✅ 一致：OcclusionQuery/集合类×2/Shader/ConstantBuffer/Adapter×4/QueryRenderTargetFormat fallback（10 项 = 10 项）/vertex_element_format（12 = 12） ⚠️ 差异盘点：部分类简化重载/构造重载缺失（标注 TODO）、状态类枚举属性依赖未移植枚举（void* 占位）、Texture2D 钩子名差异（PlatformSetData→PlatformData） 未移植盘点 # 枚举 16 个：状态依赖 10 个（Blend/BlendFunction/CompareFunction/StencilOperation/CullMode/FillMode/TextureAddressMode/TextureFilter/TextureFilterMode/BufferUsage，补后解除状态类占位）+ GraphicsDeviceStatus + Effect 家族 3 个 平台无关文件约 50 个：Model 家族/异常/事件参数/Effect 家族/TargetBlendState/动态缓冲/顶点类型等 验证 # ✅ 拆分后 34 cpp 编译链接成功（无未定义符号） ✅ 修复拆分引入的 bug（vertex_element.hpp 悬空 };） ✅ 文档同步：未完成移植清单/partial 对照表/下一步工作计划/进度日志 下一步 # 移植 10 个状态依赖枚举（解除状态类 void* 占位并补全缺失属性） TargetBlendState/GraphicsResource/Texture 基类 阶段 B：窗口（B1）→ Vulkan 后端首帧（B2，前置调研 MGFX→SPIR-V 工具链）→ 输入/音频/内容流 ","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/progress-2026-08-19/","section":"项目","summary":"","title":"进度报告（2026-08-19）：完整移植审查与一文件一类型拆分","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E4%BB%99%E5%89%91%E5%A5%87%E4%BE%A0%E4%BC%A0/","section":"Tags","summary":"","title":"仙剑奇侠传","type":"tags"},{"content":"这里收录我正在进行中的各个移植项目，按专题整理：\nMonoGame 鸿蒙移植 —— 把 MonoGame 3.8.x 运行时引擎逐行移植为 C++20，目标平台鸿蒙 HarmonyOS（Vulkan 后端） Bocchi House 移植平台 —— 基于 HarmonyOS NEXT 的游戏移植与启动平台：Vulkan 图形管线 + 2D 渲染引擎 + 各移植游戏（Unholy Heights、Paladin……） 项目一览 # 项目 一句话 状态 MonoGame 鸿蒙移植 MonoGame 3.8.x → C++20 / HarmonyOS（Vulkan） 🔄 进行中 Bocchi House HarmonyOS 游戏移植与启动平台 🔄 开发早期 Unholy Heights 移植 C# XNA → C++ / Vulkan 精灵渲染 🔄 移植中 Paladin（仙剑奇侠传）移植 C → C++ / CPU 软件渲染 320x200 ⏳ 规划中 各个专栏都会随项目进度持续更新：进度报告 + 技术解说 + 踩坑记录。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/","section":"项目","summary":"","title":"项目","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E7%A7%BB%E6%A4%8D/","section":"Tags","summary":"","title":"移植","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/unholy-heights/","section":"Tags","summary":"","title":"Unholy Heights","type":"tags"},{"content":" 为什么选它 # Unholy Heights（房东是魔王大人） 是 Petit Depotto 出品的魔物公寓经营模拟 + 塔防游戏：\n玩家扮演魔王，经营一栋住满魔物的公寓 魔物是房客也是战斗力：安排房间、收租、应对勇者入侵 美术风格独特、系统不算庞大，非常适合作为第一个完整移植对象 技术上它是 C# + XNA 4.0 写的——和 MonoGame 同源（MonoGame 就是 XNA 的开源继任者）。这意味着移植路线非常清晰：\nC# / XNA 4.0 ──► C++ / Vulkan (通过 Bocchi House 平台) 移植路线 # 1. 架构翻译 # XNA 游戏的核心循环是 Update/Draw，这正是 Bocchi House game_framework 提供的结构：\nclass Game { virtual void Initialize(); virtual void LoadContent(); virtual void Update(GameTime); virtual void Draw(GameTime); }; 所以移植第一步不是翻译代码，而是对齐架构：把 XNA 的 Game 换成平台的 Game，把 SpriteBatch.Draw 换成平台的 SpriteBatch。\n2. 渲染 API 翻译 # XNA Bocchi House SpriteBatch graphics_adapter::SpriteBatch Texture2D TextureManager 管理的 VkImage SpriteFont SpriteFont（DrawString 已实现） ContentManager rawfile 内容流（规划中） XNA 的 SpriteBatch 和 Vulkan 的渲染模型差异不小，好在这部分由平台层统一消化，游戏代码里看起来还是\u0026quot;精灵 + 纹理 + 字体\u0026quot;的老三样。\n3. 资源翻译 # 纹理：从 XNB / 原始图片格式加载，通过 TextureManager 走 staging buffer 上传到 GPU 字体：SpriteFont 负责文本绘制，依赖 SpriteBatch::Flush 完成批处理上屏 音频：audio_adapter 的 AudioCore 框架已设计完成（BGM/SE + 音量控制），待实现 当前状态 # ✅ 页面已集成 GameScreen（测试页跑通） 🔄 SpriteBatch 完整管线：着色器/顶点缓冲已建，Flush 未实现——这是当前最卡的一步 🔄 TextureManager：VkImage/View/Sampler 已建，staging upload 未实现 ⬜ 游戏逻辑 C# → C++ 完整翻译 踩坑预告 # XNA 到 Vulkan 的移植，最大的坑集中在渲染状态上：\nXNA 的 SpriteBatch.Begin/End 内部管理混合/采样状态，Vulkan 里要显式维护 RenderPass 与 Pipeline 切换 XNA 的坐标系统是\u0026quot;左上原点 + Y 向下\u0026quot;，Vulkan 的 NDC 是 Y 向上——投影矩阵要处理翻转 XNA 自动处理 DrawOrder 排序，C++ 侧要自己维护绘制列表 这些会在实现 SpriteBatch::Flush 时逐一展开记录。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/bocchi-house/unholy-heights-port/","section":"项目","summary":"","title":"Unholy Heights：把 XNA 经营塔防搬上鸿蒙（C# → C++）","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/xna/","section":"Tags","summary":"","title":"XNA","type":"tags"},{"content":" 为什么需要 RAII 封装 # Vulkan 的对象模型对 C++ 使用者很不友好：\n对象数量多：Instance、Device、Swapchain、CommandPool、Pipeline……十几个类型，每个都要手动 vkCreate* / vkDestroy* 销毁顺序敏感：Swapchain 要在 Device 之前销毁，CommandBuffer 要在 CommandPool 之前销毁，顺序错了就校验层报错 出错路径难清理：中途失败时，前面创建的对象必须全部释放，手写 goto cleanup 是常态 RAII 封装的思路很简单：每个 Vulkan 对象对应一个 C++ 类，构造函数创建、析构函数销毁。对象天然拥有资源，离开作用域自动释放，顺序问题交给成员声明顺序解决。\n12 个 RAII 类 # VulkanInstance → VkInstance (API 1.3 降级支持) VulkanSurface → VkSurfaceKHR (vkCreateSurfaceOHOS，鸿蒙专属) VulkanDevice → VkDevice + Queue (物理设备选择 + 逻辑设备 + 队列) VulkanSwapchain → VkSwapchainKHR + ImageViews VulkanCommand → CommandPool + CommandBuffer[] VulkanSync → Semaphore[] + Fence[] VulkanRenderPass → RenderPass + Framebuffer[] VulkanShader → ShaderModule + Pipeline VulkanPipeline → GraphicsPipeline + Layout VulkanBuffer → Buffer + DeviceMemory VulkanImage → Image + DeviceMemory + View + Sampler VulkanDescriptor → DescriptorPool + SetLayout + Sets 配套还有两个工具类：\nVulkanCheck：VK_CHECK 宏 + 错误码转字符串（踩坑时能把 VK_ERROR_OUT_OF_DATE_KHR 之类的错误一眼认出来） VulkanDebug：Debug Messenger 回调（校验层信息带函数名和消息类型） 初始化序列（已验证） # 鸿蒙端完整初始化序列如下，每行对应一个 RAII 类：\nVulkanInstance::Create() → VkInstance (API 1.3 降级支持) VulkanSurface::Create() → VkSurfaceKHR (vkCreateSurfaceOHOS) VulkanDevice::Create() → VkDevice + Queue (GPU: Maleoon 916) VulkanSwapchain::Create() → VkSwapchainKHR + ImageViews VulkanCommand::Create() → CommandPool + CommandBuffer[] VulkanSync::Create() → Semaphore[] + Fence[] VulkanRenderPass::Create() → RenderPass + Framebuffer[] 设备选择逻辑里有个小亮点：PickPhysicalDevice 按独显评分择优，FindQueueFamilies + CheckDeviceExtensionSupport + QuerySwapchainSupport 组成了完整的设备检测链。\n鸿蒙专属的部分 # Vulkan 是跨平台的，但鸿蒙有它自己的\u0026quot;方言\u0026quot;：\nvkCreateSurfaceOHOS：从 OHNativeWindow 创建 VkSurfaceKHR，这是鸿蒙独有的扩展 API 版本降级支持：Instance 创建时优先 API 1.3，不满足就降级 XComponent + SurfaceHolder：渲染表面来自 ArkTS 侧的 XComponent，通过 SurfaceHolderNDK 拿到 OHNativeWindow 踩坑记录 # 销毁顺序：最初把资源全部裸指针管理，Swapchain 重建时偶发校验层报错。改成 RAII 后，按成员声明顺序析构，问题消失。 Debug Messenger：忘了注册 VulkanDebug 时，VK_ERROR_OUT_OF_DATE_KHR 这类错误只有错误码没有上下文，排查全靠猜。注册后信息量大增。 float16 支持：CreateLogicalDeviceAndQueue 里显式启用了 float16Int8 / shaderInt16 / samplerAnisotropy 三个特性，某些驱动默认不启用，不声明就白屏。 下一步 # RAII 层稳定后，接下来是把 BHRender 的 SetupVKContext(window) 完整接线：创建 Instance → Surface → Device 后，启动渲染线程，让 BHGraphicsCore::InitRender 真正跑起来。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/bocchi-house/bocchi-house-vulkan-raii/","section":"项目","summary":"","title":"Bocchi House：Vulkan RAII 封装（12 个类）","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/harmonyos/","section":"Tags","summary":"","title":"HarmonyOS","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/raii/","section":"Tags","summary":"","title":"RAII","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/vulkan/","section":"Tags","summary":"","title":"Vulkan","type":"tags"},{"content":" 为什么这么分层 # 移植平台最容易变成\u0026quot;一锅粥\u0026quot;：UI、引擎、平台 API 全搅在一起。Bocchi House 从一开始就按依赖方向严格分了四层：\nproducts (启动器) │ startAbility() ▼ game_sources (游戏) ←── 调用 ──► features/adapters (图形/音频/输入) │ │ 调用 ├── 生命周期事件 │ ▼ ▼ features/game_framework common (平台封装) │ 转发事件 │ 封装 ▼ ▼ features/adapters HarmonyOS / Vulkan 核心原则：上层依赖下层，下层不感知上层。游戏代码永远不直接碰 VkInstance，UI 代码永远不直接调 vkQueueSubmit。\n各层职责 # 层 模块 职责 启动器 products/laptop、products/mobile 游戏列表 + startAbility() 启动游戏 游戏 game_sources/paladin、game_sources/unholy_heights 游戏核心逻辑 生命周期桥接 features/game_framework BHFrameworkCore 单例：Ability 生命周期 → 各 adapter；App 级窗口控制 游戏框架 features/game_framework Game（XNA 风格）、ScreenManager、GameScreen、GameTime 适配层 features/graphics_adapter VulkanRenderer 编排器、SpriteBatch 2D 渲染、TextureManager、SpriteFont 适配层 features/audio_adapter、input_adapter 音频 / 输入接口（框架完成，待实现） 平台封装 common/platform_abstraction Vulkan RAII（12 类）、BHWindowManager、NodeContentHandleTool、bh_log 生命周期事件流 # 鸿蒙的入口是 ArkTS Ability，游戏是 C++。中间的桥接是 BHFrameworkCore：\nArkTS Ability 生命周期 │ ▼ game_framework (BHFrameworkCore) │ OnCreate(rm) / OnDestroy() / OnBackground() / OnForeground() │ └──→ Game::Run() ├─ Game::LoadContent() ← 加载纹理/音频 ├─ [帧循环] ← 驱动 ScreenManager │ ├─ InputState::BeginFrame() │ ├─ Game::Update(time) │ │ └─ ScreenManager::Update(time) + HandleInput(input) │ ├─ Game::Draw(time) │ │ └─ ScreenManager::Draw(time) │ │ └─ SpriteBatch + TextureManager │ └─ InputState::EndFrame() └─ Game::UnloadContent() ← 清理资源 这个结构几乎是 XNA/MonoGame 的经典形状——因为移植的目标游戏（Unholy Heights 等）本来就是 XNA 架构，游戏开发者面对的是熟悉的 Update/Draw 循环。\nNAPI 接口设计 # ArkTS 与 C++ 之间通过 NAPI 桥接，做了静态方法与实例方法分离：\nNapiBridge：静态方法（模块级），如模块注册、初始化 BHFrameworkCore：实例方法（能力级），如 create / destroy / onBackground / onForeground、窗口控制（9 个）、帧生成（2 个） 目前注册了 15+ 个 NAPI 接口，全部通过 bridge/ 目录转发到 C++ 侧实现，保持接口面清晰。\n数据流示例：原生渲染表面 # 图形适配器创建渲染表面的链路（已经跑通）：\nArkTS GameScreen → NAPI: gfx.createNativeNode(nodeContent, tag) → PluginManager::CreateNativeNode() → Core::GenerateXComponentBasedSurfaceHolder() → CreateNodeHandleUsingSurfaceHolder() → XComponent + SurfaceHolder + SurfaceCallback → OHNativeWindow* 存入 Core::surfaces_ → Surface 就绪后自动触发: → OnSurfaceCreated → 记录 OHNativeWindow* → OnSurfaceChanged → 自动初始化 Vulkan → NAPI: gfx.initRenderer(tag) → VulkanRenderer::Init(window) → Instance → Surface → Device → Swapchain → RenderPass → Command → Sync → Shader → Pipeline → Buffer → NAPI: gfx.testDraw() → DrawTestTriangle() → 红色三角形上屏 从 createNativeNode 到红色三角形上屏，这条链路是项目第一个完整跑通的\u0026quot;里程碑时刻\u0026quot;。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/bocchi-house/bocchi-house-architecture/","section":"项目","summary":"","title":"Bocchi House 架构笔记：四层分层与生命周期事件流","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/napi/","section":"Tags","summary":"","title":"NAPI","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E6%9E%B6%E6%9E%84/","section":"Tags","summary":"","title":"架构","type":"tags"},{"content":" 这是什么 # Bocchi House 是一个运行在 HarmonyOS NEXT 平台上的游戏移植与启动平台。\n简单来说：一台鸿蒙设备上，装一个\u0026quot;游戏大厅\u0026quot;，里面可以启动一个个被移植过来的经典游戏。\n名字致敬了《孤独摇滚！》的波奇酱（Bocchi），也暗合\u0026quot;一个人折腾移植\u0026quot;的孤独感——不过移植出来的成果是可以分享的。\n为什么做这个 # 一直以来我都在折腾\u0026quot;把老游戏/老引擎搬到鸿蒙\u0026quot;这件事：\nMonoGame 的鸿蒙 C++ 移植（另一个长期项目） Paladin（仙剑奇侠传）、Unholy Heights（房东是魔王大人） 这类经典游戏的移植 移植本身已经很难，但移植完还有一个问题：怎么把游戏组织起来、怎么启动、怎么共用一套图形/音频/输入基础设施？\n每个游戏都各自实现一遍 Vulkan 初始化、窗口绑定、精灵渲染，既重复又难维护。于是就有了 Bocchi House：把底层图形能力、生命周期桥接、游戏框架做成公共层，游戏只需要专注于自己的逻辑。\n技术栈 # ArkTS + C++ (NAPI) + Vulkan + HarmonyOS SDK 6.1.0 ArkTS：启动器 UI 与 Ability 生命周期（声明式开发） C++ (NAPI)：引擎层与图形管线，通过 NAPI 与 ArkTS 桥接 Vulkan：GPU 渲染 API，鸿蒙端通过 XComponent 提供原生渲染表面 SurfaceHolderNDK：新版 Surface 生命周期管理 API 分层设计 # 项目采用四层架构，每层职责单一：\n层 做什么 products（启动器） 游戏列表 + startAbility() 拉起游戏 game_sources（游戏） 各移植游戏的核心逻辑（Paladin / Unholy Heights） features（适配层） 游戏框架（生命周期桥接）+ 图形/音频/输入适配器 common（平台封装） Vulkan RAII、窗口管理、节点内容、日志 现状与计划 # 目前处于开发早期：Vulkan RAII 封装（12 个类）、生命周期桥接、Laptop 启动器 UI 已完成；BHRender 渲染上下文、SpriteBatch 完整管线进行中。\n游戏方面，Unholy Heights 已在移植中（C# XNA → C++），Paladin 在规划中。\n后续我会在这里持续记录架构设计与踩坑过程。\n相关链接 # 项目主页：https://gitcode.com/roger_bh/bocchi_house 架构文档：ARCHITECTURE.md（仓库内） ","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/bocchi-house/bocchi-house-intro/","section":"项目","summary":"","title":"Bocchi House：一个把经典游戏搬上鸿蒙的启动平台","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/hugo/","section":"Tags","summary":"","title":"Hugo","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E5%8D%9A%E5%AE%A2/","section":"Tags","summary":"","title":"博客","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/categories/%E6%8A%98%E8%85%BE/","section":"Categories","summary":"","title":"折腾","type":"categories"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E6%8A%98%E8%85%BE/","section":"Tags","summary":"","title":"折腾","type":"tags"},{"content":" 为什么又回来折腾博客 # 第一篇文章里说过，几年前用纯 HTML 做了几篇网页交了课堂作业，后来接触了 WordPress、Hugo、Hexo 这些工具，写过一阵子，热度散去后网站就荒废了。\n最近重新开始折腾——想着反正也在做 MonoGame 移植这种值得记录的事情，不如把博客重新搭起来。\n选型：Hugo + Blowfish # 这次选了 Hugo + Blowfish 主题：\nHugo：Go 写的静态站点生成器，单二进制，构建快，内容用 Markdown 写，天然适合技术博客 Blowfish：基于 Tailwind 的 Hugo 主题，中文支持好（zh-cn 语言配置开箱即用），首页/文章/系列/标签一应俱全 搭建过程 # 1. 初始化站点 # hugo new site temp_hugo 2. 安装主题（子模块方式） # git submodule add https://gitcode.com/gh_mirrors/bl/blowfish.git themes/blowfish 3. 配置 # Hugo 的 config/_default/ 下按语言拆分配置：\nconfig/_default/ ├── hugo.toml # 站点全局（主题/baseURL/默认语言） ├── languages.zh-cn.toml # 中文站点信息（标题/作者/描述） ├── menus.zh-cn.toml # 菜单（主菜单/页脚菜单） ├── markup.toml # Markdown 渲染配置 └── module.toml 4. 备案信息 # 在国内部署，备案是绕不开的。用 Blowfish 的 footer 自定义，在 layouts/partials/footer.html 里添加了备案信息：\n浙ICP备（工信部备案） 浙公网安备（公安联网备案） 萌ICP备（萌 ICP 备，一个梗，懂的都懂） 5. 构建与发布 # hugo # 构建 → public/ 把 public/ 的内容同步到网页仓库（funbocchi.top）推送即可。\n内容规划 # 博客目前的定位：\nMonoGame 鸿蒙移植系列：partial 机制、文件结构纪律、路线图等（会持续更新） 折腾记录：局域网联机、博客搭建这类日常折腾 踩坑记录 # Hugo 建议用 extended 版（含 SCSS 编译支持），apt install hugo 装的是旧版，Blowfish 这类主题会静默失败 主题用子模块方式安装，clone 后记得 git submodule update --init --recursive 备案的 ICP 号要放在 footer 里，同时 baseURL 要配置成备案的域名 ","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/posts/blog-setup/","section":"Posts","summary":"","title":"折腾记录：用 Hugo + Blowfish 重建博客","type":"posts"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E5%B1%80%E5%9F%9F%E7%BD%91/","section":"Tags","summary":"","title":"局域网","type":"tags"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E8%81%94%E6%9C%BA/","section":"Tags","summary":"","title":"联机","type":"tags"},{"content":" 一切的开始 # 之前第一篇博客里提过，个人博客的热情慢慢转移到了搭建用于组建虚拟局域网的服务器上。这篇算是补一个详细点的记录。\n早期的工具们 # 向日葵 / 蛤蟆吃 # 最早用的是各种\u0026quot;傻瓜式\u0026quot;组网工具——向日葵、蛤蟆吃（Hamachi）这一挂。优点是开箱即用，缺点是免费版限制多：设备数量、带宽、稳定性都让人头疼。联机玩游戏时偶尔的掉线更是让人血压升高。\n小黄鸭 / NPS # 后来开始折腾更\u0026quot;硬核\u0026quot;的方案。小黄鸭（ZeroTier 系）提供了更自由的虚拟局域网能力；NPS 则是内网穿透的经典选择——自己搭服务端，把内网服务暴露出去，自由度直接拉满。\n自己搭服务器的那段时间，最大的收获是理解了内网穿透的本质：NAT 之后的设备如何通过一台公网服务器中转，把流量\u0026quot;打洞\u0026quot;过去。\n现在 # 最近发现 UU加速器 也推出了局域网联机的服务功能。工具越来越成熟，门槛越来越低——当年折腾半天才能跑通的场景，现在一键搞定。\n想来以后在 p2p 游戏联机这方面，确实不需要像以前那样折腾了。\n一些感想 # 折腾这些工具的过程，其实和写代码很像：从\u0026quot;能用就行\u0026quot;到\u0026quot;搞懂原理\u0026quot;，再到\u0026quot;自己动手实现\u0026quot;。这也是我一直喜欢折腾的原因——每一次踩坑，都在加深对网络原理的理解。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/posts/lan-gaming-history/","section":"Posts","summary":"","title":"折腾记录：局域网联机那些年","type":"posts"},{"content":" 盘点：还差什么 # 移植工程讲究\u0026quot;心里有数\u0026quot;——除了已完成的，还需要一份清晰的未移植清单。最近做了一次系统盘点：\n未移植枚举（16 个） # 其中 10 个是状态依赖枚举，补上它们就能解除状态类的 void* 占位并补全缺失属性：\nBlend / BlendFunction / CompareFunction / StencilOperation CullMode / FillMode / TextureAddressMode / TextureFilter / TextureFilterMode / BufferUsage 其余：GraphicsDeviceStatus + Effect 家族 3 个（EffectDirtyFlags/EffectParameterClass/EffectParameterType）。\n未移植平台无关文件（约 50 个） # 根目录：Texture 抽象基类、GraphicsResource 基类、GraphicsMetrics、GraphicsExtensions、DxtUtil、SpriteFont、GraphicsDeviceManager 等 Model 家族（8 个文件） 异常类（4 个）+ 事件参数类（3 个） States/TargetBlendState.cs、Vertices/ 动态缓冲与顶点类型（6 个） Effect/ 全部（24 个文件） 这些大多属于阶段 A8/B2/C 的计划项，在未完成清单里有记录——不静默省略，全部标注 TODO 或按计划推进。\n下一步路线图 # 第一步：10 个状态依赖枚举（当前焦点） # 独立小文件，按 C# 的 States/、Vertices/ 源结构移植。收益最大：\n// 例：States/Blend.cs → blend.hpp（独立枚举文件） enum class Blend { kZero = 0, kOne, // ... }; 补完后 BlendState/DepthStencilState/RasterizerState/SamplerState/VertexBuffer/IndexBuffer 里的一堆 void* 占位就能换成真实枚举，缺失的属性访问器也能补全。\n第二步：TargetBlendState + GraphicsResource/Texture 基类 # B2（Vulkan 后端）的前置依赖。\n第三步：阶段 B —— 平台层 # B1 窗口/生命周期：XComponent → NativeWindow B2 Vulkan 后端（最大头）： GraphicsDevice 的 28 个 Platform* 钩子逐一实现 资源类（Texture2D/VertexBuffer/Shader 等）的钩子 前置风险：MGFX → SPIR-V 工具链（MonoGame 官方有 ShaderProfile.Vulkan.cs 编译实现可参考） B3 输入 / B4 OHAudio / B5 rawfile 内容流 参考：鸿蒙端已有 FrameGenerationVulkan 示例（vulkan_utils/Device/Buffer/Image 等基础设施可直接借鉴），渲染状态对象参考 DirectX 实现（D3D11 显式状态对象与 Vulkan 更接近）。\n里程碑 # 里程碑 内容 M1 状态依赖枚举 + 资源基类完成（全量编译零警告） M2 B1 窗口显示 M3 B2 首帧：Clear + 三角形 M4-M6 输入/音频/完整 Game 循环 ","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/monogame-roadmap/","section":"项目","summary":"","title":"MonoGame 移植：未移植盘点与鸿蒙后端路线图","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E9%B8%BF%E8%92%99/","section":"Tags","summary":"","title":"鸿蒙","type":"tags"},{"content":" 问题：C++ 移植时\u0026quot;合并\u0026quot;很诱人，但会偏离上游 # 移植初期，为了方便，把功能相近的类型合并到了同一个头文件里：\ngraphics_resources.hpp ← 塞了 12 个类（Texture2D/3D/Cube/RenderTarget×3/VertexBuffer/...） graphics_states.hpp ← 塞了 6 个类（BlendState/DepthStencilState/...） 看起来\u0026quot;高效\u0026quot;，但有个根本问题：上游 C# 每个类型是独立文件，合并后代码结构与上游对不上。上游更新、对照审查、逐行比对都会变得困难。\n确立的纪律 # 每个 C# 文件对应一个 C++ 头文件（一文件一类型），杜绝跨文件合并。\n唯一豁免：MathHelper + Random——它们是嵌套且平台无关的 partial 整合（MathHelper.cs 跨文件合并了 Random 相关方法），这类整合允许保留。\n拆分怎么做 # 以 graphics_resources.hpp（12 类型）为例，按 C# 源结构拆成独立文件：\nC# 源文件 C++ 独立头文件 Texture2D.cs texture2d.hpp Texture3D.cs texture3d.hpp TextureCube.cs texture_cube.hpp RenderTarget2D.cs / 3D.cs / Cube.cs render_target_2d.hpp / _3d / _cube Vertices/VertexBuffer.cs vertex_buffer.hpp Vertices/IndexBuffer.cs index_buffer.hpp Shader/Shader.cs Shader/shader.hpp Shader/ConstantBuffer.cs Shader/constant_buffer.hpp OcclusionQuery.cs occlusion_query.hpp 原聚合文件改为转发头（只 include 各独立文件，不含任何类型定义），兼容既有引用。\n枚举也按 C# 源码结构独立成文件 # VertexElementUsage 这类枚举同样遵循——独立成 vertex_element_usage.hpp，而不是塞进使用它的类里：\n// vertex_element_usage.hpp：独立文件（对应 C# VertexElementUsage.cs） enum class VertexElementUsage { kPosition = 0, kColor, // ... }; 这样做的另一个好处：避免重复定义——曾有两个文件各自定义了 VertexElementUsage（同命名空间），全量包含时直接 redefinition 编译错误，拆分后从根上消除。\n拆分后验证 # 21 个平台层基类全部独立成文件 34 cpp 编译链接成功（无未定义符号） 修复了拆分过程中引入的一个小 bug（转发文件残留的悬空 };） 小结 # \u0026ldquo;一文件一类型\u0026quot;不是洁癖，是移植工程的可维护性底线——它让\u0026quot;逐行对照 C# 源码审查\u0026quot;成为可能，也让后续批量更新（上游升级、枚举补充）可以精确到文件。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/monogame-file-structure/","section":"项目","summary":"","title":"MonoGame 移植：一文件一类型纪律与文件结构拆分","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84/","section":"Tags","summary":"","title":"文件结构","type":"tags"},{"content":" 为什么 partial 机制是理解 MonoGame 的关键 # MonoGame 大量使用 C# 的 partial 类做平台适配。GraphicsDevice 在源码里是这样的：\n// Graphics/GraphicsDevice.cs（前端） public partial class GraphicsDevice : IDisposable { ... } // Platform/Graphics/GraphicsDevice.DirectX.cs（DX 平台） public partial class GraphicsDevice { ... } 多个源文件声明同一个类，编译时合并为一个类。关键规则：partial 类的所有成员（含 private）对所有 partial 部分可见。所以前端文件里调用的 PlatformSetup()，只要任何一个 partial 文件定义了它，就能编译——方法归属是\u0026quot;整个类\u0026quot;，不是\u0026quot;某个文件\u0026quot;。\nPlatformSetup 覆写的真相 # 很多人第一次看会困惑：GraphicsDevice.cs 里调用了 PlatformSetup()，但前端文件里找不到它的声明——它去哪了？\n答案：这不是继承覆写（override），而是 partial 类跨文件补充定义：\n// 前端 Setup()（GraphicsDevice.cs L349）：直接调用，无声明 private void Setup() { ...; PlatformSetup(); ... } // 平台实现（GraphicsDevice.DirectX.cs L53）：定义同名方法 private void PlatformSetup() { MaxTextureSlots = 16; MaxVertexTextureSlots = 16; CreateDeviceResources(); } partial 类编译后是同一个类，前端调用点与平台实现自动配对。\n两类钩子的形态 # MonoGame 源码里平台钩子有两种写法：\n形态 A：partial 方法（声明在前端，实现可选） # // 前端（GraphicsDevice.cs L756）：只声明，无实现 partial void PlatformReset(); // 平台（GraphicsDevice.DirectX.cs L73）：实现 partial void PlatformReset() { CorrectBackBufferSize(); ... } partial 方法的实现可以省略（省略后调用点被编译器移除），适合\u0026quot;可选钩子\u0026quot;。\n形态 B：跨 partial 文件私有方法（前端直接调用，平台必须定义） # // 前端：直接调用 PlatformSetup(); // 平台：private void PlatformSetup() { ... } 平台必须提供实现，否则编译/链接失败。PlatformSetup/PlatformInitialize/PlatformClear/PlatformDraw* 等核心钩子都是这种。\n平台实现对比：同一个 PlatformSetup，两个平台各写各的 # 步骤 DirectX OpenGL 上下文/设备 CreateDeviceResources()（D3D11Device） GL.CreateContext(windowInfo) 能力查询 _d3dDevice.FeatureLevel GL.GetInteger(...) 槽位上限 写死 16 查询驱动实际值 前端只要求\u0026quot;调用后 MaxTextureSlots 等成员被填好\u0026quot;，平台负责\u0026quot;怎么填\u0026quot;。\nC++ 移植对应 # C# 的 partial 合并，在 C++ 里对应\u0026quot;基类 + 钩子\u0026quot;：\n// 基类（graphics_device.hpp）：成员 + 属性 + 前端逻辑 + 纯虚钩子 class GraphicsDevice { public: void Clear(const Color \u0026amp;color) { PlatformClear(ClearOptions::kTarget | ClearOptions::kDepthBuffer | ClearOptions::kStencil, color.ToVector4(), viewport_.MaxDepth(), 0); } virtual void PlatformClear(ClearOptions, const Vector4 \u0026amp;, float, int) = 0; virtual void PlatformPresent() = 0; // ... }; // 平台派生类（Vulkan 后端）：override 全部钩子 class VulkanGraphicsDevice : public GraphicsDevice { void PlatformClear(ClearOptions, const Vector4 \u0026amp;, float, int) override { /* vk 代码 */ } }; 一个要注意的 C++ 语言映射：基类构造内不能调用纯虚函数（UB）——C# 前端构造里 Setup() → PlatformSetup() 的调用点，在 C++ 改由派生类构造完成后显式调用 PlatformCreate()，语义等价。\n","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/monogame-partial-mechanism/","section":"项目","summary":"","title":"MonoGame 移植：C# partial 类机制与 PlatformSetup 覆写","type":"projects"},{"content":"","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/tags/partial/","section":"Tags","summary":"","title":"Partial","type":"tags"},{"content":" 项目背景 # 最近在做一个有意思的事情：把 MonoGame 3.8.x 的运行时引擎逐行移植为 C++20，目标平台是鸿蒙 HarmonyOS，渲染后端计划采用 Vulkan。\n这个项目的定位不是\u0026quot;做一个可用的 C++ 引擎\u0026quot;，而是对源项目的完整 C++ 移植——代码结构与上游保持一致，不省略、不替代，最多以 TODO 标注待办。这是一份移植记录，会随进度持续更新。\n技术路线 # 平台层 partial 类 → 基类 + 钩子 # MonoGame 大量使用 C# 的 partial 类机制做平台适配：前端单文件（公共接口 + 逻辑）+ Platform/ 下每平台一份（辅助实现），编译期合并为同一个类。\nC++ 没有 partial，对应的做法是：\n前端 partial → C++ 基类：成员变量 + 属性 + 前端逻辑 + Platform* 虚方法钩子（如 PlatformClear/PlatformPresent/PlatformDrawPrimitives） 平台 partial → 派生类：VulkanGraphicsDevice : public GraphicsDevice 等，override 全部钩子 钩子语义：C# 的 private void PlatformSetup() 跨 partial 文件可见（合并后是同一个类）；C++ 用纯虚函数强制派生类实现，语义等价 C++ 语言映射：构造内不能调用纯虚（UB），改由派生类构造完成后显式调用 PlatformCreate()/PlatformConstruct() 一文件一类型纪律 # 移植中确立了一条纪律：每个 C# 文件对应一个 C++ 头文件（杜绝跨文件合并），唯一豁免是 MathHelper+Random 这种嵌套且平台无关的 partial 整合。枚举按 C# 源码结构独立成文件（如 VertexElementUsage 对应 vertex_element_usage.hpp）。\n当前进度（2026-08-19） # 维度 状态 工程规模 145+ 头文件 + 34 cpp，编译链接验证通过 平台层类 21 个类全部基类化（GraphicsDevice/Texture2D/3D/Cube/RenderTarget×3/VertexBuffer/IndexBuffer/Shader/ConstantBuffer/OcclusionQuery + 4 状态类 + 2 集合类 + Adapter×3） 文件结构 一文件一类型拆分（2026-08-19）：各类型独立成文件，聚合文件改转发头 已覆盖 数学/几何/曲线/组件/Input 状态类/Content 核心/Audio 主体/Media 数据类/PackedVector 19/SpriteBatch 骨架/Game 循环 与 C# 源码的逐行比对 # ✅ 一致：OcclusionQuery、集合类、Shader/ConstantBuffer、GraphicsAdapter/GraphicsCapabilities/GraphicsDebug、QueryRenderTargetFormat fallback 逻辑（C# 10 项 = C++ 10 项） ⚠️ 已盘点差异：部分类的简化重载/构造重载缺失（标注 TODO 待补）、状态类枚举属性依赖未移植枚举（void* 占位） 未移植盘点 # 枚举 16 个：状态依赖 10 个（Blend/BlendFunction/CompareFunction/StencilOperation/CullMode/FillMode/TextureAddressMode/TextureFilter/TextureFilterMode/BufferUsage，补后解除状态类占位）+ GraphicsDeviceStatus + Effect 家族 3 个 平台无关文件 ~50：Model 家族/异常类/事件参数类/Effect 家族/TargetBlendState/动态缓冲/顶点类型等 下一步 # 移植 10 个状态依赖枚举（解除状态类 void* 占位并补全缺失属性） TargetBlendState/GraphicsResource/Texture 抽象基类 阶段 B：窗口/生命周期（XComponent → NativeWindow）→ Vulkan 后端（GraphicsDevice 钩子实现 + MGFX→SPIR-V 工具链调研）→ 输入/音频/内容流 参考 # MonoGame 官方仓库 鸿蒙游戏移植指南（华为开发者联盟） Godot 鸿蒙移植教程（参考写法） ","date":"2026 年 8 月 19 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/monogame-harmonyos-porting/","section":"项目","summary":"","title":"MonoGame 鸿蒙移植记录：C++ 逐行移植进展","type":"projects"},{"content":" 本日里程碑 # 21 个接口类全部基类化——平台层类从\u0026quot;纯接口（纯虚方法）\u0026ldquo;升级为\u0026quot;完整基类（成员变量 + 属性 + 前端逻辑 + Platform* 虚方法钩子）\u0026quot;，并完成整体复查。\n背景：为什么要基类化 # 此前平台层 partial 类被移植为\u0026quot;接口类\u0026rdquo;（只含 Platform* 纯虚方法契约）。复查发现这是遗漏的根源：接口化只提取了钩子契约，而 GraphicsDevice 等完整类的成员变量与前端逻辑（600+ 行）被跳过了。经确认，改为\u0026quot;移植为基类而非接口类\u0026quot;。\n完成内容 # 批 1：GraphicsDevice 基类化（igraphics_device.hpp → graphics_device.hpp） # 53 个成员变量（_viewport/_blendState 族/预置状态/集合）照抄 C# L37-200 属性访问器（Viewport/BlendState/ScissorRectangle/IsRenderTargetBound 等） 前端逻辑（Clear×3/Present/Reset/Dispose/ApplyState） 32 个 Platform* 虚方法钩子 批 2-3：资源类与状态类基类化 # Texture2D（构造链 + SetData/GetData 前端 8 重载）、VertexBuffer/IndexBuffer/Shader/ConstantBuffer 4 个状态类（BlendState/DepthStencilState/RasterizerState/SamplerState，状态属性全集） 集合类（TextureCollection/SamplerStateCollection，索引器 + 槽位数组） C++ 语言映射确立 # 基类构造内不能调用纯虚函数（UB）——C# 构造里 PlatformConstruct(...) 的调用点，C++ 改由平台层派生类构造完成后显式调用（语义等价）。\n整体复查（对照 C# 逐类核对） # 补 GraphicsDevice 预置状态 10 个（_blendStateAdditive 等）+ EffectCache/集合 4 个/ResourcesLost 补 Shader HashKey/Samplers/Attributes（修正 Stage 注释行号） 补 ConstantBuffer _buffer/_parameters 等 6 成员 补 3 个状态类 _defaultStateObject/StencilOperation 系列等 10 项 验证 # ✅ 145 头文件独立包含零警告 + 33 cpp 链接成功 ✅ 提交：feat(graphics) 基类化 + docs 同步 下一步 # 新增《下一步工作计划》文档（8 章节：进度快照/收尾/A6-A9/B1-B5/C 阶段/优先级/里程碑/风险） 剩余 11 个接口类基类化收尾 → 阶段 A6（Reader 家族）+ A8/A9（GraphicsResource/Adapter/DeviceManager + 状态枚举） ","date":"2026 年 8 月 18 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/progress-2026-08-18/","section":"项目","summary":"","title":"进度报告（2026-08-18）：接口类基类化与整体复查","type":"projects"},{"content":" 本日里程碑 # 阶段 A（平台无关核心）完成——把不依赖任何平台 API 的引擎主体全部移植完毕。\n完成内容 # 数学/几何/曲线/组件批 # 数学库（Vector2/3/4/Matrix/Quaternion/Plane/MathHelper 等，含 MathHelper+Random 的 partial 整合） 几何体（BoundingBox/BoundingFrustum/BoundingSphere/Ray） 曲线（Curve/CurveKey）与组件（GameComponent/DrawableGameComponent 等） PackedVector 19 个类型 Input/Content 核心 # Input 状态类（Keyboard/Mouse/GamePad 等，TouchQueue 已就绪） Content 核心（ContentManager/ContentReader 骨架） Audio 主体（本日重点修正） # 复查中发现 SoundEffect 族（5 个）实为平台无关主体（参数校验/时长计算/状态机/池管理纯 C#，仅 PlatformXxx 钩子待平台层）——此前遗漏未统计。补移植：\nSoundEffect（构造校验/时长/静态音量/Play/池交互） SoundEffectInstance（音量/音调/声像钳制/状态机/Apply3D） SoundEffectInstancePool / DynamicSoundEffectInstance（缓冲队列/回调） Microphone / AudioUtil（WAV 头格式化） Platform 再核实（记录不移植原因） # .Default.cs 桩：全为 throw NotImplementedException 无逻辑 → 不移植 .Web.cs（KeyboardUtil/GamepadUtil）：语义绑定 Web 浏览器 → 不移植 其余平台文件绑定各自 SDK（鸿蒙用 NDK 重写） 验证升级 # ✅ 32 cpp 编译 .o + 链接无未定义符号（此前 -fsyntax-only 漏过声明未定义缺陷，本日起强制链接级验证） ✅ 123 个头文件独立包含编译零警告 下一步 # 鸿蒙图形后端接口设计（B2 前置，以 MGG_* 清单为蓝本）→ 阶段 B 平台层 ","date":"2026 年 8 月 17 日","externalUrl":null,"permalink":"/projects/monogame-harmonyos-port/progress-2026-08-17/","section":"项目","summary":"","title":"进度报告（2026-08-17）：阶段 A 平台无关核心冲刺","type":"projects"},{"content":" 写在前面 # 用Markdown写博客一年多了，最开始是用富文本写，后来发现Markdown更适合我，而且CSDN提供了导入导出的功能，图片可以云存储，所以导出了博文在本地也可以直接看，尤其是笔记类型很方便。所以这里总结一下自己常用模板和小伙伴们分享下 [这里写一些为啥要整理这部分笔记，整理这部分笔记的前因后果] 笔记主要是关于自己使用Morkdown的一些常用模板的版式总结。 [这里写整理笔记的具体方式，是读那本书笔记，看那个视频笔记，或者对于那个问题的笔记] 笔记由两部分内容构成: 笔记类模板和技术点问题类模板[这里写笔记内容的构成] 傍晚时分，你坐在屋檐下，看着天慢慢地黑下去，心里寂寞而凄凉，感到自己的生命被剥夺了。当时我是个年轻人，但我害怕这样生活下去，衰老下去。在我看来，这是比死亡更可怕的事。\u0026mdash;\u0026mdash;\u0026ndash;王小波[[这里写一句鼓励自己的话,可以加一个颜色(可选)]\n博客内容\n一级标题 # 二级标题 # 三级标题 # 四级标题 # 五级标题 # 内容文字颜色设置具体的正文 具体的正文 具体的正文 具体的正文 具体的正文 重点标记性文字设置**具体的标记性正文\n具体的标记性正文\n具体的标记性正文\n具体的标记性正文\n具体的标记性正文\n具体的标记性正文\nAdd a new line for nothing, the \u0026ldquo;paladin\u0026rdquo; has been on the programing zoo.\n","date":"2026 年 4 月 10 日","externalUrl":null,"permalink":"/posts/how_to_wr/","section":"Posts","summary":"","title":"How_to_wr","type":"posts"},{"content":" 咕咕嘎嘎 # 大概在4年前的时候，我在学校中接触到了个人博客这个东西。当时是作为一个课堂作业被布置下来交由我们完成的， 使用html语言做了几篇非常简单的网页便交了上去。此后又经过了一段时间，在这个基础上进一步了解到了wordpress、 Hugo、Hexo等一众可以用于搭建的此类东西，趁着当时尚未退却的劲头，写了一些东西发表在上面。\n当然，兴趣使然的事情经过一段时间后，这股冲动终究会慢慢散去。因为做这样的事情并不能得到一定的回报刺激，久而久之 这个老的网站变荒废了，在一次清仓后再不见踪迹。\n不过旧的不去新的不来，个人博客的热情被一些奇奇怪怪的事情转移到了搭建用于组建虚拟局域网的服务器上了，从最早的使用 向日葵、蛤蟆吃等软件，到小黄鸭被发掘，还有像是NPS这种软件，也是让我折腾了好一段时间。不过像现在UU加速器 也推出了局域网联机的服务功能，想来以后在p2p游戏联机这方面也不需要这样子折腾了吧。\n总而言之 # 虽然说已经有一段时间没有花时间去弄博客的事情了，最近也是又重新回到这条路上来了。\n也许，可能，大概会用来记录一些编程方面的学习记录？因为最近也移植了一些老游戏到鸿蒙平台上来，想着就只是单单移植后少了些什么东西。\n希望这次的博客之路能够更加长一些吧~\n","date":"2026 年 4 月 9 日","externalUrl":null,"permalink":"/posts/%E7%AC%AC%E4%B8%80%E7%AF%87%E5%8D%9A%E5%AE%A2/","section":"Posts","summary":"","title":"第一篇博客","type":"posts"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":" 我是谁 # 大家好，我是 FunBocchi（安双）。一名游戏引擎、图形编程与各种\u0026quot;折腾\u0026quot;的爱好者，目前把大部分业余时间投入在**把经典游戏与游戏引擎移植到鸿蒙（HarmonyOS）**这件事上。\n正在做的事 # MonoGame → C++20 / HarmonyOS 移植 # 把 MonoGame 3.8.x 运行时引擎逐行移植为 C++20，目标平台鸿蒙 HarmonyOS，渲染后端计划采用 Vulkan：\n对源项目做完整 C++ 移植——不省略、不替代，最多以 TODO 标注待办 已基类化 21 个平台层类、完成 145+ 头文件 + 34 cpp 的编译链接验证 完整系列文章见 MonoGame 鸿蒙移植专栏，随进度持续更新 Bocchi House —— 游戏移植与启动平台 # 一个运行在 HarmonyOS NEXT 上的游戏移植与启动平台：底层封装 Vulkan（12 个 RAII 类）、窗口与节点管理，上层提供 SpriteBatch 等 2D 渲染引擎，用来启动各个移植游戏：\nPaladin（仙剑奇侠传）：C 语言经典 RPG，计划以 C++ 移植 Unholy Heights（房东是魔王大人）：C# XNA 4.0 魔物公寓经营 + 塔防，移植中 Unholy Heights 鸿蒙移植 # 经典 C#/XNA 独立游戏 Unholy Heights 的 HarmonyOS 移植项目，独立仓库维护。\n这个博客 # 记录移植过程中的技术细节、踩坑经历与日常折腾（局域网联机、服务器、游戏引擎……）。内容会随项目进度持续更新。\n我的主页 # GitHub：https://github.com/FunBocchi GitCode：https://gitcode.com/funbocchi Gitee：https://gitee.com/linzx123 邮箱：lzx13735999188@petalmail.com 开源项目 # 项目 说明 仓库 MonoGame 鸿蒙移植 MonoGame 3.8.x 逐行移植为 C++20（Vulkan 后端） GitCode Bocchi House HarmonyOS 游戏移植与启动平台 GitCode Unholy Heights 移植 C#/XNA 经典独立游戏的鸿蒙移植 GitCode 联系我 # 有移植方面的交流、建议或者想一起折腾，欢迎通过上面的主页或邮箱联系我～\n","externalUrl":null,"permalink":"/about/","section":"安双的小窝","summary":"","title":"关于我","type":"page"},{"content":"本站全部文章的按年份归档。\n","externalUrl":null,"permalink":"/archive/","section":"安双的小窝","summary":"","title":"归档","type":"page"},{"content":"这里收录朋友们的博客与值得关注的站点。想交换友链，欢迎通过关于页的主页或邮箱联系我～\n朋友们 # 站点 简介 （待添加） 你的博客链接，一句话介绍 常逛的地方 # 站点 简介 Blowfish 本站所用的 Hugo 主题 Hugo 世界上最快的静态站点生成器 GitCode 代码托管与项目协作平台 ","externalUrl":null,"permalink":"/friends/","section":"安双的小窝","summary":"","title":"友链","type":"page"}]