我如何检测玩家是否在看另一个实体?

时间:2015-07-07 02:53:19

标签: bukkit

我有一名球员,当然能够以矢量形式抓住球员面对的方向。

使用此向量,我需要计算玩家是否正在查看x个区块内的实体以及是否有“咒语”命中它。如果实体前面有任何东西,我还需要考虑。

到目前为止,我的思维过程已经到了第一位,获得了播放器x块中所有实体的列表。但从那里,我不知道。

任何帮助我走向正确方向的帮助都会很棒。

2 个答案:

答案 0 :(得分:3)

我编辑的代码更精确,更简单,不会通过块。但你的方法很好:D

public static Entity getNearestEntityInSight(Player player, int range) {
    ArrayList<Entity> entities = (ArrayList<Entity>) player.getNearbyEntities(range, range, range);
    ArrayList<Block> sightBlock = (ArrayList<Block>) player.getLineOfSight( (Set<Material>) null, range);
    ArrayList<Location> sight = new ArrayList<Location>();
    for (int i = 0;i<sightBlock.size();i++)
        sight.add(sightBlock.get(i).getLocation());
    for (int i = 0;i<sight.size();i++) {
        for (int k = 0;k<entities.size();k++) {
            if (Math.abs(entities.get(k).getLocation().getX()-sight.get(i).getX())<1.3) {
                if (Math.abs(entities.get(k).getLocation().getY()-sight.get(i).getY())<1.5) {
                    if (Math.abs(entities.get(k).getLocation().getZ()-sight.get(i).getZ())<1.3) {
                        return entities.get(k);
                    }
                }
            }
        }
    }
    return null; //Return null/nothing if no entity was found
}

答案 1 :(得分:2)

在我看来,让所有实体都在玩家的某个范围内的思维过程是一个良好的开端!下面是一个方法示例,该方法使用玩家视线(光线跟踪)中的块来查找最近的未被遮挡的实体。

public static Entity getNearestEntityInSight(Player player, int range) {
    List<Entity> entities = player.getNearbyEntities(range, range, range); //Get the entities within range
    Iterator<Entity> iterator = entities.iterator(); //Create an iterator
    while (iterator.hasNext()) {
        Entity next = iterator.next(); //Get the next entity in the iterator
        if (!(next instanceof LivingEntity) || next == player) { //If the entity is not a living entity or the player itself, remove it from the list
            iterator.remove();
        }
    }
    List<Block> sight = player.getLineOfSight((Set) null, range); //Get the blocks in the player's line of sight (the Set is null to not ignore any blocks)
    for (Block block : sight) { //For each block in the list
        if (block.getType() != Material.AIR) { //If the block is not air -> obstruction reached, exit loop/seach
            break;
        }
        Location low = block.getLocation(); //Lower corner of the block
        Location high = low.clone().add(1, 1, 1); //Higher corner of the block
        AxisAlignedBB blockBoundingBox = AxisAlignedBB.a(low.getX(), low.getY(), low.getZ(), high.getX(), high.getY(), high.getZ()); //The bounding or collision box of the block
        for (Entity entity : entities) { //For every living entity in the player's range
            //If the entity is truly close enough and the bounding box of the block (1x1x1 box) intersects with the entity's bounding box, return it
            if (entity.getLocation().distance(player.getEyeLocation()) <= range && ((CraftEntity) entity).getHandle().getBoundingBox().b(blockBoundingBox)) {
                return entity;
            }
        }
    }
    return null; //Return null/nothing if no entity was found
}

注意:使用上述方法时,需要考虑一些事项/潜在的错误:

  1. 检查块的边界框是否与实体的边界框相交的方式意味着玩家可能实际上并不直接查看实体,而只是在块的一部分。这种接近检查可以以各种不同的方式完成(例如:检查实体位置是否在块的位置附近),但大多数不一定更精确。为了获得更准确的结果,您需要制作自己的光线轨迹,扫描较小的距离,以确保它不会“错过”任何实体,并检查播放器是否真正直接看实体。您希望它越精确,它将花费更多的资源/时间。检查这种方法是否足够精确。
  2. 查看附近实体的循环选择它找到的符合条件的第一个实体,这意味着如果两个或三个实体聚集在一起并且靠近,它可能不会选择“真实”最接近的实体(这可能是但需要更多检查,但可能并不那么重要。)
  3. 检查实体是否被遮挡只查找不是空气的块,因此不考虑透明块或具有小碰撞盒的块(例如,通过某些楼梯查看可能会返回null,即使您在技术上可能看到实体)。再一次,这通常没有太大的区别,我认为纠正它是相当棘手的。