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
- Java.lang.SecurityException: Necesita permiso de BLUETOOTH: Ni el usuario 10065 ni el proceso actual tiene android.permission.BLUETOOTH
- ChildFragmentManager java.lang.IllegalStateException: La actividad ha sido destruida
- ¿Se llama el método onUpgrade?
- JSONArray no funciona cuando recibo la cadena JSON del servidor
- Cómo encontrar el paquete jar de java.rmi
<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!
- Android HMAC-SHA1 Diferente de Java estándar HMAC-SHA1
- Cambiar dinámicamente el límite de una referencia de consulta de Firebase en Android
- Proyecto de Android incapaz de hacer referencia a otro proyecto en eclipse
- RelativeLayout refresh after view.setVisibility (View.GONE) y view.setVisibility (View.VISIBLE)
- Android restlet añadir no estándar de encabezado param
- Diferencia entre la biblioteca de Android y la biblioteca de Java en Android Studio
- Nota: com.google.common.cache.Striped64 accede dinámicamente a un campo declarado 'base'
- Comprobación de consultas de Sqlite - menor y mayor que
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)