• 游戏中战斗伤害范围攻击计算完整全版


    2017-03-24修正

    在以前版本中有一个错误之处需求修正,当坐标朝向是4,5,6的时候算出来的角度是错误的;导致这个时候攻击怪物的时候矩形,扇形都无法攻击;

    现在附录最新修正值

     1             case 4:
     2             case 5:
     3             case 6:
     4             case 7:
     5             case 8:
     6                 if (vz > 0) {
     7                     aTan = -90 - aTan;
     8                 } else {
     9                     aTan = 270 - aTan;
    10                 }
    11                 break;

    算出来的360°角度是错误的;

    正确的算法应该是这样的,

     1     /**
     2      * 根据0-90朝向角度,计算360°
     3      *
     4      * @param aTan 0 - 90 度
     5      * @param vector12
     6      * @param vx
     7      * @param vz
     8      * @return
     9      */
    10     public static double getATan360ByaTan(double aTan, int vector12, int vx, int vz) {
    11         switch (vector12) {
    12             case 0:
    13             case 1:
    14             case 2:
    15             case 3:
    16                 if (vector12 == 0 && vx < 0) {
    17                     aTan = 360 - aTan;
    18                 } else if (vector12 == 3 && vz < 0) {
    19                     aTan = 90 + aTan;
    20                 } else {
    21                     aTan = 90 - aTan;
    22                 }
    23                 break;
    24             case 4:
    25             case 5:
    26             case 6:
    27             case 7:
    28             case 8:
    29                 if (vx > 0) {
    30                     aTan = 90 + aTan;
    31                 } else {
    32                     aTan = 270 - aTan;
    33                 }
    34                 break;
    35             case 9:
    36             case 10:
    37             case 11:
    38                 if (vz > 0) {
    39                     aTan = 270 + aTan;
    40                 } else {
    41                     aTan = 270 - aTan;
    42                 }
    43                 break;
    44         }
    45         return aTan;
    46     }

    s

    前瞻回顾

    上一篇文章中《游戏里12方向,任意方向计算正前方矩形规则》中讲到,游戏12方向任意矩形规则计算问题,

    在后来测试发现这个算法其实有问题,因为算错矩形的时候ABCD,矩形四个坐标点必须是顺序坐标点,才能计算出任意点位

    是否在坐标中;如果方向变化,后坐标点其实位置就错误了,验证是否在矩形方案就错了;

    后来在网友帮助下,用射线算法,解决多边形问(本方案只能适用于凸多边形计算),坐标点是否在多边形内,不限于四边形。

    伤害范围划分

    在我做的游戏中,出现的计算伤害范围方式分为

    圆形,矩形(正方向或者长方形),三角形,扇形,

    当前图中所有A点(中心点或者场景对象坐标点)位当前需要计算的伤害范围起始点或者叫中心点,

    伤害范围圆形

    我相信圆形其实是做好计算的,那就是说只需要判断两个点位距离即可;

     1     /**
     2      * 计算两点距离
     3      *
     4      * @param x1
     5      * @param z1
     6      * @param x2
     7      * @param z2
     8      * @return
     9      */
    10     public static double distance(double x1, double z1, double x2, double z2) {
    11         x1 -= x2;
    12         z1 -= z2;
    13         return Math.sqrt(x1 * x1 + z1 * z1);
    14     }

    圆形计算方式,最为简单,连方向都不需要计算,

    游戏中360度方向计算

    我们需要一个类Vector表示当前攻击朝向

      1 package net.sz.game.engine.struct;
      2 
      3 import java.io.Serializable;
      4 import org.apache.log4j.Logger;
      5 
      6 /**
      7  * 表示朝向,位移量
      8  * <br>
      9  * author 失足程序员<br>
     10  * mail 492794628@qq.com<br>
     11  * phone 13882122019<br>
     12  */
     13 public class Vector implements Serializable {
     14 
     15     private static final Logger log = Logger.getLogger(Vector.class);
     16     private static final long serialVersionUID = -8252572890329345857L;
     17 
     18     /*表示当前朝向修正值 0 - 11 包含*/
     19     private int dir;
     20     /*表示未修正的x方向正负位移量 只能是1或者-1*/
     21     private int dir_x;
     22     /*表示未修正的y方向正负位移量 只能是1或者-1*/
     23     private int dir_y;
     24     /*表示未修正的z方向正负位移量 只能是1或者-1*/
     25     private int dir_z;
     26     /*在x轴方向位移 偏移量 >=0 */
     27     @Deprecated
     28     private double vrx;
     29     /*在z轴方向的位移 偏移量 >=0*/
     30     @Deprecated
     31     private double vrz;
     32     /*角 a 度数 0 - 90 包含*/
     33     private double atan;
     34     /*角 a 度数 0 ~ 360° 不包含 360*/
     35     private double atan360;
     36 
     37     public Vector() {
     38     }
     39 
     40     public Vector(Vector vector) {
     41         this.dir = vector.dir;
     42         this.dir_x = vector.dir_x;
     43         this.dir_y = vector.dir_y;
     44         this.dir_z = vector.dir_z;
     45         this.atan = vector.atan;
     46         this.atan360 = vector.atan360;
     47         this.vrx = vector.vrx;
     48         this.vrz = vector.vrz;
     49     }
     50 
     51     public void copyVector(Vector vector) {
     52         this.dir = vector.dir;
     53         this.dir_x = vector.dir_x;
     54         this.dir_y = vector.dir_y;
     55         this.dir_z = vector.dir_z;
     56         this.atan = vector.atan;
     57         this.atan360 = vector.atan360;
     58         this.vrx = vector.vrx;
     59         this.vrz = vector.vrz;
     60     }
     61 
     62     public int getDir() {
     63         return dir;
     64     }
     65 
     66     public void setDir(int dir) {
     67         this.dir = dir;
     68     }
     69 
     70     public int getDir_x() {
     71         return dir_x;
     72     }
     73 
     74     public void setDir_x(int dir_x) {
     75         this.dir_x = dir_x;
     76     }
     77 
     78     public int getDir_y() {
     79         return dir_y;
     80     }
     81 
     82     public void setDir_y(int dir_y) {
     83         this.dir_y = dir_y;
     84     }
     85 
     86     public int getDir_z() {
     87         return dir_z;
     88     }
     89 
     90     public void setDir_z(int dir_z) {
     91         this.dir_z = dir_z;
     92     }
     93 
     94     public double getAtan() {
     95         return atan;
     96     }
     97 
     98     public void setAtan(double atan) {
     99         this.atan = atan;
    100     }
    101 
    102     public double getAtan360() {
    103         return atan360;
    104     }
    105 
    106     public void setAtan360(double atan360) {
    107         this.atan360 = atan360;
    108     }
    109 
    110     @Deprecated
    111     public double getVrx() {
    112         return vrx;
    113     }
    114 
    115     @Deprecated
    116     public void setVrx(double vrx) {
    117         this.vrx = vrx;
    118     }
    119 
    120     @Deprecated
    121     public double getVrz() {
    122         return vrz;
    123     }
    124 
    125     @Deprecated
    126     public void setVrz(double vrz) {
    127         this.vrz = vrz;
    128     }
    129 
    130     @Override
    131     public String toString() {
    132         return "dir=" + dir + ", dir_x=" + dir_x + ", dir_z=" + dir_z + ", atan=" + atan + ", atan360=" + atan360;
    133     }
    134 
    135 }
    View Code

    然后如何获得朝向?

    1,通过连个坐标点获得朝向问题

    比如获取攻击对象锁定目标的释放技能,或者给定坐标点比如地面魔法施法类型

      1     /**
      2      * 获取两个坐标点的朝向
      3      *
      4      * @param x1
      5      * @param z1
      6      * @param x2
      7      * @param z2
      8      * @return
      9      */
     10     public static Vector getV12Vector(double x1, double z1, double x2, double z2) {
     11         Vector vector = new Vector();
     12         getV12Vector(vector, x1, z1, x2, z2);
     13         return vector;
     14     }
     15 
     16     /**
     17      * 获取两个坐标点的朝向
     18      *
     19      * @param vector
     20      * @param x1
     21      * @param z1
     22      * @param x2
     23      * @param z2
     24      */
     25     public static void getV12Vector(Vector vector, double x1, double z1, double x2, double z2) {
     26         vector.setAtan(getATan(x1, z1, x2, z2));
     27         vector.setDir(_getVector12(vector.getAtan(), x1, z1, x2, z2));
     28         vector.setDir_x(getVector12_x(x1, x2));
     29         vector.setDir_z(getVector12_z(z1, z2));
     30         vector.setAtan360(getATan360ByaTan(vector.getAtan(), vector.getDir(), vector.getDir_x(), vector.getDir_z()));
     31     }
     32 
     33     /**
     34      * 获取两个坐标点的朝向
     35      *
     36      * @param x1
     37      * @param z1
     38      * @param x2
     39      * @param z2
     40      * @return
     41      */
     42     public static double getATan360(double x1, double z1, double x2, double z2) {
     43         double aTan = getATan(x1, z1, x2, z2);
     44         byte _getVector12 = _getVector12(aTan, x1, z1, x2, z2);
     45         byte vector12_x = getVector12_x(x1, x2);
     46         byte vector12_z = getVector12_z(z1, z2);
     47         return getATan360ByaTan(aTan, _getVector12, vector12_x, vector12_z);
     48     }
     49 
     50     /**
     51      * 朝向是有修正,在修正下真实朝向,有正负区分
     52      *
     53      * @param z1
     54      * @param z2
     55      * @return
     56      */
     57     static public byte getVector12_z(double z1, double z2) {
     58         byte vector = 1;
     59         if (z1 > z2) {
     60             /*表示z方向递减*/
     61             vector = -1;
     62         }
     63         return vector;
     64     }
     65 
     66     /**
     67      * 朝向是有修正,在修正下真实朝向,有正负区分
     68      *
     69      * @param x1
     70      * @param x2
     71      * @return
     72      */
     73     static public byte getVector12_x(double x1, double x2) {
     74         byte vector = 1;
     75         if (x1 > x2) {
     76             /*表示x方向递减*/
     77             vector = -1;
     78         }
     79         return vector;
     80     }
     81 
     82     // <editor-fold defaultstate="collapsed" desc="位移是z轴 static float getV12Z(int vector, double offset)">
     83     public static double getV12ZD(double offset, double sin) {
     84         offset = Math.abs(offset);
     85         /* 三角函数计算器 */
     86         double sinr = (offset * Math.sin(Math.toRadians(sin)));
     87         /* 拿到保留4位小数计算器 */
     88         return BitUtil.getDouble4(sinr);
     89     }
     90     // </editor-fold>
     91 
     92     // <editor-fold defaultstate="collapsed" desc="位移时的X轴 static float getV12X(int vector, double offset)">
     93     public static double getV12XD(double offset, double cos) {
     94         offset = Math.abs(offset);
     95         /* 三角函数计算器 */
     96         double cosr = (offset * Math.cos(Math.toRadians(cos)));
     97         /* 拿到保留4位小数计算器 */
     98         return BitUtil.getDouble4(cosr);
     99     }
    100     // </editor-fold>.
    101 
    102     //<editor-fold defaultstate="collapsed" desc="获取角度 public static int getV12ATan(double x1, double y1, double x2, double y2)">
    103     public static double getATan(double x1, double z1, double x2, double z2) {
    104         //正切(tan)等于对边比邻边;tanA=a/b
    105         double a = 0;
    106         if (x1 == x2) {
    107             //x坐标相同的情况表示正上或者正下方移动
    108             a = 90;
    109         } else if (z1 != z2) {
    110             //三角函数的角度计算
    111             double ta = Math.abs(z1 - z2) / Math.abs(x1 - x2);
    112             double atan = Math.atan(ta);
    113             a = BitUtil.getDouble4(Math.toDegrees(atan));
    114         }
    115         return a;
    116     }
    117     //</editor-fold>
    View Code

    2,通过360度朝向计算坐标点问题;

    通过360°朝向是因为比如场景中的陷阱,炮塔之类的,默认配置初始朝向,可能不在改变朝向

    在计算360朝向的时候,我们游戏是和客户端u3d,模拟方式,在z轴正方向为360°起始点方向

    然后划分12方向;

      1     /**
      2      *
      3      * @param atan360
      4      * @return
      5      */
      6     public static Vector getVectorBy360Atan(double atan360) {
      7         Vector vector = new Vector();
      8         vector.setAtan360(atan360);
      9         setAtan360(vector);
     10         return vector;
     11     }
     12 
     13     /**
     14      * 根据360度算出各种朝向问题
     15      *
     16      * @param vector
     17      */
     18     public static void setAtan360(Vector vector) {
     19         double atan360 = vector.getAtan360();
     20         if (0 <= atan360 && atan360 <= 15) {
     21             vector.setDir(0);
     22             vector.setDir_x(1);
     23             vector.setDir_z(1);
     24             vector.setAtan(90 - atan360);
     25         } else if (15 < atan360 && atan360 <= 45) {
     26             vector.setDir(1);
     27             vector.setDir_x(1);
     28             vector.setDir_z(1);
     29             vector.setAtan(90 - atan360);
     30         } else if (45 < atan360 && atan360 <= 75) {
     31             vector.setDir(2);
     32             vector.setDir_x(1);
     33             vector.setDir_z(1);
     34             vector.setAtan(90 - atan360);
     35         } else if (75 < atan360 && atan360 <= 90) {
     36             vector.setDir(3);
     37             vector.setDir_x(1);
     38             vector.setDir_z(1);
     39             vector.setAtan(90 - atan360);
     40         } else if (90 < atan360 && atan360 <= 105) {
     41             vector.setDir(3);
     42             vector.setDir_x(1);
     43             vector.setDir_z(-1);
     44             vector.setAtan(atan360 - 90);
     45         } else if (105 < atan360 && atan360 <= 135) {
     46             vector.setDir(4);
     47             vector.setDir_x(1);
     48             vector.setDir_z(-1);
     49             vector.setAtan(atan360 - 90);
     50         } else if (135 < atan360 && atan360 <= 165) {
     51             vector.setDir(5);
     52             vector.setDir_x(1);
     53             vector.setDir_z(-1);
     54             vector.setAtan(atan360 - 90);
     55         } else if (165 < atan360 && atan360 <= 180) {
     56             vector.setDir(6);
     57             vector.setDir_x(1);
     58             vector.setDir_z(-1);
     59             vector.setAtan(atan360 - 90);
     60         } else if (180 < atan360 && atan360 <= 195) {
     61             vector.setDir(6);
     62             vector.setDir_x(-1);
     63             vector.setDir_z(-1);
     64             vector.setAtan(270 - atan360);
     65         } else if (195 < atan360 && atan360 <= 225) {
     66             vector.setDir(7);
     67             vector.setDir_x(-1);
     68             vector.setDir_z(-1);
     69             vector.setAtan(270 - atan360);
     70         } else if (225 < atan360 && atan360 <= 255) {
     71             vector.setDir(8);
     72             vector.setDir_x(-1);
     73             vector.setDir_z(-1);
     74             vector.setAtan(270 - atan360);
     75         } else if (255 < atan360 && atan360 <= 270) {
     76             vector.setDir(9);
     77             vector.setDir_x(-1);
     78             vector.setDir_z(1);
     79             vector.setAtan(270 - atan360);
     80         } else if (270 < atan360 && atan360 <= 285) {
     81             vector.setDir(9);
     82             vector.setDir_x(-1);
     83             vector.setDir_z(1);
     84             vector.setAtan(atan360 - 270);
     85         } else if (285 < atan360 && atan360 <= 315) {
     86             vector.setDir(10);
     87             vector.setDir_x(-1);
     88             vector.setDir_z(1);
     89             vector.setAtan(atan360 - 270);
     90         } else if (315 < atan360 && atan360 <= 345) {
     91             vector.setDir(11);
     92             vector.setDir_x(-1);
     93             vector.setDir_z(1);
     94             vector.setAtan(atan360 - 270);
     95         } else if (345 < atan360) {
     96             vector.setDir(0);
     97             vector.setDir_x(-1);
     98             vector.setDir_z(1);
     99             vector.setAtan(atan360 - 270);
    100         }
    101     }
    View Code

    以上两种方式获得攻击朝向以后方便接下来的计算

    伤害范围扇形

    扇形伤害计算范围,我们需要计算当前攻击朝向,扇形夹角度,和半径范围

    在处理扇形之前,我们需要获得方向,在之前的代码里面我们已经知道如果去当前中心点朝向性问题后,

    计算扇形范围,

    其实起算扇形范围用360°朝向是非常好算,首先计算扇形的两个边360°表现形式的角度,然后计算在

    A到任意坐标点距离以及点和点之前的360°夹角换算就知道是否在扇形攻击范围内了;

    通过当前朝向的360°角度往左(A1)和往右(A2)偏移夹角度得到扇形夹角,两边的360°表象;

    如果往左(A1)偏移出来的值大于往右(A2)偏移出来的扇形边360°的值,

    那么任意点位的朝向360°(C点表示) (A1<= C && C<=360) || (0<=C && C<=A2)

    否则是正常状态

    A2<=C && C<=A1

     1     private static final Logger log = Logger.getLogger(ATest.class);
     2 
     3     public static void main(String[] args) {
     4 
     5         /*攻击方坐标点是 2,2     被攻击 6,7*/
     6         Vector vector = MoveUtil.getV12Vector(2, 2, 6, 7);
     7         log.error(vector);
     8         /*扇形半径为5码*/
     9         double vr = 5;
    10         /*我们当前扇形是70°攻击范围*/
    11         double skillAngle = 35;
    12         /*有角度 为扇形*/
    13         double atan360 = vector.getAtan360();
    14         /*往左偏移 A1*/
    15         double aTan360_A1 = MoveUtil.getATan360(atan360, -1 * skillAngle);
    16         /*往右偏移 A2*/
    17         double aTan360_A2 = MoveUtil.getATan360(atan360, skillAngle);
    18         /*求证 5,5 点位是否在矩形内*/
    19         if (MoveUtil.distance(2, 2, 5, 5) <= vr) {
    20             double tmpTan360 = MoveUtil.getATan360(2, 2, 5, 5);
    21             log.error("当前点位(5, 5)在扇形内 360°=" + tmpTan360);
    22             if ((aTan360_A1 > aTan360_A2 && ((aTan360_A1 <= tmpTan360 && tmpTan360 <= 360) || (0 <= tmpTan360 && tmpTan360 <= aTan360_A2)))
    23                     || (aTan360_A1 < aTan360_A2 && aTan360_A1 <= tmpTan360 && tmpTan360 <= aTan360_A2)) {
    24                 /*"修正后的夹角:" + aTan360_A1 + " ~ 360 和 0 ~" + aTan360_A2*/
    25                 log.error("当前点位(5, 5)在扇形 内");
    26             } else {
    27                 log.error("当前点位(5, 5)在扇形 外");
    28             }
    29         }
    30 
    31         /*求证 1,1 点位是否在矩形内*/
    32         if (MoveUtil.distance(2, 2, 1, 1) <= vr) {
    33             double tmpTan360 = MoveUtil.getATan360(2, 2, 1, 1);
    34             log.error("当前点位(1, 1)在扇形内 360°=" + tmpTan360);
    35             if ((aTan360_A1 > aTan360_A2 && ((aTan360_A1 <= tmpTan360 && tmpTan360 <= 360) || (0 <= tmpTan360 && tmpTan360 <= aTan360_A2)))
    36                     || (aTan360_A1 < aTan360_A2 && aTan360_A1 <= tmpTan360 && tmpTan360 <= aTan360_A2)) {
    37                 /*"修正后的夹角:" + aTan360_A1 + " ~ 360 和 0 ~" + aTan360_A2*/
    38                 log.error("当前点位(1, 1)在扇形 内");
    39             } else {
    40                 log.error("当前点位(1, 1)在扇形 外");
    41             }
    42         }
    43     }

    测试结果:

    1 --- exec-maven-plugin:1.2.1:exec (default-cli) @ net.sz.game.engine ---
    2 [02-15 20:07:53:0101:ERROR: sz.ATest.main():19 ] -> dir=1, dir_x=1, dir_z=1, atan=51.3402, atan360=38.6598
    3 [02-15 20:07:53:0105:ERROR: sz.ATest.main():33 ] -> 当前点位(5, 5)在扇形内 360°=45.0
    4 [02-15 20:07:53:0105:ERROR: sz.ATest.main():37 ] -> 当前点位(5, 5)在扇形 内
    5 [02-15 20:07:53:0106:ERROR: sz.ATest.main():46 ] -> 当前点位(1, 1)在扇形内 360°=225.0
    6 [02-15 20:07:53:0106:ERROR: sz.ATest.main():52 ] -> 当前点位(1, 1)在扇形 外
    7 ------------------------------------------------------------------------

    伤害范围多边形

    多边形分为,三角形,矩形,五边形,六边形;

    由于五边形及以上多边形其实和圆形区别不大,我没有细化;目前只处理了三角形和矩形

    矩形辅助代码

     1 package net.sz.game.engine.struct;
     2 
     3 import net.sz.game.engine.utils.BitUtil;
     4 
     5 /**
     6  * 任意多边形,
     7  *
     8  */
     9 public class PolygonCheck {
    10 
    11 
    12     /*多边形的顶点*/
    13     double[] pointXs;
    14     double[] pointZs;
    15     /*当前已经添加的坐标点*/
    16     int pointCount = 0;
    17 
    18     /**
    19      *
    20      * @param size 多边形的顶点数
    21      */
    22     public PolygonCheck(int size) {
    23         pointXs = new double[size];
    24         pointZs = new double[size];
    25     }
    26 
    27     /**
    28      *
    29      * @param x 坐标点
    30      * @param z 坐标点
    31      */
    32     public void add(double x, double z) {
    33         add(pointCount, x, z);
    34         pointCount++;
    35     }
    36 
    37     /**
    38      *
    39      * @param index 当前索引
    40      * @param x 坐标点
    41      * @param z 坐标点
    42      */
    43     public void add(int index, double x, double z) {
    44         if (0 <= index && index < pointXs.length) {
    45             pointXs[index] = BitUtil.getDouble2(x);
    46             pointZs[index] = BitUtil.getDouble2(z);
    47         } else {
    48             throw new UnsupportedOperationException("index out of");
    49         }
    50     }
    51 
    52     /**
    53      * 判断点是否在多边形内 <br>
    54      * ----------原理---------- <br>
    55      * 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,<br>
    56      * 如果P在多边形外部,则交点个数必为偶数(0也在内)。<br>
    57      *
    58      * @param x 要判断的点
    59      * @param z 要判断的点
    60      * @return
    61      */
    62     public boolean isInPolygon(double x, double z) {
    63         boolean inside = false;
    64         double p1x = 0, p1z = 0, p2x = 0, p2z = 0;
    65 
    66         for (int i = 0, j = pointCount - 1; i < pointCount; j = i, i++) {
    67             /*第一个点和最后一个点作为第一条线,之后是第一个点和第二个点作为第二条线,之后是第二个点与第三个点,第三个点与第四个点...*/
    68             p1x = pointXs[i];
    69             p1z = pointZs[i];
    70 
    71             p2x = pointXs[j];
    72             p2z = pointZs[j];
    73 
    74             if (z < p2z) {/*p2在射线之上*/
    75                 if (p1z <= z) {/*p1正好在射线中或者射线下方*/
    76                     if ((z - p1z) * (p2x - p1x) >= (x - p1x) * (p2z - p1z))/*斜率判断,在P1和P2之间且在P1P2右侧*/ {
    77                         /*射线与多边形交点为奇数时则在多边形之内,若为偶数个交点时则在多边形之外。
    78                         由于inside初始值为false,即交点数为零。所以当有第一个交点时,则必为奇数,则在内部,此时为inside=(!inside)
    79                         所以当有第二个交点时,则必为偶数,则在外部,此时为inside=(!inside)*/
    80                         inside = (!inside);
    81                     }
    82                 }
    83             } else if (z < p1z) {
    84                 /*p2正好在射线中或者在射线下方,p1在射线上*/
    85                 if ((z - p1z) * (p2x - p1x) <= (x - p1x) * (p2z - p1z))/*斜率判断,在P1和P2之间且在P1P2右侧*/ {
    86                     inside = (!inside);
    87                 }
    88             }
    89         }
    90         return inside;
    91     }
    92 }
    View Code

    矩形,重要的是,根据A1,当前坐标点为AB边中心点,延伸A点和B

    也就是说A1360°朝向向左偏移90°,位移AB边一半距离位A点,向右偏移90°位移AB边一半距离为B点

    A点和A1当前朝向位移AD边距离得到D点,

    B点和A1当前朝向位移AD边距离得到C点,

    三角形是以当前坐标点A点的朝向正前方为三角形A点,偏移120°和240°;

    相当于是等角三角形等边三角形;

      1     // <editor-fold defaultstate="collapsed" desc="当前坐标点位中心点的等角(等边)三角形,当前朝向位A点顶点延伸 static public PolygonCheck getTriangle(Vector vector, double x, double z, double vr)">
      2     /**
      3      * 当前坐标点位中心点的等角(等边)三角形,当前朝向位A点顶点延伸
      4      *
      5      * @param vector
      6      * @param x
      7      * @param z
      8      * @param vr 中心点偏移位置
      9      * @param vr_width 三角形,中心点距离顶点距离
     10      * @return
     11      */
     12     static public PolygonCheck getTriangle(Vector vector, double x, double z, double vr, double vr_width) {
     13 
     14         if (vr != 0) {
     15             /* 根据三角函数计算出 中心点 偏移量 */
     16             double v12_V_X = 0;
     17             double v12_V_Y = 0;
     18             if (vr < 0) {
     19                 /* 传入负数的时候方向刚好是相反方向运动 */
     20                 v12_V_X = -1 * vector.getDir_x() * getV12XD(vr, vector.getAtan());
     21                 v12_V_Y = -1 * vector.getDir_z() * getV12ZD(vr, vector.getAtan());
     22             } else {
     23                 /* 正前方移动 */
     24                 v12_V_X = vector.getDir_x() * getV12XD(vr, vector.getAtan());
     25                 v12_V_Y = vector.getDir_z() * getV12ZD(vr, vector.getAtan());
     26             }
     27             x += v12_V_X;
     28             z += v12_V_Y;
     29         }
     30 
     31         Vector bVector = getVectorBy360Atan(getATan360(vector.getAtan360(), 120));
     32         Vector cVector = getVectorBy360Atan(getATan360(vector.getAtan360(), 240));
     33 
     34         double ax = x + (vector.getDir_x() * getV12XD(vr, vector.getAtan()));
     35         double az = z + (vector.getDir_z() * getV12ZD(vr, vector.getAtan()));
     36 
     37         double bx = x + (bVector.getDir_x() * getV12XD(vr, bVector.getAtan()));
     38         double bz = z + (bVector.getDir_z() * getV12ZD(vr, bVector.getAtan()));
     39 
     40         double cx = x + (cVector.getDir_x() * getV12XD(vr, cVector.getAtan()));
     41         double cz = z + (cVector.getDir_z() * getV12ZD(vr, cVector.getAtan()));
     42 
     43         PolygonCheck polygonCheck = new PolygonCheck(3);
     44         polygonCheck.add(ax, az);
     45         polygonCheck.add(bx, bz);
     46         polygonCheck.add(cx, cz);
     47         if (log.isDebugEnabled()) {
     48             log.debug("A_X:" + ax + " A_Y:" + az);
     49             log.debug("B_X:" + bx + " B_Y:" + bz);
     50             log.debug("C_X:" + cx + " C_Y:" + cz);
     51         }
     52         return polygonCheck;
     53     }
     54 // </editor-fold>
     55 
     56     // <editor-fold defaultstate="collapsed" desc="90°朝向矩形,以传入的坐标点为AB边中心点距离 static public PolygonCheck getRectangle(Vector vector, double x, double y, double vr, double vr_width, double vr_hight)">
     57     /**
     58      * 90°朝向矩形,以传入的坐标点为AB边中心点距离
     59      *
     60      * @param vector 当前朝向
     61      * @param x 当前坐标点
     62      * @param z 当前坐标点
     63      * @param vr 原点偏移量,AB编中心点90°偏移量 偏移,正前方(正数)或者正后方(负数)米数
     64      * @param vr_width 偏移量,矩形的宽度,左右各偏移0.2m直线是0.4m
     65      * @param vr_hight 偏移量高,矩形的长度
     66      * @return
     67      */
     68     static public PolygonCheck getRectangle(Vector vector, double x, double z, double vr, double vr_width, double vr_hight) {
     69         //宽度修正
     70         vr_width = vr_width / 2;
     71 
     72         Vector aVector = getVectorBy360Atan(getATan360(vector.getAtan360(), -90));
     73         Vector bVector = getVectorBy360Atan(getATan360(vector.getAtan360(), 90));
     74 
     75         if (vr != 0) {
     76             /* 根据三角函数计算出 中心点 偏移量 */
     77             double v12_V_X = 0;
     78             double v12_V_Y = 0;
     79             if (vr < 0) {
     80                 /* 传入负数的时候方向刚好是相反方向运动 */
     81                 v12_V_X = -1 * vector.getDir_x() * getV12XD(vr, vector.getAtan());
     82                 v12_V_Y = -1 * vector.getDir_z() * getV12ZD(vr, vector.getAtan());
     83             } else {
     84                 /* 正前方移动 */
     85                 v12_V_X = vector.getDir_x() * getV12XD(vr, vector.getAtan());
     86                 v12_V_Y = vector.getDir_z() * getV12ZD(vr, vector.getAtan());
     87             }
     88             x += v12_V_X;
     89             z += v12_V_Y;
     90         }
     91 
     92         /* 根据三角函数计算出 A 点偏移量 */
     93         double v12_A_X = aVector.getDir_x() * getV12XD(vr_width, aVector.getAtan());
     94         double v12_A_Y = aVector.getDir_z() * getV12ZD(vr_width, aVector.getAtan());
     95         /* 由于在计算12方向位移函数里面已经计算偏移量是正负值 */
     96         double A_X = x + v12_A_X;
     97         double A_Y = z + v12_A_Y;
     98 
     99         /* 根据三角函数计算出 B 点偏移量 */
    100         double v12_B_X = bVector.getDir_x() * getV12XD(vr_width, bVector.getAtan());
    101         double v12_B_Y = bVector.getDir_z() * getV12ZD(vr_width, bVector.getAtan());
    102         /* 由于在计算12方向位移函数里面已经计算偏移量是正负值 */
    103         double B_X = x + v12_B_X;
    104         double B_Y = z + v12_B_Y;
    105 
    106         /* 根据三角函数计算出 C 或者 D 点偏移量 */
    107         double v12_CD_X = vector.getDir_x() * getV12XD(vr_hight, vector.getAtan());
    108         double v12_CD_Y = vector.getDir_z() * getV12ZD(vr_hight, vector.getAtan());
    109 
    110         /* C 点应该是 B 点的垂直方向也就是原来玩家的移动方向 由于在计算12方向位移函数里面已经计算偏移量是正负值*/
    111         double C_X = B_X + v12_CD_X;
    112         double C_Y = B_Y + v12_CD_Y;
    113         /* D 点应该是 A 点的垂直方向也就是原来玩家的移动方向 由于在计算12方向位移函数里面已经计算偏移量是正负值*/
    114         double D_X = A_X + v12_CD_X;
    115         double D_Y = A_Y + v12_CD_Y;
    116 
    117         PolygonCheck polygonCheck = new PolygonCheck(4);
    118         polygonCheck.add(A_X, A_Y);
    119         polygonCheck.add(B_X, B_Y);
    120         polygonCheck.add(C_X, C_Y);
    121         polygonCheck.add(D_X, D_Y);
    122         if (log.isDebugEnabled()) {
    123             log.debug("A_X:" + A_X + " A_Y:" + A_Y);
    124             log.debug("B_X:" + B_X + " B_Y:" + B_Y);
    125             log.debug("C_X:" + C_X + " C_Y:" + C_Y);
    126             log.debug("D_X:" + D_X + " D_Y:" + D_Y);
    127         }
    128         return polygonCheck;
    129     }
    130     //</editor-fold>
    131 
    132     public static void main(String[] args) {
    133         double x1 = 20, z1 = 20, x2 = 20, z2 = 10;
    134         Vector v12Vector = getV12Vector(x1, z1, x2, z2);
    135 
    136         log.error("当前朝向:" + v12Vector);
    137 
    138 //        double v12X = v12Vector.getDir_x() * getV12X(1d, v12Vector.getAtan());
    139 //        log.error("当前位移量-x:" + v12X);
    140 //        double v12Z = v12Vector.getDir_z() * getV12Z(1d, v12Vector.getAtan());
    141 //        log.error("当前位移量-y:" + v12Z);
    142 //        double aTan = getATan360(v12Vector.getAtan360(), -10);
    143 //        log.error("修正后的角度:" + aTan);
    144 //        double aTanDir = getATan360(v12Vector.getAtan360(), 10);
    145 //        log.error("修正后的角度:" + aTanDir);
    146 //
    147 //        if (aTan > aTanDir) {
    148 //            log.error("修正后的夹角:" + aTan + " ~ 360 和 0 ~" + aTanDir);
    149 //        } else {
    150 //            log.error("修正后的夹角:" + aTan + " ~ " + aTanDir);
    151 //        }
    152 //        aTan = getATan360(aTan, -10);
    153 //        log.error("修正后的角度:" + aTan);
    154 //        aTanDir = getATan360(aTanDir, -10);
    155 //        log.error("修正后的角度:" + aTanDir);
    156 //
    157 //        if (aTan > aTanDir) {
    158 //            log.error("修正后的夹角:" + aTan + " ~ 360 和 0 ~" + aTanDir);
    159 //        } else {
    160 //            log.error("修正后的夹角:" + aTan + " ~ " + aTanDir);
    161 //        }
    162         PolygonCheck rectangle = getTriangle(v12Vector, x1, z1, 0, 4);
    163 
    164         log.error("三角形:" + rectangle.isInPolygon(19, 19));
    165 
    166     }
    View Code

    测试结果

    1 --- exec-maven-plugin:1.2.1:exec (default-cli) @ net.sz.game.engine ---
    2 [02-15 20:33:34:0522:ERROR: utils.MoveUtil.main():678] -> 当前朝向:dir=6, dir_x=1, dir_z=-1, atan=90.0, atan360=180.0
    3 [02-15 20:33:34:0525:DEBUG: utils.MoveUtil.getTriangle():590] -> A_X:20.0 A_Y:20.0
    4 [02-15 20:33:34:0526:DEBUG: utils.MoveUtil.getTriangle():591] -> B_X:20.0 B_Y:20.0
    5 [02-15 20:33:34:0526:DEBUG: utils.MoveUtil.getTriangle():592] -> C_X:20.0 C_Y:20.0
    6 [02-15 20:33:34:0526:ERROR: utils.MoveUtil.main():706] -> 三角形:false
    7 ------------------------------------------------------------------------

    以上是在攻击伤害范围攻击计算公式;

    该公式还夹杂着算偏移量,比如神龙boos(摆尾技能)攻击的是boos朝向的正后方,一个扇形范围;

    总要的是提供一种思路已经解决访问,

    此次思路最总要的地方在于我们任何方向表示都采用360°圆形无死角计算,提供的精确度是小数的后4位算法;

    在攻击场景对象的时候,就可以做到像MOBa游戏一样的进准度测试

    伤害范围弹道飞行

    本处只提供解决方案而不提供解决代码;

    仅供参考

    思路方案是根据弹道飞行速度,计算间隔时间执行比如50ms飞行距离;

    我们以扇形为例:

    我们得到一个扇形V;扇形的半径是VR=5

    然后我们从A点开始计算,每50ms计算一次飞行距离;

    第一次飞行我们得到V1然后计算V1里面可攻击对象,坐标点半径小于V1,

    第二次飞行,间隔50ms以后,我们计算出V2,那么这时候,

    我们需要计算可攻击的对象的距离是大于V1半径小于V2半径位置;

    这样就能得到弹道飞行中获取可攻击对象的伤害计算方式;

    矩形其实同理计算的;

  • 相关阅读:
    委托和事件的区别
    委托小练习
    线程安全小练习
    线程等待练习
    线程练习
    C# Parallel用法
    Winform 跨线程更新UI控件常用方法汇总
    世界顶级思维,收藏终身受用!
    Win10预览版怎么关闭自动更新?怎么更改更新设置
    win7删除桌面文件后手动刷新才会消失的解决方法
  • 原文地址:https://www.cnblogs.com/shizuchengxuyuan/p/6403312.html
Copyright © 2020-2023  润新知