Java Applet 冲突检测简单版

游戏中很重要的一个部分是检测物体之间的冲突。下面我们就来一起看看如何来通过边界盒来检测冲突。

这里讲的冲突是针对于刚体的,就是说这里所说的两个物体不会同时在同一空间存在。当我们检测出冲突时,就能够触发另一种状态。

测试实际的像素点显然非常耗时,所我们尝试用简单图形(比如说长方形)来框住物体,从而我们近似地将长方形之间的冲突看做物体之间的冲突。

长方形之间的相互重叠比较容易检测出来,所以我们选择他来作为我们检测冲突的边界盒。下面来看看示例代码:

import java.applet.Applet;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;
import java.util.Random;


public class CollisionTest extends Applet implements MouseListener, MouseMotionListener{

	private final int NUM_RECTS = 10;
	private LinkedList rectangles;
	private AlphaComposite alpha;
	private Rectangle2D pick;
	private Image bufImg;
	private Graphics bufG;
	
	public void init()
	{
		rectangles = new LinkedList();
		pick = null;
		
		alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
		Random r = new Random();
		int width = (int)getSize().getWidth();
		int height = (int)getSize().getHeight();
		for(int i = 0 ; i < NUM_RECTS ; i++)
		{
			rectangles.add(new Rectangle2D.Double(
					(double) Math.abs(r.nextInt())%width,
					(double) Math.abs(r.nextInt())%height,
					(double) Math.abs(r.nextInt())%50,
					(double) Math.abs(r.nextInt())%50));
			
		}
		addMouseListener(this);
		addMouseMotionListener(this);
	}
	
	@Override
	public void update(Graphics g) {
		bufImg = this.createImage(this.getWidth(), this.getHeight());
		bufG = bufImg.getGraphics();
		paint(bufG);
		g.drawImage(bufImg, 0, 0, this);
	}
	
	public void paint(Graphics g)
	{
		Graphics2D g2d = (Graphics2D) g;
		g2d.setComposite(alpha);
		g2d.setPaint(Color.BLACK);
		for(int i = 0 ; i < NUM_RECTS ; i++)
		{
			g2d.draw((Rectangle2D.Double) rectangles.get(i));
		}
		if(pick != null)
		{
			Rectangle2D rect;
			g2d.setPaint(Color.RED.darker());
			for(int i = 0 ; i < NUM_RECTS ; i++)
			{
				rect = (Rectangle2D) rectangles.get(i);
				if(pick != rect && pick.intersects(rect))
				{
					g2d.fill(rect);
				}
			}
			g2d.setPaint(Color.BLUE.brighter());
			g2d.fill(pick);
		}
	}
	
	@Override
	public void mouseDragged(MouseEvent arg0) {
		// TODO Auto-generated method stub
		if(pick != null)
		{
			pick.setRect(arg0.getX()-pick.getWidth()/2, arg0.getY()-pick.getHeight()/2, pick.getWidth(), pick.getHeight());
			repaint();
		}
	}

	public void mouseMoved(MouseEvent arg0) {}
	public void mouseClicked(MouseEvent arg0) {}
	public void mouseEntered(MouseEvent arg0) {}
	public void mouseExited(MouseEvent arg0) {}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		if(pick == null)
		{
			Rectangle2D rect;
			for(int i = 0 ; i < NUM_RECTS ; i++)
			{
				rect = (Rectangle2D) rectangles.get(i);
				if(rect.contains(arg0.getPoint()))
				{
					pick = rect;
					break;
				}
			}
		}
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		pick = null;
		repaint();
	}
}


成员变量中的NUM_RECTS表示要随机生成的矩形的数量,rectangles是我们用来存储矩形的一个链表,而AlphaComposite类对象alpha用来设置画图的透明度,pick表示的是当前鼠标选中的矩形。

在init()函数中我们主要做了以下事情:1)初始化链表以及透明成分;2)利用随机数生成指定数量的矩形;3)添加鼠标事件。

在paint()重载函数中,我们将矩形外框画出,同时对于相交的矩形进行颜色填充。同时我们在update()函数中利用双缓冲,使得显示效果不那么闪烁。

在mousePressed()方法中,我们设置选取的长方形。(利用了Rectangle2D中的contains方法),在mouseReleased释放选中长方形,同时在mouseDragged中设置拖动长方形的功能(利用了Rectangle2D中的setRect方法)。

实现的功能如图所示:

 

这里讲的仅是简单的冲突检测,所以它必然有很多缺陷。比如长方形与原来的形状之间有很多空隙,但是当这些空隙相重叠时我们会检测出不应该检测到得冲突。所以呢,继续学习吧,看看后面还有什么好方法。O(∩_∩)O~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值