我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java实现简单碰撞检测

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java实现简单碰撞检测

本文实例为大家分享了Java实现简单碰撞检测的具体代码,供大家参考,具体内容如下

在进行Java游戏开发时,我们经常会遇到碰撞检测的问题。如坦克大战中,炮弹与坦克相遇发生爆炸;守卫者游戏中,守卫者发射的箭与怪物相遇使怪物失血;打飞机游戏中,飞机发送的子弹与敌机相遇干掉敌机。这些都需要实现碰撞检测。

我们先来看一类比较简单的碰撞检测:规则图形的碰撞检测。

矩形碰撞检测

作为一个练手的小游戏,游戏中的物体形状一般为矩形区域,这是规则图形。它的碰撞检测可以通过Java API中的Rectangle类来实现碰撞的检测。

Rectangle指的是一个矩形区域,它通过指定左上角位置x和y,以及矩形宽度和高度来确定范围大小。所以经常使用的 Rectangle类构造方法有:


// 构造一个新的 Rectangle,其左上角的坐标为 (0,0),其宽度和高度由同名的参数指定。
public Rectangle(int width, int height)

// 构造一个新的 Rectangle,其左上角被指定为 (x,y),其宽度和高度由同名的参数指定。
public Rectangle(int x, int y, int width, int height) 

和碰撞检测相关的方法:


// 计算此 Rectangle 与指定 Rectangle 的交集
public Rectangle intersection(Rectangle r)

// 确定此 Rectangle 是否与指定的 Rectangle 相交
public boolean intersects(Rectangle r)

如果两个Rectangle对象有交集,那么他们就有碰撞了。如:

这种方法适用于地图中的物体近似为矩形或者虽然不是矩形,但是碰撞精度要求不高的情况下的碰撞检测。每个物体记录一个能够将自己框住的最小矩形的左上角坐标和矩形长宽。

采用此种方法进行碰撞检测需要注意,对于图片的实现处理应该尽量的去掉图标边角的空白,不然实际效果可以产生肉眼可辨的误差。也就是说Rectangle尽量的包住图形且Rectangle的区域尽量小。

示例:


import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;

import javax.swing.JFrame;
import javax.swing.JOptionPane;


public class Intersection extends JFrame implements Runnable {

    private static final long serialVersionUID = 156638225301569550L;
    private MediaTracker mediaTracker; // 媒体追踪器
    private Image[][] images = new Image[2][4]; // 放置所有切割的图像
    private Image[] moveTanks = new Image[2]; // 放置界面移动的两辆坦克
    private Point[] points = new Point[2]; // 两辆坦克坐标

    public Intersection() {
        setTitle("碰撞检测");
        setSize(200, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        cutImage(); // 切割图形
        
        mediaTracker = new MediaTracker(this);
        for (int i = 0, length = images.length; i < length; i++) {
            for (int j = 0, len = images[i].length; j < len; j++) {
                mediaTracker.addImage(images[i][j], i * len + j);
            }
        }

        // 等待所有图像加载完毕
        try {
            mediaTracker.waitForAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 初始化两辆坦克在窗体中坐标
        moveTanks[0] = createImage(images[0][0].getSource());
        moveTanks[1] = createImage(images[0][0].getSource());
        points[0] = new Point(80, 200);
        points[1] = new Point(80, 100);

        setVisible(true);
    }

    
    private void cutImage() {
        // 获取源图像
        Image img = Toolkit.getDefaultToolkit().getImage("images/boss.gif");
        // 循环分割图像
        for (int i = 0, length = images.length; i < length; i++) {
            for (int j = 0, len = images[i].length; j < len; j++) {
                ImageFilter filter = new CropImageFilter(0, 0, 50, 50);
                ImageProducer producer = new FilteredImageSource(
                        img.getSource(), filter);
                images[i][j] = createImage(producer); // 将分割后图像放入数组中保存
            }
        }
    }

    @Override
    public void paint(Graphics g) {
        Image img = createImage(this.getWidth(), this.getHeight());
        Graphics graphics = img.getGraphics();
        // 将两辆坦克在窗体中绘制出来
        for (int i = 0, len = moveTanks.length; i < len; i++) {
            graphics.drawImage(moveTanks[i], points[i].x, points[i].y, this);
        }
        g.drawImage(img, 0, 0, this);
        g.dispose();
    }

    @Override
    public void run() {
        while (true) {
            // 每次第二辆坦克移动距离比第一辆坦克大,即第二辆移动更快一些
            points[0].y += 30;
            points[1].y += 45;
            // 重绘
            repaint();

            
            // 第一辆坦克的矩形范围
            Rectangle tank1 = new Rectangle(points[0].x, points[0].y,
                    moveTanks[0].getWidth(null), moveTanks[0].getHeight(null));
            // 第二辆坦克的矩形范围
            Rectangle tank2 = new Rectangle(points[1].x, points[1].y,
                    moveTanks[1].getWidth(null), moveTanks[1].getHeight(null));
            // 判断两个矩形是否有交集,有则说明碰撞了
            if (tank1.intersects(tank2)) {
                JOptionPane.showMessageDialog(null, "碰到了", "提示",
                        JOptionPane.INFORMATION_MESSAGE);
                break;
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new Intersection()).start();
    }
}

当同方向移动时,两坦克发生碰撞,结果:

圆形碰撞检测

圆形检测与矩形检测方法类似,区别在于用一个能够包含物体的圆代替了矩形。主要是考虑到游戏中的物体外形以平滑为主,例如人物角色。而判断两个圆是否碰撞的计算也很简单,就是判断两个圆心之间的距离是否小于两个圆的半径之和。

示例:


import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JOptionPane;


public class Intersection2 extends JFrame implements Runnable {
    
    private int x1 = 15, y1 = 45;
    private int x2 = 35, y2 = 70;
    private int r1 = 16, r2 = 18;

    public Intersection2() {
        setTitle("碰撞检测");
        setSize(200, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        
        g.drawOval(x1, y1, 2 * r1, 2 * r1);
        g.drawOval(x2, y2, 2 * r2, 2 * r2);
    }

    @Override
    public void run() {
        
        // 两圆中心坐标
        int centerX1 = x1 + r1, centerY1 = y1 + r1;
        int centerX2 = x2 + r2, centerY2 = y2 + r2;
        // 求两圆的圆心距
        double length = Math.sqrt(Math.pow(centerX1 - centerX2, 2)
                + Math.pow(centerY1 - centerY2, 2));
        // 判断圆心距与两圆半径和的关系
        if (length < (r1 + r2)) {
            JOptionPane.showMessageDialog(null, "圆心距:" + length + ",碰撞了");
        } else {
            JOptionPane.showMessageDialog(null, "圆心距:" + length + ",未碰撞");
        }
    }

    public static void main(String[] args) {
        new Thread(new Intersection2()).start();
    }
}

运行结果:

将第一个圆半径改为18,则:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java实现简单碰撞检测

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用Java编写一个碰撞检测功能

本篇文章给大家分享的是有关使用Java编写一个碰撞检测功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。碰撞检测的过程处理主要有以下三步:1.碰撞检测(Collision De
2023-05-30

使用Canvas怎么实现文字碰撞检测并抽稀

使用Canvas怎么实现文字碰撞检测并抽稀?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。计算文字在 canvas 中所占据的范围// 计算文字所需的宽度var p = {
2023-06-09

游戏开发中的碰撞检测与处理机制(如何实现游戏中精确的碰撞检测与处理?)

碰撞检测和处理机制对于游戏开发至关重要,确保物体相互作用真实。精确检测和处理碰撞可以创建身临其境的游戏体验。有边界框、像素完美和网格等碰撞检测方法,每种方法都有其优点和缺点。碰撞处理包括刚体物理、脚本和状态机。要实现精确碰撞检测,需要考虑精度水平、实时性能和物体复杂性。具体实现涉及选择检测方法、定义处理机制、优化性能和进行广泛测试。最佳实践包括使用混合方法、利用空间分区、缓存结果和更新数据。精确的碰撞检测和处理对于创建可玩性和身临其境的玩家体验是必不可少的。
游戏开发中的碰撞检测与处理机制(如何实现游戏中精确的碰撞检测与处理?)
2024-04-02

Pygame浅析动画精灵和碰撞检测实现方法

这篇文章主要介绍了利用pygame完成动画精灵和碰撞检测,代码详细,内容丰富,对于想要学习pygame的朋友来讲是一个不错的练习,需要的朋友可以参考下
2023-01-17

怎么在Html5中使用Canvas实现动画碰撞检测功能

本篇文章为大家展示了怎么在Html5中使用Canvas实现动画碰撞检测功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。html有什么特点1、简易性:超级文本标记语言版本升级采用超集方式,从而更加灵
2023-06-09

使用Python快速实现简单的人脸检测

最近有个比较要好的朋友问我能不能从监控视频里识别到从监控跟前经过的指定的人。因为他们单位的监控室经常要花大量的人力跟时间去找某个人在哪个位置出现过的证据。听起来像是一份比较有挑战性的任务,就答应他试试看。先理一下思路,首先要做的工作是从视频
2023-01-31

Java中如何实现小球碰撞并使用按钮控制数量

这篇文章将为大家详细讲解有关Java中如何实现小球碰撞并使用按钮控制数量,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。先根据程序要求写了一个窗口package three.day; import java
2023-06-22

JAVA如何实现心跳检测

本篇内容主要讲解“JAVA如何实现心跳检测”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JAVA如何实现心跳检测”吧!1、心跳机制简介在分布式系统中,分布在不同主机上的节点需要检测其他节点的状态
2023-07-05

JAVA实现心跳检测(长连接)

本文主要介绍了JAVA实现心跳检测(长连接),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-03-01

Java如何实现简单SPI

本文小编为大家详细介绍“Java如何实现简单SPI”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java如何实现简单SPI”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。SPI标注注解标注提供SPI能力接口的注解
2023-07-05

Java Web中如何实现入侵检测

这篇文章主要介绍Java Web中如何实现入侵检测,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!  Java Web应用大致分为两种,一种纯JSP(+Java Bean)方式,一种是基于框架(如Struts、Easy
2023-06-03

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录