El trabajo propuesto

La versión 0.13 del juego todavía no hace casi nada de lo que hacía el juego original: no podemos recoger tesoros, no perdemos aire ni energía, apenas hay enemigos, no existe una tabla de las mejores puntuaciones, no hay animaciones cuando el personaje anda, ni cuando muere, ni cuando muere un enmigo...

A pesar de eso, el fuente del fichero "Juego.cs" ya ocupa 578 líneas, y empieza a ser trabajoso encontrar cada zona que queremos ampliar. A medida que lo sigamos ampliando, cada vez será más trabajoso... salvo que hagamos un rediseño.

Es el momento de pensar cómo podemos desglosar ese fuente en varios, de forma que cada uno tenga un propósito claro. Una forma de hacerlo sería replantear el problema como una serie de objetos que interaccionan. Tendríamos que pensar qué elementos forman nuestro juego, qué relaciones hay entre ellos y cómo se comunican...

Forma de conseguirlo

Vamos a pensar primero cómo sería el diagrama de clases de todo el juego (o casi), y luego lo reduciremos para quedarnos con la parte que realmente nos interesa, y que iremos ampliando poco a poco.

En una primera aproximaci�n, podemos pensar que en el juego aparecen objetos como: un personaje, un enemigo, una pantalla de presentaci�n, un mapa...

Además, desde la pantalla principal se debería poder acceder a los créditos (lista de programadores que han realizado el programa) y a la tabla de records.

Incluso podríamos afinar un poco más lo que ocurre durante una partida, distinguiendo dos tipos de enemigos: enemigos que podemos matar (como el escorpión y la araña que avanza por el suelo) y enemigos que nos matan a nosotros pero contra los que no podemos luchar (como la araña que se descuelga del techo y el ácido). Todavía no incorporaremos todos estos enemigos, pero al menos sí los tendremos en cuenta en la primera aproximación del diagrama de clases, que podría quedar así:

Clases previstas (simplificado)

En realidad, el diagrama debería incluir también las clases auxiliares que son parte del esqueleto: Hardware, Imagen, Fuente... de modo que el diagrama completo podría ser así:

Clases previstas (completo)

Pero a nosotros todavía no nos interesa crear una estructura tan grande. De momento comenzaremos por crear sólo los objetos que ya existían en nuestro juego, aunque antes eran parte de un único fuente de gran tamaño:

  • La clase "Juego" será la que coordine a todas, a alto nivel.
  • La "Presentación" mostrará la imagen de bienvenida y nos permitirá salir del juego o comenzar una partida.
  • La "Partida" será la que realmente tenga la lógica de juego que corresponde a una partida real, con elementos que interactúan como:
    • El "Mapa", que se encarga de dibujar la pantalla de fondo y de ver a qué posiciones nos podemos mover.
    • El "Personaje", al que controlamos nosotros.
    • El "Escorpión", que será un caso concreto de "Enemigo Mortal" , que se mueve solo.
    • Tanto el "Personaje" como el "Enemigo Mortal" serán subclases de "Elemento Gráfico"

Todo ello podría quedar así:

Clases previstas (completo)


Por tanto, el trabajo de esta entrega será repartir lo que antes era un fuente y ahora estará repartido en seis.

Vamos a ver el fuente final de todos ellos...

La clase "Juego", que se limita a coordinar a las demás clases de alto nivel (por ahora, Presentación y Partida), sería:

/** 
 *   Juego: Clase "de apoyo" casi vacía que lanza la presentación
 *  
 *   @see Hardware
 *   @author 1-DAI IES San Vicente 2009/10
 */
 
 
/* --------------------------------------------------         
   Parte de Death Pit - Remake
   Versiones hasta la fecha:
 
   Num.   Fecha       Por / Cambios
   ---------------------------------------------------
   0.01  08-Sep-2009  Nacho Cabanes
                      Version inicial: muestra una imagen
   0.02  07-Oct-2009  Nacho Cabanes
                      Mueve el personaje hacia la derecha
                        hasta llegar al margen
   0.03  13-Oct-2009  Nacho Cabanes
                      El personaje se mueve con flechas
                      Un primer enemigo que se mueve a la vez
   0.04  16-Oct-2009  Nacho Cabanes
                      Primera pantalla de presentacion
                      El primer enemigo rebota en los lados
                      Un segundo enemigo nos persigue
   0.05  20-Oct-2009  Nacho Cabanes
                      Array de enemigos (murcielagos)
                       que rebotan en los lados
   0.06  28-Oct-2009  Nacho Cabanes
                      Array bidimensional para imagen de fondo
   0.07  04-Nov-2009  Nacho Cabanes
                      El personaje se mueve solo por los "huecos"
                      Eliminados los enemigos (por ahora)
                      Renombradas variables i,j a fila,colum
   0.08  10-Nov-2009  Nacho Cabanes
                      Varias funciones para que el fuente sea mas modular
   0.09  16-Nov-2009  Nacho Cabanes
                      Varias pantallas conectadas
   0.10  24-Nov-2009  Nacho Cabanes
                      Un enemigo que se mueve "por los huecos"
   0.11  02-Dic-2009  Nacho Cabanes
                      Si chocamos con enemigo perdemos una vida
   0.12  04-Dic-2009  Nacho Cabanes
                      El personaje cambia de imagen según la dirección
                      Si choco con un enemigo de lado, muere él y me da puntos  
   0.13  11-Dic-2009  Joaquín, Alejandro, Miguel; retoques por Nacho
                      Cuando acaban las vidas o se pulsa ESC, acaba la partida,
                      se vuelve a la presentación y se puede volver a empezar
   0.14  23-Dic-2009  Nacho Cabanes
                      Primera versión desglosada en clases. Casi todo el 
                      contenido de "Juego" pasa a "Partida".
 ---------------------------------------------------- */
 
 
public class Juego
{
    private Presentacion presentacion;
    private Partida partida;
 
 
    // Inicialización al comenzar la sesión de juego
    public Juego()
    {
        // Inicializo modo grafico 800x600 puntos, 24 bits de color
        Hardware.Inicializar(800, 600, 24);
 
        // Inicializo componentes del juego
        presentacion = new Presentacion();
        partida = new Partida();
    }
 
 
 
    // --- Comienzo de un nueva partida: reiniciar variables ---
    public void Ejecutar()
    {    
        do
        {
            presentacion.Ejecutar();
            switch( presentacion.GetOpcionEscogida() )
            {
                    case Presentacion.OPC_PARTIDA: 
                        partida.BuclePrincipal();
                        break;
 
            }
        }
        while (presentacion.GetOpcionEscogida() != Presentacion.OPC_SALIR );
    }
 
 
 
    // --- Cuerpo del programa -----
    public static void Main() 
    {
        Juego juego = new Juego();
        juego.Ejecutar();
    }
 
 
 
} /* fin de la clase Juego */
 
 


Y la "Presentación" será:

/** 
 *   Presentacion: pantalla de presentacion
 *  
 *   @see Hardware ElemGrafico Juego
 *   @author 1-DAI IES San Vicente 2009/10
 */
 
/* --------------------------------------------------         
   Parte de Death Pit - Remake
   Versiones hasta la fecha:
 
   Num.   Fecha       Por / Cambios
   ---------------------------------------------------
   0.14  23-Dic-2009  Nacho Cabanes
                      Primera versión de Presentacion, desglosado de "Juego.cs"
                      No añade posibilidades nuevas.
 
 ---------------------------------------------------- */
 
public class Presentacion
{
    // Atributos
    private ElemGrafico imagen;
    private Fuente fuenteSans18;
    private int opcionEscogida;
 
    // Opciones posibles
    public const byte OPC_PARTIDA = 0;
    public const byte OPC_SALIR = 1;    
 
 
    /// Constructor
    public Presentacion()  // Constructor
    {
        imagen = new ElemGrafico("imagenes/present.png");
        fuenteSans18 = new Fuente("FreeSansBold.ttf",18);
   }
 
    /// Lanza la presentacion
    public  void Ejecutar()
    {
        //dibujo la imagen de la presentacion
        imagen.DibujarOculta();
 
        // Esscribo avisos de las teclas utilizables
        Hardware.EscribirTextoOculta(
                "Pulsa Espacio para jugar",
                300, 550, 0xAA, 0xAA, 0xAA, fuenteSans18);
        Hardware.EscribirTextoOculta(
                "o pulsa T para terminar",
                300, 575, 0xAA, 0xAA, 0xAA, fuenteSans18);
 
        // Finalmente, muestro en pantalla
        Hardware.VisualizarOculta();  
 
        //hasta que se pulse espacio
        do {
 
        } while ((! Hardware.TeclaPulsada(Hardware.TECLA_ESP) )
          && (! Hardware.TeclaPulsada(Hardware.TECLA_T)));
 
        opcionEscogida = OPC_PARTIDA;
        if (Hardware.TeclaPulsada(Hardware.TECLA_T))
            opcionEscogida = OPC_SALIR;
 
        //borro la presentacion
        Hardware.BorrarPantallaOculta(0,0,0);    
 
    } 
 
    public int GetOpcionEscogida()
    {
        return opcionEscogida;
    }
 
 
} /* fin de la clase Presentacion */
 


La "Partida", que controla la lógica de juego, será:

/** 
 *   Partida: Logica de juego para una partida
 *  
 *   @see Hardware
 *   @author 1-DAI IES San Vicente 2009/10
 */
 
/* --------------------------------------------------         
   Parte de Death Pit - Remake
   Versiones hasta la fecha:
 
   Num.   Fecha       Por / Cambios
   ---------------------------------------------------
   0.01  08-Sep-2009  Nacho Cabanes
                      Version inicial: muestra una imagen
   0.02  07-Oct-2009  Nacho Cabanes
                      Mueve el personaje hacia la derecha
                        hasta llegar al margen
   0.03  13-Oct-2009  Nacho Cabanes
                      El personaje se mueve con flechas
                      Un primer enemigo que se mueve a la vez
   0.04  16-Oct-2009  Nacho Cabanes
                      Primera pantalla de presentacion
                      El primer enemigo rebota en los lados
                      Un segundo enemigo nos persigue
   0.05  20-Oct-2009  Nacho Cabanes
                      Array de enemigos (murcielagos)
                       que rebotan en los lados
   0.06  28-Oct-2009  Nacho Cabanes
                      Array bidimensional para imagen de fondo
   0.07  04-Nov-2009  Nacho Cabanes
                      El personaje se mueve solo por los "huecos"
                      Eliminados los enemigos (por ahora)
                      Renombradas variables i,j a fila,colum
   0.08  10-Nov-2009  Nacho Cabanes
                      Varias funciones para que el fuente sea mas modular
   0.09  16-Nov-2009  Nacho Cabanes
                      Varias pantallas conectadas
   0.10  24-Nov-2009  Nacho Cabanes
                      Un enemigo que se mueve "por los huecos"
   0.11  02-Dic-2009  Nacho Cabanes
                      Si chocamos con enemigo perdemos una vida
   0.12  04-Dic-2009  Nacho Cabanes
                      El personaje cambia de imagen según la dirección
                      Si choco con un enemigo de lado, muere él y me da puntos  
   0.13  11-Dic-2009  Joaquín, Alejandro, Miguel; retoques por Nacho
                      Cuando acaban las vidas o se pulsa ESC, acaba la partida,
                      se vuelve a la presentación y se puede volver a empezar
   0.14  23-Dic-2009  Nacho Cabanes
                      Primera versión desglosada en clases. Casi todo el 
                      contenido de "Juego" pasa a "Partida".
 ---------------------------------------------------- */
 
 
 
public class Partida
{
 
    // Componentes del juego
    private Mapa miMapa;
    private Escorpion enemigo;
    private Personaje personaje;
 
    ElemGrafico imagenPersonaje;  // Imagen del personaje (se muestra al perder vidas)
    Fuente fuente18;   // Tipo de letra para mensajes
    int puntos = 0;
 
 
    bool partidaTerminada;  // Si ha terminado una partida puntual
 
 
    // Inicialización al comenzar la sesión de juego
    public Partida()
    {
        // Inicializo componentes del juego
        miMapa = new Mapa();
        enemigo = new Escorpion(this);
        personaje = new Personaje(this);
 
        // Cargo imagenes y tipos de letra
        imagenPersonaje = new ElemGrafico("imagenes/personaje.png");        
        fuente18 = new Fuente("FreeSansBold.ttf", 18);
    }
 
 
 
    // --- Comienzo de un nueva partida: reiniciar variable ---
     void inicializarPartida()
    {    
        puntos = 0;
        personaje.MoverA(70,50);
        personaje.SetVidas(5);
        miMapa.IrAHabitacion(0,0);        
        enemigo.Recolocar();
 
        partidaTerminada = false;
        mostrarVidasRestantes();
    }
 
 
 
    // --- Coloca el enemigo en cualquier posición "libre" de la pantalla actual -----
     void comprobarTeclas()
    {
          // Muevo si se pulsa alguna flecha del teclado
          if (Hardware.TeclaPulsada(Hardware.TECLA_DER) )
              personaje.MoverDerecha();
 
          if(Hardware.TeclaPulsada(Hardware.TECLA_ARR) )
              personaje.MoverArriba();
 
          if (Hardware.TeclaPulsada(Hardware.TECLA_IZQ) )
              personaje.MoverIzquierda();         
 
          if (Hardware.TeclaPulsada(Hardware.TECLA_ABA) )
              personaje.MoverAbajo();                  
 
          if (Hardware.TeclaPulsada(Hardware.TECLA_ESC))
              partidaTerminada = true;
    }
 
 
 
    // --- Animación de los enemigos y demás objetos "que se muevan solos" -----
     void moverElementos()
    {
        enemigo.Mover();
    }
 
 
 
    // --- Comprobar colisiones de enemigo con personaje, etc ---
     void comprobarColisiones()
    {
         if ((personaje.GetX()==enemigo.GetX()) && (personaje.GetY()==enemigo.GetY()))
        {
             if ((personaje.GetDireccion() == ElemGrafico.DERECHA) 
                 || (personaje.GetDireccion() == ElemGrafico.IZQUIERDA))
            matarEnemigo();
          else
            morir();
        }
    }
 
 
 
    // --- Matar enemigo: aumentar puntos y recolocarlo ---
    void matarEnemigo()
    {
        puntos += 10;
        enemigo.Recolocar();
    }
 
 
 
    // --- Recolocar enemigo (llamado al cambiar de habit. p.ej.) ---
    public void RecolocarEnemigo()
    {
        enemigo.Recolocar();
    }
 
 
 
    // --- Morir personaje: mostrar vidas restantes, etc ---
    void morir()
    {
        personaje.Morir();
        mostrarVidasRestantes();
 
        // Vuelvo a colocar el enemigo al azar
        enemigo.Recolocar();
 
        // Si no hay vidas, se acabó la partida
        if (personaje.GetVidas() == 0)
          partidaTerminada = true;
    }
 
 
 
    // --- Mostrar vidas restantes ---
    void mostrarVidasRestantes()
    {
        int i;
 
        // Rectángulo verde
        Hardware.RectanguloRellenoRGBA(
           0,0,490,350,  // Posicion, ancho y alto de la pantalla
           0,255,0,      // En color verde
           200);         // Con algo de transparencia
 
 
        // Dibujo las vidas restantes
        Hardware.EscribirTextoOculta(
                "Te quedan",
                250, 100, 0, 0, 0, fuente18);
        Hardware.EscribirTextoOculta(
                personaje.GetVidas().ToString(),
                250, 150, 0xFF, 0, 0, fuente18);
        Hardware.EscribirTextoOculta(
                "vidas",
                250, 200, 0, 0, 0, fuente18);
 
        for (i=0; i<personaje.GetVidas(); i++)
        {
            imagenPersonaje.MoverA( 130 , (short) (50+ i*50) );
            imagenPersonaje.DibujarOculta();
        }
 
        // Aviso de la tecla para volver
        Hardware.EscribirTextoOculta(
                "Pulsa V para volver al juego",
                120, 350, 0xAA, 0xAA, 0xAA, fuente18);
 
        // Y quito el aviso de "ESC para salir"
        Hardware.RectanguloRellenoRGBA(
                160, 370, 600,550, 
                0,0,0, 
                255);
 
        // Finalmente, muestro en pantalla
        Hardware.VisualizarOculta();  
 
        // Espero hasta que se pulse la tecla de volver
        do {
 
        } while (! Hardware.TeclaPulsada(Hardware.TECLA_V) );        
    }
 
 
 
    // --- Dibujar en pantalla todos los elementos visibles del juego ---
     void dibujarElementos()
    {
          Hardware.BorrarPantallaOculta(0,0,0);
 
          miMapa.Dibujar();
          personaje.DibujarOculta();
          enemigo.DibujarOculta();
 
          Hardware.EscribirTextoOculta(
                "Puntos",
                600, 100, 0xAA, 0xAA, 0xAA, fuente18);
          Hardware.EscribirTextoOculta(
                puntos.ToString(),
                600, 140, 0xAA, 0xAA, 0xAA, fuente18);
 
          Hardware.EscribirTextoOculta(
                "Pulsa ESC para salir",
                170, 380, 0xAA, 0xAA, 0xAA, fuente18);
 
          // Finalmente, muestro en pantalla
          Hardware.VisualizarOculta();        
    }
 
 
 
    // --- Pausa tras cada fotograma de juego, para velocidad de 25 fps -----
     void pausaFotograma() 
    {
        Hardware.Pausa( 40 );
    }
 
 
 
    // --- Bucle principal de juego -----
    public void BuclePrincipal() 
    {
        inicializarPartida();
        do {
            comprobarTeclas();
            moverElementos();
            comprobarColisiones();
            dibujarElementos();
            pausaFotograma();
        } while (! partidaTerminada);
    }
 
 
 
    // --- Devuelve el mapa, para que lo consulten el personaje
    // y el enemigo antes de moverse -----
    public Mapa GetMapa() 
    {
      return miMapa;
    }
 
 
} /* fin de la clase Juego */
 
 


Un "Enemigo Mortal" será:

/** 
 *   EnemigoMortal: Un enemigo que podemos matar
 *  
 *   @see Hardware ElemGrafico Juego
 *   @author 1-DAI IES San Vicente 2009/10
 */
 
/* --------------------------------------------------         
   Parte de Death Pit - Remake
   Versiones hasta la fecha:
 
   Num.   Fecha       Por / Cambios
   ---------------------------------------------------
   0.14  23-Dic-2009  Nacho Cabanes
                      Primera versión del EnemigoMortal
 
 ---------------------------------------------------- */
 
using System; // Para numeros aleatorios: System.Random 
 
public class EnemigoMortal : ElemGrafico
{
    short contadorFotogramas; // Contador de fotograma actual
    short pausaFotogramas;    // Para que no se mueva en cada fotograma del juego    
    Random numAleatorio;      // Para que se mueva al azar
    protected Partida miPartida;  // Para leer datos del mapa
 
    public EnemigoMortal() {
        numAleatorio = new Random( DateTime.Now.Millisecond );
        contadorFotogramas = 0;
        pausaFotogramas = 10;
        ancho = 70;
        alto = 50;
        incrX = ancho;
        incrY = alto;
    }
 
    public void Morir() {
    }
 
    public new void Mover() {
            // El enemigo solo se mueve un fotograma de cada varios
        contadorFotogramas ++;
        if (contadorFotogramas == pausaFotogramas)
        { 
            contadorFotogramas = 0;
            x += incrX;
            y += incrY;
        }
 
        // Para la siguiente posición, escojo al azar y miro si realmente se puede mover
        bool posibleMover = false;
        do 
        {
            int numeroAzar = (int) numAleatorio.Next(0,100);
            if (numeroAzar < 25) // Intento derecha
            {
                if ((x < miPartida.GetMapa().GetMaxX()) &&  // Si no ha llegado al borde
                    (miPartida.GetMapa().EsPosibleMover((short) (x+ancho),y)))
                {
                    incrX = ancho;
                    incrY = 0;
                    posibleMover = true;
                }
            } 
            else if (numeroAzar < 50) // Intento izquierda
            {
                if ((x > 0) &&  // Si no ha llegado al borde
                    (miPartida.GetMapa().EsPosibleMover((short) (x-ancho),y)))
                {
                    incrX = (short) -ancho;
                    incrY = 0;
                    posibleMover = true;
                }
            } 
            else if (numeroAzar < 75) // Intento arriba
            {
                if ((y > 0) &&  // Si no ha llegado al borde
                    (miPartida.GetMapa().EsPosibleMover(x,(short) (y-alto))))
                {
                    incrX = 0;
                    incrY = (short) -alto;
                    posibleMover = true;
                }
            }
            else // Intento abajo
            {
                if ((y < miPartida.GetMapa().GetMaxY()) &&  // Si no ha llegado al borde
                    (miPartida.GetMapa().EsPosibleMover(x,(short) (y+alto))))
                {
                    incrX = 0;
                    incrY = alto;
                    posibleMover = true;
                }
            }
 
 
 
        } while (! posibleMover);
    }
 
 
 
    // --- Coloca el enemigo en cualquier posición "libre" de la pantalla actual -----
    public void Recolocar()
    {
        do 
        {
            x = (short) ((numAleatorio.Next(0,miPartida.GetMapa().GetMaxX()-2)+1)*ancho);
            y = (short) ((numAleatorio.Next(0,miPartida.GetMapa().GetMaxY()-2)+1)*alto);
 
        } 
 
        // TODO: Falta asignar incrementos "razonables"
 
        while (! miPartida.GetMapa().EsPosibleMover(x,y));
    }
 
} /* fin de la clase EnemigoMortal */
 
 


El "Escorpión" será una subclase de "Enemigo Mortal", que sólo cambia en la imagen

/** 
 *   Escorpion: Un enemigo que podemos matar
 *  
 *   @see Hardware ElemGrafico EnemigoMortal Juego
 *   @author 1-DAI IES San Vicente 2009/10
 */
 
/* --------------------------------------------------         
   Parte de Death Pit - Remake
   Versiones hasta la fecha:
 
   Num.   Fecha       Por / Cambios
   ---------------------------------------------------
   0.14  23-Dic-2009  Nacho Cabanes
                      Primera versión del Escorpion
 
 ---------------------------------------------------- */
 
public class Escorpion: EnemigoMortal
{
 
    public Escorpion(Partida p) 
    {
        miPartida = p;
        CargarImagen("imagenes/escorpion.png");
    }
 
 
} /* fin de la clase Escorpion */
 
 


Y el personaje que nosotros controlamos quedaría:

/** 
 *   Personaje: El personaje que es controlado por el usuario
 *  
 *   @see Hardware ElemGrafico Juego
 *   @author 1-DAI IES San Vicente 2009/10
 */
 
/* --------------------------------------------------         
   Parte de Death Pit - Remake
   Versiones hasta la fecha:
 
   Num.   Fecha       Por / Cambios
   ---------------------------------------------------
   0.14  23-Dic-2009  Nacho Cabanes
                      Primera versión del Personaje, desglosado de "Juego.cs"
                      No añade posibilidades nuevas.
 
 ---------------------------------------------------- */
 
public class Personaje : ElemGrafico
{
 
  // Datos del personaje
  short vidas;
  protected Partida miPartida;
 
  public Personaje(Partida p) 
  {
    miPartida = p;
    ancho =70;
    alto = 50;
    vidas = 5;
    x = 1;
    y = 1;
    incrX = 70;
    incrY = 50;
    //Antes era: CargarImagen("imagenes/personaje.png");
    //##TODO: Falta secuencia de imágenes
    direccion = IZQUIERDA;
    CargarSecuencia( DERECHA, 
      new string[] {"imagenes/personajed1.png"} );
    CargarSecuencia( IZQUIERDA, 
      new string[] {"imagenes/personajei1.png"} );
    CargarSecuencia( ARRIBA, 
      new string[] {"imagenes/personajea1.png"} );
    CargarSecuencia( ABAJO, 
      new string[] {"imagenes/personajea1.png"} );    
  }
 
 
 
  public void MoverDerecha() 
  {
      direccion = DERECHA;
      if (x == miPartida.GetMapa().GetMaxX())
      {
        x = 0;
        miPartida.GetMapa().IrAHabitacionDerecha();
        miPartida.RecolocarEnemigo();
      }
      else if (x < miPartida.GetMapa().GetMaxX())
        if (miPartida.GetMapa().EsPosibleMover((short) (x+incrX),y))
            x += incrX;
  }
 
 
 
  public void MoverIzquierda() 
  {
      direccion = IZQUIERDA;
      if (x == 0)
      {
        x = miPartida.GetMapa().GetMaxX();
        miPartida.GetMapa().IrAHabitacionIzquierda();
        miPartida.RecolocarEnemigo();
      }
      else if ( x > 0)            
        if (miPartida.GetMapa().EsPosibleMover((short) (x-incrX),y))
            x -= incrX;
  }
 
 
 
  public void MoverArriba()
  {
      direccion = ARRIBA;
      if (y == 0)
      {
        y = miPartida.GetMapa().GetMaxY();
        miPartida.GetMapa().IrAHabitacionArriba();
        miPartida.RecolocarEnemigo();
      }
      else if ( y > 0)
        if (miPartida.GetMapa().EsPosibleMover(x, (short) (y-incrY)))
            y -= incrY;
  }
 
 
 
  public void MoverAbajo() 
  {
      direccion = ABAJO;
      if (y == miPartida.GetMapa().GetMaxY())
      {
        y = 0;
        miPartida.GetMapa().IrAHabitacionAbajo();
        miPartida.RecolocarEnemigo();
      }
      else 
      if (y < miPartida.GetMapa().GetMaxY())
        if (miPartida.GetMapa().EsPosibleMover(x, (short) (y+incrY)))
            y += incrY;
  }
 
 
 
  public int GetVidas()
  {
    return vidas;
  }
 
 
  public void SetVidas(short n)
  {
    vidas = n;
  }
 
 
  public void Morir()
  {
      vidas--;
  }
 
 
} /* fin de la clase Personaje */
 


También puedes descargar todo el paquete, incluyendo todos los fuentes, el ejecutable (en la carpeta BIN/DEBUG), las imágenes, y el proyecto de SharpDevelop, en un fichero ZIP de tamaño cercano a 1 Mb.

Siguiente entrega...