User Tag List

Resultados 1 al 3 de 3

Tema: Programación de un juego en C++ (7/11)

  1. #1

    Fecha de ingreso
    Jun 2004
    Ubicación
    Pinto (MADRID)
    Mensajes
    1,076
    Mencionado
    12 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5
    Agradecer Thanks Received 
    148
    Thanked in
    Agradecido 101 veces en [ARG:2 UNDEFINED] posts

    Programación de un juego en C++ (7/11)

    7. ENEMIGOS.

    Tenéis el proyecto en: Tutorial de programación c++ (7/11)

    En la lección anterior vimos algunas cosas bastante interesantes que conviene repasar antes. Me refiero a la forma de comprobar las colisiones entre dos sprites. ¿Cómo hemos hecho esto?

    Ya sabéis que cada bicho que se mueve por la pantalla, incluida nuestra nave, tiene un tamaño (ancho y alto) y una posición (x,y). Lo que hacemos es comprobar si esas coordenadas se tocan en algún punto. Supongamos que tenemos 2 gráficos de 10x10. Uno está en la posición (20,20) y el otro en la (25,50). El sprite1 está ocupando las posiciones en X desde 20 hasta 30, y en Y desde 20 hasta 30. Lo que debemos hacer es comprobar si el sprite2 toca alguna de esas posiciones.

    Primero comprobamos si las posiciones en X se tocan. Para eso, calculamos las casillas en X del sprite2, que son desde 25 hasta 35. Los sprites colisionan si:
    - la posición X del primero es menor que la posición X + anchura del segundo (sprite1.x<sprite2.x+sprite2.ancho)
    - la posición X + anchura del primero es mayor que la posición X del segundo (sprite1.x+sprite1.ancho>sprite2.x)

    Si se dan las dos condiciones en X y en Y, podemos decir que hay una colisión entre sprites. En este caso colisionan en X porque: 20<25+10 y 20+10>25, pero no colisionan en Y porque: 20<50+10 y 20+10>50, falla la segunda comprobación. Podemos decir que están en la misma fila pero no la misma columna.

    Vamos a aplicar el mismo sistema con los monstruos marinos de nuestro juego, y de paso veremos algunas cosillas que nos permite hacer c++.

    Código:
    ///////////////////////////////////
    /*  Librerías a utilizar         */
    ///////////////////////////////////
    #include <vector>
    Lo primero que hemos hecho es incluir una nueva librería en la cabecera. Vector nos permite utilizar listas en c++. Estas listas pueden ser de números, textos, estructuras... lo que nos venga bien. En nuestro caso la vamos a utilizar para meter los bichos. De esta forma, podemos empezar con 2 monstruos marinos y cada vez que superemos un nivel añadiremos uno más, para ir complicando la cosa. Así, la cosa se facilita bastante.

    Código:
    ///////////////////////////////////
    /*  Estructuras                  */
    ///////////////////////////////////
    struct bug_base
    {
      int x;
      int y;
      int dir_x;
      int dir_y;
    };
    Lo siguiente es crear la estructura para los bichos. Esta estructura bug_base contiene la posición (X,Y) del bicho y la velocidad con que se mueve en los ejes X e Y. ¡Qué bien habría venido esto para la nave! ¿no? ¡¡¡Pues estáis tardando en arreglar el código, que habéis tenido tiempo!!!

    Código:
    ///////////////////////////////////
    /*  Variables del juego          */
    ///////////////////////////////////
    std::vector<bug_base> bug_list;
    Más abajo definimos la lista de esta manera. Vector pertenece al namespace std, así que indicamos que la variable bug_list es un objeto de std::vector compuesto de bug_base.

    Código:
    void init_game()
    {
      srand(time(NULL));
    En la función init_game() vamos a añadir una sencilla línea que hará el juego más divertido aún. Como queremos que los bichos aparezcan en lugares aleatorios, llamamos a srand() para que inicie el sistema de números aleatorios del sistema. Se suele pasar la hora del sistema como parámetro para que siempre sea diferente. En caso de no hacer esto, los bichos siempre aparecerían en los mismos sitios. ¡A lo mejor os interesa hacer un juego en el que pase eso!

    Código:
    void new_bug()
    {
      bug_base b;
      b.x=rand()%298;
      b.y=72+rand()%132;
      b.dir_x=0;
      b.dir_y=0;
    Función nueva. Necesitamos una función para crear bichos nuevos. Cada vez que llamemos a esta función, creará un enemigo en una posición aleatoria y lo meterá en la lista de bichos. Así que primero declaramos una variable de tipo bug_base y rellenamos sus valores. Para que estén dentro de la pantalla, X tiene que estar entre 0 y 298, Y entre 72 y 132. La función rand() nos dará un número aleatorio, pero la dividimos entre el valor que nos interese y nos quedamos con el resto.

    Código:
      while(b.dir_x==0 && b.dir_y==0)
      {
        b.dir_x=-3+rand()%7;
        b.dir_y=-3+rand()%7;
      }
    Ahora le damos una velocidad X e Y. Si alguna de estas velocidades es 0, el bicho se moverá sólo en horizontal o vertical. Pero no pueden ser 0 las dos, porque si no se quedaría inmóvil en su sitio (aunque quizás... haga más divertido el juego).

    En este bucle, lo que hacemos es repetir la asignación de valores si ambos son 0. Le damos una velocidad de -3 a +3 (siempre van a ser más lentos que nuestra nave).

    Código:
      if(b.x>130 && b.x<190 && b.y<100 && b.dir_y<0)
        b.dir_y=-b.dir_y;
    
      bug_list.push_back(b);
    }
    Y por último hacemos una pequeña comprobación. Si el bicho está cerca de la posición de recogida de tesoros (justo debajo del barco) y su dirección vertical es hacia arriba (o sea, el valor de dir_y es negativo), le cambiamos la dirección para que no se coma la nave si aparece cuando estamos entregando algo. Es una pequeña ayuda para que los jugones no se desesperen.

    Al final añadimos nuestro bicho a la lista con bug_list.push_back(b). Lo que hace esto es meter la estructura del bicho justo al final de la lista.

    Código:
    void new_level()
    {
    ...
      // añadimos un bicho
      new_bug();
    ...
    }
    Por supuesto, cada vez que pasemos de nivel meteremos un bicho nuevo, así que en la función new_level() llamamos a new_bug(). ¡Más fácil imposible!

    Código:
    void reset()
    {
    ...
      bug_list.clear();
      new_bug();
      new_bug();
    }
    Y en reset(), que se llama al iniciar una partida, vaciamos la lista con bug_list.clear() y añadimos 2 bichos, para empezar con algo de presión.

    Código:
    void finish()
    {
      program_mode=PROGRAM_MODE_MENU;
    }
    Más adelante necesitaremos una función para que hacer cosas cuando nos maten, como cambiar de modo, comprobar el record, etc... Por ahora, sólo vamos a crear la función finish() y añadir el cambio de modo de juego.

    Código:
    void draw_game()
    {
    ...
      // dibujamos los bichos
      SDL_Rect rbug;
      for(int i=0; i<bug_list.size(); i++)
      {
        rbug.x=bug_list[i].x;
        rbug.y=bug_list[i].y;
        if(bug)
          SDL_BlitSurface(bug,NULL,screen,&rbug);
      }
    ¿Cómo dibujamos los bichos? La verdad es que es tan sencillo que apenas merece explicación. Con un bucle, recorremos la lista bug_list, cuyo número de elementos está definido en .size(). Así accedemos a cada uno de los bichos y sus propiedades con bug_list[i]. Recuperamos su posición X,Y y lo dibujamos en pantalla. No olvidéis comprobar si existe la superficie bug.

    Código:
    void update_game()
    ...
      // mueve los bichos
      for(int i=0; i<bug_list.size(); i++)
      {
        bug_list[i].x+=bug_list[i].dir_x;
        bug_list[i].y+=bug_list[i].dir_y;
    En update_game() movemos los bichos. Lo que haremos será recorrer la lista de bichos, de la misma forma que para dibujarla, y a sus posiciones le sumaremos la velocidad X e Y.

    Código:
        if(bug_list[i].x<0 || bug_list[i].x>298)
          bug_list[i].dir_x=-bug_list[i].dir_x;
        if(bug_list[i].y<48 || bug_list[i].y>204)
          bug_list[i].dir_y=-bug_list[i].dir_y;
    Lo siguiente es comprobar si se han salido de la zona de juego. En ese caso, si la posición X (por ejemplo) es menor de 0 o mayor de 298, significa que se han salido, así que invertimos la velocidad horizontal (dir_x=-dir_x). Es una forma rápida de asegurarnos que siempre van a estar dentro de la pantalla.

    Código:
        // comprueba si choca con la nave
        if(bug_list[i].x>ship_x-20 && bug_list[i].x<ship_x+20 && bug_list[i].y>ship_y-20 && bug_list[i].y<ship_y+20)
          finish();
      }
    Y lo más importante: poner a prueba los conocimientos de la lección anterior y del inicio de este tutorial... ¡las colisiones! Vamos a aprovechar el bucle para comprobar si alguno de los bichos choca con la nave. Aunque la nave tiene un tamaño de 24, vamos a hacer los cálculos con un tamaño de 20 para darle algo de margen al juego y que no nos maten con un simple roce. Si se produce una colisión, llamaremos a la función finish(). La verdad es que ha sido todo muy rápido y sencillo, ¿no?

    Ya hábéis visto que teniendo las cosas MUY claras, poner unos bichos en movimiento no cuesta nada. Es verdad que la inteligencia artificial brilla por su ausencia, pero pensando un poco antes de programar es posible conseguir tan rápido (o más) como lo hemos hecho.

    Si queréis practicar con el código, se pueden hacer muchas cosas... cambair velocidades de los bichos, intentar inventar nuevos moviimentos, que acelere y desacelere, que se muevan lentamente hacia la nave... etc... el juego es vuestro, ¡probad lo que queráis!

  2. #2

    Fecha de ingreso
    Jan 2008
    Ubicación
    Madrid
    Mensajes
    4,446
    Mencionado
    14 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    86
    Agradecer Thanks Received 
    152
    Thanked in
    Agradecido 90 veces en [ARG:2 UNDEFINED] posts
    Esta es la parte más interesante, sobre todo porque es complejo gestionar bien las listas de enemigos y sus propiedades. Pero también es la parte más creativa.

  3. #3

    Fecha de ingreso
    Jun 2004
    Ubicación
    Pinto (MADRID)
    Mensajes
    1,076
    Mencionado
    12 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5
    Agradecer Thanks Received 
    148
    Thanked in
    Agradecido 101 veces en [ARG:2 UNDEFINED] posts
    La verdad es que sí. En este caso, con unas pocas líneas se consiguen mover varios bichos por la pantalla de una forma muy simple, pero suficiente para hacer un juego. El día que pasemos a algo un poco más avanzado, como clases con sus propias funciones de movimiento e inteligencia, la cosa se pondrá mucho mucho más divertida.

    Lo importante es que la gente se de cuenta de que no hay nada difícil si se piensa bien antes y se implementa con dos dedos de frente.

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •