miércoles, 17 de diciembre de 2014

Aprendiendo a hacer juegos con la historia de las consolas: Atari

Bienvenidos de nuevo a nuestra aventura de imitar un juego de Atari 2600 usando Unity. En el post anterior di algunas explicaciones para cargar los gráficos necesarios para nuestra primera escena de un juego muy sencillo de lanzamiento de penaltis y sugerí a los lectores de esta sección que trataran de crear su propio pixel art. Como ya habéis tenido algún tiempo para “cacharrear” e intentarlo vosotros mismos hoy voy a traer la solución para los\las mas perezosos\as. En este enlace se puede descargar los primeros sprites necesarios para montar nuestra escena principal de juego en Unity.

Como vemos disponemos de una series de archivos png que van a hacer las funciones de campo de futbol (campo.png), balón (balon.png), flecha que usaremos para apuntar (flecha.png), portería (porteria.png), un lanzador de penaltis en dos estados (jugador.png y jugador_shoot.png) y para terminar un portero de madera que se va a mover de lado a lado para que el entrenamiento sea sencillo pero un poco más entretenido (portero_madera.png)

Ya vimos en el post anterior como introducir los gráficos ya mencionados en Unity, pero para dejarlo más claro lo vemos en la animación. Hay que arrastrar el archivo de nuestro navegador del sistema operativo a la ventana Project.


Una vez con todo cargado en nuestra escena lo configuraremos y colocaremos cada cosa en su sitio, primero arrastrando de la ventana Project a Hierarchy para poner los objetos en la escena y después ajustando su posición moviéndolos con el ratón en la ventana Scene o introduciendo números en los transform de cada objeto a través del Inspector.

Como guía puedo decir que tengo la cámara configurada en ortográfico con un tamaño de 0.8 y los objetos en las siguientes posiciones: campo (0, 0, 0), balón (0,-0.47,-0.1), jugador (0, -0.49, -0.2), portería (0,0.49, -0.03), flecha (0, 0.1, -0.5). Debemos saber que cuando manejamos el eje Z en el modo 2D de Unity podemos conseguir que unos objetos estén por delante de otros. Por eso estamos usando valores negativos, para colocar objetos delante del campo que está en Z=0. También hay que mencionar que vamos a reducir un poco el tamaño de la flecha introduciendo en sus casillas Scale correspondientes a X e Y el valor 0.95 sin preocuparnos de la Z, ya que al ser un objeto en dos dimensiones, por lo que no tiene profundidad y no nos importa. (El único motivo por el que hago esto es para que aprendáis a re-escalar desde el transform, pero si tenemos los objetos desde el principio a su tamaño original será mejor.


Ahora empezamos a ver cosas nuevas después del repaso. Además traigo buenas noticias. Empezaremos a programar un script en C# para que nuestro personajillo de uniforme azul pueda disparar a puerta.

Para empezar hay un objeto que necesitamos colocar de un modo especial, la flecha. Crearemos un objeto vacio mediante Create/Empty Object y lo arrastraremos sobre el jugador. Después arrastraremos la flecha sobre el objeto vacio (al que debemos dar un nombre, por ejemplo en mi caso lo he llamado Pivot Point). De este modo el objeto Pivot Point es hijo del jugador y la flecha es hija de Pivot Point, creándose así una relación de herencia que hace que si movemos al jugador sus hijos se muevan con él.




Crearemos por fin un Script en C# al que yo he llamado PlayerControl. (Es importante saber que se distingue entre mayúsculas y minúsculas y que el nombre de archivo del Script debe coincidir con el nombre de la clase principal, aunque Unity ya se encarga de nombrarlo todo). Lo arrastraremos sobre el objeto Pivot Point de la escena y dentro de él vamos a introducir el siguiente código (observad que hay una parte que escribe Unity al crear cualquier Script).



using UnityEngine;
using System.Collections;

public class PlayerControl : MonoBehaviour 
{

    // Public variables
 
    public float rotationSpeed; 
        // velocidad de rotacion para apuntar (90 esta bien)
 
    // Private variables

   private Transform thisTransform;  // Referencia al transform 
    private float horAxis;    // Eje horizontal 
 
    // Use this for initialization
    void Start () 
    {
        // Inicializamos las referencias a los transform
        thisTransform = transform;
    }
 
    // Update is called once per frame
    void Update () 
    {
       horAxis = Input.GetAxis("Horizontal");
  
    RotateArrow();
    }

    /*-----------------------------------------------------
     *  - RotateArrow() -
     * 
     *  Rota la flecha para apuntar desde un punto de pivote
     *  (En dicho punto esta este Script)
     * ---------------------------------------------------*/
 
    void RotateArrow()
    {

       thisTransform.Rotate(0, 0, - horAxis * rotationSpeed * Time.deltaTime); 
        // rotamos la flecha
} 

Con este código inicial vamos a hacer que nuestro tirador a portería pueda apuntar. Con flecha derecha rotaremos la flecha a la derecha y con flecha izquierda lo haremos a la izquierda. Pero, ¿Por qué?

Tenemos una variable pública llamada rotationSpeed de tipo float (public float rotationSpeed) Al ser pública Unity la va a mostrar en el Inspector si seleccionamos el objeto jugador, por lo que podremos darle un valor desde allí y testear sus efectos en tiempo real para hacer ajustes. Eso sí, hay que saber que el juego debe estar parado para que los ajustes sean permanentes. Si estamos ejecutándolo y cambiamos algún valor, recuperará los números anteriores que tenía cuando volvamos a pulsar el stop.

Las siguientes variables son privadas, es decir no se verán desde el Inspector ni serán accesibles desde otro Script o clase. Con private Transform thisTransform estamos declarando un objeto de tipo Transform en el que guardaremos una referencia al componente transform del objeto que contiene el Script (En este caso Pivot Point). Hacemos esto para optimizar el rendimiento y que Unity no tenga que buscarlo cada vez que lo vamos a utilizar gracias a que ya lo tenemos referenciado.

Después tenemos private float horAxis, que es una declaración de una variable en el que vamos a recoger el eje horizontal que Unity tiene asociado a una serie de teclas. Para saber cuáles son, solo tendremos que ir a Edit/Project Settings/Input. Allí, en el Inspector, vemos que aparecen los axes y en el horizontal el botón izquierdo lo identifica como negativo y el derecho como positivo. (Las teclas son los cursores y las teclas alternativas la A y la D). Con esto cuando pulsemos la tecla izquierda (aunque aún tenemos que hacer algo de trabajo) la variable horAxis tomará un valor negativo y cuando pulsemos la derecha, lo tomará positivo.


Llegamos ahora a la función Start(). Una función que Unity tiene predefinida y que usa normalmente para inicializar variables. Esta se va a ejecutar una sola vez al iniciarse la escena. Así dentro de ella guardamos la referencia del transform del objeto en thisTransform como ya habíamos dicho anteriormente, escribiendo la sencilla orden thisTransform = transform.

En la función siguiente, es decir Update(), vemos que tenemos otra que está predefinida y que Unity ejecuta cada fotograma. Es decir, es como un bucle principal de juego que se repetirá hasta que lo paremos. Dentro usaremos la sentencia horAxis = Input.GetAxis("Horizontal"). Para guardar el valor de las teclas del Axis horizontal en la variable horAxis. (recordemos, negativo izquierda, positivo derecha). Por último llamaremos a la función RotateArrow().

La función RotateArrow la creamos nosotros después y la usamos básicamente para tenerlo todo ordenadito. Esta función se va a ocupar de rotar la flecha al pulsar las teclas. Así, dentro encontramos un código thisTransform.Rotate(0, 0, - horAxis * rotationSpeed * Time.deltaTime) que se encarga de dejar la X e Y fijas de nuestro transform, mientras rota mediante la función Rotate a una velocidad rotationSpeed, el eje Z. Como se multiplica por el horAxis será negativo cuando pulsemos la izquierda y positivo cuando pulsemos la derecha. Pero la rotación sale al revés, por lo que pondremos un menos delante de horAxis. Respecto a Time.deltaTime,a grosso modo es una función de Unity que se encarga de mantener una velocidad constante sin importar el rendimiento del dispositivo en el que estemos ejecutando el juego. Si queréis saber más os recomiendo bucear en la documentación de Unity y tratar de entenderlo, aunque puede que lo explique más adelante porque soy un buen chico pero tengo poco espacio para escribir. :P

El fallo de este código es que permite rotar indefinidamente nuestra flecha. (En el inspector no olvidéis dar un valor a rotationSpeed o no rotará) Nosotros queremos añadirle un bloqueo para que solo pueda girar dentro de un rango, pero como se ha hecho muy largo el post lo vamos a dejar aquí por hoy. Así además, no se puede quejar nadie de que le hago copiar mucho código.


La historia de las consolas es larga y esto nos va a llevar bastante tiempo, así que tener paciencia (y tener paciencia conmigo porque es mi primer tutorial en detalle y estoy aprendiendo). Ánimo y a seguir aprendiendo. Hasta el próximo

No hay comentarios:

Publicar un comentario