嵌入式脚本引擎在软件开发领域扮演着重要的角色,它能够扩展或修改软件应用的核心功能。在游戏开发领域,脚本语言为游戏引擎开发者提供了一种方式,使得设计师能够实现游戏的剧情事件、NPC行为等,而无需游戏引擎开发者介入,避免了硬编码游戏逻辑到游戏引擎中的必要性。
本文是关于Conscript嵌入式脚本引擎的.NET实现的最后一篇文章,介绍了Conscript的IDE实现。这个IDE具有类似于Microsoft Visual Studio和其他类似IDE的功能和外观。IDE的Windows应用程序以C#源代码形式提供,包括脚本引擎本身、IDE以及一个示例主机功能模块,用于提供三角函数和2D图形渲染能力。默认情况下,IDE应用程序本身是一个主机功能模块,提供了一个Print函数,允许在IDE的输出窗口中输出文本。
IDE的窗口布局包括左侧的脚本源代码面板、右侧的虚拟机详细信息面板以及底部的输出窗口。此外,输出窗口下方的状态栏提供编译状态和文本光标坐标。
脚本面板是一个标签控制,允许编辑多个脚本。IDE提供了一个ScriptLoader实现,它通过优先考虑在IDE中加载的脚本来覆盖默认的脚本加载行为。这允许IDE中的一个脚本包含另一个IDE中的脚本,即使它没有提交到磁盘。
虚拟机面板也是一个标签控制,提供了对编译后的Conscript字节码、全局、脚本、局部作用域、调用和参数堆栈以及线程锁定状态的访问。VM面板内的字节码标签允许设置断点,并在调试期间突出显示当前执行的指令。
作用域标签允许在调试期间查看和编辑全局、脚本和局部作用域中的变量。堆栈标签允许查看当前的调用堆栈和参数堆栈,后者在函数中调节变量作用域。最后,锁标签显示多线程脚本中使用的同步锁的状态。
输出面板提供编译日志,并作为默认提供的Print()主机函数的输出设备。
应用程序的菜单栏以传统布局组织,包括文件、编辑、构建、调试和帮助菜单。文件菜单提供脚本源代码管理和IDE的终止。编辑菜单提供标准的撤销/重做和剪切/复制/粘贴功能。构建菜单允许增量或完全重建脚本。增量构建基本上只编译修改过的脚本,而重建则丢弃所有编译过的脚本,并从头开始重新编译它们。构建菜单还提供了一个构建设置对话框,用于控制调试代码生成和代码优化,以及一个主机环境对话框,用于注册主机功能模块插件。调试菜单提供了标准的调试功能,包括单步执行、监控执行、进入、跳过和退出函数的能力,以及切换和清除断点。最后,帮助菜单提供了一个信息对话框的访问。
源代码中包含的示例模块插件实现了两个主机功能模块:一个用于基本三角函数,另一个用于简单的2D图形。提供的三角函数包括:
any math_abs(any);
float math_acos(float);
float math_asin(float);
float math_atan(float);
float math_atan2(float, float);
float math_ceiling(float);
float math_cos(float);
float math_cosh(float);
float math_e();
float math_floor(float);
float math_log(float);
float math_log2(float, float);
float math_max(float);
float math_min(float);
float math_pi();
int math_round(float);
float math_round2(float, int);
any math_sign(any);
float math_sin(float);
float math_sinh(float);
float math_sqrt(float);
float math_tan(float);
float math_tanh(float);
float math_rand(float);
图形模块提供的函数包括:
bool Gfx_Initialise(int, int);
bool Gfx_Shutdown();
bool Gfx_Clear();
bool Gfx_SetColour(int, int, int);
bool Gfx_SetLineWidth(int, int, int);
bool Gfx_DrawLine(int, int, int, int);
bool Gfx_DrawRectangle(int, int, int, int);
bool Gfx_FillRectangle(int, int, int, int);
bool Gfx_DrawEllipse(int, int, int, int);
bool Gfx_FillEllipse(int, int, int, int);
bool Gfx_DrawString(int, int, string);
function main()
{
Gfx_Initialise(640, 480);
var intensity = 0;
for (var index = 0; index < 400; index += 10)
{
Gfx_SetColour(255 - intensity, 0, intensity);
intensity += 5;
Gfx_DrawLine(0, index, 400 - index, 0);
Gfx_SetColour(intensity, 255, 0);
Gfx_FillEllipse(index, 200, index / 4, index / 4);
Gfx_SetColour(0, 0, 0);
Gfx_DrawEllipse(index, 200, index / 4, index / 4);
}
// pause
for (var pause = 0; pause < 200000; pause++);
Gfx_Shutdown();
}