这次来玩mc的datapack,做一个增强版的赛船系统
使用版本为1.21.4
在这记录这个赛船系统的制作过程
我希望它能够实现以下功能:
显示速度,计时等信息
与多个变量相关的集气
脱轨、碰撞的判定(用于氮气丢失)
以铺蓝冰实现加速的氮气释放
快捷的赛道起点终点设置
比赛开始,计时,结算等
比赛影像记录,播放和挑战
我之前做过一个基础的datapack,它能够显示速度,有集气和氮气加速的功能
不过那玩意比较简单粗暴,它通过计分板准则minecraft.custom:minecraft.boat_one_cm
每个游戏刻切片并清零来做速度表
然后在最后记录这一刻的速度,到了下一个游戏刻就是上一刻的速度
相减得到加速度
然后将负的加速度加和起来就是氮气值
暴力地舍弃过大的加速度(太大基本因为是跳表、脱轨或是碰撞)
我对这个旧版不是很满意,而且里面的构造确实屎山,我都不想改
所以直接开新的
速度表
这个原理和旧版一样,是用计分准则来实现的
不过拿来给人看是足够了,我甚至直接把旧版的搬过来
每个玩家只有一个actionbar,所以dummy创建一个actionbar计分板
还有速度计分板,上一刻速度,加速度
1 | #data/common/function/load.mcfunction |
不同的数字对应不同的actionbar显示模式
1 | #data/common/function/actionbar.mcfunction |
里面有两种速度表,第一个是我新做的用于调试的速度表,第二个就是旧版的直接搬过来
1 | #data/boat_speed_monitor/function/speed_monitor_1.mcfunction |
因为我是做了几个模块后才开始写这个md,速度向量,加速度向量,和朝向向量后面会给出
1 | #data/boat_speed_monitor/function/speed_monitor_2.mcfunction |
这个就是直接从我以前做的包扒过来的,我挺满意这个
一开始我在想
集气系统应该跟这几个变量相关
加速度大小,速度大小,速度方向与船头方向的夹角大小
那肯定只用这两个变量是不够,因为缺少了方向
而且我觉得加速度的精度有点不够,因为这样得到的加速度绝对值基本只在0到4
计分板又只给整数,太少了
(因为船前进的牵引加速度只有0.04m/tick^2^)
我想了想,既然我需要能够描述“方向”,那我不如使用向量?
终点坐标减去起点坐标就是向量,可能做起来复杂一点,但不是不能实现
要得到向量就逃不开计算,要计算就逃不开计分板
因为计分板只能储存整数,那我必然逃不开精度问题
考虑什么样的精度比较合适确实让我思考了几天
1.int只有31位是数据位,如果精度过高,那么坐标范围就会比较有限
2.百分之一的精度对加速度是不够的
3.向量运算过程中很容易涉及乘法,我需要尽量保证向量能完整计算一次乘法
船的速度一般超不过4m/tick
蓝冰的最高速度也就40/11=3.6363…m/tick
加速度那更小
然后边想边试,暂时让精度为2^10
为了让精度比较好改,我把精度全部写在一个函数里
1 | #data/common/function/pos_p_get.mcfunction |
既然需要算速度,那自然需要储存上一刻的坐标
1 | #data/common/function/pos_lt_get.mcfunction |
这个函数需要放在tick的最后部分执行
接下来把pos_p减去pos_lt就能得到v_p当前游戏刻速度向量
1 | #data/common/function/v_vec_p_get.mcfunction |
同理,获取上一刻速度向量v_lt
1 | #data/common/function/v_vec_lt_get.mcfunction |
然后获取加速度向量a_p
1 | #data/common/function/a_vec_p_get.mcfunction |
脱轨、碰撞判定
本来的想法就比较直接
看看船的侧边、下方、侧边下方有没有非法方块
但是发现这玩意不好定义啊
侧边可以是类似火把,按钮,压力板一类不影响碰撞的方块,下边是冰一样能跑
也可以是像栅栏一样碰撞箱不完整的方块
(然后就有了个废稿type1)
那还不如只看下方和侧边下方的方块
如果没有墙那就只要在赛道侧边放一个方块就能表示边界
如果有墙就只需要在墙下边放一个方块就好,效果一样
1 | #data/wall_hit_judge/function/type2/judge.mcfunction |
下边一坨注释是用来坐标测试的,不重要
大体意思就是一开始先把判定值设为1,如果每个判定点的方块都属于#wall_hit_judge:boat_can_run_on,那就把判定值设为0
判定值为1代表脱轨,0代表正常
1 | #data/wall_hit_judge/tags/block/boat_can_run_on |
为了在撞墙后触发事件,我自然需要记录上一刻的碰撞状态
1 | #data/common/function/tick.mcfunction |
然后用一个新函数规定事件
1 | ##data/wall_hit_judge/function/oot_event.mcfunction |
事件触发
1 | #data/common/function/tick.mcfunction |
先睡了