para - manual de programacion android pdf
¿Cómo detectar eventos táctiles dentro de un área determinada de Renderer en Android? (3)
Creo que, como sugirió, es una buena idea pasar el renderizador en el constructor. Luego, pase el evento para que lo maneje el procesador en el ciclo del juego. GLSurfaceView tiene un método para agregar un ejecutable al hilo de representación llamado queueEvent .
Luego, en el renderizador, donde tienes todos los objetos renderizados, puedes usar el moldeado de rayos para verificar si se hizo clic en un objeto.
public SurfaceView(Context context, GLRenderer renderer) {
super(context);
setEGLContextClientVersion(2);
setRenderer(renderer);
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event == null)
return false;
// set touch coordinates to be between -1 and 1
float normalizedX = ((event.getX()/v.getWidth())*2 - 1;
float normalizedY = -((event.getY()/v.getHeight())*2 - 1);
if (event.getAction() == MotionEvent.ACTION_UP){
queueEvent(new Runnable() {
@Override
public void run() {
renderer.handleTouchUP(normalizedX,
normalizedY);
}
});
return true;
}
return false;
}
});
}
En Android he tomado un ejemplo de esfera giratoria que se da aquí . Crea una aplicación simple que muestra una esfera giratoria (la tierra).
Ahora, quiero hacer algo si se presiona la esfera giratoria en la pantalla del teléfono. No quiero reaccionar para tocar eventos fuera de la esfera giratoria. Esto es lo que he intentado hasta ahora, usando una versión derivada de GLSurfaceView
:
public class MyGLSurfaceView extends GLSurfaceView {
MyGLSurfaceView(Context context) {
super(context);
}
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
Log.d("onTouchEvent",String.format("keyCode: %d coords: %d %d", event.getActionMasked(), x, y));
Renderer renderer = this.Renderer.getRenderer(); // ERROR
return super.onTouchEvent(event);
}
}
Sin la línea ERROR este código funciona, y cuando presiono la pantalla obtengo la coordenada x / y.
Sin embargo, para evaluar si el evento estaba dentro de la esfera, mi enfoque fue obtener el renderizador que tiene el objeto Sphere
para determinar si las coordenadas x / y están dentro de la esfera.
Pero la línea ERROR no funciona, me sale un error al decir
Error:(26, 56) error: cannot find symbol method getRenderer()
¿Cómo puedo solucionar este error? ¿o hay una forma más sensata de averiguarlo automáticamente si el evento estaba en el objeto gráfico Sphere
?
Tal vez es una buena idea cambiar el constructor y pasar la instancia del renderizador a MyGLSurfaceView
también? ADDENDUM: Esta idea no parece funcionar. Me sale un error de constructor que no entiendo ...
Lo que quieres hacer aquí es comprobar si tu toque está en la esfera. La respuesta más directa es hacer un rayo 3D que pasa a través de la posición táctil y ver si el rayo colisiona con la esfera, es decir, colisión Ray-Sphere. Para lograr esto, puede usar gluUnProject () . Recuerde que necesita usar esta función dos veces con los puntos del plano cercano y lejano para obtener un vector de cerca a lejano 3D. Este vector es su rayo 3D para verificar colisiones.
Pero en tu caso tienes una esfera que simplemente gira. El centro es fijo y el radio es conocido. Por lo tanto, una forma más fácil de hacerlo es encontrar el círculo en la pantalla que se ajusta a la esfera y verificar si el tacto está dentro de este círculo.
Primero tome el centro de la esfera, a partir de su ejemplo de código vinculado en su pregunta. Como hace una traducción a (0, 0, -10) ese es el centro 3D. center3d(0.0f, 0.0f, -10.0f)
. Proyectarlo en la pantalla y obtener un centro de pantalla. Puedes usar gluProject () . Digamos que esto resulta en center2d
. Ahora tome otro punto en la superficie de su esfera, ya que el radio de la esfera es 2 (desde su enlace de código), un punto podría ser point3d(2.0f, 0.0f, -10.0f)
. Ahora proyecta esto en la pantalla y digamos que obtienes el point2d
. Ahora el radio del círculo 2D de la esfera en la pantalla sería la length(point2D - center2D)
.
Ahora compruebe si el toque de entrada está dentro del círculo. Simplemente obtenga la distancia de la posición táctil desde el centro del círculo y compruebe su radio 2D. Esta es una forma sencilla para su caso, pero si tiene formas más complicadas, el moldeado de rayos es el camino a seguir.
Tu pregunta es mucho más compleja que la simple detección de eventos táctiles. El renderizador no solo tiene el objeto esfera, sino que contiene todo el contenido de OpenGL ES. Por lo tanto, incluso después de detectar los eventos táctiles, deberá convertir las coordenadas 2D de su pantalla en 3D y comprobar si se cruzan con la esfera. Esto se llama fundición de rayos . Aquí hay una buena explicación de los algoritmos de lanzamiento de rayos. También hay un buen tutorial en video para implementar Java de lanzamiento de rayos.
También querrá pasar el renderizador en el constructor de GLSurfaceView
como lo sugirieron usted y @satm12.