⊙v⊙
本帖最后由 ⊙v⊙ 于 2018-4-9 19:30 编辑

前言

在1.13这个命令大洗地的版本下,我的命令是可以突破天际的!
大家好,我这人不太会说话,但我还是要来论坛丢一下人...

首先,有这么一个问题,如何判断玩家的朝向是否在某一个两点组成的竖直平面范围内(比如,指针是否指向挂画)

在1.13之前我们可以通过给予选择器参数rx,rxm,ryrym进而选中满足条件的玩家

玩家当前rxry按下F3能在下图蓝红框的位置找到
那么在确定好需要判断的范围后,把屏幕中间的十字指针移动到范围的左下角和右上角,记录rx和ry
然后把记录到的2个rx值,较小的数值为选择器里的rxm=<数值>,较大的数值为选择器里的rx=<数值>,ry同理


像这样,就成功了呢
当玩家的垂直旋转角度(rxm,rx)范围为-37~-10,且水平旋转角度(rym,ry)为66~113时,输出
  1. /execute @a[rxm=-37,rx=-10,rym=66,ry=113] ~ ~ ~ say 输出
复制代码

但1.13的命令格式变了啊
原本的rx和rxm合并为x_rotation,ry和rym合并为y_rotation。注意execute也有略微的变化。
所以上面的命令在1.13的格式就应该变为这样
  1. /execute as @a[x_rotation=-37..-10,y_rotation=66..113] run say 输出
复制代码




很简单对吧,那么今天的教程就到这里,希望各位喜欢

2021.12 数据,可能有更多内容
前言


在1.13这个命令大洗地的版本下,我的命令是可以突破天际的!
大家好,我这人不太会说话,但我还是要来论坛丢一下人...


首先,有这么一个问题,如何判断玩家的朝向是否在某一个两点组成的竖直平面范围内(比如,指针是否指向挂画)


在1.13之前我们可以通过给予选择器参数rx,rxm,ryrym进而选中满足条件的玩家


玩家当前rxry按下F3能在下图蓝红框的位置找到
那么在确定好需要判断的范围后,把屏幕中间的十字指针移动到范围的左下角和右上角,记录rx和ry
然后把记录到的2个rx值,较小的数值为选择器里的rxm=&lt;数值&gt;,较大的数值为选择器里的rx=&lt;数值&gt;,ry同理



像这样,就成功了呢
当玩家的垂直旋转角度(rxm,rx)范围为-37~-10,且水平旋转角度(rym,ry)为66~113时,输出

代码:

  1. /execute @a[rxm=-37,rx=-10,rym=66,ry=113] ~ ~ ~ say 输出

但1.13的命令格式变了啊
原本的rx和rxm合并为x_rotation,ry和rym合并为y_rotation。注意execute也有略微的变化。
所以上面的命令在1.13的格式就应该变为这样

代码:

  1. /execute as @a[x_rotation=-37..-10,y_rotation=66..113] run say 输出



很简单对吧,那么今天的教程就到这里,希望各位喜欢

标准 &amp; 个人要求



才怪呢...转过头来瞧瞧你自己的样子
缩在一个角落里,像条咸鱼,躺在那里,一动不动的
这可不是我想要的结果呢...


回想下之前的做法
优点
●制作简单
●方便修改,调整


缺点
●局限性   只当玩家在预设好的坐标下,才能准确判断玩家的rx,ry是否在指定两点的范围内
●局限性   玩家所在的这个坐标还必须位于此两点范围的视觉中点。换句话说,这个范围必须两边对称,玩家站中间,才能准确判断rx ry
●局限性   还有些,一时想不到...


我的目标是玩家在场景中
玩家在任意一个合理的位置下都可以准确判断出其指针是否指向特定两点组成的平面竖直范围内
我们是有理想的人,当然要把原本简单的问题给复杂化啦
但不同的坐标看向指定的范围,rx,ry是有变化的,那接下来该怎么做呢?

确定方案


可能的方案
●通过生成对应玩家朝向motion的雪球/火焰弹/箭等动向实体。在指定范围内生成marker,用于检测其范围内是否存在此类动向实体
●通过自己套自己,往前移动执行坐标,检测玩家是否在指定的方块内
●通过自己套自己,往前移动执行坐标,检测玩家是否在指定的xyz坐标,r半径范围内
●通过自己套自己,往前移动执行坐标,检测玩家是否在指定的xyz,dxdydz坐标范围内
●两点定义一面,通过在左下角,右上角各生成一个marker,获取两点的rx,ry和玩家的rx,ry做对比


以上几个都是可行的,但是,
使用雪球/火球和我当前制作的存档里某些内容起冲突
^^^精度越高,每t运行的命令数就越多。降低精度则导致远距离不准确,甚至可能跳过检测区域。用递减处理一下的话应该可以,但是感觉要注意的东西反而会变多...


所以,我还是选择了最后一条方案,获取两点范围和玩家进行对比
两点确定一条线,也可以确定一个方形的面
大概的制作方向有了,那么我们进入下一步


这里顺便规范一下后文中几个常用词
指针,光标,十字标,游戏屏幕中间十字样子的东西,F3下则以3色线显示为xyz轴的正值方向
marker,用于做标记用的实体,一般使用盔甲架(AS)或药水云(AEC)
两点,或两点范围,两点组成的平面竖直范围(暂时不考虑斜面等情况),用marker代表这两点的位置
r[1],垂直旋转坐标,或rx,x_rotation。玩家视觉围绕其x轴(并非指世界坐标的x轴)作出旋转,变化为 90朝下 ~ 0水平 ~-90朝下
r[0],水平旋转坐标,或ry,y_rotation。玩家视觉围绕其y轴(并非指世界坐标的y轴,不过感觉上和y轴一样)作出旋转,变化为 0北 ~ 90西 ~ 180南 ~ -180南 ~ -90东~ 0北


如果总是分不清rx和ry的话
rx,r[1]是玩家视觉往上下移动
ry,r[0]是玩家视觉往左右移动


后面例子和讲解将以玩家当前面向北,GUI面向南的前提下进行
而后面所提到的三类marker,分别为
●两点,左下和右上。定义范围的两个点,对应玩家r[0]
●tan,用于计算 x/z
●上下两点,对应玩家r[1]

方案细化



两点思路,上图,两黑点为marker,面向玩家眼部,获取两点的r[0]和r[1],
并储存为分数,分数组成检测的范围,最后检测玩家的分数是否在此范围下。



然而这是不可行的。准确地说,这种办法不能获取到正确的r[1]。为了更好地理解为什么
见上图,两红点为marker
紫色区域为两点形成的正确检测范围。
橙线获取r[0]的范围。相同xz轴下,面向玩家的实体,其r[0]是一样的


但是,很明显代表r[1]范围的蓝线却出了问题,
因为相同xy/yz轴下,不同z/x轴的实体,r[1]并不相等
简单地说,图中左下角的r[1]不等同于右下角的r[1],上面两角同理


最终导致检测的范围从原本的紫色区域变为蓝线橙线组成的方形区域


这样,除非知道两点之间从左到右的角度变化关系式,只能另寻办法获得这两点marker的r[1]范围了
既然如此,在玩家当前的这个角度再生成上下两点marker,获取其r[1]范围,拿这个r[1]范围和玩家做对比,不就准了吗。


现在,把思路整理,在细化一下
在需要检测的位置,生成左下,右上。两点marker,获取r[0]范围
因为前提所处的情况,左下点的x和y轴较小,右上点的x和y轴较大,但两点的z轴相等
获取任意一点marker到玩家的z轴距离差
生成另一个marker得出玩家x轴和z轴的比例
x/z的比例 = tan(玩家角度) = x轴距离差 / z轴距离差
z轴距离差 * 比例 = x轴距离差


玩家x坐标 + x轴距离差 = 玩家视觉和两点面相交的x坐标位置
玩家z坐标 + z轴距离差 = 玩家视觉和两点面相交的z坐标位置
也就是算出玩家当前角度两点形成的竖直范围交点的x,z坐标


在x,z坐标位置,生成上下两点marker,而这次的marker,用于获取r[1]范围
当玩家玩家指向两点的r[0]范围内,和后来生成的上下两点的r[1]范围内时,输出

r[0]和r[1]的情况


以下两张图是,码指令前理清部分情况写出来的,参考用。
r[0]有个当marker的分数为0时的情况没考虑进去,因为发生的几率很小


m1为左边marker,m2为右边marker
m3为高位marker,m4为低位marker
P为玩家

如左上图的范围,得出一般情况下,玩家的r[0]角度只能为90~180或-180~-90,而左右marker则为-90~90
星号左边为当分数符合此情况时执行,右边为执行的检测命令,满足任意一条即使为处于左边的情况
因为游戏内r[0]变化的关系,所以右边的一条检测m1&lt;score&lt;m2要拆分为两条执行
所以要想检测r[0],需要执行3条检测
下面星号左边的&quot;unless m1&gt;0,m2&lt;0&quot;,实际为 &quot;if m1&gt;0,unless m2&lt;0&quot; 和 &quot;unless m1&gt;0,if m2&lt;0&quot; 两种情况
所以到最后要检测r[0],需要执行4条检测



相对而言,用一条就能检测到r[1],简单多了
使用data get获取marker的r[1]时,这里顺手乘一下负数,方便后面计算

命令 &amp; 少许注释


准备工作。
运行前,此mcfunction执行一次或标记于data\minecraft\tags\functions\load.json下

代码:

  1. #◆准备工作
  2. scoreboard objectives add entity_r0 dummy
  3. scoreboard objectives add entity_r1 dummy
  4. scoreboard objectives add entity_x dummy
  5. scoreboard objectives add entity_y dummy
  6. scoreboard objectives add entity_z dummy
  7. scoreboard objectives add x_over_z dummy
  8. #◆x_over_z用于储存 x轴和z轴的比例

  9. #◆部分常量貌似写的时候没用到
  10. scoreboard objectives add 18000 dummy
  11. scoreboard players set @p 18000 18000
  12. scoreboard objectives add n36000 dummy
  13. scoreboard players set @p n36000 -36000
  14. scoreboard objectives add n18000 dummy
  15. scoreboard players set @p n18000 -18000



获取基本数值,满足条件时执行检测。
此mcfunction高频或标记于data\minecraft\tags\functions\tick.json下

代码:

  1. #◆获取玩家坐标
  2. execute as @p store result score @s entity_x run data get entity @s Pos[0] 100
  3. execute as @p store result score @s entity_y run data get entity @s Pos[1] 100
  4. execute as @p store result score @s entity_z run data get entity @s Pos[2] 100

  5. #◆获取玩家Rotation
  6. #◆中间两条用于得出对应F3的玩家r[0]
  7. execute as @p store result score @s entity_r0 run data get entity @s Rotation[0] 100
  8. execute as @p if entity @s[scores={entity_r0=..-18000}] run scoreboard players operation @s entity_r0 -= @s n36000
  9. execute as @p if entity @s[scores={entity_r0=18000..}] run scoreboard players operation @s entity_r0 += @s n36000
  10. execute as @p store result score @s entity_r1 run data get entity @s Rotation[1] 100


  11. #◆排除,当玩家超过一定距离(或者说穿过GUI,到达GUI的后面),又或者是玩家角度为理论上不可能望向两点范围的情况。
  12. #◆以此免去无意义情况下的多余高频/检测
  13. #◆获取垂直距离(z距离差),用于下面的判断,后面用于计算
  14. execute as @e[tag=menu_north,tag=menu_ld] store result score @s entity_z run data get entity @s Pos[2] 100
  15. execute as @e[tag=menu_north,tag=menu_ld] run scoreboard players operation @s entity_z -= @p entity_z

  16. #◆范围条件检测
  17. execute unless entity @p[scores={entity_r0=-9000..9000}] if entity @e[tag=menu_north,tag=menu_ld,scores={entity_z=..0}] run function uinm:main/menu/north/body



#function uinm:main/menu/north/body

代码:

  1. #◆面向玩家
  2. execute as @e[tag=menu_north] at @s run teleport @s ~ ~ ~ facing entity @p eyes

  3. #◆获取menu角度,调整至可用于和玩家对比用
  4. execute as @e[tag=menu_north] store result score @s entity_r0 run data get entity @s Rotation[0] 100

  5. execute as @e[tag=menu_north,tag=!menu_process1,tag=!menu_process2,scores={entity_r0=0..}] run tag @s add menu_process1
  6. execute as @e[tag=menu_north,tag=!menu_process1,tag=!menu_process2,scores={entity_r0=..0}] run tag @s add menu_process2
  7. execute as @e[tag=menu_process1] run scoreboard players operation @s entity_r0 -= @p 18000
  8. execute as @e[tag=menu_process2] run scoreboard players operation @s entity_r0 += @p 18000
  9. tag @e remove menu_process1
  10. tag @e remove menu_process2

  11. #◆菜单按钮
  12. execute if entity @e[tag=menu1_1,tag=menu_ld] if entity @e[tag=menu1_1,tag=menu_ru] run function uinm:main/menu/north/1_1
  13. #execute if entity @e[tag=menu1_2,tag=menu_ld] if entity @e[tag=menu1_2,tag=menu_ru] run function uinm:main/menu/north/1_2
  14. #execute if entity @e[tag=menu1_3,tag=menu_ld] if entity @e[tag=menu1_3,tag=menu_ru] run function uinm:main/menu/north/1_3
  15. #...



#function uin:main/import/x_over_z
生成一个计算x/z用的marker

mc本身operation除法计算的原因(5/3=1,10/6=1,1/2=0,向下取整?...)
为保留精度,x需始终大于z,越大得出的结果越准确

代码:

  1. kill @e[tag=tan_scale]
  2. summon minecraft:area_effect_cloud 0.0 0.0 0.0 {Invulnerable:1b,Duration:2147483647,NoGravity:1b,Tags:["tan_scale"]}
  3. execute as @e[tag=tan_scale] at @s rotated as @p run teleport ^ ^ ^1

  4. execute as @e[tag=tan_scale] store result score @s entity_x run data get entity @s Pos[0] 100000000
  5. execute as @e[tag=tan_scale] store result score @s entity_z run data get entity @s Pos[2] 10000

  6. execute as @e[tag=tan_scale] run scoreboard players operation @s x_over_z = @s entity_x
  7. execute as @e[tag=tan_scale] run scoreboard players operation @s x_over_z /= @s entity_z



#function uinm:main/menu/north/1_1
当玩家r[0]范围为4种情况之一时,视为在1_1这个GUI的r[0]范围内,获得p_gui1_1
偷懒那部分为处理 距离差+玩家x,z坐标,获得上下marker的生成坐标
gui1_1为上下两点marker
最后,当玩家指针在r[0]和r[1]范围内时,执行particles命令

代码:

  1. #◆探测r[0]范围
  2. execute as @p if entity @e[tag=menu1_1,tag=menu_ld,scores={entity_r0=0..}] if entity @e[tag=menu1_1,tag=menu_ru,scores={entity_r0=..0}] if score @s entity_r0 >= @e[tag=menu1_1,tag=menu_ld,limit=1] entity_r0 if score @s entity_r0 matches ..18000 run tag @p add p_gui1_1
  3. execute as @p if entity @e[tag=menu1_1,tag=menu_ld,scores={entity_r0=0..}] if entity @e[tag=menu1_1,tag=menu_ru,scores={entity_r0=..0}] if score @s entity_r0 <= @e[tag=menu1_1,tag=menu_ru,limit=1] entity_r0 if score @s entity_r0 matches -18000.. run tag @p add p_gui1_1

  4. execute as @p if entity @e[tag=menu1_1,tag=menu_ld,scores={entity_r0=0..}] unless entity @e[tag=menu1_1,tag=menu_ru,scores={entity_r0=..0}] if score @s entity_r0 >= @e[tag=menu1_1,tag=menu_ld,limit=1] entity_r0 if score @s entity_r0 <= @e[tag=menu1_1,tag=menu_ru,limit=1] entity_r0 run tag @p add p_gui1_1
  5. execute as @p unless entity @e[tag=menu1_1,tag=menu_ld,scores={entity_r0=0..}] if entity @e[tag=menu1_1,tag=menu_ru,scores={entity_r0=..0}] if score @s entity_r0 >= @e[tag=menu1_1,tag=menu_ld,limit=1] entity_r0 if score @s entity_r0 <= @e[tag=menu1_1,tag=menu_ru,limit=1] entity_r0 run tag @p add p_gui1_1

  6. #◆获取玩家指向^^^的 "x/z" 值
  7. execute if entity @p[tag=p_gui1_1] run function uin:main/import/x_over_z

  8. #◆location marker 垂线(z距离值)*tan比例=x距离值
  9. kill @e[tag=menu1_1_loca]
  10. execute as @p[tag=p_gui1_1] at @s run summon minecraft:area_effect_cloud ~ ~ ~ {Invulnerable:1b,Duration:2147483647,NoGravity:1b,Tags:["menu1_1_loca"]}

  11. execute as @e[tag=menu1_1_loca] run scoreboard players operation @s entity_x = @e[tag=menu1_1,tag=menu_ld,limit=1] entity_z
  12. execute as @e[tag=menu1_1_loca] run scoreboard players operation @s entity_x *= @e[tag=tan_scale,limit=1] x_over_z
  13. #这里偷懒,可以建多一个scoreboard 把距离x调整比例,和玩家坐标x相加,最后再改变location的x坐标...
  14. execute as @e[tag=menu1_1_loca] store result entity @s Pos[0] double 0.000001 run scoreboard players get @s entity_x
  15. execute as @e[tag=menu1_1_loca] store result score @s entity_x run data get entity @s Pos[0] 100
  16. execute as @e[tag=menu1_1_loca] run scoreboard players operation @s entity_x += @p entity_x
  17. execute as @e[tag=menu1_1_loca] store result entity @s Pos[0] double 0.01 run scoreboard players get @s entity_x

  18. #◆生成当前玩家角度的上下两点,探测r[1]范围
  19. kill @e[tag=gui1_1]

  20. execute as @e[tag=menu1_1_loca] at @s run summon minecraft:area_effect_cloud ~ ~ ~ {Tags:["gui_up","gui1_1"]}
  21. execute as @e[tag=menu1_1_loca] at @s run summon minecraft:area_effect_cloud ~ ~ ~ {Tags:["gui_down","gui1_1"]}

  22. execute as @e[tag=menu1_1] store result score @s entity_y run data get entity @s Pos[1] 100
  23. execute as @e[tag=menu1_1] store result score @s entity_z run data get entity @s Pos[2] 100

  24. execute as @e[tag=gui1_1,tag=gui_up] store result entity @s Pos[1] double 0.01 run scoreboard players get @e[tag=menu_ru,tag=menu1_1,limit=1] entity_y
  25. execute as @e[tag=gui1_1,tag=gui_down] store result entity @s Pos[1] double 0.01 run scoreboard players get @e[tag=menu_ld,tag=menu1_1,limit=1] entity_y
  26. execute as @e[tag=gui1_1] store result entity @s Pos[2] double 0.01 run scoreboard players get @e[tag=menu_ru,tag=menu1_1,limit=1] entity_z

  27. execute as @e[tag=gui1_1] at @s run teleport @s ~ ~ ~ facing entity @p eyes
  28. execute as @e[tag=gui1_1] store result score @s entity_r1 run data get entity @s Rotation[1] -100

  29. #◆r[0],r[1]范围内,输出
  30. execute as @p[tag=p_gui1_1] if score @s entity_r1 >= @e[tag=gui_up,tag=gui1_1,limit=1] entity_r1 if score @s entity_r1 <= @e[tag=gui_down,tag=gui1_1,limit=1] entity_r1 run execute as @p at @s anchored eyes positioned ^ ^ ^3 run particle minecraft:flame ~ ~ ~ 0 0 0 0 0 force

  31. #◆
  32. tag @p remove p_gui1_1
还有一条可以不需要的低频,防止游戏内的AEC运行3年之后消失...

代码:

  1. #◆ 保持存在,应切换至低频
  2. execute as @e[tag=uin_menu_north] run data merge entity @s {Age:41591}



最后是生成两点marker的命令
左下角的xy轴需小于右上角的xy轴,z轴必须相等

代码:

  1. #◆
  2. #summon minecraft:area_effect_cloud -2.0 5.0 2.0 {Duration:2147483647,NoGravity:1b,Tags:["menu_north","menu1_1","menu_ld"]}
  3. #summon minecraft:area_effect_cloud 1.0 7.0 2.0 {Duration:2147483647,NoGravity:1b,Tags:["menu_north","menu1_1","menu_ru"]}



效果图

绿粒子为两点范围,判断r[0]
雪球位置的marker,判断r[1]
初看雪球的位置略奇怪,不和绿色两点位于同一水平位置
其实,这个点位于雪球碰撞箱的最底部中间的一点,而不是雪球碰撞箱的中心点,所以位置是准确的
在r[0]和r[1]范围内时,执行红色粒子

结尾 &amp; 应用


在生成的上下两点,使用其和两点范围marker的距离差做点额外计算,做个其他形状的GUI应该也是可行的
把GUI做成跟着玩家走也不是问题...


在说回方案选择的时候,当初是想过用实体当范围检测,
感觉是太麻烦了,相比...这个写完一套后换一个词就能用存档就不发了,东一块西一块的...反正需要的指令都写在前面那页了
正好有几天假,看看有没有时间做个任意竖直角度的出来
算是离自己的计划又近了一小步
后来又用点心写了小半个GUI...


用心的话这GUI是能弄的很好看的
过渡动画,悬停反应,按键检测


啊对了,整篇只是关于两点的设立和判断而已,
显示内容什么的当然还是要自己去做了...





感谢以下两个大佬的大力...帮助
@pineapple_@pca006132



wzz0116
我觉得离着在mc里玩mc不远了

⊙v⊙
是呢在mc里玩mc.....
然后刚才跑去做了个存放物品用的简陋背包

削皮弹
参见巨佬

Java_command
不得不说666,从来没想过。
如果能把左键右键探测放到里面就更好了。
我记得有用矿车做GUI的。

BlackCB.
可以弄个什么用眼睛控制鼠标[雾]

BlackCB.
我的意思是在mc里搞个类似电脑的东西然后用玩家视角追踪鼠标

x小奇
说真的,看得我眼花缭乱,大佬,缺不缺腿部挂件

白色的麋鹿
我不信只有我看不懂,老实说是真的厉害

SCAME233
大佬就是大佬,说的话搞得我晕头转向。。。

bitch_meow
这个拿来做地图选单或者传送简直就是神器,楼主的技术不是一般的厉害。

RF_Tar_Railt
额。。。差不多就是把玩家的朝向数据给一个当作gui的实体然后让其能够随着玩家指针指向的改变来移动?
其实用个仿gui的材质+盔甲架应该就可以了……
没试过不知道

⊙v⊙
RF_Tar_Railt 发表于 2018-9-25 05:22
额。。。差不多就是把玩家的朝向数据给一个当作gui的实体然后让其能够随着玩家指针指向的改变来移动?
其实 ...

想过,不可以。比如需要十分精细或者十分大的时候,就成问题了...

第一页 上一页 下一页 最后一页