Whenever I run my program in windowed mode the mouse is fine but when I go full screen it flickers...
relevant code
allegro_init(); set_color_depth(32); install_keyboard(); install_mouse(); if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0)!=0) { set_gfx_mode(GFX_TEXT,0,0,0,0); allegro_message(allegro_error); exit(1); } show_mouse(screen);
and the screen rendering part.
I do rest as a way of slowing the game down, I tried to use the tick method but I couldn't even get that to compile so if you think that's the issue let me know and if you know of where a tutorial is off the top of your head let em know, if not, I'll google. :-D
Read about those two functions:
You should "scare" the mouse prior to drawing to the screen, and unscare it after you're done using screen.
That helped some, it went from being invisible (unless i moved it), to being visible for flickering like a mad man,ideas?
Show all the code you have for the main loop (where drawing happens).
1 | void setup() |
2 | { |
3 | allegro_init(); |
4 | set_color_depth(32); |
5 | install_keyboard(); |
6 | install_mouse(); |
7 | if (set_gfx_mode(GFX_AUTODETECT,1024,768,0,0)!=0) |
8 | { |
9 | set_gfx_mode(GFX_TEXT,0,0,0,0); |
10 | allegro_message(allegro_error); |
11 | exit(1); |
12 | } |
13 | show_mouse(screen); |
14 | |
15 | } |
16 | |
17 | |
18 | int main(void) |
19 | { |
20 | setup(); // sets up the screen |
21 | buffering game_screen; // creates an object where our screen will be held, handles |
22 | // double buffering for us. |
23 | select_character_menu character_menu(game_screen); |
24 | main_menu my_main_menu(game_screen); // we want to set up the main menu so we pass |
25 | // it a reference to game screen so it knows where to set up stuff. kind of important :-D |
26 | while(!game_over) |
27 | { |
28 | if(key[KEY_ESC]) |
29 | { |
30 | int answer=alert("Really Quit?", NULL, NULL, "&Yes", "&No", 'y', 'n'); |
31 | if (answer == 1) |
32 | { |
33 | game_over=true; |
34 | } |
35 | } |
36 | else if(game_state=="main_menu") |
37 | { |
38 | my_main_menu.render_menu();// puts the main menu onto the buffer |
39 | } |
40 | else if(game_state=="new_game") |
41 | { |
42 | character_menu.render_menu(); |
43 | } |
44 | |
45 | scare_mouse(); |
46 | game_screen.render(); // puts the buffer onto the viewable screen removing the flickering |
47 | unscare_mouse(); |
48 | rest(30); |
49 | |
50 | } |
51 | return 0; |
52 | } |
53 | END_OF_MAIN() |
buffering code
1 | #include <allegro.h> |
2 | #include <string> |
3 | #include <vector> |
4 | |
5 | using namespace std; |
6 | #ifndef BUFFERING |
7 | #define BUFFERING |
8 | |
9 | // i know globals make me a bad person but this is a special circumstance |
10 | // game over is something that will be used everywhere and in this one instance |
11 | // i'm breaking the rule. |
12 | bool game_over=false; |
13 | string game_state="main_menu"; |
14 | class buffering |
15 | { |
16 | private: |
17 | // we'l need a buffer and a vector to hold reference to location of bitmaps. |
18 | BITMAP * buffer; |
19 | vector<BITMAP *> bitmaps; |
20 | |
21 | public: |
22 | buffering() |
23 | { |
24 | // the buffer needs to be the entire screen |
25 | // so we use allegro defined variables to make it so. |
26 | buffer=create_bitmap(SCREEN_W,SCREEN_H); |
27 | } |
28 | void mark_bitmap_for_deletion(BITMAP *picture) |
29 | { |
30 | bitmaps.push_back(picture); |
31 | } |
32 | |
33 | // this is just a wrapper for load_bitmap so we can add their memory locations |
34 | // into a vector for automatic deletion later on. |
35 | void add_bitmap(BITMAP *picture,int x=0,int y=0) |
36 | { |
37 | draw_sprite(buffer,picture,x,y); |
38 | } |
39 | |
40 | // same thign as above |
41 | void add_stretched_bitmap(BITMAP * picture,int x=0, int y=0,int width=SCREEN_W, int height=SCREEN_H) |
42 | { |
43 | stretch_sprite(buffer,picture,x,y,width,height); |
44 | } |
45 | |
46 | // draw the buffer to the screen |
47 | void render() |
48 | { |
49 | vsync(); |
50 | blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H); |
51 | } |
52 | |
53 | void add_text(char *text,int color, int x, int y) |
54 | { |
55 | textprintf_ex(buffer,font,x,y,color,1,text); |
56 | } |
57 | |
58 | //dynamically destroy all the bitmaps. good stuff. :-D |
59 | // beats the hell out of 20 million calls to destroy_bitmap |
60 | ~buffering() |
61 | { |
62 | for(int i=0;i<bitmaps.size();i++) |
63 | { |
64 | destroy_bitmap(bitmaps<i>); |
65 | } |
66 | bitmaps.empty(); |
67 | } |
68 | }; |
69 | |
70 | #endif |
In a fully double buffering system (read: anything other than dirty rectangles), I found the best solution for the mouse pointer is to just draw the mouse sprite manually by calling the following right before blitting / flipping:
draw_sprite(backbuffer, mouse_sprite, mouse_x, mouse_y);
...and not activate the built-in mouse pointer at all (call show_mouse(NULL) just to be sure). As long as the double buffering system works reasonably fast, you get smooth, flicker-free mouse movement without any buffering artifacts (the odd wrong-color rectangles you sometimes see under the mouse cursor in windows).
Think about the order of things.
scare_mouse() // ... vsync() blit(...) // ... unscare_mouse()
So, you hide the mouse, and then execute vsync, which waits (potentially a long time) for a vertical refresh, and only then you show it again. This means the mouse stays hidden for the whole time of the wait.
Instead, reorder the calls so that the mouse is hidden for the shortest interval neccessary:
class buffering{ //... void render() { vsync(); scare_mouse(); blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H); unscare_mouse(); }; };
That might help, but I'm not sure at that point - I haven't used Allegro's built-in mouse handling for a long while.
And on a side note: What's with the bitmap vector in the buffering class?
From your comments, I take it you're trying to implement some sort of garbage collection scheme for the bitmaps you load on-the-fly...
I'd suggest you implement a resource handler and put that in a dedicated class. It can be as simple as loading an entire datafile and return the correct bitmap when asked to. More sophisticated approaches will allow for dynamic loading (load on demand), loading and unloading multiple datafiles, etc. But for now I'd say keep it at load_datafile at startup and unload_datafile when done.