Mirror Face Studios - Dawn of Rektwood

Programación Orientada a Objetos (Tower defense - kingdom rush)

Moderator: julianmartinez16

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Wed Mar 22, 2017 5:21 am

Semana 10

¿Qué hemos hecho?

Empezamos el montaje en unity ya con todos los sprites y empezamos a implementar la programación que desarrollamos durante las pruebas previas.

¿Qué haremos?

Terminaremos esta versión de preentrega para poder dedicarnos a pulir detalles y hacer sesiones de play testing con el hacer los balances necesarios en las mecánicas.

¿Qué problemas hemos tenido?


Por ahora ninguno, gracias al excelente trabajo en equipo, al adelanto de la programacio y a la pasión que le hemos dedicado al proyecto hemos logrado evitarlos.
Image

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Wed Mar 22, 2017 5:25 am

Semana 10 avances

Diseño de escenario:

Image


Diseño de estado de salud del jugador:

100%

Image

50%

Image

25%

Image

Diseños de símbolos de contadores:

Contador de rektelio (dinero del jugador):

Image

Contador de oleada:

Image

Animaciones defensas:


Image

Image

Image

Image

Image

Image

Animacion proyectiles defensas:

Image

Image

Image

Animaciones maquinas:

Image

Image

Image

Diseño nuevo Boss:


Image

Diseño nueva maquina:

Image

Nivel montado:


Image
Image

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Wed Mar 22, 2017 7:43 am

Juego funcionando

Terminadas las pruebas, llegó la hora de montar el juego, y aqui están los avances:

1) se remplazo la barra de vida, ya no se hace animada, se hace por medio de un sprite al que se le modifica la escala.
2) se hizo un pooling de enemigos que funciona bastante bien (falta optimizarlo).
3) se implementó un sistema de selección de torres.
4)Se implementó un sistema de oleadas que funciona con el pooling, y poco a poco va aumentado la dificultad aumentando un poco la velocidad de los enemigos (falta balancear valores)
5)La vida del jugador se muestra con unos dibujos y una barra de vida:

Aqui el video del gameplay de lo que se lleva hasta ahora (Alpha 1.0):



Script barra de vida enemigos:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BarraVida : MonoBehaviour {

    public GameObject Enemigo;
    public GameObject Barra_Verde;
    public GameObject Barra_Roja;
    public float escala = 0.1f;
    public SpriteRenderer sr;
    public float posBarra;
    public MovimientoEnemigos unidad;
    private float daño = 0.05f;
    public Vector3 VidaMaxima;
    public int contador = 0;




    ///valor de escala es 0.34

    // Use this for initialization
    void Start ()
    {
        sr = Barra_Verde.GetComponent<SpriteRenderer>();
        unidad = Enemigo.GetComponent<MovimientoEnemigos>();
        VidaMaxima = sr.transform.localScale;


	}

    // Update is called once per frame
    void Update() {

        if(unidad.Meta == 1)
        {
            Muerte();
            unidad.Meta = 0;
        }

        if (unidad.daño == true)
        {
          
            sr.transform.localScale -=new Vector3(escala + daño, 0);
            Barra_Verde.transform.position = Enemigo.transform.position - new Vector3(0.34f - sr.bounds.size.x / 2, posBarra);
            Debug.Log("DAÑO");
            unidad.daño = false;  
        }

        if (sr.transform.localScale.x <= 0)
        {
             Muerte();
        }

    }
        
		public void Muerte()
    {

        sr.transform.localScale = VidaMaxima;
        Barra_Verde.transform.position = Enemigo.transform.position - new Vector3(0.34f - sr.bounds.size.x / 2, posBarra);
        unidad.indice = 0;
        unidad.transform.position = unidad.posicion_inicial;
        unidad.posicion_siguiente = unidad.ruta.transform.GetChild(unidad.indice).position;
        unidad.vel = 0;
        Debug.Log("Muerte");
        contador = contador + 1;
        Destroy(unidad);
}

  

}

   
Script pooling:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PoolingEn : MonoBehaviour {
    public GameObject temp;
    public  ArrayList enemigos = new ArrayList();
    public GameObject[] almacen;
    public int cantidad;
    public GameObject enemigo;
    public int contador = 0;
    public MovimientoEnemigos enemy;
    public bool activador = false;
    public int longitud;
    public bool Listo = false;
    private float sumaVel = 0;
    public bool proxOleada = false;
    // Use this for initialization
    void Start () {

        longitud = enemigos.Count;
        enemy = enemigo.GetComponent<MovimientoEnemigos>();
        almacen = new GameObject[20];
      
    }
	
	// Update is called once per frame
	void Update () {

        Debug.Log("Cantidad de enemigos creados: " + cantidad);

        contador = contador + 1;

        if(contador == 200 || contador == 600 || contador == 1200 || contador == 1600|| contador == 2200)
        {
            activador = true;
        }

        if(contador == 4200)
        {
            contador = 0;
            Debug.Log("Siguente oleada");
            cantidad = cantidad + 3;
            sumaVel = 0.7f;
            proxOleada = true;

            
        }

        if(activador == true)
        {
            
            Listo = true;   
            Vector3 incremento = new Vector3(-3, 0);
            Vector3 posInicial = enemigo.transform.position;
            
            activador = false;
            

            for (int i = 0; i < cantidad; i++)
            {
                temp = Instantiate(enemigo, posInicial + incremento, Quaternion.identity);
                posInicial = temp.transform.position;
                almacen[i] = temp;
                ///   enemigos.Add(enemigo);
                enemy = temp.GetComponent<MovimientoEnemigos>();
                enemy.vel = Random.Range(0.5f, 1.1f) + sumaVel;
                
            }
           
        }
	}
}
Script contador de oleadas:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ContadorOleadas : MonoBehaviour {
    public GameObject decenas, unidades;
    private Animator de, un;
    private string[] estados = { "Estado_00", "Estado_01", "Estado_02", "Estado_03", "Estado_04", "Estado_05", "Estado_06", "Estado_07", "Estado_08", "Estado_09" };
    private int oleada = 0;
    PoolingEn pooling;


    public int Oleada


    {
        get
        {
            return oleada;
        }

        set
        {
            oleada = value;
        }
    }



    // Use this for initialization
    void Start()
    {
        pooling = GameObject.FindWithTag("Camara").GetComponent<PoolingEn>();
        de = decenas.GetComponent<Animator>();
        un = unidades.GetComponent<Animator>();
        oleada = 1;
        Actualizador(oleada);

            
    }

    // Update is called once per frame
    void Update()
    {

        if (pooling.proxOleada == true)

        {
            oleada = oleada + 1;
            Actualizador(oleada);
            pooling.proxOleada = false;

        }
        if (oleada == 10)

        {
            pooling.cantidad = 0;
            pooling.proxOleada = false;
        }
    }

    public void Actualizador(int numero)

    {
        int unidades = numero % 10;
        int decenas = numero % 100 - unidades;


        decenas = decenas / 10;


        if (numero > 9)
        {
            de.Play(estados[decenas]);
        }
        else

        { de.Play(estados[0]); }

        un.Play(estados[unidades]);
    }

}
Script seleccon de torres:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PonerTorres : MonoBehaviour {

    public GameObject circulos;

    void OnMouseDown()
    {
        GameObject Pad;
        Vector3 pospad = this.transform.position;
        Pad = Instantiate(circulos);
        Pad.transform.position = pospad;
        Pad.layer = 10;
        pospad.y = pospad.y + 0.7f;
        //pospad.x = pospad.x + .5f;
        ///pospad.z = pospad.z + -10f;
        ///Destroy(this.gameObject);


    }
}
Script barra de vida jugador:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class VidaJugador : MonoBehaviour

{


    public Slider vida;
    public GameObject Arbolito;
    private Animator salud;
    private GameObject unidad;
    Meta DañoJugador;
    private string[] arboles = { "Arbol01", "Arbol02", "Arbol03" };
    private float vidaMaxima = 0;
    private bool mitad = false;
    private bool unQuinto = false;


    // Use this for initialization
    void Start () {

      
        unidad = GameObject.FindWithTag("Enemigo");
        DañoJugador = GameObject.FindWithTag("Meta").GetComponent<Meta>();
        salud = Arbolito.GetComponent<Animator>();
        vidaMaxima = vida.value;

	}
	
	// Update is called once per frame
	void Update () {

        if( DañoJugador.meta == true)
        {
            vida.value = vida.value - 0.09f;
            DañoJugador.meta = false;
            Debug.Log("El jugador pierde vida");
        }


        if (vida.value < vidaMaxima/2)
        {
            mitad = true;
            
        }

        if(vida.value < vidaMaxima/5)
        {
            unQuinto = true;
            mitad = false;   
        }

        if(mitad == true)
        {
            salud.Play(arboles[1]);
        }

        if(unQuinto == true)
        {
            salud.Play(arboles[2]);
        }

		
	}
}
Image

User avatar
xacarana
Site Admin
Posts: 1213
Joined: Fri Jan 15, 2016 6:13 pm

Re: Mirror Face Studios - Dawn of Rektwood

Post by xacarana » Wed Mar 22, 2017 8:52 am

Muy bien el avance, se ve un estado funcional del juego casi listo para la preentrega. Realicen una buena presentación, recuerden que la sustentación del proyecto es individual, todos deben saber responder preguntas de animación, ilustración y codificación.

Image
Andrés Bedoya Tobón
Profesor
"I only smile in the dark, I only smile when it's complicated" Raybiez

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Fri Mar 24, 2017 1:20 am

Actualización semana 10

En estos días hemos adelantado y corregido bastantes cosas, entre ella:

*(MODIFICADO) Disparo de las torres, antes disparaban a múltiples enemigos, ahora solo le disparan a uno a la vez.
*(MODIFICADO) Marco de selección de torres.
*(MODIFICADO) Escenario del nivel, se ha hecho un pequeño ajuste para acomodar la torre del lanza rocas.
*(AGREGADO) Nueva torre, la ballesta, hace daño reducido pero es la torre más rápida y con más alcance después de la torre de la roca.
*(AGREGADO) Precio a cada una de las torres y dinero base para el jugador. NOTA: Con sesiones de play testing se está trabajando para hacer el sistema justo y balanceado.
*(AGREGADO) Dos nuevos botones, uno es para cancelar la construcción de una torreta y el otro para poner a la unidad especial lanza rocas.
*(AGREGADO) Nuevos enemigos, una unidad terrestre y dos jefes (Falta por animar los jefes).
*(MODIFICADO) La barra de vida ahora funciona mejor y se le puede cambiar su valor máximo, pero, durante el proceso se tuvo que quitar de forma temporal la forma gráfica en que esta se pierde, es decir, se reduce hacia el centro y no hacia la equina.
*(AGREGADO) Una función que se activa al llegar a la oleada final y esta se encarga de activar a uno de los dos bosses de forma aleatoria, es decir, en una partida se activa una distinto a la anterior o el mismo, dependiendo de su suerte...


Problemas:


1) No hemos logrado conseguir que la flecha se disparé apuntando al enemigo en algunas partes del nivel.
2) La barra de vida nos está dando problemas a la hora de querer escalarla de derecha a izquierda.

Por hacer y terminar:


1) Encapsular y optimizar.
2) Implementar las animaciones.


Nivel modificado:


Image

Marco de seleccion modificado:

Image

Boton de cancelar:


Image

Seleccionador de torre especial:


Image

Image

Ballesta y su proyectil:

Image

Image

Image

Vídeo de demostración:

En el siguiente vídeo se podrá ver el sistema de selección de torres con la implementacion de los nuevos botones, junto con el sistema actual de economía.
También se podrá ver como funciona la salida de los bosses.Para la demostración se reduce el numero máximo de oleadas.




Script Torre:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DisparoTorre : MonoBehaviour {

    public GameObject proyectil;
    private GameObject enemigo;
    private bool activa = false;
    public float distancia_deteccion;
    PoolingEn en;
    Proyectiles bala;
    public float tiempoDisparo;
    private float contador;
    private Vector3 objetivo;
    public GameObject Enemigo
    {
        get
        {
            return enemigo;
        }

        set
        {
            enemigo = value;
        }
    }

    // Use this for initialization
    void Start () {

        en = GameObject.FindWithTag("Camara").GetComponent<PoolingEn>();
	}
	
	// Update is called once per frame
	void Update ()
    {
        contador = contador + 1;

       if (contador >= tiempoDisparo)
        {
            Enemigo = BuscarEnemigo();
           contador = 0;

            if (Enemigo != null)

            {
                Debug.DrawLine(this.transform.position, enemigo.transform.position, Color.green);
                Disparar(enemigo.transform.position);
                
            }
        }
    }




    GameObject BuscarEnemigo()
    {
        ArrayList enemigos = en.enemigos;

        GameObject temp;
      
        
        foreach(object item in enemigos)
        {
            temp = (GameObject)item;
         

            if (Vector3.Distance(temp.transform.position,this.transform.position)<distancia_deteccion)
            {
                return temp;
            }

            
        }
        return null;
    } 

    void Disparar(Vector3 objetivo)
    {

        {
            GameObject obj = Instantiate(proyectil, transform.position, Quaternion.identity);
            bala = obj.GetComponent<Proyectiles>();
            bala.objetivo = objetivo;

            if (obj.tag == "Flecha")
            {
                if (enemigo.transform.position.y > -2)
                {
                    obj.transform.LookAt(objetivo, new Vector3(0, 0, -1));
                }

                if (enemigo.transform.position.y < 0.01)
                {
                    obj.transform.LookAt(objetivo, new Vector3(0, 0, 1));
                }

                if(enemigo.transform.position.x >= 2.1 || enemigo.transform.position.y >= 1 )
                {
                    obj.transform.LookAt(objetivo, new Vector3(0, 0, 1));
                }
            }
        }

    }
}
Script Contador oleada:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ContadorOleadas : MonoBehaviour {
    public GameObject decenas, unidades;
    private Animator de, un;
    private string[] estados = { "Estado_00", "Estado_01", "Estado_02", "Estado_03", "Estado_04", "Estado_05", "Estado_06", "Estado_07", "Estado_08", "Estado_09" };
    private int oleada = 0;
    PoolingEn pooling;
    public int oleadaMaxima;


    public int Oleada


    {
        get
        {
            return oleada;
        }

        set
        {
            oleada = value;
        }
    }



    // Use this for initialization
    void Start()
    {
        pooling = GameObject.FindWithTag("Camara").GetComponent<PoolingEn>();
        de = decenas.GetComponent<Animator>();
        un = unidades.GetComponent<Animator>();
        oleada = 1;
        Actualizador(oleada);

            
    }

    // Update is called once per frame
    void Update()
    {

        if (pooling.proxOleada == true)

        {
            oleada = oleada + 1;
            Actualizador(oleada);
            pooling.proxOleada = false;

        }
        if (oleada == oleadaMaxima)

        {
            pooling.cantidad = 0;
            pooling.proxOleada = false;
            pooling.activarBoss = true;
        }
    }

    public void Actualizador(int numero)

    {
        int unidades = numero % 10;
        int decenas = numero % 100 - unidades;


        decenas = decenas / 10;


        if (numero > 9)
        {
            de.Play(estados[decenas]);
        }
        else

        { de.Play(estados[0]); }

        un.Play(estados[unidades]);
    }

}
Función seleccionar boss:

Code: Select all

 if(activarBoss == true)
        {
            contadorBoss = contadorBoss + 1;
            if (contadorBoss == 40)
            {
                EsCogerBoss();
            }
            
             void EsCogerBoss()
    {
        
        cantidad = 0;
        contador = 5000;
        int A;
        A = Random.Range(1, 5);
        if(A <= 2)
        {
            enemyBoss1.vel = 0.2f;
            Debug.Log("Boss que llega es: " + Boss_1.name);
        }
        if(A>=3)
        {
            enemyBoss2.vel = 0.2f;
            Debug.Log("Boss que llega es" + Boss_2.name);
        }
            
        }
Image

User avatar
xacarana
Site Admin
Posts: 1213
Joined: Fri Jan 15, 2016 6:13 pm

Re: Mirror Face Studios - Dawn of Rektwood

Post by xacarana » Fri Mar 24, 2017 10:20 am

Muy bien

Image
Andrés Bedoya Tobón
Profesor
"I only smile in the dark, I only smile when it's complicated" Raybiez

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Fri Mar 31, 2017 12:13 am

Semana 11

Que hemos hecho?

Terminamos de montar la preentrega de unity y ya es funcional, ademas, preparamos la presentación y los recursos que utilizaremos en esta.

Qué harán?


Nos dispondremos a trabajar en el juego final

Que problemas han tenido?

Nada relevante de momento
Image

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Fri Mar 31, 2017 12:20 am

Semana 11

PREENTREGA

A continuación, dejaremos los elementos utilizados en la presentación y los añadidos.


Añadidos:

Defensas:

Se añadió la torre faltante, el lanza troncos, que se encarga de lanzar un tronco que dura un tiempo en el suelo y hace retroceder a los enemigos.

Image

Image

Image

Image

Script Lanza Troncos:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LanzaTronco : MonoBehaviour
{

    public GameObject Diana;
    private Vector3 pos_diana;
    public GameObject proyectil;
    private GameObject enemigo;
    public float distancia_deteccion;
    PoolingEn en;
    Proyectiles bala;
    public float tiempoDisparo;
    private float contador;
    private Vector3 objetivo;
    private Animator anim;
    private bool activarAnim = false;
    private GameObject ruta;
    public GameObject Enemigo

    {
        get
        {
            return enemigo;
        }

        set
        {
            enemigo = value;
        }
    }

    // Use this for initialization
    void Start()
    {
        ruta = GameObject.FindWithTag("Ruta");
        en = GameObject.FindWithTag("Camara").GetComponent<PoolingEn>();
        pos_diana = Diana.transform.position;
      /*  anim = GetComponent<Animator>();
        anim.SetInteger("Estado", 0);*/
    }

    // Update is called once per frame
    void Update()
    {
        pos_diana = new Vector3(Diana.transform.position.x, Diana.transform.position.y, 0);
        /// anim.SetInteger("Estado", 0);
        contador = contador + 1;

      



        if (contador >= tiempoDisparo)
        {
            Enemigo = BuscarEnemigo();
            contador = 0;

            if (Enemigo != null)

            {
            
                Debug.DrawLine(this.transform.position, enemigo.transform.position, Color.green);
                Disparar(Diana.transform.position);


            }
        }


    }

    GameObject BuscarEnemigo()
    {
        ArrayList enemigos = en.enemigos;

        GameObject temp;

        foreach (object item in enemigos)
        {
            temp = (GameObject)item;

            if (Vector3.Distance(temp.transform.position, this.transform.position) < distancia_deteccion)
            {
                return temp;
            }
        }
        return null;
    }

    void Disparar(Vector3 objetivo)
    {
        {
            GameObject obj = Instantiate(proyectil, transform.position, Quaternion.identity);
            bala = obj.GetComponent<Proyectiles>();
            bala.objetivo = objetivo;

            ///anim.SetInteger("Estado", 1);




        }
    }
}
Escenario:

Se añadió un pequeño menú de inicio:

Image

Image

Al hacer click en el botón de jugar, se empieza el juego, la programación de esto es muy simple, aqui el script:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine;

public class CambiadorNiveles : MonoBehaviour {

    private void OnMouseDown()
    {
        CambiarNivel();
    }

    public void CambiarNivel()
    {
        SceneManager.LoadScene("Nivel1");
    }
}

Nueva canción:




Se compuso una nueva canción para el soundtrack del juego

Presentación:



Trailer del juego:



Gameplay del juego:

Image

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Tue Apr 18, 2017 10:26 pm

Semana 12

¿Que han hecho?

Corregir el trailer, revisar y corregir aspectos del código, terminar el diseño de sonido.

¿Que harán?

Durante la semana haremos pruebas con el lanza troncos e implementaremos algunos sonidos

¿Qué problemas han tenido?

Por ahora, nada relevante.
Image

User avatar
JoseDavid97
Posts: 70
Joined: Fri Jul 22, 2016 10:48 am

Re: Mirror Face Studios - Dawn of Rektwood

Post by JoseDavid97 » Tue Apr 25, 2017 11:16 pm

Semana 13

Qué han hecho?

Hemos puesto en pausa la parte de programacion para terminar ciertas tareas, como pequeños diseños faltantes, musica y sonido.

Que van a hacer?

Terminar el soundtrack del juego y tener ya lista la carpeta con todos los sonidos que utilizaremos.

Qué problemas han tenido?

No sabemos bien como implementar sonidos en unity, estamos investigando sobre el uso de AudioClip y AudioSource, el viernes subiremos un avance concretada la investigación.
Image

Post Reply