游戏开发2D碰撞检测之圆与圆的碰撞

最近要做一个塔防游戏demo,防御塔需要检测敌人是否进入攻击范围内,我就得判断了。本来可以使用JBox2d的,这边自己实现一下,肯定还有很多问题,暂时做个记录,后面要优化。

关于JBox2d,我写了一篇入门教程JBox2D第一课-搭建swing绘制框架并实现小球自由落体

圆与圆碰撞分析

这里写图片描述
描述:当两个圆半径之和*r1+r2小于两个圆的圆心距c时,即发生碰撞*。
圆心距怎么算?就是求两个点的距离勾股定理
这里我们把求两个点的距离封装成一个函数distance

  /**
     *
     * @param pos1 点的位置一
     * @param pos2 点的位置二
     * @return 点与点的距离
     */
    public static double distance(Vector2 pos1, Vector2 pos2){
        return Math.sqrt(Math.pow(pos1.x - pos2.x,2) + Math.pow(pos1.y - pos2.y,2));
    }

注意:Vector2封装的2d坐标类,自己可以实现一下,可以参考jbox2d(jbox2d我第一篇文章有介绍)的代码
类似下面这样:
这里写图片描述

下面我们实现我们的碰撞函数

    /**
     * 圆形碰撞
     * @param circlePos1 圆1位置
     * @param r1 圆1半径
     * @param circlePos2 圆2位置
     * @param r2 圆2半径
     * @return 碰撞返回true,没碰撞返回false
     */
    public static boolean circleAndCircleCollision(Vector2 circlePos1,float r1, Vector2 circlePos2, float r2){
        if(distance(circlePos1,circlePos2) < r1+r2)
            return true;
        return false;
    }

看起来很简单吧,下面我们来测试一下

  if(Tools.circleAndCircleCollision(this.getPosition(),this.getAttackRangeRadius(),this.hero.getPosition(),this.hero.getR())){
            System.out.println("attacked");
            System.out.println(this.position);
            System.out.println(this.hero.getPosition());
        }

这里写图片描述

问题

你发现并不是你想象的那样,哈,为什么呢?
你发现上面代码的问题了吗?
其实我们的算法并没有问题,那问题就是我们绘制视图的问题了
找到绘制防御塔的地方
这里写图片描述

g.drawOval(this.tower.getX(), this.tower.getY(), this.tower.getAttackRangeRadius(), this.tower.getAttackRangeRadius());

是的就是这里
这是绘制椭圆的,这里我们让第三个参数和第四个参数都相等就是圆了,那些参数表示什么意思呢?
查看一下jdk api

/**
     * Draws the outline of an oval.
     * The result is a circle or ellipse that fits within the
     * rectangle specified by the <code>x</code>, <code>y</code>,
     * <code>width</code>, and <code>height</code> arguments.
     * <p>
     * The oval covers an area that is
     * <code>width&nbsp;+&nbsp;1</code> pixels wide
     * and <code>height&nbsp;+&nbsp;1</code> pixels tall.
     * @param       x the <i>x</i> coordinate of the upper left
     *                     corner of the oval to be drawn.
     * @param       y the <i>y</i> coordinate of the upper left
     *                     corner of the oval to be drawn.
     * @param       width the width of the oval to be drawn.
     * @param       height the height of the oval to be drawn.
     * @see         java.awt.Graphics#fillOval
     */
    public abstract void drawOval(int x, int y, int width, int height);

API说:

x表示 左上角的横坐标
y表示 左上角的纵坐标
width 表示画椭圆的外切矩形的宽
height 表示画椭圆的外切矩形的高

扫描二维码关注公众号,回复: 2626591 查看本文章

也就是说,我们要自己计算圆心
这里写图片描述

解决方案

我们把绘制防御塔的代码改成

  g.drawOval(this.tower.getX(), this.tower.getY(), this.tower.getAttackRangeRadius()*2, this.tower.getAttackRangeRadius()*2);

并把碰撞检测代码改成

  if(Tools.circleAndCircleCollision(new Vector2(this.getX()+this.getAttackRangeRadius(),this.getY()+this.attackRangeRadius),this.getAttackRangeRadius(),new Vector2(this.hero.getX()+this.hero.getR(),this.hero.getY()+this.hero.getR()),this.hero.getR())){
            System.out.println("attacked");
            System.out.println(this.position);
            System.out.println(this.hero.getPosition());
        }

好了再测试一下
这里写图片描述

开源地址

这样圆与圆的碰撞就完成了,上面的代码是本人在写塔防游戏demo,已经在github上了地址:https://github.com/CreOpenDream/EGame

猜你喜欢

转载自blog.csdn.net/cre2017/article/details/81349498