pvzclass是如何实现的?pvzclass源代码初步分析(1) 概览
0. 写在前面
为什么我要写这篇分析?
天青开发的pvzclass(C++),给PVZ二次创作者提供了除汇编以外的另一选择。
不过,本应是降低开发门槛的工具,却因自身的门槛,反倒是劝退了一些创作者。
而PVZ自制圈内出名的作品中,使用pvzclass的并不很多。
虽然有Z2改版、皓月的PVZ Rogue,以及百花坛的作品等等佳作,但使用汇编的作品依然占据绝大多数。
这固然有汇编自身的原因,但是汇编语言相比C++而言有很多劝退性的缺点,比如难以维护、指令复杂、极难上手等。
而且有OI基础的人显然更熟悉C++。他们上手pvzclass的难度更低,实现较复杂的功能也更轻松。
除此之外,我自己接触pvzclass时,走了很多弯路。
我撰写本文,也是希望能把自己对pvzclass的理解和大家分享,让大家能更快上手pvzclass。

接下来的部分中,笔者将默认读者已有C++的编程基础。
如果你要学习pvzclass,建议结合天青的教程观看。
虽然是代码分析,但也有可能会掺杂一些其他的东西,还请见谅。

1.pvzclass初见
从github上下载下来的应该是一个名为"pvzclass-master.zip"的压缩文件。
将其解包,可以得到一个文件夹(显然),主要包含以下内容:

其中".gitattributes"和".gitignore"不影响pvzclass的使用,我们忽略它们。
"LICENSE"是pvzclass的许可证,打开(用自带的记事本打开即可)后可以看到pvzclass使用的是MIT许可证。(许可证相关内容请自行百度)
"MemoryAddressList"看似无扩展名,实际上只是一份普通的文本文档。
该文档包含PVZ中大部分内容的指针和内部常量的储存地址,可以说是对PVZ本体进行二次创作(尤其是使用汇编语言时)的必备文档。
但本文主要是讲pvzclass的,所以我们跳过它。
接下来的"pvzclass.sln"是Visual Studio(以下简称"VS")的解决方案文件,没有安装VS应该是无法打开它来使用pvzclass的。
这也是尽量使用VS(而不是其他软件)完成pvzclass创作的理由之一。
"Readme.md"我想不用多说,这里跳过。
打开剩下的"pvzclass"文件夹,会看到这些内容:


看上去就很多很杂,对于习惯了单文件编程的人而言会有些目不暇接。我们分别来看。
这些文件中"pvzclass.sln""pvzclass.vcxporj""pvzclass.vcxproj.filters""pvzclass.vcxproj.user"是VS的文件,不要动它们(除非你不用VS)。
尤其是"pvzclass.sln",不要通过打开这个文件来开始应用pvzclass!
"README.md"是较旧版本的,不用理它。
"MemoryAddressList"和上一级文件夹中的那一份相比含有额外内容,也建议保留(但不一定留在这个文件夹里)。
剩下的头文件和源代码文件,以及"Classes""Enums"中的文件,就是pvzclass的核心组件了。
2.pvzclass组件间的关系
除去主要源代码文件"pvzclass.cpp",剩下的文件间具有如下的从属关系:

在pvzclass中,除去"pvzclass.cpp",剩余的文件均遵循“头文件包含头文件,源代码文件解释头文件”的原则。
这是什么意思呢?
"头文件包含头文件"很好理解,即头文件中包含其他的头文件。(说了和没说一样)
以"pvzclass.h"为例,实际上这个文件只有6行:

除去第一行的编译指令,剩下的就是其包括的头文件。整个"pvzclass.h"只是一个索引。
而其他头文件中,除去索引类文件,剩余的代码主要包括三个部分:定义变量,定义函数与过程,以及实现函数与过程。
但实际上,变量的赋值、函数与过程的实现只有很小一部分,这类代码大部分都在源代码文件中。此即所谓“源代码文件解释头文件”。

就先讲这么多吧。
每个基于pvzclass的作品,必然要在程序的一开始调用来自"ProcessOpener.h"的方法。
因此,下篇将从"ProcessOpener.h"开始,分析pvzclass代码的运行规则。