MONSTER DEFENDERS - FDG Productions

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

Moderator: julianmartinez16

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

Re: MONSTER DEFENDERS - FDG Productions

Post by xacarana » Tue Oct 29, 2019 6:50 am

Image



El estado del juego según las evidencias demuestra una lejanía con respecto a la meta de entrega, deben concretar en que se van a enfocar y cumplir con los requisitos mínimos del juego y además falta el diagrama de clases.
  • Hud
  • Varios enemigos
  • Oleadas
  • Varias torres
  • Interacción con el juego por parte del jugador
Andrés Bedoya Tobón
Profesor
"I only smile in the dark, I only smile when it's complicated" Raybiez

User avatar
JhonMayuza
Posts: 11
Joined: Tue Jul 16, 2019 6:26 am

Re: MONSTER DEFENDERS - FDG Productions

Post by JhonMayuza » Tue Oct 29, 2019 6:58 am

¿Qué hemos hecho?

- Se ha arreglado las torres para que disparen a los enemigos provenientes de todos los caminos.

Code: Select all

GameObject BuscarEnemigoCercano()
    {
        GameObject[] enemigos = GameObject.FindGameObjectsWithTag("Enemigo");
    }
- Se ha simplificado los codigos individuales para los enemigos de cada camino en uno para todos los caminos, que puede ser reutilizado en todos.

Code: Select all

    [SerializeField]
    private string tag_arreglo_waypoints;
    [SerializeField]
    private string tag_waypoints_individuales;
    
    wpoints = GameObject.FindGameObjectWithTag(tag_arreglo_waypoints).GetComponent<Waypoints>();//tag_arreglo_waypoints reemplaza al waypoints en especifico, que causaba que se necesitaran varios scripts para la misma funcion.
    
-Las torres cambian de objetivo inmediatamente este muere.

Code: Select all

if (Vector3.Distance(temp.transform.position, this.transform.position) < distancia_umbral && temp.GetComponent<Salud>().esta_Muerto != true)
            {
                return temp;
            }
-Las balas ya no quedan flotando si su objetivo muere mientras estas van dirigidas a el.
-Unidades implementadas, los enemigos se detendran a luchar con estos hasta que uno de los dos muera.

Code: Select all

if (contador_lucha > 0) { contador_lucha -= Time.deltaTime; }
    oponente = BuscarObjetivos();
    if (oponente != null)
    {
    AtacarObjetivo(); // Da prioridad a atacar a los enemigos a pie en lugar de avanzar por la ruta.
    }
    else
    {
    velocidad = velocidad_inicial;
    moverse();
    }

Code: Select all

   GameObject BuscarObjetivos()
    {
        GameObject[] objetivos = GameObject.FindGameObjectsWithTag("Unidad");
        GameObject temp;
        foreach (object item in objetivos)
        {
            temp = (GameObject)item;
            if (Vector3.Distance(temp.transform.position, this.transform.position) < distancia_umbral && temp.GetComponent<Salud_Antibalas>().esta_Muerto != true)
            {
                return temp;
            }
        }
        return null;
    }

    void AtacarObjetivo()
     {

        if (Vector3.Distance(transform.position, oponente.transform.position) < distancia_lucha)
        {
            velocidad = 0;
            if (contador_lucha <= 0)
            {
                luchar();
                contador_lucha = tiempo_de_espera;
            }
        }
        else {transform.position = Vector3.MoveTowards(transform.position, oponente.transform.position, velocidad * Time.deltaTime);}
    }

    void luchar()
    {
       salud_oponente = oponente.GetComponent<Salud_Antibalas>();
       salud_oponente.salud -= poder_ataque;
    }
-Se agrego un gizmo para el modo editor a torres y enemigos, con el objetivo de ver la distancia de umbral mas claramente al probar elementos.

Code: Select all

    void OnDrawGizmosSelected ()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, distancia_umbral);
    }
-Los enemigos pueden morir, despues de que su vida llegue a 0, perderan su velocidad, y desapareceran tras 5 segundos.
-Los menus, las monedas y la compra de torres han sido implementados y son funcionales.
Image
-Se ha cambiado ligeramente aspectos esteticos de la interfaz.
-Se ha replanteado el diagrama de clases del juego. (Falta por terminar)
Image
-Se ha puesto sprites temporales a las unidades.
-Las clases de enemigo especial como el enemigo sanador, enemigo inmune a torres y enemigo inmune a unidades han sido implementados, y sus caracteristicas individuales son funcionales.
Image





¿Qué falta por hacer?

-Terminar las animaciones para todos los objetos del juego.
-Hacer un sistema de oleadas funcional.
-Implementar la mejora de torres.
-Agregar a los enemigos y su muerte al sistema de monedas.
-Rehacer la interfaz de los menus para que quede acorde a la ambientacion del juego.
-Agregar sonido a los objetos del escenario.
-Hacer y agregar props de iluminacion al escenario.


¿Qué dificultades hemos tenido?


- El retiro de uno de los miembros del equipo.
- Dificultad al hacer la animacion para cada personaje.
- Problemas para desarrollar las oleadas y el sistema de mejoras.
Image
Jhon Esteban Mayuza Villegas - Programacion orientada a objetos
2019-02

User avatar
daniela.atencia
Posts: 57
Joined: Tue Jan 22, 2019 6:20 am

Re: MONSTER DEFENDERS - FDG Productions

Post by daniela.atencia » Tue Oct 29, 2019 7:21 am

Actividades faltantes:

-Terminar las animaciones para todos los objetos del juego. (Jhon Mayuza)
-Hacer y agregar props de iluminacion al escenario. (Jhon Mayuza)
-Hacer un sistema de oleadas funcional.(Jhon Mayuza)
-Agregar a los enemigos y su muerte al sistema de monedas.(Jhon Mayuza)
-Implementar la mejora de torres.(Daniela Atencia)
-Rehacer la interfaz de los menus para que quede acorde a la ambientacion del juego.(Daniela Atencia)
-Agregar sonido a los objetos del escenario.(Daniela Atencia)
-Mejorar HUD.(Daniela Atencia)
-Terminar diapositivas de la presentación (Jhon Mayuza, Daniela Atencia)
-Terminar diagrama de clases. (Jhon Mayuza, Daniela Atencia)
Daniela Atencia

Programación y diseño orientado a objeto, 2019-2.

User avatar
daniela.atencia
Posts: 57
Joined: Tue Jan 22, 2019 6:20 am

Re: MONSTER DEFENDERS - FDG Productions

Post by daniela.atencia » Tue Oct 29, 2019 10:30 pm

¿Qué hemos hecho?

-Además, de la publicación anterior, se realizó una prueba de las torres, de la ubicación de diferentes torres, su compra y mejora.



¿Qué falta por hacer?

-Arreglar el problema de la compra. Descuenta el dinero pero no sale el nuevo sprite.
-Arreglar el sistema de oleadas.
-Terminar el diagrama de clases.
-Terminar de organizar las diapositivas.

¿Qué dificultades hemos tenido?

-Que no cambia de sprite al cobrar el dinero de la mejora de la torre.

link repositorio: https://github.com/danielaatencia/PDOO
Daniela Atencia

Programación y diseño orientado a objeto, 2019-2.

User avatar
daniela.atencia
Posts: 57
Joined: Tue Jan 22, 2019 6:20 am

Re: MONSTER DEFENDERS - FDG Productions

Post by daniela.atencia » Mon Nov 18, 2019 6:05 pm

presentación:



presentación en google drive, donde se ven las animaciones:

https://docs.google.com/presentation/d/ ... 5ddc1_0_83

Códigos utilizados en el juego, en la sección de los menús:

código para cambiar de escenas:

Code: Select all

public class CargarNiveles : MonoBehaviour
{

    public void Cargar(string nombreNivel)
    {
        SceneManager.LoadScene(nombreNivel);
    }

    public void Salir()
    {
        Application.Quit();
    }

}

Code: Select all

public class Desvanecer : MonoBehaviour
{

    [SerializeField]
    private Image desvanecer;
    private byte alpha;
    public bool irse = false;
    AudioSource audio;
    [SerializeField]
    private AudioClip perdicion;

    // Start is called before the first frame update
    void Start()
    {
        alpha = 255;
        audio = GetComponent<AudioSource>();
    }

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

    void DesvanecerPantalla()
    {
        if (irse == false)
        {
            alpha -= 1;
            desvanecer.color = new Color32(0, 0, 0, alpha);
            if (alpha == 0)
            {
                this.gameObject.SetActive(false);
            }
        }
        else
        {
            if (audio.isPlaying == false)
            {
                audio.clip = perdicion;
                audio.Play();
                audio.volume -= 0.05f;
            }
            alpha += 1;
            desvanecer.color = new Color32(0, 0, 0, alpha);
            if (alpha == 255)
            {
                SceneManager.LoadScene("menu");
            }
        }
    }

    public void IrAMenu()
    {
        irse = true;
    }
}

Code: Select all

public class DesvanecerMusica : MonoBehaviour
{

    [SerializeField]
    private GameObject imagen;
    AudioSource audio;
    // Start is called before the first frame update
    void Start()
    {
        audio = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        BajarVolumen();
    }
    void BajarVolumen()
    {
        if (imagen.GetComponent<Desvanecer>().irse == true)
        {
            audio.volume -= 0.003f;
        }
    }
}

Code: Select all

public class SonidoBoton : MonoBehaviour
{
    AudioSource audio;
    [SerializeField]
    private AudioClip bip;
    [SerializeField]
    private AudioClip bip2;
    private float random;

    // Start is called before the first frame update
    void Start()
    {
        audio = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    public void Sonar()
    {
        random = Random.Range(-1f, 1f);
        if (random <= 0f) {audio.clip = bip;}
        else {audio.clip = bip2;}
        audio.Play();
    }
}

Códigos utilizados en el juego, en la sección de los niveles:

código para agregar monedas al matar a enemigos:

Code: Select all

public class AgregarMonedasAlMorir : MonoBehaviour
{
    [SerializeField]
    private int monedas_al_morir;
    private bool ya_ha_pagado;

    void Update()
    {
        SumarMonedas();
    }

    void SumarMonedas()
    {
        if (GetComponent<Salud>().esta_Muerto == true && ya_ha_pagado == false)
        {
            GameObject pagar = GameObject.FindWithTag("Moneda");
            pagar.GetComponent<Moneda>().AgregarDinero(monedas_al_morir);
            ya_ha_pagado = true;
        }
    }
}
código para la animación de enemigos:

Code: Select all

public class AnimacionEnemigos : MonoBehaviour
{

    Animator animator;

    // Start is called before the first frame update
    void Start()
    {
        animator = GetComponent<Animator>();
    }

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

    void RevisarDireccion()
    {
        GameObject a = transform.parent.gameObject;
        if (a.GetComponent<Enemigo>().mov_Izquierda == true)
        {
            animator.SetBool("mov_Izquierda", true);
        }
        else { animator.SetBool("mov_Izquierda", false); }
    }
}
código para la animación de la moneda:

Code: Select all

public class AnimacionMoneda : MonoBehaviour
{
    Animator animator;

    void Start()
    {
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        Animar();
    }
    void Animar()
    {
        GameObject a = GameObject.FindWithTag("Moneda");
        if (a.GetComponent<Moneda>().estaCambiando == true)
        {
            animator.SetBool("Cambiar", true);
        }
        else { animator.SetBool("Cambiar", false); }
    }
}
código de bala:

Code: Select all

public class Bala : MonoBehaviour
{
    private GameObject objetivo; // El objeto al que la bala se dirigira, asignado por la torre.
    private float velocidad = 5; // La rapidez de la bala.

    void OnTriggerEnter(Collider collider)
    {
        if (collider.gameObject.CompareTag("Enemigo"))
        {
            Destroy(this.gameObject);
        }
    }

    void Update()
    {
        Vector3 direccion; // Le indica la direccion de su objetivo.
        if (objetivo != null) // Mantiene la bala activa mientras su objetivo lo este.
        {
            direccion = objetivo.transform.position - this.transform.position; // Mueve la bala hacia su objetivo.
            this.transform.position += velocidad * direccion * Time.deltaTime; // Maneja la velocidad de la bala.
        }
        else {Destroy(this.gameObject);}

    }
    public void ActivarBala(Torre torre)
    {
        objetivo = torre.Enemigo; // Usado por la torre para asignar un objetivo a la bala.
    }

}

Code: Select all

public class BGM : MonoBehaviour
{
    GameObject vida;
    AudioSource audio;
    // Start is called before the first frame update
    void Start()
    {
        vida = GameObject.FindWithTag("Vida");
        audio = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        if (vida.GetComponent<Vida>().vida < 1)
        {
            DesvanecerMusica();
        }
    }

    void DesvanecerMusica()
    {
        audio.volume -= 0.001f;
    }
}

Code: Select all

public class Conclusion : MonoBehaviour
{
    [SerializeField]
    private Image desvanecer;
    private byte alpha;
    private bool fracaso = false;
    GameObject[] enemigos;
    GameObject vida;
    public bool victoria;
    [SerializeField]
    private GameObject[] spawners;
    GameObject[] enemigosRestantes;
    AudioSource audio;
    [SerializeField]
    private AudioClip sonidoVictoria;

    void Start()
    {
        audio = GetComponent<AudioSource>();
        alpha = 0;
        enemigos = GameObject.FindGameObjectsWithTag("Enemigo");
        vida = GameObject.FindWithTag("Vida");
    }

    void Update()
    {
        enemigosRestantes = GameObject.FindGameObjectsWithTag("Enemigo");

        revisarResultado();
        if (fracaso == true || victoria == true)
        {
            alpha += 1;
            desvanecer.color = new Color32(0, 0, 0, alpha);
        }
        if (alpha == 255 && fracaso == true)
        {
            SceneManager.LoadScene("gameover");
        }
        else if (alpha == 255 && victoria == true)
        {
            SceneManager.LoadScene("victoria");
        }
        
    }

    void revisarResultado()
    {
        if (vida.GetComponent<Vida>().vida < 1)
        {
            fracaso = true;
        }
        if (enemigos.Length == 0 && fracaso != true)
        {
            if (spawners[0].GetComponent<oleadas>().oleadasCompletadas == true)
            {
                if (spawners[1].GetComponent<oleadas>().oleadasCompletadas == true)
                {
                    if (spawners[2].GetComponent<oleadas>().oleadasCompletadas == true)
                    {
                        if (spawners[3].GetComponent<oleadas>().oleadasCompletadas == true)
                        {
                            if (enemigosRestantes.Length == 0)
                            {
                                victoria = true;
                                if(audio.isPlaying == false)
                                {
                                    audio.clip = sonidoVictoria; audio.Play();
                                    audio.volume -= 0.02f;
                                }

                            }
                        }
                    }
                }
            }
        }
    }
}

Code: Select all

public class Corazon : MonoBehaviour
{
    [SerializeField]
    private Image corazon;
    [SerializeField]
    private int numeroCorazon;
    [SerializeField]
    private Sprite corazon_roto;
    private byte alpha;
    [SerializeField]
    private GameObject concluir;

    void Start()
    {
        alpha = 255;
    }

    void Update()
    {
        RemoverCorazon();
    }

    void RemoverCorazon()
    {
        GameObject vida = GameObject.FindWithTag("Vida");
        if (vida.GetComponent<Vida>().vida < numeroCorazon && alpha != 0)
        {
            corazon.sprite = corazon_roto;
            alpha -= 1;
            corazon.color = new Color32(255, 0, 0, alpha);
        }
        if (concluir.GetComponent<Conclusion>().victoria == true)
        {
            corazon.color = new Color32(255, 255, 0, 255);
        }
    }
}

Code: Select all

public class Enemigo : MonoBehaviour
{
    [SerializeField]
    private float velocidad_inicial;
    private float velocidad;
    private ListaWaypoints wpoints; // Permite asignarle los Waypoints respectivos del camino a recorrer.
    private Vector3 posicion_inicial; // Guarda su posicion de inicio.
    private int contador; // Necesario para el funcionamiento del movimiento.
    [SerializeField]
    private string tag_arreglo_waypoints;
    [SerializeField]
    private string tag_waypoints_individuales;
    [SerializeField]
    private float distancia_umbral;
    [SerializeField]
    private float distancia_lucha;
    private GameObject oponente;
    private float contador_lucha;
    [SerializeField]
    private float tiempo_de_espera = 1f;
    [SerializeField]
    private int poder_ataque = 1;
    [SerializeField]
    private bool ataca_unidades;
    private Salud_Antibalas salud_oponente;
    private Vector3 pos_Anterior;
    private Vector3 pos_Actual;
    public bool atacando;
    public bool mov_Izquierda;
    public bool mov_Derecha;

    void Start()
    {
        posicion_inicial = this.transform.position; // Establece la posicion actual.
        wpoints = GameObject.FindGameObjectWithTag(tag_arreglo_waypoints).GetComponent<ListaWaypoints>(); //Detecta todos los Waypoints que pertenecen a una ruta.
    }

    void Update()
    {
    if (contador_lucha > 0 && ataca_unidades == true) { contador_lucha -= Time.deltaTime; }
    oponente = BuscarObjetivos();
    if (oponente != null && ataca_unidades == true)
    {
    AtacarObjetivo(); // Da prioridad a atacar a los enemigos a pie en lugar de avanzar por la ruta.
    }
    else
    {
    velocidad = velocidad_inicial;
    moverse();
    }
    //test muerte
    if (GetComponent<Salud>().esta_Muerto == true) { velocidad_inicial = 0; velocidad = 0; transform.Translate(0, 0, Time.deltaTime); } // Inmobiliza a la unidad, sera reemplazado en el futuro por una animacion de muerte.
    //fin de test muerte

    }

    GameObject BuscarObjetivos()
    {
        GameObject[] objetivos = GameObject.FindGameObjectsWithTag("Unidad");
        GameObject temp;
        foreach (object item in objetivos)
        {
            temp = (GameObject)item;
            if (Vector3.Distance(temp.transform.position, this.transform.position) < distancia_umbral && temp.GetComponent<Salud_Antibalas>().esta_Muerto != true)
            {
                return temp;
            }
        }
        return null;
    }

    void AtacarObjetivo()
     {

        if (Vector3.Distance(transform.position, oponente.transform.position) < distancia_lucha)
        {
            velocidad = 0;
            if (contador_lucha <= 0)
            {
                luchar();
                contador_lucha = tiempo_de_espera;
            }
        }
        else {transform.position = Vector3.MoveTowards(transform.position, oponente.transform.position, velocidad * Time.deltaTime);}
    }

    void luchar()
    {
       atacando = true;
       salud_oponente = oponente.GetComponent<Salud_Antibalas>();
       salud_oponente.salud -= poder_ataque;
    }

    void moverse()
    {
        atacando = false;
        transform.position = Vector3.MoveTowards(transform.position, wpoints.waypoints[contador].position, velocidad * Time.deltaTime); // Le da movimiento a la unidad a travez del camino.

        if (Vector3.Distance(transform.position, wpoints.waypoints[contador].position) < 0.1f)
        {
            contador++; //Cuando se encuentra extremadamente cerca de su objetivo, el contador aumenta, haciendo que cambie su rumbo al proximo waypoint.
        }

        if (GameObject.FindGameObjectsWithTag(tag_waypoints_individuales).Length == contador)
        {
            contador = 0;
            this.transform.position = posicion_inicial; //Regresa a la unidad a su posicion de inicio y reinicia su contador.
        }
        direccion();
    }

    void direccion()
    {
        pos_Anterior = pos_Actual;
        pos_Actual = this.transform.position;
        if (pos_Anterior.x > pos_Actual.x)
        {
            mov_Derecha = false;
            mov_Izquierda = true;
        }
        if(pos_Anterior.x < pos_Actual.x)
        {
            mov_Izquierda = false;
            mov_Derecha = true;
        }
    }

    void OnDrawGizmosSelected ()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, distancia_umbral);
    }

    public float Velocidad { get => velocidad; set => velocidad = value; }
}

Code: Select all

public class EsCurado : MonoBehaviour
{

    [SerializeField]
    private float tiempo_de_espera = 2f;
    private float contador = 0;
    [SerializeField]
    private int tasa_de_curacion = 1;
    [SerializeField]
    private bool esta_curandose = false;
    private float distancia_umbral = 4f;

    void Update()
    {
        if (contador > 0) { contador -= Time.deltaTime; }
        esta_curandose = BuscarCuranderoCerca();
        if (esta_curandose == true && contador <= 0)
        {
            Salud curarse = GetComponent<Salud>();
            curarse.Curar(1);
            contador = tiempo_de_espera;
        }
    }

    bool BuscarCuranderoCerca()
    {
        GameObject[] curanderos = GameObject.FindGameObjectsWithTag("Curacion");
        GameObject temp;
        foreach (object item in curanderos)
        {
            temp = (GameObject)item;
            if (Vector3.Distance(temp.transform.position, this.transform.position) < distancia_umbral)
            {
                return true;
            }
        }
        return false;
    }
}

Code: Select all

public class ListaWaypoints : MonoBehaviour
{
    public Transform[] waypoints; // Funciona como un array que permite modificar las rutas facilmente desde el editor.
}

Code: Select all

public class Moneda : MonoBehaviour
{
    public int moneda;
    private int monedaDisplay;
    [SerializeField]
    private Text uiMoneda;
    AudioSource audio;
    [SerializeField]
    private AudioClip masDinero;
    [SerializeField]
    private AudioClip menosDinero;
    public bool estaCambiando;

    void Start()
    {
        audio = GetComponent<AudioSource>();
    }
    
    void Update()
    {
        ManejarIndicadorMonedaIU();
    }

    void ManejarIndicadorMonedaIU()
    {
        if (monedaDisplay != moneda)
        {
            estaCambiando = true;
            if (monedaDisplay > moneda)
            {
                monedaDisplay -= 1;
            }
            if (monedaDisplay < moneda)
            {
                monedaDisplay += 1;
            }
        }
        else { estaCambiando = false; }
        uiMoneda.text = monedaDisplay.ToString();
    }

    public void AgregarDinero(int dinero)
    {
        moneda += dinero;
        audio.clip = masDinero;
        audio.Play();
    }

    public void QuitarDinero(int dinero)
    {
        moneda -= dinero;
        audio.clip = menosDinero;
        audio.Play();
    }
}

Code: Select all

public class oleadas : MonoBehaviour
{

    [SerializeField]
    private int cantidadOleadas;
    [SerializeField]
    private int[] enemigosPorOleada;
    [SerializeField]
    private Transform prefabEnemigo;
    [SerializeField]
    private Transform puntoAparicion;
    [SerializeField]
    private float tiempoEntreOleadas;
    [SerializeField]
    private float tiempoEntreEnemigos;
    [SerializeField]
    private float contador;
    [SerializeField]
    private int oleadaActual;
    [SerializeField]
    public bool oleadasCompletadas;
    [SerializeField]
    private int enemigosPorAparecer;

    void Update()
    {
        if (contador <= 0f && oleadaActual != cantidadOleadas)
        {
            StartCoroutine(spawnWave());
            contador = tiempoEntreOleadas;
            oleadaActual++;
        }
        else if(oleadaActual == cantidadOleadas) { oleadasCompletadas = true; }
        contador -= Time.deltaTime;
        contador = Mathf.Clamp(contador, 0f, Mathf.Infinity);
    }

    IEnumerator spawnWave()
    {
        enemigosPorAparecer = enemigosPorOleada[oleadaActual];

        for (int i = enemigosPorAparecer; i > 0; i--)
        {
            spawnEnemy();
            yield return new WaitForSeconds(tiempoEntreEnemigos);
        }
    }

    void spawnEnemy()
    {
        Instantiate(prefabEnemigo, puntoAparicion.position, puntoAparicion.rotation);
    }
}

Code: Select all

public class PonerTorre : MonoBehaviour
{
    [SerializeField]
    private GameObject torre;
    [SerializeField]
    private int costoTorre;

    private void OnMouseDown()
    {
        CrearTorre();
    }

    void CrearTorre()
    {
        GameObject temp;
        Vector3 pos = this.transform.position;
        pos.y = pos.y + .4f;
        GameObject revisarDinero = GameObject.FindWithTag("Moneda");
        if (revisarDinero.GetComponent<Moneda>().moneda >= costoTorre)
        {
            temp = Instantiate(torre);
            temp.transform.position = pos;
            temp.layer = 5;
            revisarDinero.GetComponent<Moneda>().QuitarDinero(costoTorre);
            Destroy(transform.parent.gameObject);
        }
    }
    public GameObject Torre { get => torre; set => torre = value; }
}

Code: Select all

public class Salud : MonoBehaviour
{
    [SerializeField]
    private float salud_Maxima = 20;
    [SerializeField]
    private float salud_Actual = 20; // Establece la salud de la unidad.
    private float retraso_muerte = 5f; // Genera un retraso antes de la desaparicion de la unidad, actualmente sin ser usado, sera reemplazado por la animacion de muerte.
    public bool esta_Muerto = false;
    private float frecuenciaUnidad = 1f;
    private float contador = 1f;
    AudioSource audio;
    [SerializeField]
    private AudioClip lastimado;
    [SerializeField]
    private AudioClip muerto;
    [SerializeField]
    private bool atacado_por_unidades;
    [SerializeField]
    private Image barra;
    private float saludDisplay;

    void Start()
    {
        audio = GetComponent<AudioSource>();
    }

    void Update()
    {
        ManejarBarraDeSalud();
        RevisarSalud();
    }

    void ManejarBarraDeSalud()
    {
        if (salud_Actual <= salud_Maxima / 3) { barra.color = new Color32(255, 0, 0, 255); }
        else { barra.color = new Color32(49, 91, 53, 255); }
        if (saludDisplay != salud_Actual)
        {
            if (saludDisplay / 3 > salud_Actual)
            {
                saludDisplay -= 0.5f;
            }
            if (saludDisplay * 3 < salud_Actual)
            {
                saludDisplay += 0.1f;
            }
            if (saludDisplay > salud_Actual)
            {
                saludDisplay -= 0.1f;
            }
            if (saludDisplay < salud_Actual)
            {
                saludDisplay += 0.1f;
            }
        }
        barra.fillAmount = saludDisplay / salud_Maxima;
    }

    void RevisarSalud()
    {
        if (contador > 0) { contador -= Time.deltaTime; }
        if (esta_Muerto == false && salud_Actual <= 0) { audio.clip = muerto; audio.Play(); }
        if (salud_Actual <= 0) { esta_Muerto = true; }
        if (esta_Muerto == true) { retraso_muerte -= Time.deltaTime; }// Activa el contador de muerte, sera empleado por la animacion de muerte.
        if (retraso_muerte <= 0) { Destroy(this.gameObject); }
    }

    void OnTriggerEnter(Collider collider)
    {
        if (collider.gameObject.CompareTag("Bala"))
        {
            AudioSource audio = GetComponent<AudioSource>();
            salud_Actual -= 2; // Reduce la vida de la unidad al ser impactado por una bala.
            audio.clip = lastimado;
            audio.Play();
        }
    }
    void OnTriggerStay(Collider collider)
    {
        if (collider.gameObject.CompareTag("Unidad") && contador <= 0 && atacado_por_unidades == true)
        {
            salud_Actual -= 1; // Reduce la vida de la unidad al ser impactado por una bala.
            audio.clip = lastimado;
            audio.Play();
            contador = frecuenciaUnidad;
        }
    }

    public void Curar(int curacion)
    {
        if (salud_Actual < salud_Maxima)
        {
            salud_Actual += curacion;
        }
    }
    public bool Esta_Muerto { get => esta_Muerto; set => esta_Muerto = value; }
}

Code: Select all

public class Salud_Antibalas : MonoBehaviour
{
    [SerializeField]
    private float salud_Maxima;
    public float salud; // Establece la salud de la unidad.
    private float retraso_muerte = 5f; // Genera un retraso antes de la desaparicion de la unidad, actualmente sin ser usado, sera reemplazado por la animacion de muerte.
    public bool esta_Muerto = false;
    AudioSource audio;
    [SerializeField]
    private AudioClip muerto;
    [SerializeField]
    private Image barra;
    private float contador;
    private float saludDisplay;

    void Start()
    {
        audio = GetComponent<AudioSource>();
    }

    void Update()
    {
        ManejarBarraDeSalud();
        if (contador > 0)
        {
            contador -= Time.deltaTime;
        }
        Curarse();
        RevisarSalud();
    }

    void ManejarBarraDeSalud()
    {
        if (saludDisplay != salud)
        {
            if (saludDisplay / 3 > salud)
            {
                saludDisplay -= 0.5f;
            }
            if (saludDisplay * 3 < salud)
            {
                saludDisplay += 0.1f;
            }
            if (saludDisplay > salud)
            {
                saludDisplay -= 0.1f;
            }
            if (saludDisplay < salud)
            {
                saludDisplay += 0.1f;
            }
        }
        barra.fillAmount = saludDisplay / salud_Maxima;
    }
    void Curarse()
    {
        if (salud < salud_Maxima && esta_Muerto == false && contador <= 0)
        {
            salud += 1; contador = 2.5f;
        }
    }
    void RevisarSalud()
    {
        if (esta_Muerto == false && salud <= 0)
        {
            audio.clip = muerto; audio.Play();
        }
        if (salud <= 0)
        {
            retraso_muerte -= Time.deltaTime; // Activa el contador de muerte, sera empleado por la animacion de muerte.
            esta_Muerto = true;
        }

        if (retraso_muerte <= 0)
        {
            Destroy(this.gameObject); //Intento de desaparicion de las unidades derrotadas, genera errores, desactivado hasta encontrar una solucion o alternativa.
        }
    }
}

Code: Select all

public class Torre : MonoBehaviour
{
    [SerializeField]
    private GameObject proyectil;
    private GameObject enemigo;
    private bool esta_activa;
    [SerializeField]
    private float distancia_umbral = 10f;
    [SerializeField]
    private float retraso_disparo;
    private float enfriamiento;
    [SerializeField]
    private int rafaga;
    [SerializeField]
    private int disparos_restantes;
    [SerializeField]
    private float retraso_rafaga;
    [SerializeField]
    private float enfriamiento_rafaga;
    AudioSource audio;
    [SerializeField]
    private AudioClip disparo;

    void Start()
    {
        audio = GetComponent<AudioSource>();
        disparos_restantes = rafaga;
        enfriamiento = 0;
        enfriamiento_rafaga = 0;
    }

    void Update()
    {
        if (enfriamiento > 0) {enfriamiento -= Time.deltaTime;}
        if (enfriamiento_rafaga > 0) { enfriamiento_rafaga -= Time.deltaTime; }
        Enemigo = BuscarEnemigoCercano();
        if (Enemigo != null)
        {
            Disparar();
            Debug.DrawLine(this.transform.position, Enemigo.transform.position, Color.yellow);
        }
    }

    void Disparar()
    {
        if (enfriamiento <= 0)
        {
            if (disparos_restantes > 0)
            {
                if (enfriamiento_rafaga <= 0)
                {
                    audio.clip = disparo; audio.Play();
                    GameObject obj = (GameObject)Instantiate(proyectil, this.transform.position, Quaternion.identity);
                    Bala bala = obj.GetComponent<Bala>();
                    bala.ActivarBala(this);
                    enfriamiento_rafaga = retraso_rafaga;
                    disparos_restantes -= 1;
                }
            }
            else { enfriamiento = retraso_disparo; disparos_restantes = rafaga; }
        }
    }

    GameObject BuscarEnemigoCercano()
    {
        GameObject[] enemigos = GameObject.FindGameObjectsWithTag("Enemigo");
        GameObject temp;
        foreach (object item in enemigos)
        {
            temp = (GameObject)item;
            if(temp.GetComponent<Salud>().esta_Muerto != true)
            {
                if (Vector3.Distance(temp.transform.position, this.transform.position) < distancia_umbral)
                {
                    return temp;
                }
            }
        }
        return null;
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, distancia_umbral);
    }

    public GameObject Enemigo
    {
        get => enemigo; set => enemigo = value;
    }
    public bool Esta_activa
    {
        get => esta_activa; set => esta_activa = value;
    }
}

Code: Select all

public class Unidad : MonoBehaviour
{
    void Update()
    {
        SalirDelEscenario();
    }

    void SalirDelEscenario()
    {
        if (GetComponent<Salud_Antibalas>().esta_Muerto == true) { transform.Translate(0, 0, Time.deltaTime); }
    }
}

Code: Select all

public class Vida : MonoBehaviour
{
    public int vida;
    AudioSource audio;
    [SerializeField]
    private AudioClip vidaPerdida;
    [SerializeField]
    private AudioClip perdicion;
    private bool reproducirfracaso;

    void Start()
    {
        audio = GetComponent<AudioSource>();
        reproducirfracaso = true;
    }

    void Update()
    {
        ReproducirSonidoIndicador();
    }

    void OnTriggerEnter(Collider collider)
    {
        if (collider.gameObject.CompareTag("Enemigo"))
        {
            vida -= 1; // Reduce la vida de la unidad al ser impactado por una bala.
            audio.clip = vidaPerdida;
            audio.Play();
            Destroy(collider.gameObject);
        }
    }

    void ReproducirSonidoIndicador()
    {
        if (vida == 0 && GetComponent<AudioSource>().isPlaying == false)
        {
            audio.clip = perdicion;
            audio.Play();
            reproducirfracaso = false;
            audio.volume -= 0.1f;
        }
    }
}
Last edited by daniela.atencia on Mon Nov 18, 2019 6:49 pm, edited 1 time in total.
Daniela Atencia

Programación y diseño orientado a objeto, 2019-2.

User avatar
JhonMayuza
Posts: 11
Joined: Tue Jul 16, 2019 6:26 am

Re: MONSTER DEFENDERS - FDG Productions

Post by JhonMayuza » Mon Nov 18, 2019 6:28 pm

¿Qué hemos hecho?
  • Actualizar el diagrama de clases, realizar la presentacion final, preparar el video expositivo del proyecto y completar tareas faltantes del backlog.


¿Qué falta por hacer?
  • --

¿Qué dificultades hemos tenido?
  • Problemas a la hora de subir los videos y versiones finales del juego.
Image
Jhon Esteban Mayuza Villegas - Programacion orientada a objetos
2019-02

Post Reply