自定义NPC脚本论坛

搜索
查看: 265|回复: 0

[All]坐标->横纵视角<->三维视角||是否能看到实体

[复制链接]

7

主题

8

帖子

195

积分

Lv.4 地上月影

Rank: 6Rank: 6

积分
195

论坛元老勋章

QQ
发表于 2021-8-17 23:55:50 | 显示全部楼层 |阅读模式
本帖最后由 咸鱼羊 于 2021-11-28 00:19 编辑

缝缝补补又一年,修好了一些bug,并加了个SamePos来支持1.7,大概行吧?
主要是算法上的问题和适配MC角度的调试
介绍一下作用罢,众所周知MC中有着横向角度和纵向角度。
这个函数的作用便是获取这样的正视角度。
1.12的NPC有提供获取实体横纵视角的方法。
ps:Vector我进行了精度的压缩。
如果有Bug欢迎指出,尽力修改(尽力)
var Math = Java.type("java.lang.Math");
/*function interact(e){
        e.player.message(e.player.getRotation()+','+e.player.getPitch());
        e.player.message(getLookSightToAnother(e.player,e.target).x+","+getLookSightToAnother(e.player,e.target).y)
        e.player.message(getLookSightToAnother(e.player,e.target).getVector().getLookSight().x+","+getLookSightToAnother(e.player,e.target).getVector().getLookSight().y)
        e.player.message(getLookSightToAnother(e.player,e.target).getVector().x+","+getLookSightToAnother(e.player,e.target).getVector().y+","+getLookSightToAnother(e.player,e.target).getVector().z)
        e.player.message(canSeePlace(e.target,e.player,e.target.getRotation(),e.target.getPitch()))
}
*调试部分
*/
/**
 * SamePos 作用相同的坐标,用于兼容1.7版本
 * double x,y,z 坐标
 */
function SamePos(x,y,z){
        this.x = x;
        this.y = y;
        this.z = z;
        this.getX = function(){
                return this.x;
        };
        this.getY = function(){
                return this.y;
        };
        this.getZ = function(){
                return this.z;
        };
}
/**
 * LookSight 视觉方向
 * double x 横向视角,以z轴正方向为0,向x轴负方向渐增(0~360)
 * double y 垂直视角,以水平方向为0,向y轴正方向渐减(-90~90)
 */
function LookSight(x,y){
        this.x = x;
        this.y = y;
        this.getVector = function(){
                var tempRX = Math.toRadians(this.x);
                var tempRY = Math.toRadians(-this.y-90);
                var rate = Math.sqrt(1-Math.cos(tempRY)*Math.cos(tempRY));
                return (new LookSightVector(-Math.sin(tempRX)*rate,Math.cos(tempRY),Math.cos(tempRX)*rate));
        }
}
/**
 * LookSightVector 三维向量(以前进距离一为单位)
 * double x,y,z 对于坐标轴的向量
 */
function LookSightVector(x,y,z){
        this.x = (parseInt(x*10000))/10000;
        this.y = (parseInt(y*10000))/10000;
        this.z = (parseInt(z*10000))/10000;
        this.getLookSight = function(){
                return getLookSightToAnother(new SamePos(0,0,0),new SamePos(this.x*100000,this.y*100000,this.z*100000));
        }
}
/**
 * getLookSightToAnother 获取一个实体看向另一个实体的视觉角度
 * SamePos/IEntity/IPos from 观察者
 * SamePos/IEntity/IPos target 被观察者
 * return LookSight 一个实体看向另一个实体的视觉角度
 */
function getLookSightToAnother(from,target){
        var x1 = from.getX();
        var y1 = from.getY();
        var z1 = from.getZ();
        var x2 = target.getX()-x1;
        var y2 = target.getY()-y1;
        var z2 = target.getZ()-z1;
        var d = Math.sqrt(Math.abs(x2)*Math.abs(x2)+Math.abs(z2)*Math.abs(z2));
        var xQuadrant = getQuadrant(x2,z2);
        var yQuadrant = getQuadrant(z2,y2);
        var x;
        var y;
        switch(xQuadrant){
                case 1:
                        x = 270+Math.toDegrees(Math.asin(Math.abs(z2)/Math.sqrt(Math.abs(x2)*Math.abs(x2)+Math.abs(z2)*Math.abs(z2))));
                        break;
                case 2:
                        x = 90-Math.toDegrees(Math.asin(Math.abs(z2)/Math.sqrt(Math.abs(x2)*Math.abs(x2)+Math.abs(z2)*Math.abs(z2))));
                        break;
                case 3:
                        x = 90+Math.toDegrees(Math.asin(Math.abs(z2)/Math.sqrt(Math.abs(x2)*Math.abs(x2)+Math.abs(z2)*Math.abs(z2))));
                        break;
                case 4:
                        x = 270-Math.toDegrees(Math.asin(Math.abs(z2)/Math.sqrt(Math.abs(x2)*Math.abs(x2)+Math.abs(z2)*Math.abs(z2))));
                        break;
                case 5:
                        x = 0;
                        break;
                case 6:
                        x = 90;
                        break;
                case 7:
                        x = 180;
                        break;
                case 8:
                        x = 270;
                        break;
                case 9:
                        x = 0;
                        break;
        }
        switch(yQuadrant){
                case 1:
                        y = -90+Math.toDegrees(Math.acos(Math.abs(y2)/Math.sqrt(Math.abs(d)*Math.abs(d)+Math.abs(y2)*Math.abs(y2))));
                        break;
                case 2:
                        y = -90+Math.toDegrees(Math.acos(Math.abs(y2)/Math.sqrt(Math.abs(d)*Math.abs(d)+Math.abs(y2)*Math.abs(y2))));
                        break;
                case 3:
                        y = 90-Math.toDegrees(Math.acos(Math.abs(y2)/Math.sqrt(Math.abs(d)*Math.abs(d)+Math.abs(y2)*Math.abs(y2))));
                        break;
                case 4:
                        y = 90-Math.toDegrees(Math.acos(Math.abs(y2)/Math.sqrt(Math.abs(d)*Math.abs(d)+Math.abs(y2)*Math.abs(y2))));
                        break;
                case 5:
                        y = -90;
                        break;
                case 6:
                        y = 0;
                        break;
                case 7:
                        y = 90;
                        break;
                case 8:
                        y = 0;
                        break;
                case 9:
                        y = 0;
                        break;
        }
        return new LookSight(x,y);
}
/**
 * 获取坐标象限
 * 1~4对应象限
 * 5~8对应从y正半轴逆时针旋转的坐标轴
 * 9对应原点
 * ps:可以写的更简洁一些,只是我个人喜欢看这种排版
 */
function getQuadrant(x,y){
        if(x>0&&y>0)
                return 1;
        if(x<0&&y>0)
                return 2;
        if(x<0&&y<0)
                return 3;
        if(x>0&&y<0)
                return 4;
        if(x==0){
                if(y>0)
                        return 5;
                if(y<0)
                        return 7;
        }
        if(y==0){
                if(x<0)
                        return 6;
                if(x>0)
                        return 8;
        }
        if(x==0&&y==0)
                return 9;
        return -1;
}
/**
 * canSeePlace 从某处地方的视角能否看到另一处地方,建议配合canSeeEntity使用
 * SamePos/IEntity/IPos from 观察者
 * SamePos/IEntity/IPos target 被观察者
 * float rotation 来自观察者的横视角
 * float pitch 来自观察者的纵视角
 * return Boolean 是否看得到
 */
function canSeePlace(from,target,rotation,pitch){
        var toRotation = getLookSightToAnother(from,target).x;
        var toPitch = getLookSightToAnother(from,target).y;
        var xCan = false;
        var yCan = false;
        if(rotation < toRotation-75)
                rotation += 360;
        //*当视角范围过大,将rotation转换到第二周角
        if(rotation > toRotation+75)
                rotation -= 360;
        //*当视角范围过小,将rotation转换到负角第一周
        if(rotation <= toRotation+75&&rotation >= toRotation-75)
                xCan = true;
        if(pitch <= toPitch+60&&pitch >= toPitch-60)
                yCan = true;
        return (xCan&&yCan)? true:false;
}





评分

参与人数 1金粒 +20 收起 理由
早上 + 20 我超,大佬,牛逼!

查看全部评分

暂时没有想好
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表