java 实现精确碰撞检测。

cnmm22 原创。

[http://blog.csdn.net/cnmm22/article/details/45220551]

用我的方法,你可以在java 里实现精确的斜角矩形,平行四边形,不规则矩形,不规则多边形与圆形的碰撞检测。

我们知道,在java 里有一个类,x.getRect().intersects(x1.getRect() 可以实现规则矩形的碰撞检测:

这是无法容忍的“碰撞检测”。这不是我要的游戏效果。

在使我的方法后:

cnmm22 原创,转载请随便。

实现方法:我们必须把所有的碰撞分为两类:与圆形和与多边形。

圆形与圆形解决方案:检测两个碰撞对象的圆心距离,跟两者半径之和做比较。

我把要使用的方法都封装好了,以便您直接使用 :

    /**  步骤一、检测两个圆心距离 */
    public static double getDistance(Point p, double ox, double oy) {
        double _x = Math.abs(ox - p.x);
        double _y = Math.abs(oy - p.y);
        return Math.sqrt(_x * _x + _y * _y);
    }

每一张圆形的透明 png圆形图片,我们都有一个尺寸大小,我们按尺寸大小,得到其半径。

而要碰撞的两个圆心坐标我们是很好得到的,这个相信我不须解释。

/* 步骤二、检测两个圆心距离,与两者半径之和做比较,范例代码: /

.

.

.

.

            Point p1 = new Point(x + W / 2, y + H / 2);
            if (Unit.getDistance(p1, w.yx, w.yy) < w.yr) {

.

.

.

.

以上就完成了圆形的碰撞检测。

多边形:骚复杂点,。

解决方案:1、描边,2,检测边到点距离。

例如这个图形:

先描出4个定点,这样,能以这4个点组合成4条线段。在分别检测每一条线段与对象中心的距离即可。

示例代码:

……………………….

img = tk.getImage(Wall.class.getClassLoader().getResource("images/4/k8.png"));
            rx1 = 1;
            rx2 = 14784;
            w = 168;
            h = 88;

            rx3 = 2;

            x3 = x;
            y3 = y + 5;

            w3 = w - 15;
            h3 = h - 5;

            px11 = x + 14;
            px12 = y + 35;

            px21 = x + 136;
            px22 = y + 7;

            px31 = x + 4;
            px32 = y + 85;

            px41 = x + 149;
            px42 = y + 53;

……………………….

px11,px12,是它的第一个点,px21,px22,是它的第二个点,以此类推。x,y是这张矢量图最左上角滴点,不管那个点有没有像素,或者是透明,它都是 x, y。这样通过图像工具,我们很容易得到一组 px1-pxn, px12-pxn2。

示例代码:(分别检测每一条线段与对象中心的距离)

if (Unit.pointToLine(w.px11, w.px12, w.px21, w.px22, x + W / 2, y + H / 2) < 24) {

                stay();

                return true;
            }
            if (Unit.pointToLine(w.px11, w.px12, w.px31, w.px32, x + W / 2, y + H / 2) < 24) {

                stay();

                return true;
            }
            if (Unit.pointToLine(w.px31, w.px32, w.px41, w.px42, x + W / 2, y + H / 2) < 24) {

                stay();

                return true;
            }
            if (Unit.pointToLine(w.px21, w.px22, w.px41, w.px42, x + W / 2, y + H / 2) < 24) {

                stay();

                return true;

其中 x + W / 2, y + H / 2 ,是点坐标,24是检测距离。以上只是范例。

    /**  封装方法:检测边到点距离 */
    static double pointToLine(int x1, int y1, int x2, int y2, int x0, int y0) {
        double space = 0;
        double a, b, c;
        a = lineSpace(x1, y1, x2, y2);// 线段的长度
        b = lineSpace(x1, y1, x0, y0);// (x1,y1)到点的距离
        c = lineSpace(x2, y2, x0, y0);// (x2,y2)到点的距离
        if (c <= 0.000001 || b <= 0.000001) {
            space = 0;
            return space;
        }
        if (a <= 0.000001) {
            space = b;
            return space;
        }
        if (c * c >= a * a + b * b) {
            space = b;
            return space;
        }
        if (b * b >= a * a + c * c) {
            space = c;
            return space;
        }
        double p = (a + b + c) / 2;// 半周长
        double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积
        space = 2 * s / a;// 返回点到线的距离(利用三角形面积公式求高)
        return space;
    }

无论如何,解决多边形碰撞检测,描边将会是一个相当大工作量的工作,但是一旦使用熟练后,其实也是相当简便。因为有图形工具。

这样就很迅速得到了 px11,px12,px21,px22 ;px31,px32,px41,px42 类似。

以上就完成了不规则矩形的碰撞检测。

那多边形怎样检测?

多边形方法类似,多描几条边出来,再分辨判断点到线距离即可。我就不在赘述了。

假设要检测的对象是一个椭圆又怎吗办?

你可以参考这样的方法:

记住,你描的边越多,精确度越高,工作量越大。

使用我的方法,你可以最大限度提高碰撞检测的精确程度,并且可以避免像素级碰撞检测带来的巨大性能损耗,若碰撞的对象为多边形与多边形碰撞,或多边形与曲线碰撞,无法使用我的方法检测,而实际中,这种碰撞很少,这种情况下,可以建立像素矩阵,一般的做法比如一个200*200像素的图片,我们则需要做一个[200]*[200]的数组,进行约40000次的遍历,来完成1帧里滴碰撞检测,还要考虑到透明度的计算,其性能消耗相当可观。

时间: 2024-10-07 15:42:19

java 实现精确碰撞检测。的相关文章

第二章 Java浮点数精确计算

1.实际意义 在实际开发中,如果需要进行float或double的精确计算(尤其是财务计算),直接使用float或double是不行的(具体的例子看下边的代码的main方法的测试结果),需要使用BigDecimal. 2.代码 package com.xxx.util; import java.math.BigDecimal; /** * 浮点数精准算法 */ public class BigDecimalArithUtil { private static final int DIV_SCAL

Java获取精确到毫秒的时间戳

import java.util.Date; public class Timestamp { /** 获取精确到毫秒的时间戳 * @param date * @return **/ public static Long getTimestamp(Date date){ if (null == date) { return (long) 0; } String timestamp = String.valueOf(date.getTime()); return Long.valueOf(time

JAVA中精确计算金额BigDecimal

package com.chauvet.utils; import java.math.BigDecimal;import java.text.DecimalFormat;import java.text.NumberFormat; /*** * * 金额 * * 如果需要精确计算,必须用String来够造BigDecimal! !! * * Java里面的商业计算,不能用float和double,因为他们无法 进行精确计算. * 但是Java的设计者给编程人员提供了一个很有用的类BigDeci

Java游戏之碰撞检测

在进行Java游戏开发时,我们经常会遇到碰撞检测的问题.如坦克大战中,炮弹与坦克相遇发生爆炸:守卫者游戏中,守卫者发射的箭与怪物相遇使怪物失血:打飞机游戏中,飞机发送的子弹与敌机相遇干掉敌机.这些都需要实现碰撞检测. 我们先来看一类比较简单的碰撞检测:规则图形的碰撞检测. 矩形碰撞检测 作为一个练手的小游戏,游戏中的物体形状一般为矩形区域,这是规则图形.它的碰撞检测可以通过Java API中的Rectangle类来实现碰撞的检测. Rectangle指的是一个矩形区域,它通过指定左上角位置x和y

java如何精确小数

1.(double) (Math.round(sd3*10000)/10000.0); 这样为保持4位 (double) (Math.round(sd3*100)/100.0); 这样为保持2位. 2.另一种办法 import java.text.DecimalFormat; DecimalFormat df2 = new DecimalFormat("###.00"); DecimalFormat df2 = new DecimalFormat("###.000"

JAVA简单精确计算工具类

1 public class ArithUtil { 2 3 // 默认除法运算精度 4 private static final int DEF_DIV_SCALE = 10; 5 6 private ArithUtil() { 7 8 } 9 10 /** 11 * 提供精确的加法运算. 12 * 13 * @param v1 14 * 被加数 15 * @param v2 16 * 加数 17 * @return 两个参数的和 18 */ 19 public static double a

Effective Java 之-----精确的答案与double&amp;float

题目: 假设你口袋里有1$,看到货架上有一排美味的糖果,标价分别为0.10$,0.20$,0.30$...1$,你打算从标价为0.10$的糖果开始买起,每种买一颗,一直到不能支付货架上下一种价格的糖果为止,那么可以买多少颗糖果?还可以找回多少零钱? 使用double的程序如下: double funds = 1.00; int itemsBought = 0; for(double price=.10;funds>=price;price+=.10){ funds -= price; items

7, 碰撞检测, 精确非精确

import tr = egret.sys.tr; class Main extends egret.DisplayObjectContainer { public constructor() { super(); this.once(egret.Event.ADDED_TO_STAGE, this.start, this); } private start(event:egret.Event) { /** * 绘制一个 100 * 100 的红色正方形 */ var shp:egret.Sha

第一章 Java工具类目录

在这一系列博客中,主要是记录在实际开发中会常用的一些Java工具类,方便后续开发中使用. 以下的目录会随着后边具体工具类的添加而改变. 浮点数精确计算 第二章 Java浮点数精确计算