- 浏览: 60502 次
文章分类
最新评论
android 碰撞检测
Region是一个类,这个类比较常用的方法就是用于判断一个点是否在矩形区域内,其方法是使是Regions类中的contains(int x, int y)函数创建实例:RegionCollsion
项目运行效果:
像素碰撞:在游戏开发中是不推荐使用的,虽然它很精确,但是会造成代码的效率降低。因为有可以代替像素碰撞检测的方法:多矩形、多圆形的检测方式。下面进行介绍
多矩形碰撞:顾名思义就是设置多个矩形碰撞区域
下面创建一个实例:MoreRectCollsion项目
效果图:
应该很容易看懂,函数输入的是两个矩形,前者是画圆用的外接矩形,后者是碰撞的矩形。
代码简单的分析一下:
下面的几行代码是为了求出圆的半径和圆心。
接下来的两行代码其实就是求圆心和矩形中心的距离。第一行是横坐标的距离,第二行是纵坐标的距离。
这两行是排除显而易见的情况,其实就是图上中间大的矩形外部的所有范围。第一句是表示圆形到矩形X坐标的距离大于二者半径的累加,排除图上的灰色线条两边的范围。第二句话排出的是两条蓝色线之外的范围,结合两者,正好剩余中间大的矩形范围。
就是非常单纯的检测矩形的四个角落碰撞。方法就是检验矩形和圆形的距离的平方和与圆的半径的平方的大小关系。
如果上边的你不太懂,没有关系,我用这个算法写了一个DEMO,你可以下载测试,然后注释掉算法的每一条语句来检测,看看语句的作用,到时候就懂了。
项目运行效果:
、
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
项目效果图:
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
项目效果图:
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项目
效果图:
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; }
相关推荐
实现了矩形碰撞检测和圆形碰撞检测,android2.2系统
Android 小球碰撞检测技术
这里对于cocos2d-x 3.0 的新物理引擎的物理碰撞检测单独抽离出来测试
android 两球或多球碰撞检测实例, 对于初学碰撞检测原理还是很有帮助的。
Android弹幕类游戏碰撞检测实现的毕业论文
安卓Android源码——(Region碰撞检测).rar
jpct-ae做的两个小球的碰撞检测,熟悉一下这个游戏引擎,代码的注释很详细。
安卓Android源码——(Region碰撞检测).zip
Android 游戏Region碰撞检测Demo源码.rar
还不是很完善,一些小小的基本功能还是实现了
主要介绍了Android游戏开发之碰撞检测,主要内容包含矩形碰撞、圆形碰撞、像素碰撞、多矩形碰撞的代码,感兴趣的小伙伴们可以参考一下
Android手持设备游戏中的碰撞检测算法研究.pdf
Android应用源码之(Region碰撞检测).zip项目安卓应用源码下载Android应用源码之(Region碰撞检测).zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
智能手机碰撞检测及在汽车事故自救中的应用 碰撞算法设计
Android 检测游戏碰撞的原理实现~~~~~~~~~
ANDROID碰撞最简单的碰撞检测源码,新手学习用。
android游戏引擎andengine:Physics物理碰撞效果 andengine Physics物理碰撞效果 自由碰撞 碰撞检测 小球碰撞 实例代码的下载,很有用的物理模型游戏引擎。
android 利用重力感应监听 微修改代码可以解决 来电时翻转手机后静音。