因为写弹球游戏,有涉及到矩形和圆的碰撞,网上搜了一下,有简单有复杂,参考写了一个Demo放到这里。
矩形和圆的碰撞,分两种情况,一种是圆碰到矩形的四边(如上图中的圆心在1,2,3,4四块区域),还一种是圆刚好正中矩形的四个顶角(如上图中圆心在5,6,7,8四地位区域)。
直接上代码:
package com.android.ball;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class TestHit extends View implements Runnable {
private int ball_x, ball_y, ball_r, left, top, right, bottom;
private int offsetX = 5; // 圆移动的X步长
private int offsetY = 5; // 圆移动的Y步长
private Paint paint_Ball, paint_Rect;
public TestHit(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public TestHit(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public TestHit(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
/**
* 初始化数据
*/
private void init() {
ball_x = 100; // 圆心的X
ball_y = 100; // 圆心的Y
ball_r = 20; // 圆的半径(半径要大于移动的步长)
left = 180;
top = 320;
right = 300;
bottom = 480;
paint_Ball = new Paint();
paint_Ball.setAntiAlias(true);
paint_Ball.setColor(0xfff444f4);
paint_Rect = new Paint();
paint_Rect.setColor(0xff220066);
new Thread(this).start();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
// 画圆
canvas.drawCircle(ball_x, ball_y, ball_r, paint_Ball);
// 画矩形
canvas.drawRect(left, top, right, bottom, paint_Rect);
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
while (true) {
Thread.sleep(10);
ball_x += offsetX;
ball_y += offsetY;
// 判断圆和屏幕四周的碰撞
hitAround();
// 判断圆和矩形的碰撞
hitRect();
postInvalidate(); // 刷新
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 判断圆和屏幕四周的碰撞 假设屏幕是 480*800 注意:此测试程序应是全屏,不然800高屏幕底部会越界
*/
private void hitAround() {
if (ball_x - ball_r <= 0 || ball_x + ball_r >= 480) { // 判断和左右两边的碰撞
offsetX *= -1; // 反弹
// Log.e(VIEW_LOG_TAG, "圆碰撞到屏幕左右边界");
}
if (ball_y - ball_r <= 0 || ball_y + ball_r >= 800) { // 判断和上下两边的碰撞
offsetY *= -1; // 反弹
// Log.e(VIEW_LOG_TAG, "圆碰撞到屏幕上下边界");
}
}
/**
* 判断圆和矩形的碰撞
*/
private void hitRect() {
// 球在1,3区域的碰撞判断
if (ball_x >= left && ball_x <= right) {
if (ball_y + ball_r >= top && ball_y < top) { // 1区域判断
offsetY *= -1;
Log.e(VIEW_LOG_TAG, "圆在1区域碰到矩形");
} else if (ball_y - ball_r <= bottom && ball_y > bottom) { // 3区域判断
offsetY *= -1;
Log.e(VIEW_LOG_TAG, "圆在3区域碰到矩形");
}
}
// 球在2,4区域的碰撞判断
if (ball_y >= top && ball_y <= bottom) {
if (ball_x - ball_r <= right && ball_x > right) { // 2区域判断
offsetX *= -1;
Log.e(VIEW_LOG_TAG, "圆在2区域碰到矩形");
} else if (ball_x + ball_r >= left && ball_x < left) { // 4区域判断
offsetX *= -1;
Log.e(VIEW_LOG_TAG, "圆在4区域碰到矩形");
}
}
// 圆在5区域的碰撞判断
if (Math.pow(left - ball_x, 2) + Math.pow(top - ball_y, 2) <= Math.pow(
ball_r, 2) && ball_x < left && ball_y < top) {
offsetX *= -1;
offsetY *= -1;
Log.e(VIEW_LOG_TAG, "圆在5区域碰到矩形");
}
// 圆在6区域的碰撞判断
if (Math.pow(ball_x - right, 2) + Math.pow(top - ball_y, 2) <= Math
.pow(ball_r, 2) && ball_x > right && ball_y < top) {
offsetX *= -1;
offsetY *= -1;
Log.e(VIEW_LOG_TAG, "圆在6区域碰到矩形");
}
// 圆在7区域的碰撞判断
if (Math.pow(ball_x - right, 2) + Math.pow(ball_y - bottom, 2) <= Math
.pow(ball_r, 2) && ball_x > right && ball_y > bottom) {
offsetX *= -1;
offsetY *= -1;
Log.e(VIEW_LOG_TAG, "圆在7区域碰到矩形");
}
// 圆在8区域的碰撞判断
if (Math.pow(left - ball_x, 2) + Math.pow(ball_y - bottom, 2) <= Math
.pow(ball_r, 2) && ball_x < left && ball_y > bottom) {
offsetX *= -1;
offsetY *= -1;
Log.e(VIEW_LOG_TAG, "圆在8区域碰到矩形");
}
}
}
当然,上面只是一个View文件,要运行看效果的话,用个MainActivity创建这个View对象就可以了,代码:
package com.android.ball;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private TestHit testHit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
testHit = new TestHit(this);
setContentView(testHit);
}
}
嫌网页看着不爽的,可以下载Demo源码,地址在: http://download.csdn.net/detail/bellovin/6641309