Single Tech Games

3. A Full-Screen Exclusive Mode (FSEM) Worm – part 1

Esta parte es por demas interesante, El modo exclusivo de pantalla completa lo que hace es suspende el entrono windows de java (llamese las capas swing o awt) ofreciendo un acceso casi directo a la pantalla, dandonos oportunidad de controlar algunas carateristicas de las tarjetas gráficas, como son page flipping y stereo buffering, y tb controlar la resolucion de pantalla
Existe una pequeña desventaja, la memoria de video es muy volatil por lo que el SO (Sist. Ope.) puede redibujar la pantalla cuando, por ejemplo, necesita dibujar una ventana, o levanta el protector de pantalla. Entonces la imagen tendra que ser reconstruida desde 0, tampoco es un recurso inifinito, tratar de colocarle muchas imagenes hará que el SO los comience a intercambiar fuera de la memoria haciendo lento el renderizado.
Por eso vemos lo que es VolatileImage, que permite a la imagenes tomar ventaja de la VRAM (memoria de video). Les recomiendo leer lo que es VolatileImage
Bueno si ya leyeron lo del volatileImage la verdad es que el practica no es requerida usualmente ia que la mayoria de aplicaciones, en swing, emplean la aceleracion por hardware de por si, en vez d eso utilizan VolatileImage como double buffer.
Otra cosa que debrian sabes es que los dibujos de lineas diagonales o curvas utilizan aceleracion por software y utilizar VolatileImage aca seria contraproducente, lean la documentacion ^_^
Otra cosa VolatileImage es una caracteristica mas recomendada en windows ya que este es un SO que permite la manipulacion directa de la vram, en solaris o linux se usa las pixmap
Bueno si dibujaramos el uml tendria que desparecer los windows listener y el jpanel y muchas funciones que venia con ellas en las clases, por lo tanto se reducira en un porcentaje el codigo que utilizamos asi quedarian, ademas le decimos adios a WormPanel para que WormChase ocupe su lugar.
3.1. The WormChase Class
Ahora WormChase sera el nuevo WormPanel
agregamos estas variables globales

  private static final int NUM_BUFFERS = 2;    // usado para page flipping
  private static int DEFAULT_FPS = 100;
    // usado por el modo exclusivo de pantalla completa
  private GraphicsDevice gd;
  private Graphics gScr;
  private BufferStrategy bufferStrategy;


Modificamos el constructor

  public WormChase(long period)
  {
    super("Worm Chase");
    this.period = period;
    initFullScreen();// cambia a FSEM
    readyForTermination();
    // crea componentes del juego
    obs = new Obstacles(this);
    fred = new Worm(pWidth, pHeight, obs);
    gameOver = false;
    addMouseListener( new MouseAdapter() {
      public void mousePressed(MouseEvent e)
      { testPress(e.getX(), e.getY()); }
    });
    addMouseMotionListener( new MouseMotionAdapter() {
      public void mouseMoved(MouseEvent e)
      { testMove(e.getX(), e.getY()); }
    });
    // fuente del mensaje
    font = new Font("SansSerif", Font.BOLD, 24);
    metrics = this.getFontMetrics(font);
    // especifica las areas en pantalla para los botones
    pauseArea = new Rectangle(pWidth-100, pHeight-45, 70, 15);
    quitArea = new Rectangle(pWidth-100, pHeight-20, 70, 15);
    fpsStore = new double[NUM_FPS];
    upsStore = new double[NUM_FPS];
    for (int i=0; i < NUM_FPS; i++) {
      fpsStore[i] = 0.0;
      upsStore[i] = 0.0;
    }
    gameStart();
  }  // fin de WormPanel()


Ahora gameStart() es lo que fue addNotify()

    private void gameStart(){
        if (animator == null || !running) {  // comienza el hilo
          animator = new Thread(this);
              animator.start();
        }
    }


3.2. Setting up Full-Screen Exclusive Mode
Ahora comenzamos a declarar las funcion initFullScreen()

      private void initFullScreen()
      {
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            gd = ge.getDefaultScreenDevice();
            setUndecorated(true);    // Sin la barra de menu, bordes, etc. o cualuqier componente Swing
            setIgnoreRepaint(true);  // apaga todos los eventos de pintado ya que estamos utilizando renderizado activo
            setResizable(false);
            if (!gd.isFullScreenSupported()) {
              System.out.println("Full-screen exclusive mode not supported");
              System.exit(0);
            }
            gd.setFullScreenWindow(this); // cambian al modo exclusivo de pantalla completa
            //Podemos ajustar el modo en q se muestra si asi lo deseamos
            showCurrentMode();
            // setDisplayMode(800, 600, 8);
            // setDisplayMode(1280, 1024, 32);
            pWidth = getBounds().width;
            pHeight = getBounds().height;
            setBufferStrategy();
      }  // fin de initFullScreen()


La tarjeta grafica es accesible a raves del objeto GraphicsDevice. utilizamos la funcion gd.isFullScreenSupported() que nos devuelve si se peude usar el modo de pantalla completa o no, si no se pudiera usar el modo a pantalla completa deberia poder usarse el modo AFS o UFS, pero aca solo salimos del programa.
Despues utilizamos la funcion showCurrentMode() para ver las caracteristicas actuales de la pantalla, y la funcion que puede cambiar las resolucion de la pantalla y los bits, es setDisplayMode() que esta comentada.

  private void showCurrentMode()
  // imprime los detalles de la resolcuion de pantalla
  {
    DisplayMode dm = gd.getDisplayMode();
    System.out.println("Current Display Mode: (" +
                           dm.getWidth() + "," + dm.getHeight() + "," +
                           dm.getBitDepth() + "," + dm.getRefreshRate() + ")  " );
  }


Ahora veremos la fucnion setBufferStrategy() que almacena la estrategias de buffer para la actualizacion de la pantalla

    private void setBufferStrategy()
  /* Enciende el page flipping: NUM_BUFFERS == 2 por lo tanto habra
   * una "superficie primaria" y su "respaldo"
   *
   * createBufferStrategy() es una operacion asincrona, por lo
   * tanto debemos dormir un ratito para que la funcion getBufferStrategy()
   * obtenga los detalles correctos
   */
  { try {
      EventQueue.invokeAndWait( new Runnable() {
        public void run()
        { createBufferStrategy(NUM_BUFFERS);  }
      });
    }
    catch (Exception e) {
      System.out.println("Error cuando se crea la estrategia buffer");
      System.exit(0);
    }
    try {  // duerme para darle tiempo a la estrategia que se lleve a cabo
      Thread.sleep(500);  // 0.5 seg
    }
    catch(InterruptedException ex){}
    bufferStrategy = getBufferStrategy();  // guarda para despues
  }  // fin de setBufferStrategy()


La naturaleza asincrona de muchos de los metodos de FSEM es la debilidad de ete API ya que es muy dificl sabre cuando una operacion ha sido completada, utilizar sleep() de forma arbitraria es una forma que no debheria darse y que quizas estemos bajando la velocidad de ejecucion sin ninguna necesidad. Otros metodos asincronos son setDisplayMode(), show(), y setFullScreenWindow().
Algo que quiero explicar antes de continuar es algo que estuve revisando ahora, lo que pasa es que este libro fue escrito cuando el jdk 1.4 estaba en el aire, pero ¿hello? ia estamos en jdk 1.6 muchas cosas se han mejorado, un blog que es muy interesante de leer, tiene un tema que discute sobre que tipo de imagenes o estrategias a usar, se llama ToolkitBufferedVolatileManagedImage Strategies y esta interesantisimo sobre todo cuando habla Managed Images, si tengo tiempo en post mas adelante lo voy a explicar ya que en esto de juegos, sobre todo en el manejo de Sprites es muy importante.
Tambien es importante que lean acerca de las mejora que se hacen en java 2D con cada nueva version del jdk, por ejemplo el 1.5 o el 1.6
3.3. Double Buffering, Page Flipping, and More
Lo que antes hicimos era dibujar una imagen en un buffer fuera de pantalla y luego copiarlo a la pantalla con drawImage, esto en terminos de resolucion de pantalla y bits se traduciria, por ejemplo en 1024 x 768 y 32 bits, en 3mb por frame, y si hablamos de 80 FPS imaginense.
Page flipping evade todo esto al utilizar un “video pointer” (si se puede), un video pointer le dice a tu tarjeta de video adonde buscar la imagen a mostrar en su VRAM. Para esto Page Flipping utiliza 2 buffers, mientras 1 se muestra en pantalla, el otro se actualiza y llegado el momento de refrescar la pantalla se intercambian.
La gran ventaja de esta tecnica es que solo mueves el video pointer sin necesidad de copiar nada.
Ahora ¿por que no utilizar mas de 1 buffer? bueno eso es el siguiente paso, usar 2 o mas buffers como una cadena, esto se llama “flip chain”. ¿Que sucede? que ahora el video pointer hace ciclos a traves de los buffers mientras que los otros son renderizados.
Y ¿como hacemos esto? pues utilizaremos una tecnica que me gusta llamar “Los programadores de Sun lo han hecho por ti”, es bastante sencilla y util, y no solo eso, sino que ya la hemos llevado a cabo, lo hicimos en la funcion setBufferStrategy(), especificamente en la linea: createBufferStrategy(NUM_BUFFERS); al cual le hemos dicho que use 2 buffers.
Bueno para los que quieran saber que es lo que sucede en esta linea de codigo, les voy a explicar muy brevemente, primero se tratara de utilizar la estrategia de Page Flipping, y para esto utilizamos la aceleracion por hardware, si en caso no se pudiera se utlizaria una estrategia de copiado sin aceleramiento.
Es momento de sacar el diccionario y buscar que es “aceleracion por hardware”, lindo io, les voya dar un pequeño empujoncito. Existen muchas tecnicas para mejorar el rendimiento de un cpu, una de ellas es la mencionada, y lo que pasa es que la aceleracion por software es concurrente, osea una a una las tareas van pasando mientras que en hardware podemos tener muchas al mismo tiempo, esto requiere de codigos mas pesados, y de procesadores diferentes al del cpu, pues les comento, que si no saben o no han escuchado vayan a leer un poquito porque es cultura general, que las tarjetas graficas (no todas) tienen GPU’s osea unidades de procesado de graficos, mas al español procesadores exclusivos para graficos, y como ia deben haberse figurado es aqui donde trabaja createBufferStrategy().
Tarea: Si estan en Windows vayan a las propiedades pantalla-configuracion, luego click en el boton opciones avanzadas y despues en la pestaña solucionador de problemas y ¡Wala! veran que uds pueden desactivar la aceleracion por hardware, interesante ¿no?
Y Dios que se me esta haciendo larguisimo este post asi que mejor lo divido en 2 ahora, o sino llego al mes y sigo sin postear

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments