java碰撞_JAVA小游戏之两个物体碰撞产生的碰撞检测

本文介绍了如何在JAVA中进行物体碰撞检测,包括使用Rectangle类进行矩形碰撞检测,以及通过计算圆心距判断圆形碰撞。通过示例代码详细展示了碰撞检测的实现过程。
摘要由CSDN通过智能技术生成

首先必须了解两个物体,在移动时,会有怎样的效果,比如沪我们小时候耍过的坦克大战。看起来很简单,但是写起代码来,复杂的要多;

下面举个例子:

// 构造一个新的 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对象有交集,那么他们就有碰撞了。如:

6e8aa4d2940b4977f7f19e8e8fdc84b6.png

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

采用此种方法进行碰撞检测需要注意,对于图片的实现处理应该尽量的去掉图标边角的空白,不然实际效果可以产生肉眼可辨的误差。也就是说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;

/**

* 碰撞检测测试,判断两个同方向移动的坦克是否会发生碰撞

*

*@author 小明

*

*/

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();

}

}

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

33dcfba089c5a0614ecce41f8af0b53c.png

圆形碰撞检测

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

示例:

import java.awt.Graphics;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

/**

* 碰撞检测测试,判断两个圆是否会发生碰撞

*

*@author 小明

*

*/

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();

}

}

运行结果:

db47ef97c7d915fa919a9d123807170c.png

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

d0b71643e14bb9bfc2773a3aa9c1d0d8.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值