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

时间:2022-02-20 04:16:46
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半径位置;

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

矩形其实同理计算的;