簡體   English   中英

(Java) 矢量問題 - 檢查怪物是否在 3 個矢量內

[英](Java) Vector problems - Check if a monster is inside 3 Vectors

目前,除了矢量和檢查生物是否在實際三角形內之外,我擁有所有需要的工具。 如果您想了解更多詳細信息,請查看所附圖片。 別擔心圓圈,我已經知道了。 一張圖片簡要說明我希望代碼做什么以及我希望它如何工作

目前我的代碼如下所示:

public void cleaveCone(Player damager, LivingEntity victim, int level) {
    for(Entity lentity : damager.getNearbyEntities(3, 2, 3)) {
        if(!(lentity instanceof LivingEntity)) continue;
        LivingEntity entity = (LivingEntity) lentity;
    }
}

目前我需要三角形的 3 個向量,我需要檢查它們是否在三角形內,圓圈已經被覆蓋,在代碼中,僵屍是實體,玩家是破壞者。

要獲得三角形的三個坐標或頂點,您可以使用一些三角學和玩家的yaw 根據您的圖像,三角形的一個頂點是玩家的Location 內部angle在該點的三角形和一個的length ,其限定了三角形從播放器突出的兩側多久是,定義整個三角形。 定義這兩個值后,我們就可以找到三角形剩余兩個頂點的坐標。 這是一個粗略的草圖:

在此處輸入圖片說明

如何獲取兩個頂點的Location的示例:

double angle = 90; // An example angle of 90 degrees
double length = 5; // An example length of 5

Location v1 = player.getLocation(); // The first vertex of the triangle, the player's location

double yaw = v1.getYaw(); // The player's yaw (in degrees) between 0º and 360º

World world = player.getWorld(); // The player's world

Location v2 = new Location(world, (-Math.sin(Math.toRadians(yaw - (angle / 2))) * distance) + v1.getX(), 0, (Math.cos(Math.toRadians(yaw - (angle / 2))) * distance) + v1.getZ()); // The second vertex
Location v3 = new Location(world, (-Math.sin(Math.toRadians(yaw + (angle / 2))) * distance) + v1.getX(), 0, (Math.cos(Math.toRadians(yaw + (angle / 2))) * distance) + v1.getZ()); // The third vertex

以弧度為單位的角度的負正弦用於 X 坐標,而以弧度為單位的角度的余弦用於 Z 坐標。

我在 Minecraft 中使用了一些粒子來可視化三角形的線條,這個三角形的長度為 5,角度為 90 度:

在此處輸入圖片說明

您可以用來檢查一個點是否在二維三角形內的一種方法被發布為該問題的答案,並使用重心坐標。 這是一個適用於 Bukkit/Spigot 的示例方法。

// v1, v2 and v3 are the vertices of the triangle, in no specific order
// The Y coordinates are ignored (two dimensional)
public static boolean isLocationInTriangle(Location location, Location v1, Location v2, Location v3) {
    // Bunch of math...
    double a = 0.5 * (-v2.getZ() * v3.getX() + v1.getZ() * (-v2.getX() + v3.getX()) + v1.getX() * (v2.getZ() - v3.getZ()) + v2.getX() * v3.getZ());
    int sign = a < 0 ? -1 : 1;
    double s = (v1.getZ() * v3.getX() - v1.getX() * v3.getZ() + (v3.getZ() - v1.getZ()) * location.getX() + (v1.getX() - v3.getX()) * location.getZ()) * sign;
    double t = (v1.getX() * v2.getZ() - v1.getZ() * v2.getX() + (v1.getZ() - v2.getZ()) * location.getX() + (v2.getX() - v1.getX()) * location.getZ()) * sign;

    return s > 0 && t > 0 && (s + t) < 2 * a * sign;
}

我用這個做了一些測試,它似乎工作得很好。

您可以在您的方法中使用它,如下所示:

List<Entity> nearbyEntities = player.getNearbyEntities(8, 2, 8); // Get entities within 16x4x16 box centered around player
for (Entity entity : nearbyEntities) { // For each Entity found
    if (entity instanceof LivingEntity) { // If the Entity is an instance of a LivingEntity
        LivingEntity living = (LivingEntity) entity; // Cast
        if (isLocationInTriangle(living.getLocation(), player.getLocation(), v2, v3)) { // If the LivingEntity is inside the triangle
            living.damage(6); // Damage the entity (just as an example)
        }
    }
}

請注意,即使IsLocationInTriangle方法忽略 Y 坐標或高度(因為它是二維檢查), getNearbyEntities方法getNearbyEntities查找框內的實體,在此示例中,框的高度為 4 個塊,中心位於玩家的位置。 因此,玩家上方或下方超過 2 個方塊的實體將不會被檢查。

或者,一旦您擁有三角形v1v2v3的三個坐標,您當然也可以使用它們來創建像Joop提到的 JavaFX Polygon並使用其contains方法檢查實體是否在三角形內,而不是使用重心坐標法。

制作一個多邊形並檢查它。 更正:使用 JavaFX Polygon - 雙點。

更底層:有三個向量a -> b -> c -> a表示三角形,並檢查點向量的 in 乘積是否都是正數或諸如此類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM