|
[A5] Copying a bitmap from a transformed screen |
Neil Roy
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... // 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_set_target_bitmap(menuback); al_draw_bitmap(al_get_backbuffer(setting.screen), 0, 0, 0); al_set_target_bitmap(al_get_backbuffer(setting.screen)); 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... {"name":"608559","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/4\/140aaf57f7c183403dc189ddf34f0c56.jpg","w":800,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/4\/140aaf57f7c183403dc189ddf34f0c56"} But with true Fullscreen mode, I get this... {"name":"608560","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/7\/c7d66c59df6f79abd7477d5a40e0fde7.jpg","w":1920,"h":1080,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/7\/c7d66c59df6f79abd7477d5a40e0fde7"} 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. --- |
beoran
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. |
Neil Roy
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); with: 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. --- |
|