how to get mickeys to work with unlimited mouse movement range
altalena

This program I put together from the wiki gives accurate ev.mouse.dx, but the mouse runs into the edge of the screen and doesn't move past it. If I warped the mouse to the centre of the screen every frame, that might give me what I want, but doing so makes the ev.mouse.dx give me the mouse movement since the start of the program, so I've commented out the warp code. Is there a solution? Here's the code so it should be easy to test. You might have to change the font name or install a font.

#SelectExpand
1#include <stdio.h> 2#include <allegro5/allegro.h> 3#include <allegro5/allegro_font.h> 4#include <allegro5/allegro_ttf.h> 5 6const float FPS = 60; 7const int SCREEN_W = 640; 8const int SCREEN_H = 480; 9const int BOUNCER_SIZE = 32; 10 11int main(int argc, char **argv) 12{ 13 ALLEGRO_DISPLAY *display = NULL; 14 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 15 ALLEGRO_TIMER *timer = NULL; 16 ALLEGRO_BITMAP *bouncer = NULL; 17 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0; 18 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0; 19 bool redraw = true; 20 21 if(!al_init()) { 22 fprintf(stderr, "failed to initialize allegro!\n"); 23 return -1; 24 } 25 26 if(!al_install_mouse()) { 27 fprintf(stderr, "failed to initialize the mouse!\n"); 28 return -1; 29 } 30 31 timer = al_create_timer(1.0 / FPS); 32 if(!timer) { 33 fprintf(stderr, "failed to create timer!\n"); 34 return -1; 35 } 36 37 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 38 display = al_create_display(SCREEN_W, SCREEN_H); 39 if(!display) { 40 fprintf(stderr, "failed to create display!\n"); 41 al_destroy_timer(timer); 42 return -1; 43 } 44// al_hide_mouse_cursor(display); 45 46 al_init_font_addon(); 47 al_init_ttf_addon(); 48 ALLEGRO_FONT *font24 = al_load_ttf_font("pirulen.ttf",24,0 ); 49 50 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE); 51 if(!bouncer) { 52 fprintf(stderr, "failed to create bouncer bitmap!\n"); 53 al_destroy_display(display); 54 al_destroy_timer(timer); 55 return -1; 56 } 57 58 al_set_target_bitmap(bouncer); 59 60 al_clear_to_color(al_map_rgb(255, 0, 255)); 61 62 al_set_target_bitmap(al_get_backbuffer(display)); 63 64 event_queue = al_create_event_queue(); 65 if(!event_queue) { 66 fprintf(stderr, "failed to create event_queue!\n"); 67 al_destroy_bitmap(bouncer); 68 al_destroy_display(display); 69 al_destroy_timer(timer); 70 return -1; 71 } 72 73 al_register_event_source(event_queue, al_get_display_event_source(display)); 74 75 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 76 77 al_register_event_source(event_queue, al_get_mouse_event_source()); 78 79 al_clear_to_color(al_map_rgb(0,0,0)); 80 81 al_flip_display(); 82 83 al_start_timer(timer); 84 85 while(1) 86 { 87 ALLEGRO_EVENT ev; 88 al_wait_for_event(event_queue, &ev); 89 90 if(ev.type == ALLEGRO_EVENT_TIMER) { 91 redraw = true; 92 } 93 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 94 break; 95 } 96 else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || 97 ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { 98 99 bouncer_x = ev.mouse.dx; 100 bouncer_y = ev.mouse.dy; 101/* 102 al_set_mouse_xy(display, 103 al_get_display_width(display)/2, 104 al_get_display_height(display)/2); 105*/ 106 } 107 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { 108 break; 109 } 110 111 if(redraw && al_is_event_queue_empty(event_queue)) { 112 redraw = false; 113 114 al_clear_to_color(al_map_rgb(0,0,0)); 115 116 al_draw_textf(font24, al_map_rgb(255,255,255), al_get_display_width(display)/2, 48, 117 ALLEGRO_ALIGN_CENTRE, "y %f x %f", bouncer_x, bouncer_y); 118// al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0); 119 120 al_flip_display(); 121 } 122 } 123 124 al_destroy_bitmap(bouncer); 125 al_destroy_timer(timer); 126 al_destroy_display(display); 127 al_destroy_event_queue(event_queue); 128 129 return 0; 130}

Elias

Have a look at ex_warp_mouse. ex_warp_mouse works here (in Linux). If it doesn't work on another platform that's a bug which needs to be fixed.

altalena

after copying common.c into my compiler include directory, ex_warp_mouse.c compiles but crashes when I run it.

The program I wrote should be working. Does it work for other people? It compiles and runs for me, but the mouse warping doesn't work.

Elias

It works for me in Linux (after removing the font loading).

altalena

What I'm trying to achieve is a program that warps the mouse cursor to the centre of the screen every time the mouse moves, and prints to the screen how far the mouse has moved since the last redraw. so with the al_set_mouse_xy code enabled on the example program I wrote it works ok? Thanks. you might have to install a font and change the font name to that font to get the program to work, or find some other way of displaying the mouse mickeys.

I'm starting to think there's a mouse driver bug in my system, I'm using allegro 5.0.4 devpak with Orwell's dev-cpp 5.0.0.4 on windows 7 professional.

The help is much appreciated.

Slartibartfast

Maybe instead of checking the dx and dy parameters you can check the x and y parameters and calculate the change from where you warp the mouse?
The if the behaviour is inconsistent between operating systems (I'm not really sure what you are expecting and what you are getting, and what Elias is getting) then I guess it is still a bug that needs to be reported.

altalena

The problem with that is the mouse cursor still hits the edge of the screen, and what I need is unlimited mouse movement. Warping the cursor to the centre of the screen every frame - or every time the mouse changes position - will let me have unlimited mouse movement like in a first person shooter.

In an FPS, you can keep rotating left or right as much as you want, but I can't make that happen without getting the mouse to warp the the screen centre, while still getting accurate mouse mickeys from ev.mouse.dx

I'm running the program in fullscreen of course, and once I get the mouse code working well, I can, for the game menu, draw a custom cursor with primitives that keeps on the screen while the (hidden) real cursor is constantly being warped to the centre of the screen.

I've attached what I've done so far on the Allegro 5 program code as well as the Allegro 4.2 code and executable that I'm trying to port to fullscreen Allegro 5.

Slartibartfast
altalena said:

Warping the cursor to the centre of the screen every frame - or every time the mouse changes position - will let me have unlimited mouse movement like in a first person shooter.

Exactly.
In pseudo-code:
1) dx <- mouse.x - center_x
2) dy <- mouse.y - center_y
3) warp_mouse(center_x, center_y)

altalena

The problem is that warping the mouse to the centre of the screen on each mouse event somehow makes ev.mouse.dx give a number from -960 to 959 based on where the mouse is. The screen I'm using is 1920 pixels wide.

I think it's the mouse warp code that's the problem - it doesn't actually make the mouse cursor move, maybe it's because I'm using Windows 7 Pro, and Dev-c++ with the allegro 5.0.4 devpak.

Matthew Leverton

You already posted about this, and I already gave a solution.

If it's not working then Windows is erroneously generating a mouse move event when you position the mouse. It doesn't happen on OS X, and apparently it doesn't happen on Linux.

altalena

Thanks for testing this on Linux and OSX. I hope someone can test this on Windows 7. Here's the code, the mouse cursor should stay in the centre of the screen. And the text on the screen should be small numbers reflecting how far the mouse has moved since the last mouse event.

http://www.1001freefonts.com/Pirulen.php
(copy Pirulen.ttf to the same directory as your executable).

#SelectExpand
1#include <stdio.h> 2#include <allegro5/allegro.h> 3#include <allegro5/allegro_font.h> 4#include <allegro5/allegro_ttf.h> 5 6const float FPS = 60; 7const int SCREEN_W = 640; 8const int SCREEN_H = 480; 9const int BOUNCER_SIZE = 32; 10 11int main(int argc, char **argv) 12{ 13 ALLEGRO_DISPLAY *display = NULL; 14 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 15 ALLEGRO_TIMER *timer = NULL; 16 ALLEGRO_BITMAP *bouncer = NULL; 17 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0; 18 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0; 19 bool redraw = true; 20 21 if(!al_init()) { 22 fprintf(stderr, "failed to initialize allegro!\n"); 23 return -1; 24 } 25 26 if(!al_install_mouse()) { 27 fprintf(stderr, "failed to initialize the mouse!\n"); 28 return -1; 29 } 30 31 timer = al_create_timer(1.0 / FPS); 32 if(!timer) { 33 fprintf(stderr, "failed to create timer!\n"); 34 return -1; 35 } 36 37 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 38 display = al_create_display(SCREEN_W, SCREEN_H); 39 if(!display) { 40 fprintf(stderr, "failed to create display!\n"); 41 al_destroy_timer(timer); 42 return -1; 43 } 44// al_hide_mouse_cursor(display); 45 46 al_init_font_addon(); 47 al_init_ttf_addon(); 48 ALLEGRO_FONT *font24 = al_load_ttf_font("pirulen.ttf",24,0 ); 49 50 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE); 51 if(!bouncer) { 52 fprintf(stderr, "failed to create bouncer bitmap!\n"); 53 al_destroy_display(display); 54 al_destroy_timer(timer); 55 return -1; 56 } 57 58 al_set_target_bitmap(bouncer); 59 60 al_clear_to_color(al_map_rgb(255, 0, 255)); 61 62 al_set_target_bitmap(al_get_backbuffer(display)); 63 64 event_queue = al_create_event_queue(); 65 if(!event_queue) { 66 fprintf(stderr, "failed to create event_queue!\n"); 67 al_destroy_bitmap(bouncer); 68 al_destroy_display(display); 69 al_destroy_timer(timer); 70 return -1; 71 } 72 73 al_register_event_source(event_queue, al_get_display_event_source(display)); 74 75 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 76 77 al_register_event_source(event_queue, al_get_mouse_event_source()); 78 79 al_clear_to_color(al_map_rgb(0,0,0)); 80 81 al_flip_display(); 82 83 al_start_timer(timer); 84 85 while(1) 86 { 87 ALLEGRO_EVENT ev; 88 al_wait_for_event(event_queue, &ev); 89 90 if(ev.type == ALLEGRO_EVENT_TIMER) { 91 redraw = true; 92 } 93 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 94 break; 95 } 96 else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || 97 ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { 98 99 bouncer_x = ev.mouse.dx; 100 bouncer_y = ev.mouse.dy; 101/**/ 102 al_set_mouse_xy(display, 103 al_get_display_width(display)/2, 104 al_get_display_height(display)/2); 105/**/ 106 } 107 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { 108 break; 109 } 110 111 if(redraw && al_is_event_queue_empty(event_queue)) { 112 redraw = false; 113 114 al_clear_to_color(al_map_rgb(0,0,0)); 115 116 al_draw_textf(font24, al_map_rgb(255,255,255), al_get_display_width(display)/2, 48, 117 ALLEGRO_ALIGN_CENTRE, "y %f x %f", bouncer_x, bouncer_y); 118// al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0); 119 120 al_flip_display(); 121 } 122 } 123 124 al_destroy_bitmap(bouncer); 125 al_destroy_timer(timer); 126 al_destroy_display(display); 127 al_destroy_event_queue(event_queue); 128 129 return 0; 130}

Edgar Reynaldo

I don't have any problems with event.mouse.dx or .dy on Vista at all :

Code used :

#SelectExpand
1 2#include <stdio.h> 3#include <allegro5/allegro.h> 4 5const float FPS = 60; 6const int SCREEN_W = 640; 7const int SCREEN_H = 480; 8const int BOUNCER_SIZE = 32; 9 10int main(int argc, char **argv) 11{ 12 ALLEGRO_DISPLAY *display = NULL; 13 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 14 ALLEGRO_TIMER *timer = NULL; 15 ALLEGRO_BITMAP *bouncer = NULL; 16 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0; 17 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0; 18 bool redraw = true; 19 20 if(!al_init()) { 21 fprintf(stderr, "failed to initialize allegro!\n"); 22 return -1; 23 } 24 25 if(!al_install_mouse()) { 26 fprintf(stderr, "failed to initialize the mouse!\n"); 27 return -1; 28 } 29 30 timer = al_create_timer(1.0 / FPS); 31 if(!timer) { 32 fprintf(stderr, "failed to create timer!\n"); 33 return -1; 34 } 35 36 al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_REQUIRE); 37 38 display = al_create_display(SCREEN_W, SCREEN_H); 39 if(!display) { 40 fprintf(stderr, "failed to create display!\n"); 41 al_destroy_timer(timer); 42 return -1; 43 } 44 45 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE); 46 if(!bouncer) { 47 fprintf(stderr, "failed to create bouncer bitmap!\n"); 48 al_destroy_display(display); 49 al_destroy_timer(timer); 50 return -1; 51 } 52 53 al_set_target_bitmap(bouncer); 54 55 al_clear_to_color(al_map_rgb(255, 0, 255)); 56 57 al_set_target_bitmap(al_get_backbuffer(display)); 58 59 event_queue = al_create_event_queue(); 60 if(!event_queue) { 61 fprintf(stderr, "failed to create event_queue!\n"); 62 al_destroy_bitmap(bouncer); 63 al_destroy_display(display); 64 al_destroy_timer(timer); 65 return -1; 66 } 67 68 al_register_event_source(event_queue, al_get_display_event_source(display)); 69 70 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 71 72 al_register_event_source(event_queue, al_get_mouse_event_source()); 73 74 al_clear_to_color(al_map_rgb(0,0,0)); 75 76 al_flip_display(); 77 78 al_start_timer(timer); 79 80 int mx = SCREEN_W/2; 81 int my = SCREEN_H/2; 82 al_set_mouse_xy(display , SCREEN_W/2 , SCREEN_H/2); 83 al_flush_event_queue(event_queue); 84 85 bool quit = false; 86 87 while (!quit) { 88 int num_events = 0; 89 do { 90 ALLEGRO_EVENT ev; 91 al_wait_for_event(event_queue, &ev); 92 ++num_events; 93 if(ev.type == ALLEGRO_EVENT_TIMER) { 94 redraw = true; 95 } 96 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 97 quit = true; 98 break; 99 } 100 else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || 101 ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { 102 mx += ev.mouse.dx; 103 my += ev.mouse.dy; 104 printf("dx,dy = %i,%i , mx,my = %i,%i , mouse.x , mouse.y = %i,%i\n" , ev.mouse.dx , ev.mouse.dy , mx , my , ev.mouse.x , ev.mouse.y); 105 bouncer_x = ev.mouse.x; 106 bouncer_y = ev.mouse.y; 107 al_set_mouse_xy(display , SCREEN_W/2 , SCREEN_H/2); 108 } 109 else if (ev.type == ALLEGRO_EVENT_MOUSE_WARPED) { 110 mx += ev.mouse.dx; 111 my += ev.mouse.dy; 112 113 } 114 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { 115 quit = true; 116 break; 117 } 118// if (al_is_event_queue_empty(event_queue)) { 119// printf("Event queue empty.\n"); 120// } 121 } while (!al_is_event_queue_empty(event_queue)); 122 123// printf("Number of events processed : %i\n" , num_events); 124 125 if (redraw) { 126 redraw = false; 127 al_clear_to_color(al_map_rgb(0,0,0)); 128 129 al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0); 130 al_flip_display(); 131 } 132 } 133 134 al_destroy_bitmap(bouncer); 135 al_destroy_timer(timer); 136 al_destroy_display(display); 137 al_destroy_event_queue(event_queue); 138 139 return 0; 140}

It prints out reasonable numbers for dx and dy, and the mouse x and y I tracked using dx and dy from EVENT_MOUSE_AXES and EVENT_MOUSE_WARPED matches the mouse x and y that EVENT_MOUSE_AXES reports.

Aside from that though, the bouncer doesn't follow the mouse worth shit (major display delays - could be stalled in al_wait_for_event somehow?), and I have no idea why. Couldn't figure it out in the other thread where this was happening either.

Matthew Leverton

What if you don't use the WARP event? That shouldn't be necessary. As I understand it, it should work like this:

  • set mouse to 320,240; set x,y to 320,240

  • move mouse to 300,240

  • axes event: dx = -20; set x -= 20

  • set position to 320,240

  • warp event: dx = 20 (ignore)

  • move mouse to 300,240

  • axes event: dx = -20; set x -= 20

So after this, x should be 280.

If you have to listen to the warp event to achieve that, something is wrong.

altalena

Edgar's code works for me in windowed mode but not in fullscreen.

http://www.allegro.cc/forums/thread/608627/934943#target
This code works pretty well in windowed mode, but seems to only work on one mouse axis at a time - when x is 0, y is usually 2, and when y is 0, x is usually 2.
It doesn't work in fullscreen.

Matthew, I'm not sure what you mean by not using a warp event. Is there a way to move the mouse cursor in fullscreen without using a warp event?

Edgar Reynaldo

I can confirm that al_set_mouse_xy(display , SCREEN_W/2 , SCREEN_H/2) does nothing in fullscreen in Vista using the default driver at 800 X 600.

I can also confirm that in the same mode that event.mouse.dx and event.mouse.dy from the EVENT_MOUSE_AXES event show the distance from the center of the screen and not the actual dx and dy of the last mouse move.

altalena

Thanks Edgar! I wish I knew enough about programming to help fix this 'bug'.

Unfortunately, my only programming experience is a few 3d programs in Turing, and some sine-wave programs and Lissajous curve generators in BASIC. I've learned the basics of the C language, but don't know how to use recursion or pointers.

Edgar Reynaldo

Well, I don't see anything obviously wrong with set_mouse_xy (called by al_set_mouse_xy) or with al_win_mouse_handle_move (sends ALLEGRO_EVENT_MOUSE_AXES events). Any one else see any problems with them?

A5.1 SVN r15021 :

wmouse.c lines 146-178

#SelectExpand
1 2static bool set_mouse_xy(ALLEGRO_DISPLAY *disp, int x, int y) 3{ 4 int dx, dy; 5 int wx, wy; 6 ALLEGRO_DISPLAY_WIN *win_disp = (void*)disp; 7 8 if (!installed) 9 return false; 10 11 dx = x - mouse_state.x; 12 dy = y - mouse_state.y; 13 14 if (dx || dy) { 15 mouse_state.x = x; 16 mouse_state.y = y; 17 18 generate_mouse_event( 19 ALLEGRO_EVENT_MOUSE_WARPED, 20 mouse_state.x, mouse_state.y, mouse_state.z, mouse_state.w, 21 dx, dy, 0, 0, 22 0, (void*)win_disp); 23 } 24 25 _al_win_get_window_position(win_disp->window, &wx, &wy); 26 27 if (!(win_disp->display.flags & ALLEGRO_FULLSCREEN)) { 28 SetCursorPos(x+wx, y+wy); 29 } 30 31 return true; 32}

wmouse.c 289-321

#SelectExpand
1 2void _al_win_mouse_handle_move(int x, int y, bool abs, ALLEGRO_DISPLAY_WIN *win_disp) 3{ 4 int dx, dy; 5 int oldx, oldy; 6 7 oldx = mouse_state.x; 8 oldy = mouse_state.y; 9 10 if (!installed) 11 return; 12 13 if (!abs) { 14 mouse_state.x += x; 15 mouse_state.y += y; 16 dx = x; 17 dy = y; 18 } 19 else { 20 dx = x - mouse_state.x; 21 dy = y - mouse_state.y; 22 mouse_state.x = x; 23 mouse_state.y = y; 24 } 25 26 if (oldx != mouse_state.x || oldy != mouse_state.y) { 27 generate_mouse_event(ALLEGRO_EVENT_MOUSE_AXES, 28 mouse_state.x, mouse_state.y, mouse_state.z, mouse_state.w, 29 dx, dy, 0, 0, 30 0, (void*)win_disp); 31 } 32}

Maybe there's something wrong with the way wwindows.c's window_callback calls al_win_mouse_handle_move. I don't really know. Maybe I can look more tomorrow.

Elias

What does the if (!(win_disp->display.flags & ALLEGRO_FULLSCREEN)) { check do? Seems the mouse position deliberately is not altered in fullscreen.

Matthew Leverton

Looking at older revisions, there used to be a huge "else" block for full screen.

altalena

OK that's good to know. Maybe in the next version of Allegro the else block can go back in?

Matthew Leverton

It might not be needed. It looks like the mouse input code was simplified to use a different Windows API at some point.

Trent Gamblin

Without that fullscreen check it seems to sort of work here. The pink bitmap doesn't display or displays corrupt though, for some reason (both OpenGL and D3D).

altalena

So it looks like this problem wont be fixed before the next version of Allegro. Should I close this thread? I'm grateful to the people who tested this.

Thomas Fjellstrom

I think it'll get fixed if the people who know the windows code figure out where the problem is.

altalena

OK I'll just wait for an Allegro devpak to come out with this problem fixed.
Have a good weekend folks!

Trent Gamblin

Can anyone tell me if full screen (not full screen window) works for them in 5.1 svn on Windows? I haven't tested yet myself except Edgar's example where the
magenta square shows up blank or with a little corrupted data and the rest blank.

Edgar Reynaldo

Downloading latest SVN now... Will build in a bit and then test again.

Edit
Nope - Revision 15053 still doesn't work. al_set_mouse_xy still doesn't do anything in fullscreen. MOUSE_AXES dx and dy are still screwed up, reporting the distance from the center of the screen except for occasionally being right???

Edit2
Well, if I enable the SetCursorPos call for full screen, it works for me. No corruption of the bouncer bitmap for me.

src/win/wmouse.c lines 172-174

#SelectExpand
172// if (!(win_disp->display.flags & ALLEGRO_FULLSCREEN)) { 173 SetCursorPos(x+wx, y+wy); 174// }

Trent Gamblin

Revision 15053 still doesn't work

I didn't commit anything yet.

Quote:

Well, if I enable the SetCursorPos call for full screen, it works for me. No corruption of the bouncer bitmap for me.

Ok, it worked for me besides the bitmap corruption, so I'll commit it.

Thread #608627. Printed from Allegro.cc