前言
众所周知,Region是android graphics一族中比较低调的东西类,首要原因仍是在磕碰检测方面存在一些不足,乃至能够说成事不足败事有余,以至于难以用于2D游戏开发。
用法
既然这么失利的东西为什么要介绍呢,首要咱们介绍一下它能成事的部份,以及正确的用法。
- Region类能成事的部份首要仍是Op布尔操作和矩阵操作,可是这个似乎又和Path的作用重合,别的一部分contain包含关系判别,contain能准确的判别点和矩形是不是被包含了,可是其他形状那就没办法了。
- 成事不足败事有余的部份,是quickXXX 快速检测办法,返回值true-能保证物体没有磕碰,但false无法保证是不是现已磕碰了,换句话说true是100%没磕碰,可是false还需求你自己进一步承认,不过这点能够作为削减判别的优化办法,但不是判定办法。
学习的意义
关于一些粒子,咱们不太关注巨细,这个时分是能够利用中心点去检测的,别的quickXXX其实用途不大,不过能够削减一部分代码,可是咱们仍然还需求了解它的用法。
非Path用法
关于非Path用法,Region仍是适当简略的,直接运用set办法即可
mainRegion.set((int) -radius, (int) -radius, (int) radius, (int) radius);
Path办法
这个用法比较奇怪,需求2个参数,最终一个是Region类,弄不好便是鸡生蛋蛋生鸡一样令人利诱,第二个能够看作被裁剪的区域,如下操作,求并集区域。不过话说回来,这个意义在哪里?
circlePath.reset();
circlePath.addCircle(x- width/2f,y - height/2f,10, Path.Direction.CCW);
circleRegion.setPath(circlePath,mainRegion);
小试一下
完成开头的图片效果
定义一些变量
private float x; //x事件坐标
private float y; //y事件坐标
//所以形状
Path[] objectPaths = new Path[5];
//形状区域检测
Region objectRegion = new Region();
//小圆球区域
Region circleRegion = new Region();
//小圆
Path circlePath = new Path();
//制作区域
Region mainRegion = new Region();
构建物体
三角形、圆等物体
for (int i = 0; i < objectPaths.length; i++) {
Path path = objectPaths[i];
if (path == null) {
path = new Path();
objectPaths[i] = path;
} else {
path.reset();
}
}
Path path = objectPaths[0];
path.moveTo(radius / 2, -radius / 2);
path.lineTo(0, -radius);
path.lineTo(radius / 2, -radius);
path.close();
path = objectPaths[1];
path.moveTo(-radius / 2, radius / 2);
path.lineTo(-radius / 2 - 100, radius / 2);
path.arcTo(-radius / 2 - 100, radius / 2, -radius / 2, radius / 2 + 100, 0, 180, false);
path.lineTo(-radius / 2, radius / 2);
path.close();
path = objectPaths[2];
path.addCircle(-radius + 200f, -radius + 100f, 50f, Path.Direction.CCW);
path = objectPaths[3];
path.addRoundRect(-radius / 2, -radius / 2, -radius / 2 + 20, 0, 10, 10, Path.Direction.CCW);
path = objectPaths[4];
path.addRect(120, 120, 200, 200, Path.Direction.CCW);
区域检测
检测是否发生了磕碰,准确度不高,但还能凑合
circlePath.reset();
circlePath.addCircle(x- width/2f,y - height/2f,10, Path.Direction.CCW);
circleRegion.setPath(circlePath,mainRegion);
mCommonPaint.setColor(Color.CYAN);
for (int i = 0; i < objectPaths.length; i++) {
objectRegion.setPath(objectPaths[i],mainRegion);
if(!objectRegion.quickReject(circleRegion)){
Log.d("RegionView"," 可能发生了磕碰");
mCommonPaint.setColor(Color.YELLOW);
}else{
mCommonPaint.setColor(Color.CYAN);
}
canvas.drawPath(objectPaths[i], mCommonPaint);
}
总结
到这儿结束了,关于Region类,咱们其实最有用的仍是contain类办法,contain(x,y)准确度很高,便于咱们检测粒子是不是在几何内部,本篇没有涉及到,可是有些制作地图类的运用会运用到这个,首要原因是地图犬牙交错,不是矩形也不是圆形,乃至还有飞地,因此运用containXXX是最好的方案之一。
悉数代码
public class RegionView extends View {
private final DisplayMetrics mDM;
private TextPaint mCommonPaint;
public RegionView(Context context) {
this(context, null);
}
public RegionView(Context context, AttributeSet attrs) {
super(context, attrs);
mDM = getResources().getDisplayMetrics();
initPaint();
setClickable(true); //触发hotspot
}
private void initPaint() {
//否则提供给外部纹理制作
mCommonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
mCommonPaint.setAntiAlias(true);
mCommonPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mCommonPaint.setStrokeCap(Paint.Cap.ROUND);
mCommonPaint.setFilterBitmap(true);
mCommonPaint.setDither(true);
mCommonPaint.setStrokeWidth(dp2px(20));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
widthSize = mDM.widthPixels / 2;
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
heightSize = widthSize / 2;
}
setMeasuredDimension(widthSize, heightSize);
}
private float x;
private float y;
//所以形状
Path[] objectPaths = new Path[5];
//形状区域检测
Region objectRegion = new Region();
//小圆球区域
Region circleRegion = new Region();
//小圆
Path circlePath = new Path();
//制作区域
Region mainRegion = new Region();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
if (width < 1 || height < 1) {
return;
}
int save = canvas.save();
canvas.translate(width / 2f, height / 2f);
float radius = Math.min(width / 2f, height / 2f);
mainRegion.set((int) -radius, (int) -radius, (int) radius, (int) radius);
for (int i = 0; i < objectPaths.length; i++) {
Path path = objectPaths[i];
if (path == null) {
path = new Path();
objectPaths[i] = path;
} else {
path.reset();
}
}
Path path = objectPaths[0];
path.moveTo(radius / 2, -radius / 2);
path.lineTo(0, -radius);
path.lineTo(radius / 2, -radius);
path.close();
path = objectPaths[1];
path.moveTo(-radius / 2, radius / 2);
path.lineTo(-radius / 2 - 100, radius / 2);
path.arcTo(-radius / 2 - 100, radius / 2, -radius / 2, radius / 2 + 100, 0, 180, false);
path.lineTo(-radius / 2, radius / 2);
path.close();
path = objectPaths[2];
path.addCircle(-radius + 200f, -radius + 100f, 50f, Path.Direction.CCW);
path = objectPaths[3];
path.addRoundRect(-radius / 2, -radius / 2, -radius / 2 + 20, 0, 10, 10, Path.Direction.CCW);
path = objectPaths[4];
path.addRect(120, 120, 200, 200, Path.Direction.CCW);
circlePath.reset();
circlePath.addCircle(x- width/2f,y - height/2f,10, Path.Direction.CCW);
circleRegion.setPath(circlePath,mainRegion);
mCommonPaint.setColor(Color.CYAN);
for (int i = 0; i < objectPaths.length; i++) {
objectRegion.setPath(objectPaths[i],mainRegion);
if(!objectRegion.quickReject(circleRegion)){
Log.d("RegionView"," 可能发生了磕碰");
mCommonPaint.setColor(Color.YELLOW);
}else{
mCommonPaint.setColor(Color.CYAN);
}
canvas.drawPath(objectPaths[i], mCommonPaint);
}
mCommonPaint.setColor(Color.WHITE);
canvas.drawPath(circlePath,mCommonPaint);
canvas.restoreToCount(save);
}
@Override
public void dispatchDrawableHotspotChanged(float x, float y) {
super.dispatchDrawableHotspotChanged(x, y);
this.x = x;
this.y = y;
postInvalidate();
}
@Override
protected void dispatchSetPressed(boolean pressed) {
super.dispatchSetPressed(pressed);
postInvalidate();
}
public float dp2px(float dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mDM);
}
public static int argb(float red, float green, float blue) {
return ((int) (1 * 255.0f + 0.5f) << 24) |
((int) (red * 255.0f + 0.5f) << 16) |
((int) (green * 255.0f + 0.5f) << 8) |
(int) (blue * 255.0f + 0.5f);
}
}