En la primera parte establecimos la clase base de nuestro así como definimos la clase Ball y la hicimos rebotar contra las paredes, en esta segunda parte terminaremos de elaborar nuestro juego implementando las palas, la inteligencia artificial, la entrada del usuario y un sistema de puntuaciones.
La clase Paddle
La clase Paddle va a representar las palas o raquetas de nuestro juego. Una será controlada por el jugador (la de la izquierda) y otra por una inteligencia artificial muy básica (derecha). Podríamos hacerla igual que la clase Ball heredando de Sprite, pero para ver más herramientas de SFML 2 esta vez usaremos la clase RectangleShape que a su vez hereda de Shape y nos permite dibujar rectángulos en pantalla.
como siempre empezaremos echando un vistazo a nuestro Paddle.hpp.
Vemos como hereda de RectangleShape y en esta ocasión tenemos dos métodos update, updateHuman y updateIA. Como habrás imaginado el primero controla la pala del jugador y solo necesitamos enviarle el tiempo para moverla. El segundo controla la pala de la IA y además del tiempo la pasamos una referencia a la bola parque necesita "ver" donde está para moverse en consecuencia.
Como atributos solo tenemos la velocidad, al contrario que la clase Ball no es un Vector sino un float ya que las palas solo se mueven arriba y abajo por lo que solo necesitamos la velocidad en el eje Y.
Sin más pasemos a ver el Paddle.cpp
El constructor
Bueno en el constructor hacemos lo de siempre inicializar los valores de la pala, establecemos el tamaño, el origen en el centro, definimos un color, un borde y la velocidad.
Prestar atención a que no definimos la posición de la Pala ya que no es para las dos igual la pala del jugador estará en un sitio y la de la IA en otro, por lo que la definiremos más adelante.
El método updateHuman
Este método implementa el movimiento de la pala del jugador que respondo al teclado. Lo primero es obtener la parte superior e inferior de la pala.
A continuación vemos el estado del teclado en tiempo real con el método estático isKeyPressed de la clase Keyboard. Este método nos devuelve true si la tecla pasada por parámetro en ese mismo instante está siendo pulsada y false en caso contrario.
Aparte de esto comprobamos si ha chocado con los límites superior o inferior para que no se pueda salir de la pantalla.
El metodo updateIA
Este método contiene la "Inteligencia Artificial" de nuestro juego, la pongo entre comillas porque es algo muy básico. La idea es que la pala sepa la posición y de la bola si está más arriba que su posición se mueva hacia arriba y si está más abajo pues se mueve hacia abajo, así de simple.
Para que sea más realista solo moveremos la pala si la bola va hacia la pala (velocidad positiva, para esto necesitábamos el método getSpeedX de la clase Ball) y si esté en el campo de la IA (la posición es mayor a la mitad del WIDTH). Con esto evitamos que la pala se mueva cuando la bola está yendo hacia el otro lado.
Ahora hay que modificar el método update de la clase Ball para que reaccione al chocar contra las palas.
Ahora recibe dos parámetros más que son dos FloatRect que seran los GlobalBounds de las palas. Con el método intersects de los rectángulos de la bola y la pala podemos ver si están chocando y en consecuencia cambiar la velocidad de la bola.
Hacemos los respectivos cambios en el Ball.hpp para que update reciba estos nuevos parámetros. Nuevamente modificamos Pong.hpp añadiendo dos objetos Paddle.
Y también modificamos el Pong.cpp.
Como vemos ahora en el constructor definimos la posición de cada una de las palas que no habíamos hecho antes. Llamamos a los métodos update de la bola y las dos pala pasando la información necesaria y a continuación dibujamos todos los objetos.
En este punto deberíamos tener un juego del Pong totalmente funcional con una pala controlada por el jugador y otra controlada por la IA.
Puntuaciones
Para ver el tratamiento de texto por parte de SFML 2 vamos a crear dos marcadores que lleven los puntos de cada jugador y los muestren en la parte superior.
La clase Score
Lo que haremos será una clase Score que llevará las puntuaciones del juego, este es el Score.hpp.
Tenemos tres métodos show que recibe una referencia a la ventana y se encargará de dibujar en pantalla las puntuaciones. Luego tenemos addPointPlayer y addPointIA que lo que hacen es aumentar los puntos del jugador y la IA en uno respectivamente.
Como atributos tenemos un Objeto Font que será los que usen los textos, tenemos dos objetos Text que representan los textos de la puntuación del jugador y la IA. y por último tenemos dos enteros sin signo que son los puntos en sí de cada jugador.
Ahora vamos a ver el Score.cpp.
Como siempre el código es casi autoexplicativo, la constructor inicializa los valores a 0 de las puntuaciones, cargamos la fuenta,se la asignamos a los textos, establecemos el tamaño, el color y la posición de los mismos.
Los metodos addPointPlayer y addPointIA que aumentan las variables en uno no tienen más consideración.
Por último el método show que crea dos objetos stringstream para poder convertir los objetos int en String y asignarlos a los textos con setString. Ojo, en realidad el objeto que reciben es un sf::String y lo que le estamos pasando es un std::string (de la STL), pero la clase sf::String tiene un constructor que resibe un std::String y lo convierte por lo que no debemos preocuparnos.
Por último antes de dibujarlos recalculamos la posición del texto de la derecha para que se mantenga alineado a la derecha si el contador crece a más de una cifra.
Ahora solo hay que crear un objeto Score en nuestro Pong y actualizarlo. Se marca un punto cuando conseguimos colarle la bola a la pala contraria, es decir, uno de los jugadores gana un punto cuando la bola "choca" contra el lado opuesto de la pantalla. Por tanto debe ser la bola la que asigne los puntos ya que es ella que sabe cuando choca contra el lado opuesto, así que modificamos el método update de Ball pasando una referencia al objeto Score y aumentando los puntos.
Según en que lado demos anotamos un punto al jugador o a la IA. Ahora solo nos queda ver como queda nuestro Pong.hpp.
Y nuestro Pong.cpp.
Ya tenemos nuestro juego terminado, la Inteligencia Artificial es prácticamente invencible, pero podemos cambiar esto haciendo que su velocidad sea menor impidiéndole llegar a todas las bolas
Repositorio de código
He creado un repositorio del juego donde puede ver todo el código fuente final, así como el proyecto generado para Visual Studio 2010. Sería una buena iniciativa hacer forks para añadir dentro de la carpeta builds soluciones para otros entornos y/o sistemas y que se puede ejecutar el juego en el máximo número de plataformas. Si alguien se anima estaré encantado de añadirlos al proyecto principal.
Primera parte | SFML 2: Elaborando un juego completo I Github | Repositorio del juego