<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Reverse-Engineering on yzh119</title><link>https://yzh119.github.io/zh/tags/reverse-engineering/</link><description>Recent content in Reverse-Engineering on yzh119</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 09 Sep 2026 05:48:54 +0800</lastBuildDate><atom:link href="https://yzh119.github.io/zh/tags/reverse-engineering/index.xml" rel="self" type="application/rss+xml"/><item><title>[AI]英雄无敌3的素材格式和引擎限制</title><link>https://yzh119.github.io/zh/posts/h3-engine-constraints/</link><pubDate>Sun, 06 Sep 2026 12:00:00 +0800</pubDate><guid>https://yzh119.github.io/zh/posts/h3-engine-constraints/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;本文记录发布时的实现与测量。文中的版本号、费用和检查数量属于该阶段；后续兵种安装记录见&lt;a href="https://yzh119.github.io/zh/posts/necropolis-vampires/"&gt;吸血鬼交付&lt;/a&gt;，现行工具入口见&lt;a href="https://yzh119.github.io/zh/posts/h3-art-tools/"&gt;独立仓库&lt;/a&gt;。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;我想把英雄无敌 3 的兵种美术换掉，在 &lt;a href="https://vcmi.eu"&gt;VCMI&lt;/a&gt; 上做。&lt;/p&gt;&#10;&lt;p&gt;动手生成任何东西之前，我先去读了引擎代码，想知道它到底要什么。结果发现一堆规矩，&#10;基本没文档，而且&lt;strong&gt;踩了不报错&lt;/strong&gt;——你只会得到一个看着别扭的兵种，还不知道哪儿不对。&lt;/p&gt;&#10;&lt;h2 id="画布尺寸只认第一帧"&gt;画布尺寸只认第一帧&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;CreatureAnimation&lt;/code&gt; 从当前动画组的头一帧取尺寸：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;fullWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;但 &lt;code&gt;pos.w&lt;/code&gt;/&lt;code&gt;pos.h&lt;/code&gt; 在单位创建时就定死了，后面每一帧都得从这个矩形里过：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;topLeft&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;比待机帧大的，超出部分直接裁掉；比它小的，就悬在半空。所以每个动画组的每一帧&#10;都得用同一张画布，靠透明像素填满。&lt;/p&gt;&#10;&lt;h2 id="站位不看兵种"&gt;站位不看兵种&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;getStackPositionAtHex&lt;/code&gt; 算绘制位置只看六边形——一个写死的 &lt;code&gt;basePos(-189, -139)&lt;/code&gt; 加偏移，&#10;兵种自己的尺寸压根不参与。&lt;/p&gt;&#10;&lt;p&gt;从 PNG 读进来的帧 &lt;code&gt;margins&lt;/code&gt; 是 (0,0)，不像 &lt;code&gt;.def&lt;/code&gt; 帧自带边距。换句话说，&lt;strong&gt;兵种画在画布&#10;哪个位置，就是唯一的锚点&lt;/strong&gt;。放偏了，单位要么浮空要么陷地，后面没有任何环节能补救。&lt;/p&gt;</description></item></channel></rss>