Flame 引擎 Jenny 脚本语言数值函数指南:ceil、floor、round 与 decimal 全解析 📅 发布时间:2026/9/16 21:51:25 👁 浏览次数: Flame 引擎 Jenny 脚本语言数值函数指南ceil、floor、round 与 decimal 全解析【免费下载链接】flameA Flutter based game engine.项目地址: https://gitcode.com/GitHub_Trending/fl/flame本指南以 Flame 引擎内置的 Jenny 对话脚本语言为背景系统讲解其内置数值函数ceil、dec、decimal、floor、inc、int、round、round_places的语义、返回值边界、正负数行为与典型应用场景。读完本文你将掌握如何在 Yarn 脚本中用set、if等指令可靠地做取整、取小数位、精度保留与步进运算并理解这些函数在 Jenny 运行时中的底层实现与类型检查规则。函数在 Jenny 表达式中的位置在 Jenny 中函数与任何编程语言或数学中的函数概念一致它接收一定数量的参数计算并返回一个结果。函数调用由函数名后跟括号内的参数组成即使没有参数括号也必须保留set $roll_2d6 dice(6) dice(6) set $random random()Jenny 共内置约 20 个函数其中数值函数Numeric functions是处理数字的核心工具集。函数定义总览可参考 functions.md完整的数值函数清单集中收录于本文所讲解的 numeric.md。从源码结构看每个内置函数在 packages/flame_jenny/jenny/lib/src/structure/expressions/functions/ 目录下都有独立的实现文件如ceil.dart、floor.dart、round.dart它们统一继承自NumExpression通过num1Builder之类的工厂函数完成参数数量与类型的校验。例如 round.dart 中RoundFn的核心计算只有一行num get value arg.value.round();直接复用 Dart 标准库的取整语义。ceil(x)向正无穷取整ceil(x)返回x向正无穷方向取整的值即大于或等于x的最小整数。title: ceil --- { ceil(0) } // 0 { ceil(0.3) } // 1 { ceil(5) } // 5 { ceil(5.001) } // 6 { ceil(5.999) } // 6 { ceil(-2.07) } // -2 注意负数行为ceil(-2.07)的结果是-2因为 -2 是大于 -2.07 的最小整数。这与 floor.dart 中的向下取整恰好对称。底层实现见 ceil.dartnum get value arg.value.ceil();直接映射 Dartnum.ceil()。典型用途计算所需的最小格子数如 UI 分页、道具堆叠数量、将怪物血量向上取整为整数。floor(x)向负无穷取整floor(x)返回x向负无穷方向取整的值即小于或等于x的最大整数与ceil方向相反。title: floor --- { floor(0) } // 0 { floor(0.3) } // 0 { floor(5) } // 5 { floor(5.001) } // 5 { floor(5.999) } // 5 { floor(-2.07) } // -3 floor(-2.07)返回-3因为 -3 是小于 -2.07 的最大整数。这与很多人直觉中的去掉小数截断不同在处理负数时务必区分。实现同样是一行arg.value.floor()见 floor.dart。典型用途计算杀怪掉落物数量的下限、经验值结算中的向下取整、计时器向下取整显示秒数。int(x)向零截断提取整数部分int(x)截断x的小数部分向零方向取整只返回x的整数部分。title: int --- { int(0) } // 0 { int(0.3) } // 0 { int(5.0) } // 5 { int(5.001) } // 5 { int(5.999) } // 5 { int(-2.07) } // -2 对比floor(-2.07) -3与int(-2.07) -2可以看出int与floor在负数上的结果不同int是截断floor是向下。int与decimal满足恒等式x int(x) decimal(x)见下文。典型用途从价格中分离元部分、从时间戳中提取整秒数、坐标换算中的格坐标下取整。decimal(x)提取小数部分decimal(x)返回x的小数部分。若x为正返回值位于[0, 1)若x为负返回值位于(0, -1]。恒等式x int(x) decimal(x)恒成立。title: decimal --- { decimal(0) } // 0 { decimal(0.3) } // 0.3 { decimal(5.0) } // 0 { decimal(5.001) } // 0.001 { decimal(5.999) } // 0.999 { decimal(-2.07) } // -0.07 注意decimal(-2.07)是-0.07而不是0.07因为int(-2.07) -2需要-2 (-0.07) -2.07才能维持恒等式。源码实现见 decimal.dartfinal x arg.value; return x - x.toInt();。典型用途显示进度条的小数位、判断某个值是否为整数decimal(x) 0、拆分时间中的分秒显示。round(x)四舍五入到最近整数round(x)将x舍入到最近的整数。关键规则以.5结尾的值正数时向上舍入负数时向下舍入。title: round --- { round(0) } // 0 { round(0.3) } // 0 { round(5.0) } // 5 { round(5.001) } // 5 { round(5.5) } // 6 { round(5.999) } // 6 { round(-2.07) } // -2 { round(-2.5) } // -3 注意round(-2.5) -3负数.5向下舍入这与5.5 - 6正数向上舍入对称即远离零方向。这符合 Dart 标准库num.round()的默认行为见 round.dart。对应测试见 round_test.dart。典型用途金币结算、经验结算中的最近整数显示、数值浮点误差后的显示规整。round_places(x, n)保留 n 位小数的四舍五入round_places(x, n)将x舍入到n位小数。n必须是整数可以为正、负或零n 0等价于普通round(x)n 0保留n位小数第n1位四舍五入n 0舍入到最近的十、百、千位等。title: round_places --- { round_places(0, 1) } // 0 { round_places(0.3, 1) } // 0.3 { round_places(5.001, 1) } // 5.0 { round_places(5.001, 2) } // 5.0 { round_places(5.001, 3) } // 5.001 { round_places(5.5, 1) } // 5.5 { round_places(5.999, 1) } // 6.0 { round_places(-2.07, 1) } // -2.1 { round_places(13, -1) } // 10 { round_places(252, -2) } // 200 源码实现round_places.dart展示了精确的算法override num get value { final precision places.value.toInt(); final factor pow(10, precision); return (arg.value * factor).roundToDouble() / factor; }即先乘以10^n、四舍五入、再除以10^n。负精度时pow(10, -1) 0.113 * 0.1 1.3舍入为1再除以0.1得10从而实现对十位、百位的舍入。参数校验来自源码make()方法要求恰好两个参数——参数过多或过少都会报错function round_places() requires two arguments第一、第二参数都必须是数值类型否则分别报first argument in round_places() should be numeric/second argument in round_places() should be numeric。这些规则被 round_places_test.dart 中的测试用例覆盖例如title: Start --- 2 - {round_places(2, 0)}, {round_places(2, 1)}, {round_places(2, 2)} // 2, 2, 2 1/7 - {round_places(1/7, 3)}, {round_places(1/7, 5)} // 0.143, 0.14286 274.5 - {round_places(274.5, -1)}, {round_places(274.5, -2)} // 270, 300 典型用途显示货币金额的两位小数、战斗伤害的精确浮点结算、展示百分比round_places($ratio * 100, 1)得到如 33.3% 的显示值。inc(x)与dec(x)向相邻整数步进inc(x)返回x向下一个整数方向步进的值若x已是整数返回x 1否则返回ceil(x)。title: inc --- { inc(0) } // 1 { inc(0.3) } // 1 { inc(5.0) } // 6 { inc(5.001) } // 6 { inc(5.999) } // 6 { inc(-2.07) } // -2 dec(x)则向前一个整数方向步进若x已是整数返回x - 1否则返回floor(x)。title: dec --- { dec(0) } // 0 { dec(0.3) } // 0 { dec(5.0) } // 4 { dec(5.001) } // 5 { dec(5.999) } // 5 { dec(-2.07) } // -3 注意inc/dec与简单的x 1/x - 1并不等价当x是非整数时它们会先吸附到相邻整数。源码inc.dart、dec.dart通过x.ceil() / x.floor()与x比较来实现这一语义// inc final x arg.value; final y x.ceil(); return x y ? y 1 : y; // dec final x arg.value; final y x.floor(); return x y ? y - 1 : y;典型用途逐级遍历关卡/楼层编号如set $floor inc($floor)、分页器中的上一页/下一页、对浮点计数器的凑整式步进。函数参数与类型检查的通用规则数值函数大多只接收一个数值参数源码中统一通过num1Builder工厂校验恰好一个参数且为数值类型见 _common.dart。唯一的双参数函数是round_places(x, n)其校验规则如上文所述。此外Jenny 还允许开发者向YarnProject注册用户自定义函数签名在注册时固定参数个数、参数类型、返回类型均不可变。若脚本中调用了未知函数或参数数量/类型不匹配编译期即报错。数值函数可在自定义函数中自由组合使用——例如官方 functions.md 中的Blacksmith示例就展示了round(value(main_hand) / 5)这样的用法将游戏中物品的价值换算为修理费。更多关于注册自定义函数的机制可参考 function_storage.md。选择正确的取整函数行为对照速查下表汇总了各函数在代表性输入上的差异帮助你在不同语义需求下快速选择输入 xceilfloorintroundincdec0.31000105.9996556655.0555564-2.07-2-3-2-2-2-35.5655665-2.5-2-3-2-3-2-3选择原则向正无穷ceil向负无穷floor向零截断丢弃小数int四舍五入到最近整数round.5边界按远离零处理保留指定位数round_places(x, n)整数步进 / 整数自增自减inc/dec仅取小数部分decimal。与火焰引擎中的其他模块配合Jenny 作为 Flame 引擎的对话/叙事脚本语言其数值函数可以直接用于变量初始化与状态机set $level 1后用set $level inc($level)推进关卡条件分支if round_places($gold, -2) 100判断金币是否达到百位级别文本插值显示你获得了 {round($exp / 10)} 点经验直接在对话文本中输出格式化数值。若要进一步了解 Jenny 的完整内置函数体系随机函数dice/random/random_range、类型转换函数bool/number/string、以及if/plural/visit_count/visited等杂项函数可继续阅读 functions.md 及其子文档 random.md、type.md、misc.md。若想动手验证本文中的全部示例可在仓库的 flame_jenny 包中运行 round_places_test.dart、round_test.dart、decimal_test.dart 等测试用例所有输出结果均与上文示例一致。【免费下载链接】flameA Flutter based game engine.项目地址: https://gitcode.com/GitHub_Trending/fl/flame创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考