虽然碰撞检测不一定要自己去写,一些游戏引擎直接就提供了相关的方法。但是掌握了碰撞检测的基本方法,还是想当有用的。
2D游戏中碰撞一般是矩形的碰撞,但是一般会有一些误差,因为边缘可能是透明的。
以下介绍3种碰撞检测的方法:
1. 圆的碰撞检测
碰撞条件:
两个圆心的距离 < 两圆半径和 则碰撞
2. 矩形的碰撞检测方法1
碰撞条件:
x抽距离差 < 两矩形宽度之和 / 2
y抽距离差 < 两矩形高度之和 / 2
3. 矩形的碰撞检测方法2
碰撞条件:
s表示起点,e表示终点。需要知道矩形的两点。
一般在实际中
第二种与第三种任选一种即可。
第一种 “ 圆的碰撞检测 ” 代码:
public class CircleCrash extends SurfaceView implements SurfaceHolder.Callback,
Runnable
{
private SurfaceHolder holder;
private Canvas canvas;
private boolean isRunning = true;
private Paint paint;
private float cx, cy;//动圆的圆心坐标
public CircleCrash(Context context)
{
super(context);
this.setFocusable(true);
holder = this.getHolder();//这个this指的是这个Surface
holder.addCallback(this); //这个this表示实现了Callback接口
paint = new Paint();
}
@Override
public void run()
{
while (isRunning)
{
drawView();
try
{
Thread.sleep(100);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
private void drawView()
{
try
{
if (holder != null)
{
//draw
canvas = holder.lockCanvas();
canvas.drawColor(Color.BLACK);
paint.setColor(Color.BLUE);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0,
Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
// 圆的碰撞 (一个动的圆去碰撞一个禁止的圆, 碰撞后动圆禁止)
canvas.drawCircle(150, 150, 33, paint); //禁止的圆
//碰撞检测 . (没有碰撞时cx,cy自增, 即圆移动)
if (Math.sqrt((150 - cx) * (150 - cx) + (150 - cy) * (150 - cy)) > (33 + 22))
{
cx+=3;
cy+=3;
System.out.println(cx + " " + cy);
}
canvas.drawCircle(cx, cy, 22, paint); //动的圆(都在对角线上运动)
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
new Thread(this).start();
isRunning = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
isRunning = false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
isRunning = false;
return super.onKeyDown(keyCode, event);
}
}
效果:
第二种 “ 矩形的碰撞检测1 ” 代码:(核心部分)
private void drawView()
{
try
{
if (holder != null)
{
//draw
canvas = holder.lockCanvas();
canvas.drawColor(Color.BLACK);
paint.setColor(Color.BLUE);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0,
Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
//矩形的碰撞 (碰撞后动的矩形禁止)
canvas.drawRect(150, 151, 220, 221, paint);
//当没有碰撞时才自增移动
if (!((150 - cx) < (70 + 60) / 2 && (151 - cy) < (70 + 60) / 2))
{
cx += 4;
cy += 4;
}
canvas.drawRect(cx, cy, cx + 60, cy + 60, paint);//动的矩形(都在对角线上运动)
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
}
效果:
第三种 “ 矩形的碰撞检测 2” 代码:
private void drawView()
{
try
{
if (holder != null)
{
//draw
canvas = holder.lockCanvas();
canvas.drawColor(Color.BLACK);
paint.setColor(Color.BLUE);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0,
Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
//矩形的碰撞 (碰撞后动的矩形禁止)
//s(150,151), e(220,221)
canvas.drawRect(150, 151, 220, 221, paint);
//当没有碰撞时才自增移动(取反)
if (220 <= cx || 221 <= cy || 150 >= (cx + 60)
|| 151 >= (cy + 60))
{
cx += 5;
cy += 5;
}
canvas.drawRect(cx, cy, cx + 60, cy + 60, paint);//动的矩形(都在对角线上运动)
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
}