博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
游戏中战斗伤害范围攻击计算完整全版
阅读量:5098 次
发布时间:2019-06-13

本文共 26572 字,大约阅读时间需要 88 分钟。

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方向任意矩形规则计算问题,

在后来测试发现这个算法其实有问题,因为算错矩形的时候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  * 
9 * author 失足程序员
10 * mail 492794628@qq.com
11 * phone 13882122019
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 @Deprecated111 public double getVrx() {112 return vrx;113 }114 115 @Deprecated116 public void setVrx(double vrx) {117 this.vrx = vrx;118 }119 120 @Deprecated121 public double getVrz() {122 return vrz;123 }124 125 @Deprecated126 public void setVrz(double vrz) {127 this.vrz = vrz;128 }129 130 @Override131 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     // 
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 //
91 92 //
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 //
.101 102 //
103 public static double getATan(double x1, double z1, double x2, double z2) {104 //正切(tan)等于对边比邻边;tanA=a/b105 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 //
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.65983 [02-15 20:07:53:0105:ERROR: sz.ATest.main():33 ] -> 当前点位(5, 5)在扇形内 360°=45.04 [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.06 [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      * 判断点是否在多边形内 
54 * ----------原理----------
55 * 注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,
56 * 如果P在多边形外部,则交点个数必为偶数(0也在内)。
57 *58 * @param x 要判断的点59 * @param z 要判断的点60 * @return61 */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     // 
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 //
55 56 //
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 //
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.03 [02-15 20:33:34:0525:DEBUG: utils.MoveUtil.getTriangle():590] -> A_X:20.0 A_Y:20.04 [02-15 20:33:34:0526:DEBUG: utils.MoveUtil.getTriangle():591] -> B_X:20.0 B_Y:20.05 [02-15 20:33:34:0526:DEBUG: utils.MoveUtil.getTriangle():592] -> C_X:20.0 C_Y:20.06 [02-15 20:33:34:0526:ERROR: utils.MoveUtil.main():706] -> 三角形:false7 ------------------------------------------------------------------------

 

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

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

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

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

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

伤害范围弹道飞行

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

仅供参考

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

我们以扇形为例:

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

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

 

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

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

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

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

矩形其实同理计算的;

 

转载于:https://www.cnblogs.com/shizuchengxuyuan/p/6403312.html

你可能感兴趣的文章
android 通过AlarmManager实现守护进程
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
win7下把电脑设置成wlan热
查看>>
Java 多态 虚方法
查看>>
jquery.validate插件在booststarp中的运用
查看>>
java常用的包
查看>>
PHP批量覆盖文件并执行cmd命令脚本
查看>>
Unity之fragment shader中如何获得视口空间中的坐标
查看>>
支持向量机——内核
查看>>
MFC注册热键
查看>>
万能的SQLHelper帮助类
查看>>
如何在 Terminal 内可以“用惯用的编辑器”快速打开“目前正在做”的专案(project)呢?...
查看>>
uboot分析:uboot的启动过程分析
查看>>
tmux的简单快捷键
查看>>
springboot笔记04——读取配置文件+使用slf4j日志
查看>>
[Swift]LeetCode653. 两数之和 IV - 输入 BST | Two Sum IV - Input is a BST
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
微信小程序的wxml文件和wxss文件在webstrom的支持
查看>>
Html5 离线页面缓存
查看>>
[php]在PHP中读取和写入WORD文档的代码
查看>>