Java Spigot 设置 vector 相对于玩家位置的方向

标签 java vector bukkit spigot

我对正确的 vector 对齐有疑问。我想得到一个指向与玩家相同方向的 vector ,但 Y 值为 0。关键是,无论玩家的垂直和水平旋转, vector 的 Y 值为 0。 vector 始终应该指向水平(值为 0),但保持玩家旋转的方向。

这张图是侧面的情况。红线代表玩家的观看方向(上 - 下)的示例,绿线代表我想要实现的效果。无论玩家朝哪个方向看,向上或向下,绿线都保持不变:

Side view

这里,反过来,我已经从顶部展示了这种情况。红线是玩家的观看方向(左-右),绿线是我想要达到的效果。如您所见,玩家在此轴上的旋转设置我的 vector 完全相同。

View from above

我能够编写一段代码,但它的行为不正确:随着玩家向上或向下转动,Y 轴变得越来越高。我不知道为什么:

Vector playerDirection = player.getLocation().getDirection();

Vector vector = new Vector(playerDirection.getX(), 0, playerDirection.getZ()).normalize().multiply(3);

如何正确操作?

最佳答案

tl;博士:

Vector vector = new Vector(-1 * Math.sin(Math.toRadians(player.getLocation().getYaw())), 0, Math.cos(Math.toRadians(player.getLocation().getYaw())));

您缺少基于玩家注视位置创建新 Vector 的基本原则。我不太了解它的数学,但我可以和那些在几何方面比我好的人的数学混在一起。

因此,让我们尝试减少您定义的 Vector 变量的数量。快速浏览一下 Location 的来源,我们实际上可以直接创建您的 Vector 以避免定义多个。

public Vector getDirection() {
    Vector vector = new Vector();

    double rotX = this.getYaw();
    double rotY = this.getPitch();

    vector.setY(-Math.sin(Math.toRadians(rotY)));

    double xz = Math.cos(Math.toRadians(rotY));

    vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
    vector.setZ(xz * Math.cos(Math.toRadians(rotX)));

    return vector;
}

如您所见,玩家的俯仰和偏航不是 1:1 的关系。不知道为什么,但让我们重新调整他们的逻辑。

下面是我们将如何做到这一点:

public Vector getVectorForAdixe(Location playerLoc) {
    Vector vector = new Vector();
    
    double rotX = playerLoc.getYaw();
    double rotY = 0; // this is the important change from above

    // Original Code:
    // vector.setY(-Math.sin(Math.toRadians(rotY)));
    // Always resolves to 0, so just do that
    vector.setY(0);

    // Original Code:
    // double xz = Math.cos(Math.toRadians(rotY));
    // Always resolves to 1, so just do that
    double xz = 1;

    vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
    vector.setZ(xz * Math.cos(Math.toRadians(rotX)));

    return vector;

不错!现在,稍微清理一下以删除那些注释和不必要的变量:

public Vector getVectorForAdixe(Location playerLoc) {
    Vector vector = new Vector();
    
    double rotX = playerLoc.getYaw();

    vector.setY(0);

    vector.setX(-1 * Math.sin(Math.toRadians(rotX)));
    vector.setZ(Math.cos(Math.toRadians(rotX)));

    return vector;

为什么这个数学会这样?不知道!但这几乎肯定对你有用。如果你真的想保持它原来的样子,甚至可以内联它:

Vector vector = new Vector(-1 * Math.sin(Math.toRadians(player.getLocation().getYaw())), 0, Math.cos(Math.toRadians(player.getLocation().getYaw())));

结束语,如果你想从 vector 中获得俯仰/偏航,代码在这里:https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/Location.java#310

关于Java Spigot 设置 vector 相对于玩家位置的方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74185528/

相关文章:

java - ANTLR 没有为 Scala 语法提供正确的输出标记

Java JSON 奇怪的错误

java - 我尝试编写我的第一个 Bukkit 插件,但无法安装它

java - 如何从 JList 中的组件获取文本?

java - 如何在 Debug模式下运行配置单元

c++ - 如何初始化不同对象指针的 vector ?

c++ - 如何从 C++ Vector 中删除尾随 0

r - 将不同大小的命名向量合并到数据框中

java - 有没有办法在没有 AsyncPlayerChatEvent 的情况下捕获玩家聊天输入?

java - MySQL 和 SQLite 类