Hello Everyone, I'm new here. I'm currently programming a program for a College assignment and I've run into a problem - they program isn't responding the the user input. Everything else is working fine, but when the user presses a key, nothing happens. I think this has got something to do with the order that I call various functions (e.g. moveplayer() and setupgame()) in my main() function, but I'm not really too sure. If anyone could take a look at my code and make any suggestions it would be very much appreciated. Thanks.
1 | #include <allegro.h> |
2 | |
3 | BITMAP* box; |
4 | BITMAP* buffer; |
5 | |
6 | int x = 15; |
7 | int y = 11; |
8 | |
9 | int tempX = 15; |
10 | int tempY = 11; |
11 | |
12 | int boxes; |
13 | |
14 | int map[24][32] = {}; //Removed map data |
15 | |
16 | int objMap[24][32] = {}; //Removed object map data |
17 | |
18 | void setupGame(){ |
19 | |
20 | buffer = create_bitmap( 640, 480); |
21 | box = load_bitmap( "coin.bmp", NULL); |
22 | boxes = 1; |
23 | |
24 | for (int i = 0; i <= 24; i++){ |
25 | |
26 | for( int t = 0; t <= 32; t++){ |
27 | |
28 | if( map<i>[t] == 1) rectfill( buffer, t * 20, i * 20, (t + 1) * 20, (i + 1) * 20, makecol( 128, 255, 255)); |
29 | else if( map<i>[t] == 2) rectfill( buffer, t * 20, i * 20, (t + 1) * 20, (i + 1) * 20, makecol( 255, 128, 0)); |
30 | else if( map<i>[t] == 3) rectfill( buffer, t * 20, i * 20, (t + 1) * 20, (i + 1) * 20, makecol( 255, 0, 0)); |
31 | else if( map<i>[t] == 4) rectfill( buffer, t * 20, i * 20, (t + 1) * 20, (i + 1) * 20, makecol( 0, 0, 0)); |
32 | |
33 | } |
34 | |
35 | } |
36 | |
37 | for (int i = 0; i <= 24; i++){ |
38 | |
39 | for( int t = 0; t <= 32; t++){ |
40 | |
41 | if( objMap<i>[t] == 100) circlefill( buffer, (t * 20) + 10, (i * 20) + 10, 10, makecol( 255, 255, 0)); |
42 | else if( objMap<i>[t] == 101) draw_sprite( buffer, box, t * 20, i * 20); |
43 | |
44 | } |
45 | |
46 | } |
47 | |
48 | draw_sprite( screen, buffer, 0, 0); |
49 | |
50 | } |
51 | |
52 | void movePlayer(){ |
53 | |
54 | tempX = x; |
55 | tempY = y; |
56 | |
57 | if ( key[KEY_UP] && map[y - 1][x] == 3){ |
58 | |
59 | if( objMap[y - 1][x] = 101){ |
60 | --y; |
61 | } else if( objMap[y - 1][x] == 101 && map[y - 2][x] == 3 || objMap[y - 1][x] == 101 && map[y - 2][x] == 4){ |
62 | |
63 | if (map[y - 2][x] == 4) --boxes; |
64 | |
65 | objMap[y - 2][x] = 101; |
66 | |
67 | --y; |
68 | } |
69 | |
70 | } else if ( key[KEY_DOWN] && map[y + 1][x] == 3){ |
71 | |
72 | if( objMap[y + 1][x] = 101){ |
73 | ++y; |
74 | } else if( objMap[y + 1][x] == 101 && map[y + 2][x] == 3 || objMap[y + 1][x] == 101 && map[y + 2][x] == 4){ |
75 | |
76 | if (map[y + 2][x] == 4) --boxes; |
77 | |
78 | objMap[y + 2][x] = 101; |
79 | |
80 | ++y; |
81 | } |
82 | |
83 | } else if ( key[KEY_RIGHT] && map[y][x + 1] == 3){ |
84 | |
85 | if( objMap[y][x + 1] = 101){ |
86 | ++x; |
87 | } else if( objMap[y][x + 1] == 101 && map[y][x + 2] == 3 || objMap[y][x + 1] == 101 && map[y][x + 2] == 4){ |
88 | |
89 | if (map[y][x + 2] == 4) --boxes; |
90 | |
91 | objMap[y][x + 2] = 101; |
92 | |
93 | ++x; |
94 | } |
95 | |
96 | } else if ( key[KEY_LEFT] && map[y][x - 1] == 3){ |
97 | |
98 | if( objMap[y][x - 1] = 101){ |
99 | --x; |
100 | } else if( objMap[y][x - 1] == 101 && map[y][x - 2] == 3 || objMap[y][x - 1] == 101 && map[y][x - 2] == 4){ |
101 | |
102 | if (map[y][x - 2] == 4) --boxes; |
103 | |
104 | objMap[y][x - 2] = 101; |
105 | |
106 | --x; |
107 | } |
108 | |
109 | } |
110 | |
111 | |
112 | acquire_screen(); |
113 | |
114 | rectfill( buffer, tempX * 20, tempY * 20, (tempX + 1) * 20, (tempY + 1) * 20, makecol( 255, 0, 0)); |
115 | |
116 | circlefill( buffer, (x * 20) + 10, (y * 20) + 10, 10, makecol( 255, 255, 0)); |
117 | |
118 | draw_sprite( screen, buffer, 0, 0); |
119 | release_screen(); |
120 | |
121 | objMap[tempY][tempX] = 0; |
122 | objMap[y][x] = 101; |
123 | |
124 | if ( boxes) |
125 | { |
126 | textout_ex( screen, font, "Copyright Bede Morrissey, 2007", 5, 466, makecol(0, 0, 0), makecol(255, 128, 0)); |
127 | |
128 | } |
129 | |
130 | |
131 | rest(100); |
132 | } |
133 | |
134 | volatile int speed_counter = 0; |
135 | |
136 | void increment_speed_counter() |
137 | { |
138 | speed_counter++; |
139 | } |
140 | |
141 | int main(){ |
142 | |
143 | allegro_init(); |
144 | install_keyboard(); |
145 | set_color_depth(16); |
146 | set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0); |
147 | |
148 | setupGame(); |
149 | |
150 | BITMAP *bmpBackBuffer = create_bitmap(640,480); |
151 | install_int_ex(increment_speed_counter, BPS_TO_TIMER(1)); //should this be 1 or 60? |
152 | int seccount = 0; |
153 | while (!key[KEY_ESC]) |
154 | { |
155 | while (speed_counter > 0) |
156 | { |
157 | seccount++; |
158 | speed_counter--; |
159 | } |
160 | clear(bmpBackBuffer); |
161 | textprintf_ex(bmpBackBuffer, font, 5, 5, makecol(255, 255, 255), 1, "Secs: %d", seccount); |
162 | blit(bmpBackBuffer,screen,0,0,0,0,70,20); |
163 | } |
164 | |
165 | while( !key[KEY_ESC]) |
166 | { |
167 | movePlayer(); |
168 | } |
169 | |
170 | return 0; |
171 | } |
172 | END_OF_MAIN(); |
movePlayer() will never be called. When you exit the first loop, key[ESC] will still be set, and the second loop will be skipped. That's your main problem. As soon as you've fixed that, however, you'll discover why mixing logic and drawing is a bad idea...
install_int_ex(increment_speed_counter, BPS_TO_TIMER(1)); //should this be 1 or 60?
That should be however many logic updates you want per second.
There are more errors and bad practices in there (like not destroying bitmaps you create), but that's as much as I'm willing to correct until the first two items are fixed: move movePlayer() into the actual timed loop, and separate your logic and drawing (see the FAQ for a hint on how it should look) and I'll tell you the rest.
Thank you very much, gnolam. I have moved my movePlayer() function into the main loop and it now looks like this:
1 | int main() |
2 | { |
3 | allegro_init(); |
4 | install_keyboard(); |
5 | set_color_depth(16); |
6 | set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0); |
7 | |
8 | setupGame(); |
9 | |
10 | BITMAP *bmpBackBuffer = create_bitmap(640,480); |
11 | install_int_ex(increment_speed_counter, BPS_TO_TIMER(1)); //should this be 1 or 60? |
12 | int seccount = 0; |
13 | while (!key[KEY_ESC]) |
14 | { |
15 | while (speed_counter > 0) |
16 | { |
17 | movePlayer(); |
18 | seccount++; |
19 | speed_counter--; |
20 | } |
21 | clear(bmpBackBuffer); |
22 | textprintf_ex(bmpBackBuffer, font, 5, 5, makecol(255, 255, 255), 1, "Secs: %d", seccount); |
23 | blit(bmpBackBuffer,screen,0,0,0,0,70,20); |
24 | } |
25 | |
26 | return 0; |
27 | } |
28 | END_OF_MAIN(); |
My keyboard now works and everything else. However, the sprite will only move once every second. So I changed the install_int_ex(increment_speed_counter, BPS_TO_TIMER(1)) value from 1 to a higher number (10 and 60). Now the input is working perfectly correctly, but the timer in the top corner is now not displayed at all! Do you have any idea what could be causing this and how to fix it?
Also, I realize that my code really is horrible. At this stage though, all I am trying to do is to get something actually working (undoubtedly terrible practice I'm sure) and go back and fix it up later. Or perhaps though, it would be better to start from scratch again and actually do a decent job of my code this time?
Once again, thanks for your help.
You're drawing your buffer bitmap too many times per frame. You only ever want to draw it to the screen once per loop. The way your code is above, to achieve this, simply remove all your calls to draw_sprite(), acquire_screen() and release_screen(), make your blit call at the end of the loop encompass the entire screen (640 x 480) and you should be fine. Also, move your clear command to the top of your loop before you process speed_counter.
--- Kris Asick (Gemini)
--- http://www.pixelships.com
Thank you for your help, but I'm not sure that I fully understand. Is this what you were meaning?
1 | int main() |
2 | { |
3 | allegro_init(); |
4 | install_keyboard(); |
5 | set_color_depth(16); |
6 | set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0); |
7 | |
8 | setupGame(); |
9 | |
10 | BITMAP *bmpBackBuffer = create_bitmap(640,480); |
11 | install_int_ex(increment_speed_counter, BPS_TO_TIMER(1)); //should this be 1 or 60? |
12 | int seccount = 0; |
13 | while (!key[KEY_ESC]) |
14 | { |
15 | clear(bmpBackBuffer); |
16 | while (speed_counter > 0) |
17 | { |
18 | movePlayer(); |
19 | seccount++; |
20 | speed_counter--; |
21 | } |
22 | textprintf_ex(bmpBackBuffer, font, 5, 5, makecol(255, 255, 255), 1, "Secs: %d", seccount); |
23 | blit(bmpBackBuffer,screen,0,0,0,0,640,480); |
24 | } |
25 | |
26 | return 0; |
27 | } |
28 | END_OF_MAIN(); |
The above code makes the screen flash once every second between a black screen with the counter on it, and the normal game screen. Everything else works but is their any way that I can stop this flashing? Thanks.
No. Keep the clear(bmpBackBuffer) where it was.
Your movePlayer() should only do that - move the player. It should have no draw_sprite() or blit() calls in it at all. This is so that you separate your game logic from your drawing.
You should have another function drawPlayer(BITMAP*) that draws the player to the screen. You want to call this function after you've cleared the buffer.
1 | ... |
2 | while (!key[KEY_ESC]) |
3 | { |
4 | while (speed_counter > 0) |
5 | { |
6 | movePlayer(); |
7 | seccount++; |
8 | speed_counter--; |
9 | } |
10 | clear(bmpBackBuffer); |
11 | drawPlayer(bmpBackBuffer); |
12 | textprintf_ex(bmpBackBuffer, font, 5, 5, makecol(255, 255, 255), 1, "Secs: %d", seccount); |
13 | blit(bmpBackBuffer,screen,0,0,0,0,640,480); |
14 | } |
15 | ... |
I just noticed you have TWO buffers...
You only need one buffer, and all drawing should happen on it. When you're finished drawing everything, you simply blit the entire buffer to the screen.
Thus to fix your code as it is without any major changes, change all references to "buffer" to "bmpBackBuffer".
And HardTranceFan's advice is good, you should separate your rendering code from everything else so that it can all be grouped together, but until you do, leave the clear(bmpBackBuffer) command in its new spot. Worry about making it work first, then separate the rendering from everything else.
--- Kris Asick (Gemini)
--- http://www.pixelships.com
Thank you all for all your assistance. Kris Asick, I think the having two buffers was causing a lot of the problems, as it is now working much better. Now I need to go about fixing up my code :-) - thank you for your ideas on how to begin this.
Thank you again.