Programando un juego de Breakout (Arkanoid) para Android: Parte 2

Creando la raqueta del jugador

Haz click derecho en la carpeta java en el explorador de AndroidStudio como se muestra en la siguiente imagen.

create-a-new-java-class-300x288

Ahora selecciona New|Java class luego selecciona …\app\source\main\java y haz click en OK. Ahora introduce Paddle (raqueta) como el nombre para nuestra nueva clase y haz click en OK. Hemos creado una nueva clase de Java en un archivo separado llamada Paddle. El código no está entre el resto de nuestro código pero aún podemos tener acceso a él cómo podremos ver en breve. Esto nos ayuda a compartimentar nuestro código y mantenerlo organizado en áreas lógicas. Haremos lo mismo para nuestra pelota y para un ladrillo.

El código para la clase Paddle

Programemos esta clase en su totalidad luego podremos cambiarnos nuevamente a la clase BreakoutGame y a su clase interna BreakoutView y poner a funcionar a nuestro paddle.

Echa un vistazo a lo largo del listado del código para la clase Paddle. Asegúrate de leer todos los comentarios para clarificar hablaremos de ellos después. Copia y pega este código abajo del paquete de declaración en tu archivo Paddle.java.

Variables, especificadores de acceso y constantes

Primero que todo, antes de la declaracion de clase hacemos import (Importamos) a una clase llamada RectF. Veremos a RectF en acción pronto. Basicamente nos permite crear un rectángulo en cuatro coordenadas float. Esto es perfecto para representar las coordenadas que necesitamos para trazar y también veremos cuando nos encarguemos de la detección de colisión la clase RectF tiene un método para hacer todo el trabajo pesado por nosotros.

Siguiente, declaramos un montón de variables miembro las cuales son auto explicativas a parte de una cosa que no hemos visto antes en el tutorial pero que si hablamos en turorial Understanding OOP for Java games (Entendiendo OOP para juegos Java). Todas las variables tienen un especificador de acceso, ya sea private (privado) o public (público). El especificador private significa que la variable puede ser leída o cambiada solo desde dentro de esta clase (Paddle) y public significa que cualquier clase que tenga un objeto de tipo Paddle puede accesarla.

Las variables private se protegen a sí mismas de ser cambiadas en maneras para las cuales no estaban destinadas. Al hacer las cosas de esta manera mejoramos nuestro código porque controlamos como opera dentro del alcance de solo esta clase. Se llama encapsulación y nuestro código al hacerse cada vez más y más largo y añadimos más clases es invaluable para mantener manejable nuestro código. Pero si estas variables son private, ¿cómo demonios hacemos uso de ellas? En breve veremos cómo.

Antes de que lo hagamos, también surge la pregunta de por qué tres de nuestras variables STOPPED (detenido), LEFT (izquierda) y RIGHT (derecha) son declaradas públicas. Técnicamente no son variables, son constantes, como definidas por la palabra clave final. No pueden ser cambiadas. Lo que hacen es hacer obvio para las clases que usan la clase Paddle exactamente en que tres estados un objeto Paddle puede estar. Veremos exactamente cómo funcionan luego en esta clase y también en la clase BreakoutView cuando nos encarguemos del input del jugador.

El constructor de la clase Paddle

A continuación, tenemos el método constructor que empieza public void Paddle (...) . Este es el método que establece el objeto cuando lo inicializamos. Cuando inicializamos un objeto del tipo Paddle necesitamos introducir valores que concuerden con aquellos de la firma. En este caso, dos variables int, screenX y screenY. Estas variables contendrán la resolución de pixeles horizontal y vertical.

Dentro del constructor, luego inicializamos las variables length (ancho) y height (largo) para nuestro futuro paddle, divide el ancho de la pantalla entre dos y resta 20 de la altura para obtener el centro en borde inferior la pantalla como punto de partida para el paddle.

Luego inicializamos nuestro objeto RectF al introducir cuatro x, y, x+ length, y+ height coordenadas. Este objeto ahora contiene cuatro coordenadas que empiezan con una esquina superior izquierda y (x,y) completa con una esquina inferior derecha x+ length, y+ height. El constructor alterará las variables length y height para lograr el posicionamiento del paddle casi en el centro del borde inferior de la pantalla sin importar la resolución de la pantalla del dispositivo.

Finalmente, en el constructor, establecemos la velocidad del paddle a 350 pixeles por segundo al inicializar paddleSpeed a 350.

Accessing private variables with getters and setters (Teniendo acceso a variables private con getters y setters)

El siguiente método es getRect. Es llamado un getter porque obtiene el valor de las variables y los regresa. Nota que es public. Esto significa que nuestra clase BreakoutView podrá usarlo. Y mira lo que hace. Sólo una cosa. Regresa una copia de rect. BreakoutView ahora podrá usar este método para obtener las coordenadas del paddle para que pueda trazarlo en la pantalla o detectar si ha golpeado la pelota.

El siguiente método setMovementState hace solo una cosa. Recibe un parámetro int y lo asigna la variable private paddleMoving. BreakoutView En pronto usaremos las variables constantes STOPPED, LEFT y RIGHT en conjunción con este método para alterar la variable paddleMoving. Cuando lo hagamos controlará lo que pasa cuando es llamado el siguiente método public que veremos.

El método de actualización del Paddle explicado

El método update de la clase Paddle es separado del método update de nuestra clase BreakoutView. Una vez por cuadro, el método update de la clase BreakoutView llamará al método update de la clase Paddle. En este método update, al paddle se le asignaran nuevas coordenadas de ser necesario, listo cuando el método draw sea llamado.

En el método update, chequeamos por dos condiciones posibles paddleMoving == LEFT y paddleMoving == RIGHT. Luego cambiamos la coordenada x por la velocidad por segundo dividida por los cuadros por segundo introducidos en el método. Luego de las dos declaraciones ifactualizamos las coordenadas iniciales (rect.left y rect.right) y finales de rect. Nota que si paddleMoving == STOPPED es verdadero entonces nada cambiará en ese cuadro.

Ahora que hemos programado y discutido la clase Paddlepodemos ponerla en uso.

Usando la clase Paddle

Haremos esto en unos pocos pasos. Como necesitamos insertar el código en diferentes lugares dentro de nuestro motor de juego (BreakoutGame.Java). Explicaré tan claro como se pueda dónde va cada porción de código. Para absoluta claridad chequea el listado del código al final del artículo donde el código finalizado para la clase BreakoutGame incluyendo la clase interior BreakoutView se encuentra listada por completo.

Primero que todo, declaramos un objeto del tipo Paddle llamado paddle. Puedes añadir este código en cualquier lugar después de la declaración de BreakoutView pero antes del constructor; yo lo añadí después de la declaración de screenX y screenY.

Ahora necesitamos instanciarlo. Como necesitamos introducir la resolución horizontal y vertical de la pantalla. El lugar ideal para hacerlo es en el constructor BreakoutView después que inicializamos code>screenX y screenY.

Ahora simplemente añadimos un llamado al método de update de objetos paddle. Este código va, como podríamos esperar en el método update de la clase BreakoutView.

Luego, en el método draw, podemos trazar el rectángulo que representa el paddle. Nota que cuando usamos drawRect, comparado con el proyecot Drawing graphics demo (demo de Trazando gráficas), reemplazamos la coordenadas del rectángulo con un llamado a paddle.getRect. Como discutimos este método devuelve cuales sean los coordenadas del paddle. Añade este código al método draw justo después del llamado a paint.setColor.

Un paso más antes de que podamos ver a nuestra paddle en acción.

Detectando input y moviendo el paddle

Aquí añadiremos código al métodoonTouchEvent. Todo lo que necesitamos hacer es obtener las coordenadas en las cuales ocurrió el toque dentro del ACTION_DOWN case con motionEvent.getX(), podemos determinar cuál mitad de la pantalla fue pulsada al determinar si la coordenada es más pequeña o más grande que screenX dividida entre dos. Si es más grande llamamos a setMovementState(paddle.RIGHT), si no usamos paddle.LEFT. Además en el ACTION_DOWN case establecemos paused como false el cual iniciará nuestro motor de juego actualizando porque envolvimos una declaración if(!paused) alrededor del llamado a update en el método run.

También, nota que por el ACTION_UP case no importan las coordenadas en las cuales ocurrió la acción solo llamamos setMovementState(paddle.STOPPED). Aquí está el código entero para el método onTouchEvent con el nuevo código que acabamos de discutir.

Ahora tenemos control total sobre el paddle y podemos iniciar el juego. Corre el juego, pulsa la pantalla para despausar y mueve el paddle a izquierda y derecha al presionar y dejar de presionar la mitad apropiada de la pantalla.

android_breakout_moving_paddle-300x180

Hagamos una pelota.

Programando un juego de Breakout (Arkanoid) para Android: Parte 3