游戲中戰斗傷害范圍攻擊計算完整全版


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半徑位置;

這樣就能得到彈道飛行中獲取可攻擊對象的傷害計算方式;

矩形其實同理計算的;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM