本帖最后由 贰逼 于 2015-10-29 21:12 编辑

本人这些天费劲心思,终于探究出了Minecraft物理系统的工作方式,并编写了此软件供大家使用。


使用方式:


  • 通过方向和方向上的速度算Motion值


1.找到Motion by Speed一栏;
2.填写RotationXRotationYSpeed
3.按下Work out Motion按钮即可。


4.点击ClearAll按钮清空所有。

  • 通过起点坐标和终点坐标算Motion

1.填写起点坐标终点坐标(有没有填写的会有提示);


2.填写加速度阻力抛射角度
3.点击Work out Motion生成,注意不是所有角度都符合条件,如果不符合条件会有提示




4.填写一个正确的抛射角度后,点击Work out Motion算出Motion值。




6.点击Export Rotation按钮生成NBT的Rotation。

  • 画线功能
由于不是所有抛射角度都能经过最终坐标/测试Motion速度效果,所以本软件自带画线功能。(画线指平面对运动轨迹视图)




1.在得到Motion后(可以自行填写),点击Draw the line画出运动轨迹。



2.点击确定。如果拥有起点坐标,左上会写出起点坐标;如果有终点坐标,两条直线交点则是终点坐标



3.点击Clear the line清空画线面板。



4.修改画面比例可以得到全图运动轨迹。通过速度算出的Motion可以算出最终距离起点多少长度。



5.同样按下确定,如果有,能够显示起点坐标终点坐标



6.点击ClearAll按钮清空所有。

  • 贴心功能

英文看不懂、参数看不透?

点击文字获得更多信息



下一页为算法;

第三页为下载地址;



算法1——速度+方向算Motion


速度 就是这个方向上的速度

那么通过这个方向反过来可以分别求出向x轴,y轴,z轴的速度。(此处轴的方向为正方向)



sp:速度;

xyzmov:分别的Motion;

xdeg:Rx角度;

ydeg:Ry角度。





通过上图可以得知:



  1. xmov = sp * sin(xdeg) * cos(ydeg)
  2. ymov = sp * sin(ydeg)
  3. zmov = sp * cos(xdeg) * cos(ydeg)
复制代码

绿线则是ymov,蓝线是zmov,紫线是xmov。



由于Mc中的Ry略有特殊,所以真正算法是:

  1. xmov = -sp * sin(xdeg) * cos(ydeg)
  2. ymov = sp * sin(ydeg)+0.1
  3. zmov = sp * cos(xdeg) * cos(ydeg)
复制代码
其中y+0.1是为了保持运动。


算法2——两坐标算方向

前面提到了Ry,Rx有些特别,


根据规律:




Rx:




Ry:





  1. <b style="font-size: x-large;">                </b><font size="1">Rx = atan2(delZ, delX)
  2.                 Ry = atan2(delY,Sqrt(delX * delX + delZ * delZ)))</font>
复制代码
其中:

delX,delZ,delY是表示终点坐标减去起点坐标;

Sqrt就是开方。


具体还需要自己体会。

算法3——两坐标算Motion


这个问题困扰了我几天,

我试过斜抛公式

  1. v = f + (Math.Sqrt(g * lenx * lenx) / (Math.Cos(d * Math.PI / 180) * Math.Sqrt(2 * lenx * Math.Tan(d * Math.PI / 180) - leny))) * Math.PI
复制代码
也试过二次函数抛物线,但是都不是。


后来无耻的翻源码,才发现Minecraft物理运动系统其实比较偷懒

  1.         this.posX += this.motionX;
  2.         this.posY += this.motionY;
  3.         this.posZ += this.motionZ;

  4.         this.motionX *= (double)var18;
  5.         this.motionY *= (double)var18;
  6.         this.motionZ *= (double)var18;
  7.         this.motionY -= (double)var19;
  8.         this.setPosition(this.posX, this.posY, this.posZ);
复制代码
其中:

var19=g=加速度(其实应该是重力,不过wiki里面说没有重力所以命名加速度,这有点误导)
var18=f=1-阻力


加速度和阻力可以去WIKI查看(其中包含运动一栏):




经过进一步整理

  1. x=mx+fmx+f^2 mx+……+f^t mx
  2. =(f^0+f^1+f^2+……+f^t)mx

复制代码
因为mx mz关于rx关联,所以合并成一个mx

再整理:

  1. mx=x/(-100(0.99^t-1))
  2. my=(y+gt)/(-100(0.99^t-1))
复制代码
其中要使mx my有关联,

可以设定抛射角度θ


因此能进一步推导t,也可以通过另类求法:



此处的t就是

(无重力的y坐标-最终坐标)/重力

不该是推导还是这种求法,得到的t:

  1. θ<45
  2. tan(θ)=my/mx=(y+gt)/10(1-0.99^t)*10(1-0.99^t)/x=(y+gt)/x
  3. y+gt=x*tan(θ)
  4. gt=x*tan(θ)-y
  5. t=(x*tan(θ)-y)/g

  6. θ>45
  7. tan(90-θ)=mx/my
  8. t=(x/tan(90-θ)-y)/g
复制代码

求出t后,mx my mz只需要:

  1.                 motx = delX / (-100 * (Math.Pow(1 - d, t) - 1));
  2.                 moty = (delY + G * t) / (-100 * (Math.Pow(1 - d, t) - 1)) + 0.1;
  3.                 motz = delZ / (-100 * (Math.Pow(1 - d, t) - 1));
复制代码
(Math.Pow代表x的n次幂)


由于角度不能偏值太大,否则t太大,得出的Motion不准确,所以设定了一个范围(具体这个范围就不解释了)

总之角度越接近Rotation中的Ry,运动得越远


具体可以使用画线功能看看运动是否经过终点坐标


下载地址:


密码:n7tk






[groupid=546]Command Block Logic[/groupid]