`
wo_deqing
  • 浏览: 64224 次
文章分类
社区版块
存档分类
最新评论

android 碰撞检测

 
阅读更多
Region是一个类,这个类比较常用的方法就是用于判断一个点是否在矩形区域内,其方法是使是Regions类中的contains(int x, int y)函数创建实例:RegionCollsion
项目运行效果:

1.jpg


package com.rectCollsion;
  
 
import android.content.Context;
  
import android.graphics.Canvas;
  
import android.graphics.Color;
  
import android.graphics.Paint;
  
import android.graphics.Paint.Style;
  
import android.graphics.Rect;
  
import android.view.KeyEvent;
  
import android.view.MotionEvent;
  
import android.view.SurfaceHolder;
  
import android.view.SurfaceHolder.Callback;
  
import android.view.SurfaceView;
  
 
public class MySurfaceView extends SurfaceView implements Callback,Runnable{
  
        //用于控制SurfaceView
  
        private SurfaceHolder sfh;
  
        //声明一个画笔
  
        private Paint paint;
  
        //声明一个线程
  
        private Thread th;
  
        //线程消亡的标志位
  
        private boolean flag;
  
        //声明一个画布
  
        private Canvas canvas;
  
        //声明屏幕的宽高
  
        private int screenW,screenH;
  
        //定义两个矩形的宽高坐标
  
        private int rectX1 = 10,rectY1 = 10,rectW1 = 40,rectH1 = 40;
  
        private int rectX2 = 100,rectY2 = 110,rectW2 = 40,rectH2 = 40;
  
        //便于观察是否发生碰撞设置一个标识位
  
        private boolean isCollsion;
  
        //定义第一个矩形的矩形碰撞数组
  
        private Rect clipRect1 = new Rect(0,0,15,15);
  
        private Rect clipRect2 = new Rect(rectW1 - 15, rectH1 - 15,rectW1,rectH1);
  
        private Rect[] arrayRect1 = new Rect[]{clipRect1,clipRect2};
  
        //定义第二个矩形的矩形碰撞数组
  
        private Rect clipRect3 = new Rect(0,0,15,15);
  
        private Rect clipRect4 = new Rect(rectW2 - 15,rectH2 - 15,rectW2,rectH2);
  
        private Rect[] arrayRect2 = new Rect[]{clipRect3,clipRect4};
  
         
  
        /**
  
         * SurfaceView初始化函数
  
         */
  
        public MySurfaceView(Context context){
  
                super(context);
  
                //实例SurfaceHolder
  
                sfh = this.getHolder();
  
                //为SurfaceView添加状态监听
  
                sfh.addCallback(this);
  
                //实例一个画笔
  
                paint = new Paint();
  
                //设置画笔颜色为白色
  
                paint.setColor(Color.WHITE);
  
                //设置焦点
  
                setFocusable(true);
  
        }
  
        @Override
  
        public void surfaceCreated(SurfaceHolder holder) {
  
                // TODO Auto-generated method stub
  
                screenW = this.getWidth();
  
                screenH = this.getHeight();
  
                flag = true;
  
                //实例线程
  
                th = new Thread(this);
  
                //启动线程
  
                th.start();
  
        }
  
         
  
         
  
        /**
  
         * 游戏绘图
  
         */
  
        public void myDraw(){
  
                try {
  
                        canvas = sfh.lockCanvas();
  
                        if(canvas != null){
  
                                //刷屏
  
                                canvas.drawColor(Color.BLACK);
  
                                //判断是否发生了碰撞
  
                                if(isCollsion){//发生碰撞
  
                                        paint.setColor(Color.RED);
  
                                        paint.setTextSize(20);
  
                                        canvas.drawText("Collision!", 0, 30, paint);
  
                                         
                                } else{//没发生碰撞
  
                                        paint.setColor(Color.WHITE);
  
                                }
  
                                //绘制两个矩形
  
                                canvas.drawRect(rectX1, rectY1, rectX1 + rectW1, rectY1 + rectH1, paint);
  
                                canvas.drawRect(rectX2, rectY2, rectX2 + rectW2, rectY2 + rectH2, paint);
  
                                //----绘制碰撞区为非填充,并设置画笔为白色
  
                                paint.setStyle(Style.STROKE);
  
                                paint.setColor(Color.WHITE);
  
                                //---绘制第一个矩形所有矩形碰撞区域
  
                                for(int i=0; i < arrayRect1.length; i++){
  
                                        canvas.drawRect(arrayRect1[i].left + this.rectX1, arrayRect1[i].top + this.rectY1,
                                                        arrayRect1[i].right + this.rectX1, arrayRect1[i].bottom + this.rectY1, paint);
  
                                }
  
                                //---绘制第二个矩形所有矩形碰撞区域
  
                                for(int i=0;i < arrayRect2.length; i++){
  
                                        canvas.drawRect(arrayRect2[i].left + this.rectX2, arrayRect2[i].top + this.rectY2,
  
                                                        arrayRect2[i].right + this.rectX2,arrayRect2[i].bottom + this.rectY2, paint);
  
                                }
  
                                 
  
                        }
  
                }catch(Exception e){
  
                         
  
                }finally{
  
                        if(canvas != null)
  
                                sfh.unlockCanvasAndPost(canvas);
  
                }
  
        }
  
        /**
  
         * 触屏事件监听
  
         */
  
        @Override
  
        public boolean onTouchEvent(MotionEvent event) {
  
                // TODO Auto-generated method stub
  
                //让矩形1随着触屏位置移动(触屏点设为此矩形的中心点)
  
                rectX1 = (int) event.getX() - rectW1/2;
  
                rectY1 = (int) event.getY() - rectH1/2;
  
                //当矩形之间发生碰撞
  
                if(isCollsionWithRect(arrayRect1, arrayRect2)){
  
                        isCollsion = true;//设置标志位为真
  
                        //当矩形之间没有发生碰撞
  
                }else{
  
                        isCollsion = false; //设置标志位为假
  
                }
  
                return true;
  
        }
  
        /**
  
         * 矩形碰撞的函数
  
         * @param left 表示矩形左上角坐标的X坐标
  
         * @param top  表示矩形左上角坐标Y坐标
  
         * @param right 表示矩形右下角坐标X坐标
  
         * @param buttom 表示矩形右下角坐标Y坐标
  
         */
  
        public boolean isCollsionWithRect(Rect[] rectArray, Rect[] rect2Array){
  
                Rect rect = null;
  
                Rect rect2 = null;
  
                for(int i = 0; i < rectArray.length; i++){
  
                        //依次取出第一个矩形数组的每个矩形实例
  
                        rect = rectArray[i];
  
                        //获取到第一个矩形数组中每个矩形元素的属性值
  
                        int x1 = rect.left + this.rectX1;
  
                        int y1 = rect.top + this.rectY1;
  
                        int w1 = rect.right - rect.left;
  
                        int h1 = rect.bottom - rect.top;
  
                        for(int j = 0; j < rect2Array.length; j++){
  
                                //依次取出第二个矩形数组的每个矩形实例
  
                                rect2 = rect2Array[i];
  
                                //获取到第二个矩形数组中每个矩形的属性值
  
                                int x2 = rect2.left + this.rectX1;
  
                                int y2 = rect2.top + this.rectY2;
  
                                int w2 = rect2.right - rect2.left;
  
                                int h2 = rect2.bottom - rect2.top;
  
                                //进行循环遍历两个矩形碰撞数组所有元素之间的位置关系
  
                                if(x1 >= x2 && x1 > x2 + w2){
  
                                }else if(x1 <= x2 && x1 + w1 <= x2) {
  
                                }else if(y1 >=y2 && y1 >= y2 + h2){
  
                                }else if(y1 <=y2 && y1 + h1 <= y2){
  
                                }else {
  
                                        //只要有一个碰撞矩形数组与另一个碰撞矩形数组发生碰撞则认为碰撞
  
                                        return true;
  
                                }
  
                        }
  
                }
  
                return false;
  
        }
  
 
         
  
        /**
  
         * 按键事件监听
  
         */
  
        @Override
  
        public boolean onKeyDown(int keyCode, KeyEvent event) {
  
                // TODO Auto-generated method stub
  
                return super.onKeyDown(keyCode, event);
  
        }
  
        /**
  
         * 游戏逻辑
  
         */
  
        private void logic(){
  
                 
        }
  
        @Override
  
        public void run() {
  
                // TODO Auto-generated method stub
  
                while(flag){
  
                        long start = System.currentTimeMillis();
  
                        myDraw();
  
                        logic();
  
                        long end = System.currentTimeMillis();
  
                        try {
  
                                if (end - start < 50) {
  
                                        Thread.sleep(50 - (end - start));
  
                                }
  
                        } catch(InterruptedException e){
  
                                e.printStackTrace();
  
                        }
  
                }
  
                 
        }
  
        /**
  
         * Surfaceview视图状态发生改变,响应此函数
  
         */
  
        @Override
  
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
  
                        int height) {
  
                // TODO Auto-generated method stub
  
                 
        }
  
        /**
  
         * Surfaceview视图消亡,响应此函数
  
         */
  
        @Override
  
        public void surfaceDestroyed(SurfaceHolder holder) {
  
                // TODO Auto-generated method stub
  
                 
        }
  
}


矩形碰撞就是利用两个矩形之间的位置关系来进行判断,如果一个矩形的像素在另外一个矩形之中,或者之上都可以认为这两个矩形发生了碰撞。其实两个矩形不发生碰撞的情况就只有四种,其他情况就是发生碰撞了
创建实例:RectCollion, 游戏框架为SurfaceView
项目效果图:

1.jpg

2.jpg
MySurfaceView.java


package com.rectCollsion;
  
import android.content.Context;
  
import android.graphics.Canvas;
  
import android.graphics.Color;
  
import android.graphics.Paint;
  
import android.view.KeyEvent;
  
import android.view.MotionEvent;
  
import android.view.SurfaceHolder;
  
import android.view.SurfaceHolder.Callback;
  
import android.view.SurfaceView;
  
public class MySurfaceView extends SurfaceView implements Callback,Runnable{
  
//用于控制SurfaceView
  
private SurfaceHolder sfh;
  
//声明一个画笔
  
private Paint paint;
  
//声明一个线程
  
private Thread th;
  
//线程消亡的标志位
  
private boolean flag;
  
//声明一个画布
  
private Canvas canvas;
  
//声明屏幕的宽高
  
private int screenW,screenH;
  
//定义两个矩形的宽高坐标
  
private int x1 = 10,y1 = 110,w1 = 40,h1 = 40;
  
private int x2 = 10,y2 = 110,w2 = 40,h2 = 40;
  
//便于观察是否发生碰撞设置一个标识位
  
private boolean isCollsion;
  
 
/**
  
  * SurfaceView初始化函数
  
  */
  
public MySurfaceView(Context context){
  
  super(context);
  
  //实例SurfaceHolder
  
  sfh = this.getHolder();
  
  //为SurfaceView添加状态监听
  
  sfh.addCallback(this);
  
  //实例一个画笔
  
  paint = new Paint();
  
  //设置画笔颜色为白色
  
  paint.setColor(Color.WHITE);
  
  //设置焦点
  
  setFocusable(true);
  
}
  
@Override
  
public void surfaceCreated(SurfaceHolder holder) {
  
  // TODO Auto-generated method stub
  
  screenW = this.getWidth();
  
  screenH = this.getHeight();
  
  flag = true;
  
  //实例线程
  
  th = new Thread(this);
  
  //启动线程
  
  th.start();
  
}
  
 
 
/**
  
  * 游戏绘图
  
  */
  
public void myDraw(){
  
  try {
  
   canvas = sfh.lockCanvas();
  
   if(canvas != null){
  
    //刷屏
  
    canvas.drawColor(Color.BLACK);
  
    //判断是否发生了碰撞
  
    if(isCollsion){//发生碰撞
  
     paint.setColor(Color.RED);
  
     paint.setTextSize(20);
  
     canvas.drawText("Collision!", 0, 30, paint);
  
      
  
    } else{//没发生碰撞
  
     paint.setColor(Color.WHITE);
  
    }
  
    //绘制两个矩形
  
    canvas.drawRect(x1, y1, x1 + w1, y1 + h1, paint);
  
    canvas.drawRect(x2, y2, x2 + w2, y2 + h2, paint);
  
     
   }
  
  }catch(Exception e){
  
    
  
  }finally{
  
   if(canvas != null)
  
    sfh.unlockCanvasAndPost(canvas);
  
  }
  
}
  
/**
  
  * 触屏事件监听
  
  */
  
@Override
  
public boolean onTouchEvent(MotionEvent event) {
  
  // TODO Auto-generated method stub
  
  //让矩形1随着触屏位置移动(触屏点设为此矩形的中心点)
  
  x1 = (int) event.getX() - w1/2;
  
  y1 = (int) event.getY() - h1/2;
  
  //当矩形之间发生碰撞
  
  if(isCollsionWithRect(x1,y1,w1,h1,x2,y2,w2,h2)){
  
   isCollsion = true;//设置标志位为真
  
   //当矩形之间没有发生碰撞
  
  }else{
  
   isCollsion = false; //设置标志位为假
  
  }
  
  return true;
  
}
  
/**
  
  * 矩形碰撞的函数
  
  * @param x1 第一个矩形的X坐标
  
  * @param y1 第一个矩形的Y坐标
  
  * @param w1 第一个矩形的宽
  
  * @param h1 第一个矩形的高
  
  * @param x2 第二个矩形的X坐标
  
  * @param y2 第二个矩形的Y坐标
  
  * @param w2 第二个矩形的宽
  
  * @param h2 第二个矩形的高
  
  */
  
public boolean isCollsionWithRect(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  
  //当矩形1位于矩形2的左侧
  
  if (x1 >= x2 && x1>= x2 + w2){
  
   return false;
  
  //当矩形1位于矩形2的右侧
  
  } else if (x1<= x2 && x1 + w1 <= x2){
  
   return false;
  
  //当矩形1位于矩形2的上方
  
  } else if (y1 >= y2 && y1>= y2 + h2){
  
   return false;
  
  } else if (y1 <= y2 && y1 + h1 <= y2){
  
   return false;
  
  }
  
  //所有不会发生碰撞都不满足时,肯定就是碰撞了
  
  return true;
  
}
  
 
/**
  
  * 按键事件监听
  
  */
  
@Override
  
public boolean onKeyDown(int keyCode, KeyEvent event) {
  
  // TODO Auto-generated method stub
  
  return super.onKeyDown(keyCode, event);
  
}
  
/**
  
  * 游戏逻辑
  
  */
  
private void logic(){
  
   
  
}
  
@Override
  
public void run() {
  
  // TODO Auto-generated method stub
  
  while(flag){
  
   long start = System.currentTimeMillis();
  
   myDraw();
  
   logic();
  
   long end = System.currentTimeMillis();
  
   try {
  
    if (end - start < 50) {
  
     Thread.sleep(50 - (end - start));
  
    }
  
   } catch(InterruptedException e){
  
    e.printStackTrace();
  
   }
  
  }
  
   
  
}
  
/**
  
  * Surfaceview视图状态发生改变,响应此函数
  
  */
  
@Override
  
public void surfaceChanged(SurfaceHolder holder, int format, int width,
  
   int height) {
  
  // TODO Auto-generated method stub
  
   
  
}
  
/**
  
  * Surfaceview视图消亡,响应此函数
  
  */
  
@Override
  
public void surfaceDestroyed(SurfaceHolder holder) {
  
  // TODO Auto-generated method stub
  
   
  
}
  
}


RectCollsionActivity.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
	
package com.rectCollsion;
  
import android.app.Activity;
  
import android.os.Bundle;
  
import android.view.Window;
  
import android.view.WindowManager;
  
public class RectCollsionActivity extends Activity {
  
    /** Called when the activity is first created. */
  
    @Override
  
    public void onCreate(Bundle savedInstanceState) {
  
        super.onCreate(savedInstanceState);
  
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
          WindowManager.LayoutParams.FLAG_FULLSCREEN);
  
        setContentView(new MySurfaceView(this));
  
    }
  
}


圆形碰撞:主要是利用两圆形的圆心距进行判定的;当两圆的圆心距小于两圆半径之和,判定发生了碰撞。
创建实例:CircleCollsoin
项目效果图:

1.jpg2.jpg
MySurfaceView.java


package com.circleCollsion;
  
import android.content.Context;
  
import android.graphics.Canvas;
  
import android.graphics.Color;
  
import android.graphics.Paint;
  
import android.view.KeyEvent;
  
import android.view.MotionEvent;
  
import android.view.SurfaceHolder;
  
import android.view.SurfaceHolder.Callback;
  
import android.view.SurfaceView;
  
public class MySurfaceView extends SurfaceView implements Callback,Runnable{
  
//用于控制SurfaceView
  
private SurfaceHolder sfh;
  
//声明一个画笔
  
private Paint paint;
  
//声明一个线程
  
private Thread th;
  
//线程消亡的标志位
  
private boolean flag;
  
//声明一个画布
  
private Canvas canvas;
  
//声明屏幕的宽高
  
private int screenW,screenH;
  
//定义两个圆的半径和坐标
  
private int r1 = 20, r2 = 20;
  
private int x1 = 50, y1 = 100, x2 = 150, y2 = 100;
  
//便于观察是否发生碰撞设置一个标识位
  
private boolean isCollsion;
  
 
/**
  
  * SurfaceView初始化函数
  
  */
  
public MySurfaceView(Context context){
  
  super(context);
  
  //实例SurfaceHolder
  
  sfh = this.getHolder();
  
  //为SurfaceView添加状态监听
  
  sfh.addCallback(this);
  
  //实例一个画笔
  
  paint = new Paint();
  
  //设置画笔颜色为白色
  
  paint.setColor(Color.WHITE);
  
  //设置焦点
  
  setFocusable(true);
  
}
  
@Override
  
public void surfaceCreated(SurfaceHolder holder) {
  
  // TODO Auto-generated method stub
  
  screenW = this.getWidth();
  
  screenH = this.getHeight();
  
  flag = true;
  
  //实例线程
  
  th = new Thread(this);
  
  //启动线程
  
  th.start();
  
}
  
 
 
/**
  
  * 游戏绘图
  
  */
  
public void myDraw(){
  
  try {
  
   canvas = sfh.lockCanvas();
  
   if(canvas != null){
  
    //刷屏
  
    canvas.drawColor(Color.BLACK);
  
    //判断是否发生了碰撞
  
    if(isCollsion){//发生碰撞
  
     paint.setColor(Color.RED);
  
     paint.setTextSize(20);
  
     canvas.drawText("Collision!", 0, 30, paint);
  
      
  
    } else{//没发生碰撞
  
     paint.setColor(Color.WHITE);
  
    }
  
    //绘制两个圆
  
    canvas.drawCircle(x1, y1, r1, paint);
  
    canvas.drawCircle(x2, y2, r2, paint);
  
   }
  
  }catch(Exception e){
  
    
  
  }finally{
  
   if(canvas != null)
  
    sfh.unlockCanvasAndPost(canvas);
  
  }
  
}
  
/**
  
  * 触屏事件监听
  
  */
  
@Override
  
public boolean onTouchEvent(MotionEvent event) {
  
  // TODO Auto-generated method stub
  
  x1 = (int) event.getX();
  
  y1 = (int) event.getY() ;
  
  //当圆形之间发生碰撞
  
  if(isCollsionWithCircle(x1,y1,x2,y2,r1,r2)){
  
   isCollsion = true;//设置标志位为真
  
   //当矩形之间没有发生碰撞
  
  }else{
  
   isCollsion = false; //设置标志位为假
  
  }
  
  return true;
  
}
  
/**
  
  * 圆形碰撞
  
  * @param x1圆形1的圆心x坐标
  
  * @param y1圆形1的圆心y坐标
  
  * @param x2圆心2的圆形x坐标
  
  * @param y2圆形2的圆形y坐标
  
  * @param r1圆形1的半径
  
  * @param r2圆形2的半径
  
  */
  
private boolean isCollsionWithCircle(int x1,int y1,int x2,int y2,int r1,int r2){
  
  //Math.sqrt:开平方
  
  //Math.pow(double x,double y):X的Y次方
  
  if(Math.sqrt(Math.pow(x1 - x2, 2)+ Math.pow(y1 - y2,2))<= r1 + r2){
  
   //如果两圆的圆心距小于或等于两圆半径则认为发生碰撞
  
   return true;
  
  }
  
  return false;
  
}
  
 
/**
  
  * 按键事件监听
  
  */
  
@Override
  
public boolean onKeyDown(int keyCode, KeyEvent event) {
  
  // TODO Auto-generated method stub
  
  return super.onKeyDown(keyCode, event);
  
}
  
/**
  
  * 游戏逻辑
  
  */
  
private void logic(){
  
   
  
}
  
@Override
  
public void run() {
  
  // TODO Auto-generated method stub
  
  while(flag){
  
   long start = System.currentTimeMillis();
  
   myDraw();
  
   logic();
  
   long end = System.currentTimeMillis();
  
   try {
  
    if (end - start < 50) {
  
     Thread.sleep(50 - (end - start));
  
    }
  
   } catch(InterruptedException e){
  
    e.printStackTrace();
  
   }
  
  }
  
   
  
}
  
/**
  
  * Surfaceview视图状态发生改变,响应此函数
  
  */
  
@Override
  
public void surfaceChanged(SurfaceHolder holder, int format, int width,
  
   int height) {
  
  // TODO Auto-generated method stub
  
   
  
}
  
/**
  
  * Surfaceview视图消亡,响应此函数
  
  */
  
@Override
  
public void surfaceDestroyed(SurfaceHolder holder) {
  
  // TODO Auto-generated method stub
  
   
  
}
  
}

像素碰撞:在游戏开发中是不推荐使用的,虽然它很精确,但是会造成代码的效率降低。因为有可以代替像素碰撞检测的方法:多矩形、多圆形的检测方式。下面进行介绍

多矩形碰撞:顾名思义就是设置多个矩形碰撞区域
下面创建一个实例:MoreRectCollsion项目
效果图:

1.jpg


package com.rectCollsion;
  
 
import android.content.Context;
  
import android.graphics.Canvas;
  
import android.graphics.Color;
  
import android.graphics.Paint;
  
import android.graphics.Paint.Style;
  
import android.graphics.Rect;
  
import android.view.KeyEvent;
  
import android.view.MotionEvent;
  
import android.view.SurfaceHolder;
  
import android.view.SurfaceHolder.Callback;
  
import android.view.SurfaceView;
  
 
public class MySurfaceView extends SurfaceView implements Callback,Runnable{
  
        //用于控制SurfaceView
  
        private SurfaceHolder sfh;
  
        //声明一个画笔
  
        private Paint paint;
  
        //声明一个线程
  
        private Thread th;
  
        //线程消亡的标志位
  
        private boolean flag;
  
        //声明一个画布
  
        private Canvas canvas;
  
        //声明屏幕的宽高
  
        private int screenW,screenH;
  
        //定义两个矩形的宽高坐标
  
        private int rectX1 = 10,rectY1 = 10,rectW1 = 40,rectH1 = 40;
  
        private int rectX2 = 100,rectY2 = 110,rectW2 = 40,rectH2 = 40;
  
        //便于观察是否发生碰撞设置一个标识位
  
        private boolean isCollsion;
  
        //定义第一个矩形的矩形碰撞数组
  
        private Rect clipRect1 = new Rect(0,0,15,15);
  
        private Rect clipRect2 = new Rect(rectW1 - 15, rectH1 - 15,rectW1,rectH1);
  
        private Rect[] arrayRect1 = new Rect[]{clipRect1,clipRect2};
  
        //定义第二个矩形的矩形碰撞数组
  
        private Rect clipRect3 = new Rect(0,0,15,15);
  
        private Rect clipRect4 = new Rect(rectW2 - 15,rectH2 - 15,rectW2,rectH2);
  
        private Rect[] arrayRect2 = new Rect[]{clipRect3,clipRect4};
  
         
  
        /**
  
         * SurfaceView初始化函数
  
         */
  
        public MySurfaceView(Context context){
  
                super(context);
  
                //实例SurfaceHolder
  
                sfh = this.getHolder();
  
                //为SurfaceView添加状态监听
  
                sfh.addCallback(this);
  
                //实例一个画笔
  
                paint = new Paint();
  
                //设置画笔颜色为白色
  
                paint.setColor(Color.WHITE);
  
                //设置焦点
  
                setFocusable(true);
  
        }
  
        @Override
  
        public void surfaceCreated(SurfaceHolder holder) {
  
                // TODO Auto-generated method stub
  
                screenW = this.getWidth();
  
                screenH = this.getHeight();
  
                flag = true;
  
                //实例线程
  
                th = new Thread(this);
  
                //启动线程
  
                th.start();
  
        }
  
         
  
         
  
        /**
  
         * 游戏绘图
  
         */
  
        public void myDraw(){
  
                try {
  
                        canvas = sfh.lockCanvas();
  
                        if(canvas != null){
  
                                //刷屏
  
                                canvas.drawColor(Color.BLACK);
  
                                //判断是否发生了碰撞
  
                                if(isCollsion){//发生碰撞
  
                                        paint.setColor(Color.RED);
  
                                        paint.setTextSize(20);
  
                                        canvas.drawText("Collision!", 0, 30, paint);
  
                                         
                                } else{//没发生碰撞
  
                                        paint.setColor(Color.WHITE);
  
                                }
  
                                //绘制两个矩形
  
                                canvas.drawRect(rectX1, rectY1, rectX1 + rectW1, rectY1 + rectH1, paint);
  
                                canvas.drawRect(rectX2, rectY2, rectX2 + rectW2, rectY2 + rectH2, paint);
  
                                //----绘制碰撞区为非填充,并设置画笔为白色
  
                                paint.setStyle(Style.STROKE);
  
                                paint.setColor(Color.WHITE);
  
                                //---绘制第一个矩形所有矩形碰撞区域
  
                                for(int i=0; i < arrayRect1.length; i++){
  
                                        canvas.drawRect(arrayRect1[i].left + this.rectX1, arrayRect1[i].top + this.rectY1,
                                                        arrayRect1[i].right + this.rectX1, arrayRect1[i].bottom + this.rectY1, paint);
  
                                }
  
                                //---绘制第二个矩形所有矩形碰撞区域
  
                                for(int i=0;i < arrayRect2.length; i++){
  
                                        canvas.drawRect(arrayRect2[i].left + this.rectX2, arrayRect2[i].top + this.rectY2,
  
                                                        arrayRect2[i].right + this.rectX2,arrayRect2[i].bottom + this.rectY2, paint);
  
                                }
  
                                 
  
                        }
  
                }catch(Exception e){
  
                         
  
                }finally{
  
                        if(canvas != null)
  
                                sfh.unlockCanvasAndPost(canvas);
  
                }
  
        }
  
        /**
  
         * 触屏事件监听
  
         */
  
        @Override
  
        public boolean onTouchEvent(MotionEvent event) {
  
                // TODO Auto-generated method stub
  
                //让矩形1随着触屏位置移动(触屏点设为此矩形的中心点)
  
                rectX1 = (int) event.getX() - rectW1/2;
  
                rectY1 = (int) event.getY() - rectH1/2;
  
                //当矩形之间发生碰撞
  
                if(isCollsionWithRect(arrayRect1, arrayRect2)){
  
                        isCollsion = true;//设置标志位为真
  
                        //当矩形之间没有发生碰撞
  
                }else{
  
                        isCollsion = false; //设置标志位为假
  
                }
  
                return true;
  
        }
  
        /**
  
         * 矩形碰撞的函数
  
         * @param left 表示矩形左上角坐标的X坐标
  
         * @param top  表示矩形左上角坐标Y坐标
  
         * @param right 表示矩形右下角坐标X坐标
  
         * @param buttom 表示矩形右下角坐标Y坐标
  
         */
  
        public boolean isCollsionWithRect(Rect[] rectArray, Rect[] rect2Array){
  
                Rect rect = null;
  
                Rect rect2 = null;
  
                for(int i = 0; i < rectArray.length; i++){
  
                        //依次取出第一个矩形数组的每个矩形实例
  
                        rect = rectArray[i];
  
                        //获取到第一个矩形数组中每个矩形元素的属性值
  
                        int x1 = rect.left + this.rectX1;
  
                        int y1 = rect.top + this.rectY1;
  
                        int w1 = rect.right - rect.left;
  
                        int h1 = rect.bottom - rect.top;
  
                        for(int j = 0; j < rect2Array.length; j++){
  
                                //依次取出第二个矩形数组的每个矩形实例
  
                                rect2 = rect2Array[i];
  
                                //获取到第二个矩形数组中每个矩形的属性值
  
                                int x2 = rect2.left + this.rectX1;
  
                                int y2 = rect2.top + this.rectY2;
  
                                int w2 = rect2.right - rect2.left;
  
                                int h2 = rect2.bottom - rect2.top;
  
                                //进行循环遍历两个矩形碰撞数组所有元素之间的位置关系
  
                                if(x1 >= x2 && x1 > x2 + w2){
  
                                }else if(x1 <= x2 && x1 + w1 <= x2) {
  
                                }else if(y1 >=y2 && y1 >= y2 + h2){
  
                                }else if(y1 <=y2 && y1 + h1 <= y2){
  
                                }else {
  
                                        //只要有一个碰撞矩形数组与另一个碰撞矩形数组发生碰撞则认为碰撞
  
                                        return true;
  
                                }
  
                        }
  
                }
  
                return false;
  
        }
  
 
         
  
        /**
  
         * 按键事件监听
  
         */
  
        @Override
  
        public boolean onKeyDown(int keyCode, KeyEvent event) {
  
                // TODO Auto-generated method stub
  
                return super.onKeyDown(keyCode, event);
  
        }
  
        /**
  
         * 游戏逻辑
  
         */
  
        private void logic(){
  
                 
        }
  
        @Override
  
        public void run() {
  
                // TODO Auto-generated method stub
  
                while(flag){
  
                        long start = System.currentTimeMillis();
  
                        myDraw();
  
                        logic();
  
                        long end = System.currentTimeMillis();
  
                        try {
  
                                if (end - start < 50) {
  
                                        Thread.sleep(50 - (end - start));
  
                                }
  
                        } catch(InterruptedException e){
  
                                e.printStackTrace();
  
                        }
  
                }
  
                 
        }
  
        /**
  
         * Surfaceview视图状态发生改变,响应此函数
  
         */
  
        @Override
  
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
  
                        int height) {
  
                // TODO Auto-generated method stub
  
                 
        }
  
        /**
  
         * Surfaceview视图消亡,响应此函数
  
         */
  
        @Override
  
        public void surfaceDestroyed(SurfaceHolder holder) {
  
                // TODO Auto-generated method stub
  
                 
        }
  
}


第一种:就是圆形与矩形边框的碰撞检测
检测Y轴圆心到矩中心的距离是否小于半径+矩形X轴1/2宽
检测X轴圆心到矩中心的距离是否小于半径+矩形Y轴1/2高
第二种:就是特殊的矩形四个角检测
四个矩形顶角到圆心的距离是否小于半径

相信后面的大家就很容易理解:
这篇文章讲解一下基本的矩形和圆形之间的碰撞检测算法。上次我已经介绍过了矩形和矩形之间的碰撞检测,这次比上次麻烦那么一点。

二者碰撞最主要还是位于矩形的四个角。为了简洁,我还是运用上次的函数框架,虽然不是很方便,下面直接上代码:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
bool OverLap(RECT round, RECT rect)
{
int cr = (round.right - round.left)/2;
int cx = round.left + cr;
int cy = round.top + cr;
int distanceX = abs(cx - rect.left - (rect.right-rect.left)/2);
int distanceY = abs(cy - rect.top - (rect.bottom-rect.top)/2);
if(distanceX > ((rect.right-rect.left)/2 + cr)) return false;
if(distanceY > ((rect.bottom-rect.top)/2 + cr)) return false;
if(distanceX <= (rect.right-rect.left)/2) return true;
if(distanceY <= (rect.bottom-rect.top)/2) return true;
int sq = (distanceX-(rect.right-rect.left)/2)*(distanceX-(rect.right-rect.left)/2) +
(distanceY-(rect.bottom-rect.top)/2)*(distanceY-(rect.bottom-rect.top)/2);
return (sq <= cr*cr);
}

应该很容易看懂,函数输入的是两个矩形,前者是画圆用的外接矩形,后者是碰撞的矩形。
代码简单的分析一下:
1
2
3
int cr = (round.right - round.left)/2;
int cx = round.left + cr;
int cy = round.top + cr;

下面的几行代码是为了求出圆的半径和圆心。
1
int distanceX = abs(cx - rect.left - (rect.right-rect.left)/2); int distanceY = abs(cy - rect.top - (rect.bottom-rect.top)/2);

接下来的两行代码其实就是求圆心和矩形中心的距离。第一行是横坐标的距离,第二行是纵坐标的距离。
1
2
if(distanceX > ((rect.right-rect.left)/2 + cr)) return false;
if(distanceY > ((rect.bottom-rect.top)/2 + cr)) return false;

这两行是排除显而易见的情况,其实就是图上中间大的矩形外部的所有范围。第一句是表示圆形到矩形X坐标的距离大于二者半径的累加,排除图上的灰色线条两边的范围。第二句话排出的是两条蓝色线之外的范围,结合两者,正好剩余中间大的矩形范围。
1
2
if(distanceX <= (rect.right-rect.left)/2+r) return true;
if(distanceY <= (rect.bottom-rect.top)/2+r) return true;
就是非常单纯的检测矩形的四个角落碰撞。方法就是检验矩形和圆形的距离的平方和与圆的半径的平方的大小关系。

如果上边的你不太懂,没有关系,我用这个算法写了一个DEMO,你可以下载测试,然后注释掉算法的每一条语句来检测,看看语句的作用,到时候就懂了。


线段与矩形碰撞检测
*
* @param x1 线段一端点x坐标
* @param y1 线段一端点y坐标
* @param x2 线段二端点x坐标
* @param y2 线段二端点y坐标
* @param x 矩形左上角x坐标
* @param y 矩形左上角y坐标
* @param width 矩形宽度
* @param height 矩形高度
* @return


public static boolean lineWidthRect(int x1, int y1, int x2, int y2, int x, int y, int width, int height) {
  
double a =(double) ((y1 - y2)) / (double) ((x1 - x2));
  
double b =y1 - a * x1;
  
if (x1 < x2) {
  
for (int i =x1; i <= x2; i++) {
  
int tempY =(int) (a * i + b);
  
if (intersectRect(i, tempY, 1, 1, x, y, width, height)) {
  
return true;
  
}
  
}
  
} else if (x1 > x2) {
  
for (int i =x1; i >= x2; i--) {
  
int tempY =(int) (a * i + b);
  
if (intersectRect(i, tempY, 1, 1, x, y, width, height)) {
  
return true;
  
}
  
}
  
} else {
  
if (y1 <= y2) {
  
for (int i =y1; i < y2; i++) {
  
if (intersectRect(x1, i, 1, 1, x, y, width, height)) {
  
return true;
  
}
  
}
  
} else {
  
for (int i =y2; i > y2; i--) {
  
if (intersectRect(x1, i, 1, 1, x, y, width, height)) {
  
return true;
  
}
  
}
  
}
  
}
  
return false;
  
}


分享到:
评论

相关推荐

    Android范围碰撞检测

    本篇文章将深入探讨"Android范围碰撞检测",包括矩形碰撞检测和圆形碰撞检测,并以在Android 2.2系统上实现为例进行说明。 首先,我们要理解什么是碰撞检测。碰撞检测是指在二维或三维空间中,检测两个或多个物体...

    Android基础软件源码(Region碰撞检测).zip

    开发者可以通过学习和使用这个项目的源码,更深入地理解Android碰撞检测的原理和应用。源码的公开对学习Android开发和提升编程技能大有裨益,它不仅能够帮助开发者理解复杂的概念,还能让他们通过实践来提高解决问题...

    Android 小球碰撞检测技术

    Android 小球碰撞检测技术

    物理碰撞检测实例

    在游戏开发中,物理碰撞检测是一项至关重要的技术,它使得游戏中的对象能够相互交互,产生真实的运动效果。本文将深入探讨“物理碰撞检测实例”,特别是针对cocos2d-x 3.0版本的新物理引擎。 cocos2d-x是一款开源的...

    android 两球或多球碰撞检测实例

    在Android游戏开发中,碰撞检测是一项基础且关键的技术,它涉及到物体之间的交互,尤其是在物理模拟或者运动物体的游戏场景中。本实例将详细讲解如何实现两球或多球的碰撞检测,这对于初学者理解碰撞检测原理非常有...

    Android 3D jpct-ae 两个小球的碰撞检测

    在Android平台上进行3D游戏开发时,我们常常会遇到如何实现3D物体之间的碰撞检测问题。本示例中,我们关注的是"Android 3D jpct-ae 两个小球的碰撞检测",这是一个利用jpct-ae游戏引擎实现的案例。jpct-ae(jPCT-AE...

    安卓Android源码——(Region碰撞检测).rar

    这个压缩包文件“安卓Android源码——(Region碰撞检测).rar”显然包含了一个关于Region碰撞检测的详细讲解。Region碰撞检测是游戏开发、动画设计以及用户界面交互中的关键技术,它用于判断两个或多个图形区域是否...

    android碰撞球

    《Android碰撞球游戏开发详解》 在Android平台上开发一款简单的“碰撞球”游戏,虽然描述中提到它可能尚未完善,但基本功能已经实现,这涵盖了基础的编程逻辑、图形渲染和物理模拟等关键知识点。接下来,我们将深入...

    Tiled Map中使用碰撞检测

    2. **精确碰撞检测**:如果需要更精确的碰撞检测,可以使用像素级碰撞检测。这通常涉及将对象的图像转换为Alpha遮罩,然后逐像素比较两个遮罩的重叠部分。虽然这种方法更准确,但计算量较大,可能会降低游戏性能。 ...

    Android矩形碰撞

    在计算机图形学和游戏开发中,碰撞检测是至关重要的一个环节,特别是在移动设备上的Android应用开发。"Android矩形碰撞"这一主题主要关注如何在Android平台上实现矩形之间的碰撞检测算法。这种技术广泛应用于游戏中...

    android 碰撞球游戏

    3. **物理引擎**:虽然简单的碰撞球游戏不需要复杂的物理引擎,但处理碰撞检测仍然很重要。可以利用几何原理,如矩形与圆形的碰撞检测,计算出碰撞后的位置和速度变化。 4. **触摸事件处理**:玩家通过触摸屏幕控制...

    Android 游戏Region碰撞检测Demo源码.rar

    在Android游戏开发中,Region碰撞检测是一个至关重要的技术,它涉及到游戏对象间的交互,比如角色与障碍物的碰撞、子弹与敌人的碰撞等。这个"Android游戏Region碰撞检测Demo源码"应该包含了一个完整的示例,用于演示...

    安卓Android源码——(Region碰撞检测).zip

    本资料"安卓Android源码——(Region碰撞检测).zip"提供了一个关于如何在Android平台上实现Region碰撞检测的详细案例。 首先,我们要理解什么是Region。在Android中,Region是一个表示矩形区域的对象,它可以由一个...

    Android 检测游戏碰撞的原理实现

    本文将深入探讨Android平台下游戏碰撞检测的原理与实现方法。 一、基本概念 碰撞检测是游戏编程中的核心部分,其目的是判断游戏中的两个或多个物体(如角色、障碍物等)是否发生接触。根据复杂程度,碰撞检测可以...

    Android应用源码之(Region碰撞检测).zip

    在Android应用开发中,Region碰撞检测是一项重要的技术,主要用于游戏开发、动画制作或者任何需要检测图形元素之间相互作用的场景。本源码提供了一个具体的实现示例,帮助开发者理解和掌握如何在Android平台上进行...

    Android游戏开发之碰撞检测(矩形碰撞、圆形碰撞、像素碰撞)

    在Android游戏开发中,碰撞检测是一项关键的技术,用于判断游戏对象之间是否发生接触。本篇文章主要探讨了三种基本的碰撞检测方法:矩形碰撞、圆形碰撞以及像素碰撞,并且涉及到了多矩形碰撞的处理。 1. **矩形碰撞...

    android 动画 碰撞矩形

    "android 动画 碰撞矩形"这个主题涉及到Android中的动画机制、碰撞检测以及图形绘制技术。接下来,我们将深入探讨这些核心知识点。 首先,我们来看Android动画。Android提供了多种动画实现方式,包括帧动画(Frame ...

    Android手持设备游戏中的碰撞检测算法研究.pdf

    【Android手持设备游戏中的碰撞检测算法研究】 在Android手持设备上的游戏开发中,碰撞检测是不可或缺的一个重要环节,它涉及到游戏对象之间的交互和物理行为模拟。这篇研究论文主要探讨了一种基于包围球和轴对齐...

Global site tag (gtag.js) - Google Analytics