Parin游戏引擎
欢迎来到2025年9月Parin的开发日志.
新调色板
本月新增了8种预定义的颜色``调色板.其中两款灵感来自GameBoy和NES,其他则引入了林操极客元素,比如Gruvbox.
cpp
HexPalette!4 gb4 = [ .. ];
HexPalette!8 nes8 = [ .. ];
HexPalette!16 gruvboxDark = [ .. ];
HexPalette!16 gruvboxLight = [ .. ];
HexPalette!16 oneDark = [ .. ];
HexPalette!16 oneLight = [ .. ];
HexPalette!16 solarizedDark = [ .. ];
HexPalette!16 solarizedLight = [ .. ];
此外,现在有一个可解析CSV文件中的调色板的叫csvRowToPalette的助手函数.
画画
在速度比安全更重要的环境中,新增了叫ParinSkipDrawChecks的版本.无效的绘画值会导致游戏崩溃,所以只有在准备好了时才用.
该版本还在试绘画(未加载)空资源时禁止调试形状.
帧分配器与更优容器
该引擎现在提供一个针对临时内存的帧分配器.该配置只在当前帧内生效,并在结束时自动清理.这对像串或每帧创建的小对象等临时数据``非常有用,无需担心释放它们.
cpp
void* frameMalloc(Sz size, Sz alignment);
void* frameRealloc(void* ptr, Sz oldSize, Sz newSize, Sz alignment);
T* frameMakeBlank(T)();
T* frameMake(T)(const(T) value = T.init);
T[] frameMakeSliceBlank(T)(Sz length);
T[] frameMakeSlice(T)(Sz length, const(T) value = T.init);
引擎内部已用该配置器来处理loadTempText和prepareTempText等函数.与此同时,在分配策略上内置容器更加常见.
之前,它们只支持堆分配.现在它们也可以是栈分配或由外部内存管理.
一个实际示例是映射模块中的磁帖地图层,现在使用固定大小的容器:
cpp
//`固定大小`的容器.
alias TileMapLayerData = FixedList!(short, maxTileMapLayerCapacity);
//`固定大小`的容器.
alias TileMapLayer = Grid!(TileMapLayerData.Item, TileMapLayerData);
//`动态容器`.
alias TileMapLayers = List!TileMapLayer;
内存跟踪
Parin有个轻量可检测调试构建中的泄漏或无效释放的内存跟踪系统.默认,只有在检测到泄漏时才会在关机时打印出来.
cpp
bool isLoggingMemoryTrackingInfo();
void setIsLoggingMemoryTrackingInfo(bool value, IStr filter = "");
示例输出:
cpp
Memory Leaks: 4 (total 699 bytes, 5 ignored)
1 leak, 20 bytes, source/app.d:24
1 leak, 53 bytes, source/app.d:31
2 leak, 32 bytes, source/app.d:123
这不完全是Parin的功能.它来自Parin用来分配内存的库的Joka.会自动跟踪Joka分配的内存.
可用static if (isTrackingMemory)检测是否激活内存跟踪,如果激活了,可用_memoryTrackingState检查当前跟踪状态.
_memoryTrackingState是线本的,因此每线程都有自己的独立跟踪状态.当你查看状态或摘要时,记住它主要是一个调试工具.
一般,这些信息在调试构建中很正常,并不表示错误.
可用ignoreLeak函数忽略一些泄漏,比如这样:
cpp
// struct Game { int hp; int mp; }
// Game* game;
game = jokaMake!Game().ignoreLeak();
该功能看似简单,但它可帮你了解内存发生的事情.如,它帮助我将引擎某部分的堆分配数量从19个减少到9个.
附加集合
新增了可选库的额外合集.当前它只包含microui,但未来可能会添加更多.这主要是电池附加的功能,无需下载依赖,允许内部Parin代码使用库.
方便
新增了两个结构:
Tween:在两个浮数值间调整
SmoothToggle:处理一般是开/关的两个状态间的平滑转换.
这里有一个用SmoothToggle类型创建了基本转换效果的基本示例:
cpp
auto color = cyan;
auto state = SmoothToggle();
bool update(float dt) {
if ('q'.isPressed) state.toggle();
auto value = smoothstep(resolutionHeight, resolutionHeight, state.update(dt));
if (state.isAtEnd) {
state.toggleSnap();
color.r = cast(ubyte) (randi % 255);
color.g = cast(ubyte) (randi % 255);
color.b = cast(ubyte) (randi % 255);
};
drawRect(Rect(0, value, resolution), color);
return false;
}
两者体积都小,因此可方便地在动画数组中迭代.Tween是20字节,SmoothToggle是8字节.Tween还支持Tween2,Tween3和Tween4类型的向量.
更快的格式化与打印改进
得益于更简单的格式实现,项目编译速度应该会更快.用来串格式化的格式模板现在只有8行代码,所有工作都转发给了一个非模板函数``fmtIntoBufferWithStrs.
还新增了打印函数的方便分隔标记的叫Sep的结构.如:
cpp
//将打印:`"1 2 3`开始`!"`
println(Sep(" "), 1, 2, 3, "Go!");
在打印时可轻松控制分隔符,方便快速调试.