- Online Community Forums » Programming Questions » [A5] Copying a bitmap from a transformed screen

This thread is locked; no one can reply to it. rss feed Print
[A5] Copying a bitmap from a transformed screen
Member #2,229
April 2002

I have been working on a game and have noticed a small problem. The game works perfectly so far, I was working on my options menu where I can switch from WINDOWED to a FULLSCREEN_WINDOW and FULLSCREEN. The game resolution is 800x600 and I use a transform and clipping to fit it to FULLSCREEN (Matthew's function):

1#include <allegro5/allegro.h> 2 3float scale_x; 4float scale_y; 5int offset_x; 6int offset_y; 7 8// Use to get mouse position on scaled screen 9float scale_x = 1; 10float scale_y = 1; 11int offset_x = 0; 12int offset_y = 0; 13 14// usage: a5_scale_screen(BUFFER_WIDTH, BUFFER_HEIGHT, display_width, display_height); 15void a5_scale_screen(int bw, int bh, int dw, int dh) 16{ 17 ALLEGRO_TRANSFORM t; 18 19 // Calculate the horizontal and vertial aspect ratios 20 const float HAR = dw / (float)bw; 21 const float VAR = dh / (float)bh; 22 23 // The aspect ratio, x-offset and y-offset (in pixels) 24 float ar, ox, oy; 25 26 if(bw == dw && bh == dh) { 27 // 1:1, just reset everything 28 al_identity_transform(&t); 29 al_use_transform(&t); 30 al_set_clipping_rectangle(0, 0, bw, bh); 31 scale_x = 1; 32 scale_y = 1; 33 offset_x = 0; 34 offset_y = 0; 35 al_clear_to_color(al_map_rgb(0, 0, 0)); 36 al_flip_display(); 37 } 38 else { 39 // Choose the smaller aspect ratio 40 if(HAR < VAR) { 41 // horizontal bars on the top and bottom 42 ar = HAR; 43 ox = 0; 44 oy = (dh - (ar * bh)) / 2.0; 45 } 46 else { 47 // vertical bars on the left and right 48 ar = VAR; 49 ox = (dw - (ar * bw)) / 2.0; 50 oy = 0; 51 } 52 53 // set the global scale/offset so the mouse coords can be inverted 54 // use the following code to get the proper mouse position 55 // mouse_x = (event.mouse.x - offset_x) / scale_x; 56 // mouse_y = (event.mouse.y - offset_y) / scale_y; 57 scale_x = ar; 58 scale_y = ar; 59 offset_x = ox; 60 offset_y = oy; 61 62 // set up the transformation to scale and translate 63 al_build_transform(&t, ox, oy, ar, ar, 0); 64 al_use_transform(&t); 65 66 // clear out the screen before setting the clipping 67 al_set_clipping_rectangle(0, 0, dw, dh); 68 al_clear_to_color(al_map_rgb(0, 0, 0)); 69 al_flip_display(); 70 71 // make sure nothing is drawn into the black bars 72 al_set_clipping_rectangle(ox, oy, ar * bw, ar * bh); 73 } 74}

Now my problem is in my game, when you press ESC a small menu pops up. In my game I copy the background game screen so when you move between menu items, the background is redrawn, then the menu. This works fine in WINDOWED and in FULLSCREEN_WINDOWED, but it FULLSCREEN the background ignores the clipping that was set in the above function and the background is drawn way off. So on a 1920x1080 screen, the upper left 800x600 is copied rather than the game screen.

Code used to copy the background...
(WIDTH = 800, HEIGHT = 600)

   // Copy game screen onto a bitmap
   menuback = al_create_bitmap(WIDTH, HEIGHT);
   if(!menuback) {
      a5_error(AT, setting.screen, "Failed to create menuback");
      goto SHUTDOWN;
   al_draw_bitmap(al_get_backbuffer(setting.screen), 0, 0, 0);

Here is what the menu looks like on an 800x600 window (it also looks that way on a larger 1920x1080 Fullscreen Window, only scaled up with black borders obviously...


But with true Fullscreen mode, I get this...


Is there a special way to copy this properly in Fullscreen mode, or am I going to have to store the clipping co-ordinates and use that in Fullscreen mode?

Thanks in advance.

"C is quirky, flawed, and an enormous success." - Dennis M. Ritchie

Member #12,636
March 2011

Well, I think you'll need to keep track of the clipping coordinates if you want to do it like that.

However, I'd reccomend a different approach. I wouln't store the game screen in a buffer. Rather I'd redraw the game screen as usual and use a game state machine to see whether or not the menu is active or not. If the menu is active the game logic is paused, the menu is drawn and keystrokes are rerouted to interaction with the menu. If the menu is not active the menu is not drawn and the input is sent to the game input handler.

Like that, you don't need any extra bitmap buffers, and any menu you draw will scale in the same way as the game screen.

Member #2,229
April 2002

Okay, I managed to fix it. The solution was very simple. The scaling function which Matthew came up with has some variables that are set automatically originally for use with mouse movement which I can use to copy the game screen for use with this menu.

The variables offset_x, offset_y, scale_x, and scale_y all give the information needed to copy the screen properly in fullscreen mode.

I basically replaced:

al_draw_bitmap(al_get_backbuffer(setting.screen), 0, 0, 0);


al_draw_scaled_bitmap(al_get_backbuffer(setting.screen), offset_x, offset_y, WIDTH*scale_x, HEIGHT*scale_y, 0, 0, WIDTH, HEIGHT, 0);

Which works perfectly in all screen modes.

I needed to do it this way as my menu that pops up is in it's own function and I want to leave it separate from the rest of the game code.

"C is quirky, flawed, and an enormous success." - Dennis M. Ritchie

Go to: