Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » ALLEGRO_RESIZABLE & Mouse Pointer Collision Detection

This thread is locked; no one can reply to it. rss feed Print
 1   2 
ALLEGRO_RESIZABLE & Mouse Pointer Collision Detection
pkrcel
Member #14,001
February 2012

GaryT said:

If the following is true then that's exactly what I've been looking for:

That IS definitely true, I've played around ex_resize2.exe in the allegro examples and if you fail to acknowledge the resize event (commenting the proper code) you see the picture that gets resized (automagically transformed) proportionally.

Althou this means that I see in your video means you're NOT acknowledging the resize.

Which could be what you were looking for, if you don not want to clip the graphics but would like to have the screen automatically re-proportioned.

In that case, you WILL have to transform the mouse input, but to get the resized coordinates you have to look in the EVENT struct fields, namely:

 event.display.x 
 event.display.y 
 event.display.width
 event.display.height

when handling the resize event.

Which should yield the information you need to transform your mouse input accordingly.

I know, I'm a bit confused in my exposition....hope this anyway helps.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

jmasterx
Member #11,410
October 2009

Yeah, your video shows that the display is not being acknowledged. I'm not sure why since you are indeed acknowledging it.

One thing that is very important. Do you register your display to your event queue?

Notice how I do it:

 int main(int argc, char *argv[]) { 
// Start the event queue to handle keyboard input and our timer
 ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue(); 
al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_get_keyboard_event_source()); 
al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_get_mouse_event_source()); 
al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)timer); 
al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)display);
 ALLEGRO_EVENT event;
 while(!done) {

If you do not register your display, certain things might not work correctly, and resizing might be one of them.

You probably will not receive the resize event.

If you can, print the bool returned by acknowledge resize call to see if it returns true.

Thomas Fjellstrom
Member #476
June 2000
avatar

It's probably a better idea to use al_get_display_event_source and al_get_timer_event_source rather than just casting the pointers, "just in case" of a future change.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

jmasterx
Member #11,410
October 2009

Oh wow, I never even knew about those functions hahah

At the time that I wrote the template, I was using 4.9.something and I'm not sure if those API's had been added yet :P

Thomas Fjellstrom
Member #476
June 2000
avatar

jmasterx said:

At the time that I wrote the template, I was using 4.9.something and I'm not sure if those API's had been added yet :P

You could be right ;D

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Member #8,592
May 2007
avatar

IIRC, Edgar Reynaldo had a system where the button coordinates were a percentage of the screen dimensions.

This is basically the gist of the whole thing :

#SelectExpand
1 2Rectangle LayoutArea(Rectangle outer_area , LayoutRectangle layout_area) { 3 float x = outer_area.X(); 4 float y = outer_area.Y(); 5 float w = outer_area.W(); 6 float h = outer_area.H(); 7 8 // apply percentages from layout_area 9 float nx = x + layout_area.fx*w; 10 float ny = y + layout_area.fy*h; 11 float nw = w*layout_area.fw; 12 float nh = h*layout_area.fh; 13 14 // transform to integer boundaries, shrink to prevent overlap 15 int nxpos = (int)(ceil(nx)); 16 int nypos = (int)(ceil(ny)); 17 int nwid = (int)(floor(nw)); 18 int nht = (int)(floor(nh)); 19 20 return Rectangle(nxpos , nypos , nwid , nht); 21}

outer_area is your screen, layout_area is the percentage rectangle, and LayoutArea returns the new rectangle based on the combination of the two.
fx,fy,fw,and fh are all floats representing the percentage from 0 to 1.0 (or beyond, but then offscreen) of that dimension's x or y or w or h.

Really, you should check to make sure you're transforming your buttons to the new position properly. All I saw was += fx + ... which is just a translation, and not a scaling.

GaryT
Member #14,875
January 2013

It's all working as it should now I think :)

See video link:

http://www.youtube.com/watch?v=TjRlW3E-LDw&list=UU2XSIT3tAf_-7ilWHAaiocA

Before, I was making the mistake of assuming the instant resizing of the graphics within the window when adjusting the window size via the mouse, to be what al_acknowledge_resize() actually does :D

Now I just need to transform the fonts and bitmaps (perhaps all put onto one bitmap first, not quite sure yet) to match the new size as it's acknowledged. Also I now have the values to compensate for the mouse collision detection.

Interesting though. I'm left wondering if some people simply use the instant resizing of the graphics as usable for one of their display modes, as after all it does seem to work okay, as seen from my first video, but there's no values to use for compensating for the mouse issue I've was having, as I know all too well. Also I'm suspecting the graphics are only intended as a preview or even abandoned data which just happens to stay in tack enough to form an okay image, although it does seem to break up slightly irregular at points as the widow changes size, but this mostly seems to only distort the text.

Edit 4: My last sentence immediately above starting "Also I'm" is perhaps rubbish, I simply don't know.

Anyway I'm pretty sure at last that I'm on the right track ;D

Also here's my modified routine with several mistakes corrected:

#SelectExpand
1{ 2 bool realevent; 3 4 bool wait = true; 5 6 bool isplaying = false; 7 8 string displaymode; // Used For Display Name In Buttons 9 10 vector<Buttons> mode(3); // Number Of Buttons To Display 11 12 int stdx= 100; // Amount To Shift Everything Left 13 int stdoffset = -27; // Vertical Pitch 14 for(unsigned int pos = 0; pos < mode.size(); ++pos, stdoffset += 55) // Set mode Button Parameters 15 { 16 mode[pos].x = WIDTH / 2 - stdx; 17 mode[pos].y = 200 + stdoffset; 18 mode[pos].boundx = mode[pos].x + 188; 19 mode[pos].boundy = mode[pos].y + 23; 20 } 21 22 int r = 20; 23 int g = 20; 24 int b = 20; 25 26 int width_test = al_get_display_width(display); // My New Test Variable 27 int height_test = al_get_display_height(display); // My New Test Variable 28 29 while(wait) 30 { 31 realevent = al_get_next_event(event_queue, &ev); 32 33 if(realevent) 34 if(ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE) // Start of Acknowledge Resize 35 { 36 al_acknowledge_resize(display); 37 width_test = al_get_display_width(display); 38 height_test = al_get_display_height(display); // End of Acknowledge Resize 39 } 40 41 al_get_mouse_state(&state); 42 int x = al_get_mouse_state_axis(&state, 0); 43 int y = al_get_mouse_state_axis(&state, 1); 44 int z = al_get_mouse_state_axis(&state, 2); 45 46 al_clear_to_color(al_map_rgb(0,0,0)); 47 48 for(unsigned int pos = 0; pos < mode.size(); ++pos) 49 { 50 if(pos == 0) 51 displaymode = " Full Screen"; 52 if(pos == 1) 53 displaymode = " Windowed Normal"; 54 if(pos == 2) 55 displaymode = "Windowed Resizeable"; 56 57 if(x > mode[pos].x && x < mode[pos].boundx && y > mode[pos].y && y < mode[pos].boundy) // Collision Check For Mode Buttons 58 { 59 r = 120; 60 g = 120; 61 b = 120; 62 63 if(realevent) 64 { 65 if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) 66 { 67 if(ev.mouse.button == 1 && pos == 0) 68 { 69 DestroyBitmaps(); 70 DestroyFonts(); 71 72 al_destroy_display(display); // This Might Destroy Bitmaps And Fonts Anyway But Still Destroy Them Independently Just To Make Sure As Immediately Above 73 74 ALLEGRO_DISPLAY_MODE disp_data; 75 al_get_display_mode(al_get_num_display_modes() - 1, &disp_data); 76 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 77 display = al_create_display(disp_data.width, disp_data.height); 78 79 al_register_event_source(event_queue, al_get_display_event_source(display)); // Re-register Display onto Event Queue 80 81 width_test = al_get_display_width(display); 82 height_test = al_get_display_height(display); 83 84 fsx = (disp_data.width - WIDTH) / 2; 85 fsy = (disp_data.height - HEIGHT) / 2; 86 87 LoadBitmaps(); 88 LoadFonts(); 89 90 for(unsigned int pos = 0; pos < mode.size(); ++pos) // Move Buttons To The Right For Full Screen Mode 91 { 92 mode[pos].x += fsx; // Because fsx And fsy Are Used To Set Actual Button Postions Just Here This Means 93 mode[pos].y += fsy; // al_get_mouse_state_axis() And The al_draw Functions For The Buttons! Dont Need To 94 mode[pos].boundx += fsx; // Use fsx And fsy !!! 95 mode[pos].boundy += fsy; 96 } 97 } 98 99 if(ev.mouse.button == 1 && pos == 1) 100 { 101 DestroyBitmaps(); 102 DestroyFonts(); 103 104 al_destroy_display(display); // This Might Destroy Bitmaps And Fonts Anyway But Still Destroy Them Independently Just To Make Sure As Immediately Above 105 106 al_set_new_display_flags(ALLEGRO_WINDOWED); 107 108 display = al_create_display(WIDTH, HEIGHT); 109 110 al_register_event_source(event_queue, al_get_display_event_source(display)); // Re-register Display onto Event Queue 111 112 width_test = al_get_display_width(display); 113 height_test = al_get_display_height(display); 114 115 LoadBitmaps(); 116 LoadFonts(); 117 118 for(unsigned int pos = 0; pos < mode.size(); ++pos) // Move Buttons Back To The Left For Windowed Mode 119 { 120 mode[pos].x -= fsx; 121 mode[pos].y -= fsy; 122 mode[pos].boundx -= fsx; 123 mode[pos].boundy -= fsy; 124 } 125 126 fsx = 0; // Reset offSet After Having Moved Buttons Back To The Left Just Above 127 fsy = 0; // Reset offSet After Having Moved Buttons Back To The Left Just Above 128 } 129 130 if(ev.mouse.button == 1 && pos == 2) 131 { 132 DestroyBitmaps(); 133 DestroyFonts(); 134 135 al_destroy_display(display); // This Might Destroy Bitmaps And Fonts Anyway But Still Destroy Them Independently Just To Make Sure As Immediately Above 136 137 al_set_new_display_flags(ALLEGRO_RESIZABLE); 138 139 display = al_create_display(WIDTH, HEIGHT); 140 141 al_register_event_source(event_queue, al_get_display_event_source(display)); // Re-register Display onto Event Queue 142 143 LoadBitmaps(); 144 LoadFonts(); 145 146 for(unsigned int pos = 0; pos < mode.size(); ++pos) // Move Buttons Back To The Left For Windowed Mode 147 { 148 mode[pos].x -= fsx; 149 mode[pos].y -= fsy; 150 mode[pos].boundx -= fsx; 151 mode[pos].boundy -= fsy; 152 } 153 154 fsx = 0; // Reset offSet After Having Moved Buttons Back To The Left Just Above 155 fsy = 0; // Reset offSet After Having Moved Buttons Back To The Left Just Above 156 } 157 } 158 } 159 } 160 161 else 162 { 163 r = 40; 164 g = 40; 165 b = 40; 166 } 167 168 al_draw_filled_rectangle(mode[pos].x, mode[pos].y, mode[pos].boundx, mode[pos].boundy, al_map_rgb(r, g, b)); 169 al_draw_text(font18, al_map_rgb(130, 190, 130), mode[pos].x + 3, mode[pos].y, 0, displaymode.c_str()); 170 } 171 172 al_draw_text(font30, al_map_rgb(0, 200, 255), WIDTH / 2 + fsx, 350 + fsy, ALLEGRO_ALIGN_CENTRE, "Press 'M' To Begin Munching Or Press Space To Create A Maze"); 173 174 al_draw_textf(font30, al_map_rgb(100, 200, 255), WIDTH / 2 + fsx, 100 + fsy, ALLEGRO_ALIGN_CENTRE, "Width %i Height %i", width_test, height_test); 175 176 al_flip_display(); 177 178 if(realevent) 179 if(ev.type == ALLEGRO_EVENT_KEY_DOWN) 180 { 181 if(ev.keyboard.keycode == ALLEGRO_KEY_M) 182 { 183 wait = false; 184 } 185 186 if(ev.keyboard.keycode == ALLEGRO_KEY_SPACE) 187 { 188 BonusLevel(isplaying); 189 } 190 } 191 } 192}

EDIT: Sorry all, I've only just spotted it's now on page two, I'll get reading your posts :o

Edit 2: I'm still reading, but yes you're absolutely correct jmasterx I was forgetting to re-register the display on the event queue.

Edit 3: pkrcel are you saying my suggestion of using the instant resizing of the display might be a valid option. And if so are you saying by using:

if(ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)

I could compensate for the mouse pointer position as the window size changes and indeed not bother using:

al_acknowledge_resize(display)

Whether you are or not, I'm still extremely happy because now I understand :D

More About This: If I store the mouse position values instantly before ALLEGRO_EVENT_DISPLAY_RESIZE starts, and then compare them the instant ALLEGRO_EVENT_DISPLAY_RESIZE stops, then I should have the correct values to compensate for the mouse. Along with the above is this along the lines of what you mean.

Another Edit: Thanks Edgar and Thomas, I've found this which I think could help as well: https://wiki.allegro.cc/index.php?title=Achieving_Resolution_Independence

jmasterx
Member #11,410
October 2009

The main disadvantage of the resolution independence methods you linked is that your game can only run on 1 aspect ratio. If you want your game to run on 4:3,16:9,16:10 aspect ratios etc, then you will have to have black borders or everything will look stretched.

GaryT
Member #14,875
January 2013

Up to now I've been thinking that either black borders or stretching are the only two possibilities for any method. Are you saying there are more options for certain other methods.

jmasterx
Member #11,410
October 2009

Yes, the other option involves using layouts / relative size algorithms for your gui, and for the game, you can use transformations such that the character is always the same size, but more land is in view in widescreen and so forth. My game supports just about any common aspect ration because of how I designed it.

The basic idea of layouts is that you specify constraints for your widgets/components. You put Widgets into containers with these constraints and the algorithm will size and position your Widgets such that they look optimal for the selected width and height.

Java's Swing API allows this sort of flexibility. My GUI API and a few other GUI APIs on a.cc support this sort of Layout concept.

Otherwise, the alternative quick n dirty way is for you to specify when you get a resize event:
button1.size = width * 0.2f, 60;
button1.location = width / 2, height / 2;

So basically, when the screen is resized, set the button to the center of the screen, and set its width 20% of the screen width, and its height to a fixed 60 pixels.

This way at any resolution the button will look correct.

It's a lot more work to do it this way but I personally prefer it over a static solution.

GaryT
Member #14,875
January 2013

Totally Awesome :)

Sounds complicated, and thank you for such a clear explanation. Hopefully one day I'll be able to do it myself :D

pkrcel
Member #14,001
February 2012

GaryT said:

Before, I was making the mistake of assuming the instant resizing of the graphics within the window when adjusting the window size via the mouse, to be what al_acknowledge_resize() actually does :D

If you run both allegro examples ex_resize and ex_resize2 you might end up thinking that, since both programs resize what's in the screen automatically; this led me to the initial confusion because clashed with what jamsterx said (and I actually remebered like that as well).

Upon looking at the code of the examples thou it was clear that's not the case.

Dunno, maybe the two examples could be tinkered with.

moving on...

Quote:

pkrcel are you saying my suggestion of using the instant resizing of the display might be a valid option

Not exactly, because I don't know what are you aiming for specifically, but in principle if you're not bothered by the shrinking/stretching you indeed COULD use the automatic gfx adaptation.

It's not elegant nor eyecandy thou, you should at least set display constraints that set for a minimum and maximum width/height (see al_set_window_constraints), and could even handle the resize event (still without acknowledging) calling al_resize_display to FORCE a certain aspect ratio.

At least that's how it come to mind seeing your video, which admittedly it's not the optimal way to do it (I dunno if the gfx driver performance would be bothered for example, even thou I guess not).

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

GaryT
Member #14,875
January 2013

Thanks again pkrcel.

There's a lot for me to play around with now, and I'm feeling positive :-*

Edgar Reynaldo
Member #8,592
May 2007
avatar

Felt obligated to mention this - the way the display looks during a resize is just a temporary way to keep something on the screen that looks remotely appropriate. The mouse and its positions will NOT be affected until you call al_acknowledge_resize or al_resize_display. Then they should work as expected. Allegro does not transform the mouse. It just stretches the display to the intermediate size.

pkrcel
Member #14,001
February 2012

Yeah, that's the main point in me saying it's not "elegant"....it's basically hijacking a side effect.

But you can transform yourself mouse coordinates if you query the relevant fields in the allegro resize event.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

 1   2 


Go to: