游戏里12方向,任意方向计算正前方矩形规则

来源:互联网 发布:java类命名规则 编辑:程序博客网 时间:2024/05/29 03:45
此文章意在记录我是如何处理游戏里面特殊技能需求处理方案,
之前做游戏很多年,技能打出去都是扇形,圆形为主的攻击范围获取伤害;然后昨天策划提出一个需求,从玩家当前坐标点开始打出正前方一个矩形返回获取伤害值计算;

 

 1     //<editor-fold defaultstate="collapsed" desc="获取角度 public static int getATan(float x1, float y1, float x2, float y2)"> 2     public static int getATan(float x1, float y1, float x2, float y2) { 3         //正切(tan)等于对边比邻边;tanA=a/b 4         int a = 0; 5         if (x1 == x2) { 6             //x坐标相同的情况表示正上或者正下方移动 7             a = 90; 8         } else if (y1 != y2) { 9             //三角函数的角度计算10             float ta = Math.abs(y1 - y2) / Math.abs(x1 - x2);11             //Math.sin(sina * (2 * Math.PI / 360))12             Double atan = Math.atan(ta);13             //Math.tan(x * (2 * Math.PI / 360));14             a = (int) Math.round(atan / (2 * Math.PI / 360));15         }16         return a;17     }18     //</editor-fold>

这两个函数可以计算出两个点位的12方向计算法则,

由于真实环境是360°,然后在实际计算是12方向,所以修正值,正移偏移12°包含值是正方向;

 1     // <editor-fold defaultstate="collapsed" desc="获取方向 static public int getVector12(float x1, float y1, float x2, float y2)"> 2     /** 3      * 获取方向 4      * <br> 5      * 根据特点,0方向是x轴正方向,顺时针移动 6      * 7      * @param x1 8      * @param y1 9      * @param x210      * @param y211      * @return12      */13     static public byte getVector12(float x1, float y1, float x2, float y2) {14 15         byte vector = 0;16         //正切(tan)等于对边比邻边;tanA=a/b17         int a = getATan(x1, y1, x2, y2);18 19         if (0 <= a && a <= 15) {20             if (x1 > x2) {21                 vector = 6;22             } else {23                 vector = 0;24             }25         } else if (15 < a && a <= 45) {26             if (x1 < x2) {27                 if (y1 < y2) {28                     vector = 11;29                 } else {30                     vector = 1;31                 }32             } else if (y1 < y2) {33                 vector = 7;34             } else if (y1 > y2) {35                 vector = 5;36             }37         } else if (45 < a && a <= 75) {38             if (x1 < x2) {39                 if (y1 < y2) {40                     vector = 10;41                 } else {42                     vector = 2;43                 }44             } else if (y1 < y2) {45                 vector = 8;46             } else if (y1 > y2) {47                 vector = 4;48             }49         } else {50             if (y1 > y2) {51                 vector = 3;52             } else {53                 vector = 9;54             }55         }56 57         return vector;58     }59     // </editor-fold>

 

把我难住了,难点在哪里呢??

难点是在于玩家是是以12方位做基础运算对象,那么他在坐标系里面就有可能是任意坐标点,和任意朝向,

相对于当前方向垂直的左右延伸坐标法系,算出四个坐标点。如下图:

图中我只是提出,最简单的移动的图形,当玩家当前朝向是y轴正方向,左右延伸,D和C两个点,

然后还要计算出A,B、两个坐标点,

然而在实际做法中,玩家当前朝向肯定是很多朝向,

所以,在计算矩形范围的时候是需要使用三角函数,来就是X轴和Y实际坐标点的位移量。

我是把方向都切分了,不存在钝角三角形一说,所以计算方式略有不同。

下面我们来看代码

 1     // <editor-fold defaultstate="collapsed" desc="保留四位小时函数 static Double getDouble4(float souse)"> 2     /** 3      * 保留四位小时函数 4      * 5      * @param souse 6      * @return 7      */ 8     static float getDouble4(float souse) { 9         BigDecimal b = new BigDecimal(souse);10         float df = b.setScale(4, BigDecimal.ROUND_HALF_UP).floatValue();11         return df;12     }13     // </editor-fold>

三角函数计算公式

 1     // <editor-fold defaultstate="collapsed" desc="位移是y轴 static float getV12Y(int vector, float offset)"> 2     /** 3      * 位移是y轴 4      * 5      * @param vector 方向向量,正上方位1起点顺时针旋转 12方向 6      * @param offset 位移量 7      * @return 8      */ 9     public static float getV12Y(int vector, float offset) {10         int sina = 0;11         switch (vector) {12             case 3:13             case 9:14                 sina = 90;15                 break;16             case 0:17             case 6:18                 sina = 0;19                 break;20             case 2:21             case 4:22             case 8:23             case 10:24                 sina = 60;25                 break;26             case 1:27             case 5:28             case 7:29             case 11:30                 sina = 30;31                 break;32         }33         /* 三角函数计算器 */34         float sinr = (float) (offset * Math.sin(sina * (2 * Math.PI / 360)));35         /* 拿到保留4位小数计算器 */36         float double2 = getDouble4(sinr);37         /* 根据方向计算向量位移是增加还是减少 */38         if ((0 < vector && vector < 6)) {39             return -1 * double2;40         } else {41             return double2;42         }43     }44     // </editor-fold>45 46     // <editor-fold defaultstate="collapsed" desc="位移时的X轴 static float getV12X(int vector, float offset)">47     /**48      * 位移时的X轴49      *50      * @param vector 方向向量,正上方位1起点顺时针旋转 12方向51      * @param offset 位移量52      * @return53      */54     public static float getV12X(int vector, float offset) {55         int cosa = 0;56         /* 这里根据方向拿到对应的实际坐标系角度 */57         switch (vector) {58             case 3:59             case 9:60                 cosa = 90;61                 break;62             case 0:63             case 6:64                 cosa = 0;65                 break;66             case 2:67             case 4:68             case 8:69             case 10:70                 cosa = 60;71                 break;72             case 1:73             case 5:74             case 7:75             case 11:76                 cosa = 30;77                 break;78         }79         /* 三角函数计算器 */80         float cosr = (float) (offset * Math.cos(cosa * (2 * Math.PI / 360)));81         /* 拿到保留4位小数计算器 */82         float double2 = getDouble4(cosr);83         /* 根据方向计算向量位移是增加还是减少 */84         if ((0 <= vector && vector <= 3) || (9 <= vector && vector <= 11)) {85             return double2;86         } else {87             return -1 * double2;88         }89     }90     // </editor-fold>

上面的三角函数计算公式,就能计算出12方向任意方向位移的偏移量

我们以12方向为例,任意方向90°位移,都是左右偏移三个方向计算,

然后我们是12为单位的;

1         int vdir = 3; //相对玩家的90°朝向偏移量2         /* 减方向偏移量 */3         int attdir1 = dir - vdir;4         if (attdir1 < 0) {5             /* 12方向修正,12是一个轮回 */6             attdir1 = 12 + attdir1;7         }8         /* 加方向偏移量 12方向修正,12是一个轮回*/9         int attdir2 = (dir + vdir) % 12;

当我们得到一个方向的需要计算一次,左右两个偏移位移的方向

 1 /** 2      * 90°朝向矩形,以传入的坐标点为AB边中心点距离 3      * 4      * @param dir 5      * @param x 6      * @param y 7      * @param vr_width 偏移量,左右各偏移0.2m直线是0.4m 8      * @return 9      */10     static public java.awt.Polygon getRectangle(int dir, float x, float y, float vr_width, float vr_hight) {11 12         int vdir = 3; //相对玩家的90°朝向偏移量13         /* 减方向偏移量 */14         int attdir1 = dir - vdir;15         if (attdir1 < 0) {16             /* 12方向修正,12是一个轮回 */17             attdir1 = 12 + attdir1;18         }19         /* 加方向偏移量 12方向修正,12是一个轮回*/20         int attdir2 = (dir + vdir) % 12;21         /* 根据三角函数计算出 A 点偏移量 */22         float v12_A_X = getV12X(attdir1, vr_width);23         float v12_A_Y = getV12Y(attdir1, vr_width);24         /* 由于在计算12方向位移函数里面已经计算偏移量是正负值 */25         float A_X = x + v12_A_X;26         float A_Y = y + v12_A_Y;27 28         /* 根据三角函数计算出 B 点偏移量 */29         float v12_B_X = getV12X(attdir2, vr_width);30         float v12_B_Y = getV12Y(attdir2, vr_width);31         /* 由于在计算12方向位移函数里面已经计算偏移量是正负值 */32         float B_X = x + v12_B_X;33         float B_Y = y + v12_B_Y;34 35         /* 根据三角函数计算出 C 或者 D 点偏移量 */36         float v12_CD_X = getV12X(dir, vr_hight);37         float v12_CD_Y = getV12Y(dir, vr_hight);38 39         /* C 点应该是 A 点的垂直方向也就是原来玩家的移动方向 由于在计算12方向位移函数里面已经计算偏移量是正负值*/40         float C_X = A_X + v12_CD_X;41         float C_Y = A_Y + v12_CD_Y;42 43         /* D 点应该是 B 点的垂直方向也就是原来玩家的移动方向 由于在计算12方向位移函数里面已经计算偏移量是正负值*/44         float D_X = B_X + v12_CD_X;45         float D_Y = B_Y + v12_CD_Y;46 47         Point2D.Double pointA = new Point2D.Double(A_X, A_Y);48         Point2D.Double pointB = new Point2D.Double(B_X, B_Y);49         Point2D.Double pointC = new Point2D.Double(C_X, C_Y);50         Point2D.Double pointD = new Point2D.Double(D_X, D_Y);51 52         java.awt.Polygon p = new Polygon();53 54         int px = (int) (pointC.x * TIMES);55         int py = (int) (pointC.y * TIMES);56         p.addPoint(px, py);57 58         px = (int) (pointD.x * TIMES);59         py = (int) (pointD.y * TIMES);60         p.addPoint(px, py);61 62         px = (int) (pointB.x * TIMES);63         py = (int) (pointB.y * TIMES);64         p.addPoint(px, py);65 66         px = (int) (pointA.x * TIMES);67         py = (int) (pointA.y * TIMES);68         p.addPoint(px, py);69         return p;70     }71 72     static final int TIMES = 1000;73 74     // 验证一个点是否在矩形内75     static public boolean checkRectangle(float x, float y, java.awt.Polygon polygon) {76         int px = (int) (x * TIMES);77         int py = (int) (y * TIMES);78         return polygon.contains(px, py);79     }

由于我们在游戏中获取周围玩家或者怪物的时候,往往需要很多坐标点验证,所以验证函数独立出来,是为了减少验证计算次数

测试代码

 1     public static void main(String[] args) throws FileNotFoundException, IOException, Exception { 2  3         float x = 0.0f; 4         float y = 0.0f; 5         int dir = 9;//当前玩家朝向 6         Polygon rectangle = getRectangle(dir, x, y, 0.4f, 0.4f); 7         log.error(checkRectangle(x + 0.2f, y + 0.1f, rectangle)); 8         log.error(checkRectangle(x - 0.2f, y + 0.1f, rectangle)); 9         log.error(checkRectangle(x + 1.2f, y + 0.1f, rectangle));10         log.error(checkRectangle(x + 0.2f, y + 1.1f, rectangle));11     }

以上是本次12方向,任意点位任意方向计算正前方矩形范围生产以及验证过程。

不知道还有没有大神有更好的方式进行处理!!!

 

原创粉丝点击