Pixel Perfect Collision detection entre una vista personalizada y un ImageView

Tengo una vista personalizada y una vista de imagen. El CustomView es una bola que se mueve alrededor de la pantalla y rebotes de las paredes. La imagen es un cuarto de círculo que se puede girar en un círculo al tocar. Estoy intentando hacer mi juego de modo que cuando los pixeles llenados de las trayectorias cruzadas de CustomView con los pixeles llenados de la colisión de ImageView sean detectados. El problema que estoy teniendo es que no sé cómo recuperar donde están los píxeles llenos en cada vista.

Aquí está mi código XML

<com.leytontaylor.bouncyballz.AnimatedView android:id="@+id/anim_view" android:layout_height="fill_parent" android:layout_width="fill_parent" /> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/quartCircle" android:layout_gravity="center_horizontal" android:src="@drawable/quartercircle" android:scaleType="matrix"/> 

Mi principalActividad

 public class MainActivity extends AppCompatActivity { private static Bitmap imageOriginal, imageScaled; private static Matrix matrix; private ImageView dialer; private int dialerHeight, dialerWidth; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // load the image only once if (imageOriginal == null) { imageOriginal = BitmapFactory.decodeResource(getResources(), R.drawable.quartercircle); } // initialize the matrix only once if (matrix == null) { matrix = new Matrix(); } else { // not needed, you can also post the matrix immediately to restore the old state matrix.reset(); } dialer = (ImageView) findViewById(R.id.quartCircle); dialer.setOnTouchListener(new MyOnTouchListener()); dialer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // method called more than once, but the values only need to be initialized one time if (dialerHeight == 0 || dialerWidth == 0) { dialerHeight = dialer.getHeight(); dialerWidth = dialer.getWidth(); // resize Matrix resize = new Matrix(); resize.postScale((float) Math.min(dialerWidth, dialerHeight) / (float) imageOriginal.getWidth(), (float) Math.min(dialerWidth, dialerHeight) / (float) imageOriginal.getHeight()); imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false); // translate to the image view's center float translateX = dialerWidth / 2 - imageScaled.getWidth() / 2; float translateY = dialerHeight / 2 - imageScaled.getHeight() / 2; matrix.postTranslate(translateX, translateY); dialer.setImageBitmap(imageScaled); dialer.setImageMatrix(matrix); } } }); } 

Clase MyOnTouchListener:

 private class MyOnTouchListener implements View.OnTouchListener { private double startAngle; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startAngle = getAngle(event.getX(), event.getY()); break; case MotionEvent.ACTION_MOVE: double currentAngle = getAngle(event.getX(), event.getY()); rotateDialer((float) (startAngle - currentAngle)); startAngle = currentAngle; break; case MotionEvent.ACTION_UP: break; } return true; } } private double getAngle(double xTouch, double yTouch) { double x = xTouch - (dialerWidth / 2d); double y = dialerHeight - yTouch - (dialerHeight / 2d); switch (getQuadrant(x, y)) { case 1: return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI; case 2: return 180 - Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI; case 3: return 180 + (-1 * Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI); case 4: return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI; default: return 0; } } /** * @return The selected quadrant. */ private static int getQuadrant(double x, double y) { if (x >= 0) { return y >= 0 ? 1 : 4; } else { return y >= 0 ? 2 : 3; } } /** * Rotate the dialer. * * @param degrees The degrees, the dialer should get rotated. */ private void rotateDialer(float degrees) { matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2); dialer.setImageMatrix(matrix); } 

Y mi AnimatedView

 public class AnimatedView extends ImageView { private Context mContext; int x = -1; int y = -1; private int xVelocity = 10; private int yVelocity = 5; private Handler h; private final int FRAME_RATE = 60; public AnimatedView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; h = new Handler(); } private Runnable r = new Runnable() { @Override public void run() { invalidate(); } }; protected void onDraw(Canvas c) { BitmapDrawable ball = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.smallerball); if (x<0 && y <0) { x = this.getWidth()/2; y = this.getHeight()/2; } else { x += xVelocity; y += yVelocity; if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) { xVelocity = xVelocity*-1; } if ((y > this.getHeight() - ball.getBitmap().getHeight()) || (y < 0)) { yVelocity = yVelocity*-1; } } c.drawBitmap(ball.getBitmap(), x, y, null); h.postDelayed(r, FRAME_RATE); } public float getX() { return x; } public float getY() { return y; } } 

Mi pregunta es: ¿Cómo puedo recuperar los píxeles llenos de ambas vistas y pasarlas a través de una función que detecta una colisión.

Gracias de antemano por la ayuda!

Realmente necesita definir "píxeles llenos". Supongo que quieres decir los píxeles no transparentes. La forma más fácil de encontrarlos es convertir la vista completa en un mapa de bits e iterar a través de sus píxeles. Puede convertir una View en un Bitmap siguiente manera:

 private Bitmap getBitmapFromView(View view) { view.buildDrawingCache(); Bitmap returnedBitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(returnedBitmap); canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN); Drawable drawable = view.background; drawable.draw(canvas); view.draw(canvas); return returnedBitmap; } 

También es necesario obtener la ubicación absoluta de las vistas:

 Point getViewLocationOnScreen(View v) { int[] coor = new int[]{0, 0}; v.getLocationOnScreen(coor); return new Point(coor[0], coor[1]); } 

Entonces sólo tienes que iterar a través de los píxeles de cada Bitmap de Bitmap , comprobar sus colores para saber si están "llenos", y también comprobar si se superponen en función de su coordinación dentro de los mapas de bits y la ubicación absoluta de las vistas en la pantalla .

La iteración a través de un mapa de bits se hace de la siguiente manera:

 for (int x = 0; x < myBitmap.getWidth(); x++) { for (int y = 0; y < myBitmap.getHeight(); y++) { int color = myBitmap.getPixel(x, y); } } 

Pero debo decir, no creo que realizar este tipo de cálculos pesados ​​en el hilo de interfaz de usuario es realmente una buena idea. Hay docenas de maneras mucho mejores de detectar colisiones que la comprobación perfecta de píxeles. Esto probablemente saldrá extremadamente laggy.

Podrías encapsular tus imágenes con Array de puntos que marcan tus coordenadas de borde (y actualizarlas en movimiento / calcularlas basadas en el origen) entonces podrás decidir si el objeto oposing está en contacto o no (si alguno de los arrays oposing comparte el Mismo punto)

  • No se puede degradar la base de datos de la versión 2 a 1 incluso después de una nueva instalación y volver a ejecutar
  • Android M Permisos: onRequestPermissionsResult () no se llama
  • Acceso al flujo de medios de Android para la visualización de audio
  • Especificar argumentos Cipher.getInstance ()?
  • Java ordena una matriz de meses en varios arreglos por mes
  • Cómo crear un nuevo cuadro de diálogo "circle" datepicker android
  • Cómo permitir que sólo 1 botón de conmutación de Android de 3 para estar en una vez
  • ¿Advertencia de código muerto?
  • HTTPS con resultado de autenticación básico en Unauthorized
  • ¿Cómo agrega encabezados HTTP personalizados a las pestañas personalizadas de Chrome?
  • Creación de asistente de configuración en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.