So, im working on a general purpose framework for 2d allegro games; right know i've got the screen update part ready.
We have gfx.c:
1 | /* |
2 | Name: gfx.c |
3 | Copyright: 2005 FMC |
4 | Author: Fabio Maria Carlucci |
5 | Date: 03/12/05 15.23 |
6 | Description: graphical routines related (update, gfx loading, ...) |
7 | */ |
8 | #include "game_includes.h" |
9 | |
10 | static int iPage, iMode, iHasSetup = 0, iX, iY, iFatalError, iColours; |
11 | BITMAP *bDbuf, *vPages[3], *bDraw; |
12 | |
13 | int gfx_setup(int mode, int x, int y, int cols){ |
14 | iPage = 0; |
15 | iMode = mode; |
16 | iHasSetup = 1; |
17 | iX = x; |
18 | iY = y; |
19 | iFatalError = 0; |
20 | iColours = cols; |
21 | |
22 | return GM_OK; |
23 | } |
24 | |
25 | int gfx_start(){ |
26 | if(!iHasSetup){ |
27 | P_ERROR("You must first setup for gfx!"); |
28 | return GM_FAIL; |
29 | } |
30 | |
31 | int iOk; |
32 | set_color_depth(iColours); |
33 | if(iMode & S_FULL) |
34 | iOk = set_gfx_mode(GFX_AUTODETECT, iX, iY, 0, 0); |
35 | else |
36 | iOk = set_gfx_mode(GFX_AUTODETECT_WINDOWED, iX, iY, 0, 0); |
37 | |
38 | if(iOk){ |
39 | iMode = 0; |
40 | P_ERROR("\nCan't init selected video mode"); |
41 | iFatalError = 1; //fatal error triggered |
42 | return GM_FAIL; |
43 | } |
44 | |
45 | bDraw = screen; //by default the screen is the "drawable" surface |
46 | |
47 | //if triple buffering is enabled |
48 | if(iMode & TRIPLE_BUF){ |
49 | /* triple buffering setup */ |
50 | if (!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) |
51 | enable_triple_buffer(); |
52 | if (!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) { |
53 | P_ERROR("\nCan't do triple buffering... will try page flipping"); |
54 | iMode -= TRIPLE_BUF; |
55 | iMode += PAGE_FLIP; |
56 | } |
57 | else { |
58 | vPages[0] = create_video_bitmap(iX, iY); |
59 | vPages[1] = create_video_bitmap(iX, iY); |
60 | vPages[2] = create_video_bitmap(iX, iY); |
61 | } |
62 | bDraw = vPages[iPage]; |
63 | } |
64 | //if page flipping is enabled |
65 | if(iMode & PAGE_FLIP){ |
66 | vPages[0] = create_video_bitmap(iX, iY); |
67 | vPages[1] = create_video_bitmap(iX, iY); |
68 | bDraw = vPages[iPage]; |
69 | } |
70 | //if double buffering is enabled |
71 | if(iMode & DOUBLE_BUF){ |
72 | bDbuf = create_bitmap(iX, iY); |
73 | if(!bDbuf){ //if it can't init the double buffer say so and try a workaround |
74 | iMode -= DOUBLE_BUF; |
75 | P_ERROR("\nCan't create double buffer!"); |
76 | } |
77 | else |
78 | bDraw = bDbuf; //double buffer can be the drawable bitmap even if page flipping or triple buf are enabled |
79 | } |
80 | |
81 | return GM_OK; |
82 | } |
83 | |
84 | int gfx_update(){ |
85 | if(iFatalError)return GM_FAIL; |
86 | |
87 | if(iMode & TRIPLE_BUF){ |
88 | if(iMode & DOUBLE_BUF)blit(bDbuf, vPages[iPage], 0, 0, 0, 0, screen->w, screen->h); |
89 | |
90 | do { |
91 | } while (poll_scroll()); |
92 | |
93 | request_video_bitmap(vPages[iPage]); |
94 | iPage = (iPage+1)%3; |
95 | if(!(iMode & DOUBLE_BUF))bDraw = vPages[iPage]; |
96 | } |
97 | else if(iMode & PAGE_FLIP){ |
98 | if(iMode & DOUBLE_BUF)blit(bDbuf, vPages[iPage], 0, 0, 0, 0, screen->w, screen->h); |
99 | |
100 | show_video_bitmap(vPages[iPage]); |
101 | iPage = 1-iPage; |
102 | if(!(iMode & DOUBLE_BUF))bDraw = vPages[iPage]; |
103 | } |
104 | else if(iMode & DOUBLE_BUF){ |
105 | blit(bDbuf, screen, 0, 0, 0, 0, screen->w, screen->h); |
106 | } |
107 | |
108 | return GM_OK; |
109 | } |
110 | |
111 | int gfx_end(){ |
112 | if(iFatalError)return GM_FAIL; |
113 | |
114 | if(iMode & DOUBLE_BUF)destroy_bitmap(bDbuf); |
115 | |
116 | if(iMode & PAGE_FLIP){ |
117 | destroy_bitmap(vPages[0]); |
118 | destroy_bitmap(vPages[1]); |
119 | } |
120 | else if(iMode & TRIPLE_BUF){ |
121 | destroy_bitmap(vPages[0]); |
122 | destroy_bitmap(vPages[1]); |
123 | destroy_bitmap(vPages[2]); |
124 | } |
125 | |
126 | |
127 | return GM_OK; |
128 | } |
gfx.h:
//gfx.h extern BITMAP *bDraw; int gfx_setup(int mode, int x, int y, int cols); int gfx_start(); int gfx_update(); int gfx_end();
game_includes.h (this is game specific, now i just show the most simple case)
//game related includes #include <allegro.h> #include "global_defs.h" #include "gfx.h"
global_defs.h
//global definitions go here #define DOUBLE_BUF 1 #define TRIPLE_BUF 2 #define PAGE_FLIP 4 #define S_WINDOWED 8 #define S_FULL 16 //function returns #define GM_OK 0 #define GM_FAIL -1
---------------
As you can see there are 4 functions to call:
int gfx_setup(int mode, int x, int y, int cols);
This has to be called as a first thing, x,y set the resolution, cols the color depth, mode specifies if windowed or not and which screen update mode to use, parameters are a mix of (DOUBLE_BUF, TRIPLE_BUF, PAGE_FLIP, S_WINDOWED, S_FULL)
int gfx_start();
has to be called to actually start the graphic mode
int gfx_update();
must be called every game cycle
int gfx_end();
must be called before exiting, frees memory
The use is very simple, you do all the drawing to bDraw (regardless of the update mode you selected) and then just call gfx_update();
A very simple program(with no error checking) that moves a rectangle across the screen would look like:
1 | #include "game_includes.h" |
2 | |
3 | int main(){ |
4 | allegro_init(); |
5 | // |
6 | gfx_setup(PAGE_FLIP + DOUBLE_BUF + S_FULL, 640, 480, 16); |
7 | gfx_start(); |
8 | |
9 | install_keyboard(); |
10 | int k= 0; |
11 | while(!key[KEY_ESC]){ |
12 | clear_to_color(bDraw, makecol(10,10,10)); |
13 | rectfill(bDraw, 40 + k/2, 40, 120 + k/2, 120, makecol(190,0,0)); |
14 | k = (k+1)%800; |
15 | |
16 | gfx_update(); |
17 | } |
18 | gfx_end(); |
19 | |
20 | |
21 | return 0; |
22 | } |
23 | END_OF_MAIN() |
As you can see you can combine Page flipping with double buffering, usefull if you need to use some transparencies in your game (so do not have to read from video memory)
It should work correctly and anyone can use but what i'd like are some critics, mainly about things that should/could be done in a cleaner and/or more efficient way. Thanks.
[EDIT]Attached a working example with source and binary (4.2 dll needed)
Looks ok, I guess, but have you looked at Chris Barry's screen update mechanism (which is Allegro 4.3's screen update mechanism, basically)?
I knew he had done something similar but i wanted to make something on my own, so i didn't check his code
It's ok, altough it's a bit limited, but I guess you just started working on it.
So far I have two things to say:
gfx_setup() doesn't do enough checks, passing, i.e., 0 as second argument made the program crash
I think your framework should hide calls like allegro_init() and install_keyboard()
That's it