Display

Global variables Creating the display Process screen change Display transform double Detecting window move

Global variables I use these global variables for the display:

    ALLEGRO_DISPLAY *display;
    int fullscreen;

    // current size and position
    int disp_x_curr;
    int disp_y_curr;
    int disp_w_curr;
    int disp_h_curr;

    // size and position of windowed mode
    int disp_x_wind;
    int disp_y_wind;
    int disp_w_wind;
    int disp_h_wind;

    // In windowed mode current values are same as windowed values.
    // In fullscreen mode, they are read from the display struct.

    int display_transform_double = 2;
    int SCREEN_W;
    int SCREEN_H;

These values are also saved in the config file:

    int fullscreen;
    int disp_x_wind;
    int disp_y_wind;
    int disp_w_wind;
    int disp_h_wind;

Creating the display

    int init_screen(void)
    {
       al_set_new_display_option(ALLEGRO_COLOR_SIZE, 16, ALLEGRO_SUGGEST);
       // (most of the time I get a 32 bit anyway, but if I get 16, it can be faster)

       int flags = ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE;
       if (fullscreen) flags = ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_RESIZABLE;
       al_set_new_display_flags(flags);

       display = al_create_display(disp_w_wind, disp_h_wind);
       if(!display)
       {
          sprintf(msg, "Error creating display\n");
          m_err(msg);
          exit(0);
       }

       if (!fullscreen)
       {
          disp_x_curr = disp_x_wind;
          disp_y_curr = disp_y_wind;
          al_set_window_position(display, disp_x_curr, disp_y_curr);
       }

       disp_w_curr = al_get_display_width(display);
       disp_h_curr = al_get_display_height(display);
       al_get_window_position(display, &disp_x_curr, &disp_y_curr);

       auto_set_display_transform_double();
       return 1;
    }

Process screen change This function is called when: - an event 'ALLEGRO_EVENT_DISPLAY_RESIZE' is received - F12 is used to toggle fullscreen - proc_controllers() detects the window has been moved

    void proc_screen_change(int new_sw, int new_sh, int new_sx, int new_sy, int new_fs)
    {
       if ((!fullscreen) && (new_fs)) //  changing to fullscreen
       {
          fullscreen = 1;
          al_set_display_flag(display, ALLEGRO_FULLSCREEN_WINDOW, 1);
          al_get_window_position(display, &disp_x_curr, &disp_y_curr);
          disp_w_curr = al_get_display_width(display);
          disp_h_curr = al_get_display_height(display);
          auto_set_display_transform_double();
          rebuild_bitmaps();
          save_config();
          Redraw = 1;
       }
       else if ((fullscreen) && (!new_fs)) //  changing away from fullscreen
       {
          fullscreen = 0;
          al_resize_display(display, disp_w_wind, disp_h_wind);
          al_set_display_flag(display, ALLEGRO_FULLSCREEN_WINDOW, 0);
          al_set_window_position(display, disp_x_wind, disp_y_wind);
          al_get_window_position(display, &disp_x_curr, &disp_y_curr);
          disp_w_curr = al_get_display_width(display);
          disp_h_curr = al_get_display_height(display);
          auto_set_display_transform_double();
          rebuild_bitmaps();
          save_config();
          Redraw = 1;
       }
       else if (!fullscreen)
       {
          if ((new_sw != disp_w_curr) || (new_sh != disp_h_curr)) // window has been resized
          {
             al_acknowledge_resize(display);
             disp_w_curr = disp_w_wind = al_get_display_width(display);
             disp_h_curr = disp_h_wind = al_get_display_height(display);
             auto_set_display_transform_double();
             rebuild_bitmaps();
             save_config();
             Redraw = 1;
         }
         if ((new_sx != disp_x_curr) || (new_sy != disp_y_curr)) // window has been moved
         {
            disp_x_curr = disp_x_wind = new_sx;;
            disp_y_curr = disp_y_wind = new_sy;;
            save_config();
         }
      }
    }

Display transform double I also use an orthographic transform to double or triple the screen size. This was implemented to address large screen sizes and small text on menus and overlays.

    void set_display_transform(void)
    {
       al_set_target_backbuffer(display);
       SCREEN_W = disp_w_curr/display_transform_double;
       SCREEN_H = disp_h_curr/display_transform_double;
       ALLEGRO_TRANSFORM trans;
       al_identity_transform(&trans);
       al_orthographic_transform(&trans, 0, 0, -1.0, SCREEN_W, SCREEN_H, 1.0);
       al_use_projection_transform(&trans);
    }

    void auto_set_display_transform_double(void)
    {
       display_transform_double = 1;

       if (disp_w_curr > 1023) display_transform_double = 2;
       if (disp_h_curr > 1023) display_transform_double = 2;

       if (disp_w_curr < 1024) display_transform_double = 1;
       if (disp_h_curr < 700) display_transform_double = 1;

       if (level_editor_running) display_transform_double = 1;

       if (help_screens_running)
       {
          if (disp_w_curr > 1279) display_transform_double = 2;
          if (disp_w_curr < 1280) display_transform_double = 1;
       }
       set_display_transform();
       set_map_var();
    }

This extern variable controls the doubling:

    extern int display_transform_double = 1;
    // 1 = normal (no double)
    // 2 = double
    // 3 = triple

Then all of my drawing functions throughout the rest of the game that need to know screen size use the prescaled 'SCREEN_W' and 'SCREEN_H' instead of the actual sizes. The mouse_x and mouse_y positions are also scaled like this:

    mouse_x = ev.mouse.x / display_transform_double;
    mouse_y = ev.mouse.y / display_transform_double;

Detecting window move Because no events are triggered when the display window is moved, I had to detect it myself. Every frame, in the function 'proc_controllers()', I compare the display's window position to the stored values. If they differ, I call 'proc_screen_change()' with the new values.

    if (!fullscreen) // detect if window was moved
    {
       int x, y;
       al_get_window_position(display, &x, &y);
       if ((x != disp_x_curr) || (y != disp_y_curr))
       proc_screen_change(disp_w_curr, disp_h_curr, x, y, fullscreen);
    }