PEC FINAL Programacion de videojuegos 2D

Muy buenas,

Les dejo el readme de la practica final para programacion de videojuegos 2D, espero que les guste.

 

2d Pec03

Juego de emulacion espacial para la PEC Final.

Como jugar

Controles:

  • A / Flecha Izquierda -> Ir hacia la izquierda
  • D / Flecha Derecha -> Ir hacia la derecha
  • W / Flecha Hacia Arriba -> Saltar
  • SPACE -> Disparar o interactuar
  • Q -> Cambiar de arma
  • TAB -> Mostrar mapa

Pasos para comenzar el juego:

  1. Iniciar el ejecutable del juego.
  2. En el menu puede ver los creditos y jugar.
  3. Una vez dentro del juego debera recolectar recursos por el espacio y interactuar con el sector, pero cuidado porque la nave ira perdiendo vida y debera conseguir dinero de los recursos (asteroides), para reparar la nave y su municion puede visitar la estacion mas cercana y hablar con un comerciante o mercader.

Video

Enlace al video gameplay

Instaladores

Partes importantes del codigo

Estructura del proyecto

  • Assets
    • Scenes: En esta carpeta se encuentran las diferentes escenas del juego (menu y juego).
    • Scripts: Se encuentra los scripts de todo el juego.
    • Imagenes: Contiene todas las imagenes y tiles del juego.
    • Prefabs: Contiene los prefabs que se utilizan en el juego.
    • Sonidos: Contiene los sonidos utilizados en el juego.

Intro

Archivo: Assets/Scripts/Intro/Video.cs
Para la intro creamos un video player y le indicamos que tiene que iniciar al cargarse. Aparte le agregamos un script que se ocupa de ver cuando termina el video y carga el menu.

    /// <summary>
    /// Hace referencia al reproductor de video
    /// </summary>
    UnityEngine.Video.VideoPlayer video;
    // Start is called before the first frame update
    void Start()
    {
        video = GetComponent<UnityEngine.Video.VideoPlayer>();
    }
    // Update is called once per frame
    void Update()
    {
        if (video.frame == (video.frameCount - 1.0f))
        {
            //Pasamos al menu una vez que termina la intro
            SceneManager.LoadScene("Menu");
        }
    }

Estacion

La estacion esta realizada por varias capas de tilemaps, la idea detras de esto era hacer los edificions y terrenos en diferentes tiles para solapar uno con otro y que de la sensacion de profundidad.

Nave

Assets/Scripts/Naves/Nave.cs
La nave basa su movimiento en aplicar velocidad constante al presionar como se puede ver en el codigo, ademas rota la nave segun la direccion de pulsacion.

    /// <summary>
    /// Acelera hacia arriba la nave
    /// </summary>
    private void acelerar()
    {
        rigid.velocity = new Vector2(rigid.velocity.x,4.0f);
        this.transform.rotation = Quaternion.Euler(Vector3.forward);
        this.anima.SetInteger("Velocidad", 1);
        rigid.constraints = RigidbodyConstraints2D.FreezePositionX;
    }
    /// <summary>
    /// Acelera hacia abajo la nave
    /// </summary>
    private void frenar()
    {
        rigid.velocity = new Vector2(rigid.velocity.x,-2.0f);
        this.transform.rotation = Quaternion.Euler(Vector3.forward * 180);
        this.anima.SetInteger("Velocidad", 1);
        rigid.constraints = RigidbodyConstraints2D.FreezePositionX;
    }
    /// <summary>
    /// Acelera la nave hacia la derecha
    /// </summary>
    private void haciaDerecha()
    {
        rigid.velocity = new Vector2(2.0f, rigid.velocity.y);
        this.transform.rotation = Quaternion.Euler(Vector3.forward * -90);
        rigid.constraints = RigidbodyConstraints2D.FreezePositionY;
        this.anima.SetInteger("Velocidad", 1);
    }
    /// <summary>
    /// Acelera la nave hacia la izquierda
    /// </summary>
    private void haciaIzquierda()
    {
        rigid.velocity = new Vector2(-2.0f, rigid.velocity.y);
        this.transform.rotation = Quaternion.Euler(Vector3.forward * 90);
        rigid.constraints = RigidbodyConstraints2D.FreezePositionY;
        this.anima.SetInteger("Velocidad", 1);
    }

Personaje

Assets/Scripts/Npcs/Player.cs
Entre las particularidades que tiene el personaje dentro de una estacion esta la mas importante que accionar elementos (dialogos, negocios), para detectar estas acciones tira un raycast en 2d que recibe la accion de los npcs o objetos que tienen una accion.
Una vez que tiene la accion la pueda accionar con el espacio.

    //Revisa si esta mirando en la direccion y si se puede realizar alguna accion
    private void hayAccion()
    {
        Vector2 direccionVector = new Vector2(0,0);
        if (direccion == 1)
            direccionVector = Vector2.down;
        if (direccion == 2)
            direccionVector = Vector2.up;
        if (direccion == 3)
            direccionVector = Vector2.left;
        if (direccion == 4)
            direccionVector = Vector2.right;
        if(!direccionVector.Equals(new Vector2(0, 0)))
        {
            int layerMask = 1 << 8;
            layerMask = ~layerMask;
            RaycastHit2D golpe = Physics2D.Raycast(transform.position, direccionVector,2,layerMask);
            Debug.DrawRay(this.transform.position, direccionVector*2, Color.green);
            if (golpe.collider != null
                && !golpe.collider.name.ToLower().Contains("protagonista")
                && golpe.collider.gameObject.GetComponent<Accion>() != null)
            {
                accionActual = golpe.collider.gameObject.GetComponent<Accion>();
                EventosInterfaces.mostrarAccionPersonalizado(accionActual.tipo, accionActual.nombre);
                return;
            }
        }
        
        ocultarAccion();
    }

Asteroide

El asteroide tiene una animacion de destruccion que acaba llamando a un evento que proporciona dinero y destruye el objeto.

    // si la vida llega a cero o menos se acciona animacion de explosion que acaba llamando por evento a la funcion destruir()
    void Update()
    {
        if(vida <= 0)
        {
            anima.SetInteger("estado", 1);
        }
    }
    /// <summary>
    /// se destruye y proporciona dinero
    /// </summary>
    public void destruir()
    {
        EventosInterfaces.mostrarPanel(Random.Range(1, 10));
        Destroy(this.gameObject);
    }

Partida (save)

Archivo: Assets/Scripts/Npcs/PartidaEventos.cs
Se ha implementado la posibilidad de guardar partidas y recuperarlas en el juego, cuando presionas el boton de iniciar partida te crea una partida en memoria que va cambiando durante tu avance en el juego. El juego solo guarda cuando entras y sales de una estacion.
Para guardar cogemos una clase serializable que hemos llamado partida.

    /// <summary>
    /// Guarda la partida
    /// </summary>
    /// <returns></returns>
    public static bool guardar()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/partida.gd");
        bf.Serialize(file, partida);
        file.Close();
        Debug.Log(Application.persistentDataPath + "/partida.gd");
        return true;
    }

Para recuperarla simplemente nos dirigimos a la misma carpeta y recogemos los datos.

    /// <summary>
    /// Carga la partida
    /// </summary>
    /// <returns></returns>
    public static bool cargar()
    {
        if (File.Exists(Application.persistentDataPath + "/partida.gd"))
        {
            BinaryFormatter bf = new BinaryFormatter();
            FileStream file = File.Open(Application.persistentDataPath + "/partida.gd", FileMode.OpenOrCreate);
            partida = (Partida)bf.Deserialize(file);
            file.Close();
            Debug.Log(Application.persistentDataPath + "/partida.gd");
            return true;
        }
        return false;
    }

Mejoras

Mejoras para siguientes versiones:

  • Implementar enemigos
  • Implementar algun radar o formas de localizar elementos en el mapa
  • Mejorar interfaces
  • Mas sonidos de efectos especiales y menus

Creditos

Este apartado se puede encontrar en el juego, en el apartado de creditos.

Deja una respuesta