¡¡Felices Fiestas!!

Como ya os he comentado en clase, espero que durante las vacaciones extendáis ese mundo Tortuga en el que hemos vivido estas últimas semanas. Podéis, incluso, ampliar el mundo con todas las ideas que se os ocurran. Al volver, jugaremos todos con lo que hayáis programado.

Se que esperábamos todos estas vacaciones para descansar (¡todos!;-), pero es bueno no desconectar del todo, que luego volvemos muy oxidados…

Y, dicho lo anterior, solo me queda desearos que disfrutéis de las vacaciones y…

¡¡¡FELIZ NAVIDAD!!!

o

¡¡¡FELIZ SOLSTICIO DE INVIERNO!!!

Además, para que os entretengáis un ratito, os dejo unos vídeos relacionados con estas fiestas. Ambos están enmarcados en la tradición católica de la Navidad. El primero es una curiosa reinterpretación de la historia de la Navidad…algo friki. El segundo, un cuento de Navidad interpretado al violín de manera increible por Lindsey Stirling.

Lo dicho, a descansar y ¡volved con las pilas cargadas! ;-P

08 – Vamos a practicar lo aprendido: la tortuga tiene una tortuguita

Para practicar con todo lo aprendido hasta ahora, os propongo programar el siguiente juego. Consiste en el mismo juego de persecución pero con una pequeña variante: la tortuga tiene  una super-tortuguita.

Las especificaciones del juego son las siguientes:

  • Los personajes, es decir, las clases del juego son la clase ContadorTortuga, Serpiente, Lechuga y Babytortuga.
  • Al iniciar el escenario, el mundo debe crear:
    • un Contador para mostrar las lechugas que lleva comidas la Tortuga .
    • 3 serpientes con giro aleatorio y en posiciones aleatorias del escenario.
    • 20 lechugas en posiciones aleatorias del escenario.
    • una tortuga en la posición x=50, y=400.
  • Los objetos de la clase Serpiente deben tener el siguiente comportamiento:
    • moverse de 5 en 5 píxels en línea recta por el escenario.
    • al llegar al borde del escenario girar con el ángulo de giro que tenga predeterminado desde su nacimiento.
    • si en algún momento toca a la tortuga grande, se la debe comer y se acaba el juego sonando el sonido game_over.
  • Los objetos de la clase Tortuga deben tener el siguiente comportamiento:
    • debe tener un atributo privado de nombre hija que será la referencia a su tortuga hija, un objeto de tipo BabyTortuga.
    • debe tener un constructor que le asigne al atributo hija la BabyTortuga (objeto de dicha clase) que se crea al iniciarse el escenario.
    • debe tener un atributo privado de nombre lechugasComidas, de tipo entero, para acumular las lechugas que se vaya comiendo.
    • la tortuga avanzará de 6 en 6 píxeles por el escenario. Al presionar las teclas flecha izquierda o flecha derecha, la tortuga girará 5 grados a la derecha o a la izquierda, respectivamente. Además, si se pulsa la barra espaciadora (“space”), la tortuga deberá detenerse hasta que se libere la pulsación de la barra de espacio.
    • cuando pase por encima de una lechuga, debe comérsela y sonará el sonido slurp. Además, acumulará una unidad en su atributo lechugasComidas y, también, alimentará a su hija, invocando al método crece() de su hija.
  • La tortuga hija, de la clase BabyTortuga, debe tener el siguiente comportamiento:
    • debe tener un atributo privado de nombre crecimiento, que irá aumentando a medida que su madre coma lechugas. Al nacer la BabyTortuga, crecimiento tendrá un valor de 0;
    • para aumentar su crecimiento, deberá tener un método crece(), que al ser invocado por su madre aumentará en uno el atributo privado crecimiento.
    • debe tener un atributo privado serpientesComidas que acumulará el número de serpientes que se ha comido (sí, cuando crezca comerá serpientes!)
    • cuando el atributo crecimiento tenga un valor igual a 5, deberá cambiar su aspecto de pequeña a grande (crecerá) cambiándose la piel (la imagen de la clase) por la de la tortuga de caparazón negro.
    • cuando la tortuguita haya crecido, puede moverse. La tortuga hija ya crecida avanzará de 7 en 7 píxeles por el escenario. Al presionar las teclas “a” o “d”, la tortuga girará 5 grados a la izquierda o a la derecha, respectivamente.
    • la tortuga negra es evolución de su madre, y ha ganado la capacidad de comer serpientes. Cuando pase por encima de una, se la comerá y acumulará uno en su atributo serpientesComidas.
    • cuando se haya comido a las tres serpientes, el juego acabará y sonará el sonido juego ganado.

El diagrama de clases correspondiente a la especificación anterior es el siguiente.

diagramadeclase

(En la clase BabyTortuga hay que añadir el método crece() ).

07-Comunicación entre objetos

Como hemos visto en la entrada anterior, el mundo en el que viven nuestros objetos no es sino otro objeto que los contiene. A su vez, los objetos pueden pedirle al mundo en el que viven hacer cosas o comunicarle mensajes para que el propio mundo haga algo por ellos.

Vamos a ver algunos ejemplos de esta interacción entre objetos (objetos<->mundo y objeto<->objeto).

Los ejemplos que vamos a plantear y resolver para introducir el concepto de comunicación entre objetos se introducen en los vídeos que incluyo a continuación.

(OBSERVACIÓN: en el vídeo 27 se hace uso de clases que se han introducido en vídeos anteriores. Para conocer más qué hacen esas clases, se pueden visionar dichos vídeos, pero no es necesario para comprender el proceso de comunicación que se está explicando.)

Lo que nosotros nos vamos a plantear es el embarazo de la tortuga y nacimiento de una BabyTortuga. Imaginemos que comer lechugas hace que la Tortuga quede “embarazada” y, al alcanzar las 10 lechugas comidas, la tortuga da a luz a una nueva BabyTortuga.

Esa BabyTortuga nacida debe estar presente en el mundo y, para ello, la Tortuga debe ser capaz de comunicarse con el mundo donde vive para comunicarle dicho nacimiento y que la BabyTortuga se añada al mundo. El mundo debe ofrecer la posibilidad de crear estas pequeñas tortugas, por lo que añadiremos una clase de nombre BabyTortuga, a la que le asociaremos la imagen de una pequeña tortuga (seguir el enlace).

Para todo lo planteado anteriormente, deberemos hacer varias cosas:

  • en primer lugar, la tortuga debe estar preparada para tener una BabyTortuga, incluyendo en la clase Tortuga una referencia (un nuevo campo) a la posible BabyTortuga hija que posiblemente tenga

BabyTortuga bt;

  • a continuación, en el momento en que la tortuga se haya comido 5 lechugas, deberemos crear una nueva BabyTortuga, mediante el uso del constructor de la clase BabyTortuga que habremos creado y asociaremos esa nueva tortuga a la referencia bt anterior (así la Tortuga reconocerá a su hija…)

bt = new BabyTortuga();

  • finalmente, debemos informar al mundo del nacimiento de la BabyTortuga (es como ir al registro de nacimientos), para que la BabyTortuga pase a formar parte del mundo. Es en este momento cuando hacemos una llamada de atención al mundo donde viven las tortugas mediante el método getWorld() que todo actor dispone. El método devuelve una referencia  al mundo donde vive y, una vez sabe esto, puede invocar al método addObject del mundo para añadir la BabyTortuga.

World miMundo = this.getWorld();

miMundo.addObject(bt, posX, posY),

Vamos ahora a suponer que queremos visualizar cuantas lechugas lleva comidas la tortuga, para poder prever el feliz alumbramiento. Para ello, vamos a hacer uso de la clase Contador que os podéis bajar del enlace.

Con esta clase, podemos crear un objeto de tipo Contador en el mundo donde viven las tortugas para ir informando de cuántas lechugas se ha comido la tortuga y prever el feliz desenlace del alumbramiento. Sin embargo, la tortuga debe poder decirle a ese contador que añada una lechuga más, cada vez que se coma una. Podríamos hacerlo recuperando el mundo donde vive la tortuga y tratar de utilizar el contador que en él hay, pero nos obligaría a hacer determinadas conversiones (o type casting) que ahora nos resultarían extrañas.

Lo que vamos a hacer es utilizar otra manera de comunicar objetos que es pasarlos como referencia en el momento de crear la Tortuga en el mundo. Para ello:

  • crearemos en la Tortuga una referencia a un objeto Contador, que será el que nos ayude a notificar al contador del mundo que nos hemos comido una lechuga más.

Contador c;

  • vamos a crear un constructor para la clase Tortuga, que le pase como argumento el contador del mundo (es como hacerte la ficha del ginecólogo que te va a hacer el seguimiento del embarazo…)

public Tortuga (Contador cont){

this.c=cont;

}

  • en el momento de crear la tortuga en el mundo, le pasaremos el contador a esa Tortuga

Tortuga t=new Tortuga(c);

  • cada vez que la Tortuga se coma una lechuga, aumentaremos en uno el contador usando el método aumentaUno() del Contador c

c.aumentaUno();

De esta manera, lo que hemos hecho es poner en comunicación los objetos Tortuga y Contador usando como gestor intermediario el MundoTortuga que los contiene a ambos.

06 – Un poco de teoría que recopila lo aprendido: la estructura de una clase.

Con todo lo que hemos visto hasta ahora, podemos concentrarnos ya en lo que es la estructura de una clase en Java, conceptos que se explican en el vídeo que os incluyo a continuación.

A modo de resumen, una clase Java tiene la estructura que se muestra en la imagen siguiente.

estructura-clase

En el inicio del código fuente de una clase es habitual encontrarnos con clausulas import. Las cláusulas import permiten el acceso en nuestra clase a otras clases definidas en el paquete que se importa con import.

En particular, en nuestro proyectos de Greenfoot siempre encontramos la cláusula

import greenfoot.*

que hace accesibles todas las clases definidas en el paquete greenfoot, disponible en el entorno. Podemos así usar, por ejemplo, la generación de número aleatorios mediante el método getRandonNumber de la clase Greenfoot incluido en el paquete greenfoot.

A continuación comienza la declaración de la clase, donde se indica si es subclase de otra mediante la palabra reservada extends.

El cuerpo de la clase, entre llaves, recoge toda la definición de la clase, es decir, sus posibles atributos, los constructores y, a continuación, los métodos de clase, conceptos que hemos ido explicando poco a poco en las entradas anteriores de este blog.

estructura-clase2

De esta manera, la programación orientada a objetos, con su estructura principal de clase, nos permite representar, abstrayendo cómo funciona el mundo real, objetos que pueden tener características comunes y heredadas de otros, con unas características propias que definen su estado en un momento dado, y que saben realizar determinadas acciones para interactuar con el mundo en el que viven.

En las siguientes entradas plantearemos ejercicios que traten de recoger todo lo aprendido hasta ahora… y un paso más: la comunicación entre objetos.