矩形碰撞算法
在2D游戏中,通常使用AABB(Axis-Aligned Bounding Box,轴对齐的包围盒)来进行碰撞检测。这种方法的主要思想是,如果两个物体在各自的X轴和Y轴上的投影都有重叠,那么这两个物体就是碰撞的。
具体来说,如果你有两个物体A和B,每个物体都有各自的位置(X,Y)和尺寸(宽度,高度),你可以通过以下步骤来进行碰撞检测:
首先,你需要确定每个物体的边界。物体A的边界是 (A.X, A.Y) 到 (A.X + A.Width, A.Y + A.Height),物体B的边界是 (B.X, B.Y) 到 (B.X + B.Width, B.Y + B.Height)。
然后,检查这两个边界是否有重叠。如果物体A的右边界超过物体B的左边界,或者物体A的下边界超过物体B的上边界,那么这两个物体就没有碰撞。数学表达式如下:
- A.X + A.Width < B.X
- A.Y + A.Height < B.Y
- B.X + B.Width < A.X
- B.Y + B.Height < A.Y
只有当这四个条件都不满足时,物体A和B才会碰撞。
以上是一种基本的碰撞检测方法,实际的游戏开发中可能会有更复杂的需求,例如考虑物体的旋转、形变等,这时可能需要使用更复杂的碰撞检测算法。
创建Alive.java接口
package com.xzm.tank;
import java.awt.*;
/**
* @Author XueZhimin
* @PROJECT_NAME: Java_Lab001
* @Description 活着的意义
* @Date 2023/9/17 18:01
* @Version 1.0
*/
public interface Alive Cloneable {
/**
* 物体X轴
* @return
*/
Integer aliveX();
/**
* 物体Y轴
* @return
*/
Integer aliveY();
/**
* 物体宽度
* @return
*/
Integer aliveWidth();
/**
* 物体高度
* @return
*/
Integer aliveHeight();
/**
* 显示绘图
*
* @param g
*/
default void showDraw(Graphics g) {}
/**
* 画形状
*
* @param g
*/
default void drawShape(Graphics g) {}
/**
* 碰撞检测
* @param other 其他物体
* @return true表示碰撞了
*/
default boolean isColliding(Alive other) {return false;}
}
Tank类实现
/**
* @Author XueZhimin
* @PROJECT_NAME: Java_Lab001
* @Description Tank类
* @Date 2023/9/15 22:31
* @Version 1.0
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Tank extends JPanel implements Alive {
/**
* 图像图标:默认为上
*/
protected ImageIcon imageIcon = tankImageIcon.getUpIcon();
/**
* 图片描边颜色
*/
protected Color imageStrokeColor;
/**
* 坦克的初始X坐标
*/
protected Integer tankX = 100;
/**
* 坦克的初始Y坐标
*/
protected Integer tankY = 100;
/**
* 碰撞检测
* @param other 其他物体
* @return
*/
@Override
public boolean isColliding(Alive other) {
return (this.aliveX() + this.aliveWidth() > other.aliveX()) &&
(this.aliveX() < other.aliveX() + other.aliveWidth()) &&
(this.aliveY() + this.aliveHeight() > other.aliveY()) &&
(this.aliveY() < other.aliveY() + other.aliveHeight());
}
@Override
public Integer aliveX() {
return this.tankX;
}
@Override
public Integer aliveY() {
return this.tankY;
}
@Override
public Integer aliveWidth() {
return this.imageIcon.getIconWidth();
}
@Override
public Integer aliveHeight() {
return this.imageIcon.getIconHeight();
}
}
测试运行
public static void main(String[] args) {
ImageIcon downIcon = new TankImageIconImpl().getDownIcon();
System.out.println("图片尺寸:宽x高"+downIcon.getIconWidth()+","+downIcon.getIconHeight());
Tank tank1 = new Tank(0,0);
tank1.setImageIcon(new TankImageIconImpl().getDownIcon());
Tank tank2 = new Tank(0,119);
tank2.setImageIcon(new TankImageIconImpl().getDownIcon());
boolean colliding = tank1.isColliding(tank2);
System.out.println(colliding);
}
运行结果
图片尺寸:宽x高115,120
true
Process finished with exit code 0
椭圆碰撞算法
椭圆碰撞检测算法的思路涉及使用数学和几何学的原理来确定两个椭圆是否相交或碰撞。以下是椭圆碰撞检测算法的基本思路:
获取椭圆参数:首先,获取每个椭圆的参数。椭圆通常由中心坐标(x,y),水平轴半径(a),和垂直轴半径(b)来定义。
计算椭圆之间的距离:使用两个椭圆的中心坐标,计算它们之间的欧几里德距离。距离计算可以使用以下公式:
distance = sqrt((x1 - x2)^2 + (y1 - y2)^2)
这会计算两个椭圆的中心之间的距离。
检查碰撞:接下来,你需要检查两个椭圆是否相交或碰撞。通常,你会比较两个椭圆的距离与它们各自的水平轴半径和垂直轴半径之和。
- 如果
distance <= a1 + a2
且distance <= b1 + b2
,其中a1
和a2
分别是两个椭圆的水平轴半径,b1
和b2
分别是两个椭圆的垂直轴半径,那么它们碰撞。这是因为椭圆的外接矩形是一个矩形,因此可以使用矩形的碰撞检测方法来判断椭圆是否碰撞。
返回结果:根据检测的结果,返回布尔值来指示是否碰撞。
这是一种常见的方法来检测两个椭圆是否碰撞。你可以将这个逻辑封装成一个方法,接受两个椭圆的参数,然后返回一个布尔值表示它们是否碰撞。
/**
* 检测两个由它们的位置和尺寸定义的椭圆是否发生碰撞。
*
* @param x1 第一个椭圆的 x 坐标。
* @param y1 第一个椭圆的 y 坐标。
* @param width1 第一个椭圆的宽度。
* @param height1 第一个椭圆的高度。
* @param x2 第二个椭圆的 x 坐标。
* @param y2 第二个椭圆的 y 坐标。
* @param width2 第二个椭圆的宽度。
* @param height2 第二个椭圆的高度。
* @return 如果两个椭圆发生碰撞,则返回 {@code true},否则返回 {@code false}。
*/
private boolean checkCollision(int x1, int y1, int width1, int height1, int x2, int y2, int width2, int height2) {
Rectangle ellipse1 = new Rectangle(x1, y1, width1, height1);
Rectangle ellipse2 = new Rectangle(x2, y2, width2, height2);
return ellipse1.intersects(ellipse2);
}
圆形碰撞检测算法
圆形碰撞检测算法的思路相对简单,涉及到使用欧几里德几何学原理来确定两个圆形是否相交或碰撞。以下是圆形碰撞检测算法的基本思路:
获取圆形参数:首先,获取每个圆形的参数,通常是中心坐标(x,y)和半径(r)。
计算圆心距离:使用两个圆的中心坐标,计算它们之间的欧几里德距离。距离计算可以使用以下公式:
distance = sqrt((x1 - x2)^2 + (y1 - y2)^2)
这计算了两个圆心之间的距离。
检查碰撞:接下来,你需要检查两个圆是否相交或碰撞。通常,你会比较两个圆心之间的距离与它们各自的半径之和。
- 如果
distance <= r1 + r2
,其中r1
和r2
分别是两个圆的半径,那么它们碰撞。这是因为两个圆的最远点之间的距离正是它们半径之和。
返回结果:根据检测的结果,返回布尔值来指示是否碰撞。
这是一种常见的方法来检测两个圆是否碰撞。你可以将这个逻辑封装成一个方法,接受两个圆的参数,然后返回一个布尔值表示它们是否碰撞。这个算法适用于简单的圆形碰撞检测,但对于椭圆或更复杂的几何形状,需要使用更复杂的碰撞检测方法。
/**
* 检测两个圆形是否碰撞。
*
* @param x1 第一个圆的中心点 x 坐标。
* @param y1 第一个圆的中心点 y 坐标。
* @param radius1 第一个圆的半径。
* @param x2 第二个圆的中心点 x 坐标。
* @param y2 第二个圆的中心点 y 坐标。
* @param radius2 第二个圆的半径。
* @return 如果两个圆形发生碰撞,则返回 {@code true},否则返回 {@code false}。
*/
private boolean checkCircleCollision(int x1, int y1, int radius1, int x2, int y2, int radius2) {
// 计算两个圆心之间的距离
double distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
// 如果两个圆心之间的距离小于两个半径之和,则发生碰撞
return distance < (radius1 + radius2);
}