游戏里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方向,任意点位任意方向计算正前方矩形范围生产以及验证过程。
不知道还有没有大神有更好的方式进行处理!!!
阅读全文
0 0
- 游戏里12方向,任意方向计算正前方矩形规则
- 方向~
- 方向
- 方向
- 方向
- 方向..
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向
- 方向?
- 面试和面试者如何保持心态
- 看我是如何处理自定义线程模型---java
- 游戏中精灵对象的属性功能设计
- 我是如何设计游戏服务器架构的
- POJ2175 Evacuation Plan 【 最小费用流+消圈定理】
- 游戏里12方向,任意方向计算正前方矩形规则
- 存在即合理,重复轮子orm java版本
- 更加强健的线程模型,解决线程卡死,退出异常情况
- 游戏中战斗伤害范围攻击计算完整全版
- 游戏中战斗伤害范围-弹道飞行
- 3秒钟完成50万条并发日志 文件写入
- 【数论-异或】nyoj-备用 2345: A problem that's so easy
- 微服务--webapi实现,脱离iis,脱离tomcat
- net.sz.framework 框架 轻松搭建服务---让你更专注逻辑功能---初探