Java 如何在布雷艇的圆形或椭圆形产卵区域中获得随机离散点?

Java 如何在布雷艇的圆形或椭圆形产卵区域中获得随机离散点?,java,minecraft,bukkit,Java,Minecraft,Bukkit,在为Minecraft编写了第一个随机繁殖插件之后,我立即想升级到允许圆形和椭球形繁殖区域作为有限繁殖区域来选择随机点 得到给定范围内的两个随机数,然后将它们四舍五入到最接近的整数,可以有效地在笛卡尔平面上生成一个矩形区域,每个单元都有离散点 看起来是这样的: // in Util.java // get a random whole number in range public static int getRandomNumber(int min, int max) { return

在为Minecraft编写了第一个随机繁殖插件之后,我立即想升级到允许圆形和椭球形繁殖区域作为有限繁殖区域来选择随机点

得到给定范围内的两个随机数,然后将它们四舍五入到最接近的整数,可以有效地在笛卡尔平面上生成一个矩形区域,每个单元都有离散点

看起来是这样的:

// in Util.java
// get a random whole number in range
public static int getRandomNumber(int min, int max) {
    return (int) ((Math.random() * (max - min)) + min);
}

// in the class that controls spawning
// get random x, z co-coordinates within range; refer to the *center* of blocks
double tryLocation_x = Math.rint(Util.getRandomNumber((int)min_x, (int)max_x)) + 0.5;
double tryLocation_z = Math.rint(Util.getRandomNumber((int)min_z, (int)max_z)) + 0.5;
但如何将有效椭球面积作为这些离散点的限制范围进行积分

我们需要添加一些东西,使我们能够忽略将出现在由
半径X,半径Z
定义的椭圆外的随机生成的数字。这是因为如上所述,以这种方式生成的坐标会生成有效离散点的有效矩形区域

经过大量研究和询问,我终于找到了一个简单的解决方案,相对于常规矩形繁殖区域,它不会显著影响性能


让我解释一下。

对于我来说,这个解决方案绝对需要的最困难的信息是:

public static int isInEllipse(int h, int k, int x, int y, int a, int b) {
    // h, k are center point | x, y are co-ords to check | a, b are ellipse radii
    int p = ((int)Math.pow((x - h), 2) / (int)Math.pow(a, 2))
            + ((int)Math.pow((y - k), 2) / (int)Math.pow(b, 2));

    return p;
}
椭圆由其两个半径定义;短半径和长半径。然而,正如前面所说,这两个随机生成的数字可以在椭圆周长的外部、内部以及顶部生成离散点

如果坐标在椭圆内,上述方法将返回小于1的值,如果坐标在圆周上,则返回小于1的值。否则它们在椭圆之外


现在我们有了一种方法来检查随机坐标在定义的椭圆中的有效性。 让我们开始工作吧

// get random x, z co-coordinates within range; refer to the *center* of blocks
double tryLocation_x = Math.rint(Util.getRandomNumber((int)radius_X*-1, (int)radius_X)) + 0.5;
double tryLocation_z = Math.rint(Util.getRandomNumber((int)radius_Z*-1, (int)radius_Z)) + 0.5;
int ellipseCheck = Util.isInEllipse(0, 0, (int)tryLocation_x, (int)tryLocation_z, (int)radius_X, (int)radius_Z);
好的,太好了。现在我们有了一种创建随机坐标的方法,然后检查它们是否在定义的椭圆区域内

这样,我们可以继续循环此检查,直到找到有效的坐标:

final double spawnLoc_x;
final double spawnLoc_z;

boolean isValidRespawn = false;
while (!isValidRespawn) {
    double tryLocation_x = Math.rint(Util.getRandomNumber((int)radius_X*-1, (int)radius_X)) + 0.5;
    double tryLocation_z = Math.rint(Util.getRandomNumber((int)radius_Z*-1, (int)radius_Z)) + 0.5;
    int ellipseCheck = Util.isInEllipse(0, 0, (int)tryLocation_x, (int)tryLocation_z, (int)radius_X, (int)radius_Z);
    
    if (ellipseCheck > 1) continue;
    else isValidRespawn = true;

    spawnLoc_x = tryLocation_x;
    spawnLoc_z = tryLocation_z;
}
你现在可以用你从这里得到的坐标来改变玩家的。至于Y值,可以使用来保持简单

我花了很多时间寻找这个答案。我希望这篇文章能帮助很多peep找到这个解决方案。干杯

参考: