I was digging through some old code and found this by Elias Pschernig from back in 1999. I only really had to change 1 line of code for this to be up to date with Allegro 4 (the textprintf line).
I just thought that this was a nice little gem that shows how to code large 2D tile scrolling maps for anyone looking for help in this area. This does it all, creates it's own bitmaps for the example, uses keyboard or mouse and has a really large map.
Hope this helps someone, I hate to see this kind of thing go to waste, it really helped me understand how to do it back then. (note: I doubt that Elias' email is still at geocities, but I left it in for kicks
)
Edit: Oh yes, I also changed the mouse code so that when you press the left mouse button it acts more like you are dragging the map around (it was the opposite before). So now with the left mouse button clicked the map can be "dragged", which is kind of a kewl effect.
Edit2: Changed the -1 in textprintf_ex to makecol(0,0,0)... oops.
(for background colour).
#SelectExpand
1/*
2// Elias Pschernig 1999
3*/
4
5/*
6// tile.c
7*/
8
9/*
10// displays a tile map
11*/
12
13/*
14// extreme speed increase can be achieved by
15// using hardware acceleration (vbeaf driver)
16// and replacing 'create_bitmap' with
17// 'create_video_bitmap' throughout the program
18//
19// speed increase will also result from using
20// rle_sprites for the tiles instead of bitmaps
21*/
22
23#include <allegro.h>
24#include <stdio.h>
25
26#define COLOR_BITS 16 // video mode
27
28#define NUM_OF_TILES 100 // possible different tiles
29
30#define MAP_WIDTH 100 // how big do you want the
31#define MAP_HEIGHT 100 // test map ?
32
33#define TILE_WIDTH 32 // how big is one (square) tile ?
34
35#define WIN_L 0
36#define WIN_T 0
37#define WIN_R 640
38#define WIN_B 359
39
40#define FPS 60
41// how many frames to do each second...
42// i don't really understand all the timer things
43// i guess there are better ways of keeping sync
44// between time and frames
45// i just set this FPS, then set 'starttime' and
46// keep the number of frames and the time in sync...
47
48int gametime
=0; // the application timer
49void gametimer
() {
50 gametime
++;
51}
52int starttime
; // starttime
53int pframes,gframes
; // counts the different frames
54int second_ago_gframetime
;// used to calculate the fps
55int second_ago_gframes
;
56int fps
; // this are the grafix frames
57 // the process frames always run
58 // as defined in FPS
59
60BITMAP *tile
[NUM_OF_TILES
]; // this is the tiles
61BITMAP *map
=0; // the map
62int scrollx
=0,scrolly
=0; // the pixel position of upper left
63 // screen corner inside map
64
65// load one single tile
66// (normally you use datafiles)
67void loadtile
(int n
) {
68 tile
[n
]=create_video_bitmap(TILE_WIDTH,TILE_WIDTH
);
69 switch(n
) {
70 default:
clear_to_color(tile
[n
],
makecol(0,
0,
0)); break;
71 case 1:
72 clear_to_color(tile
[n
],
makecol(255,
0,
0));
73 circlefill(
74 tile
[n
],
75 TILE_WIDTH
/2,
76 TILE_WIDTH
/2,
77 TILE_WIDTH
/2,
78 makecol(255,
255,
0));
79 break;
80 case 2:
81 clear_to_color(tile
[n
],
makecol(255,
255,
0));
82 triangle(
83 tile
[n
],
84 TILE_WIDTH
/2,
0,
85 0,TILE_WIDTH-1,
86 TILE_WIDTH-1,TILE_WIDTH-1,
87 makecol(255,
0,
0));
88 break;
89 }
90}
91
92// load all the tiles
93// (normally this is already done by loading datafile)
94void loadtiles
() {
95 int n
;
96 for(n
=0;n
<NUM_OF_TILES
;n
++) {
97 loadtile
(n
);
98 }
99}
100
101// load the map
102// (normally datafile...)
103void loadmap
() {
104 int x,y
;
105 map
=create_bitmap_ex(8,MAP_WIDTH,MAP_HEIGHT
);
106 clear_to_color(map,
0);
107
108 for(y
=0;y
<MAP_HEIGHT
;y
++) {
109 for(x
=0;x
<MAP_WIDTH
;x
++) {
110 int r
=rand()%
4;
111 if(r
==1) putpixel(map,x,y,
1);
112 if(r
==2) putpixel(map,x,y,
2);
113 }
114 }
115}
116
117// display part of the tilemap,
118// starting at scrollx, scrolly as
119// upper left corner and filling
120// the parameter bitmap 'screen'
121// screen in most cases will be
122// a subbitmap of the screen or
123// of a doublebuffer
124
125void displaymap
(BITMAP *screen) {
126 int screenx,screeny
;
127 int mapx,mapy
;
128 int screenleft,mapleft
;
129
130 mapleft
=scrollx
/TILE_WIDTH
;
131 mapy
=scrolly
/TILE_WIDTH
;
132 screenleft
=mapleft
*TILE_WIDTH-scrollx
;
133 screeny
=mapy
*TILE_WIDTH-scrolly
;
134
135 while(screeny
<screen->h
) {
136 mapx
=mapleft
;
137 screenx
=screenleft
;
138 while(screenx
<screen->w
) {
139
140 {int t
=getpixel(map,mapx,mapy
);
141 if(t>
=0)
142 blit(tile
[t
],
screen,
0,
0,screenx,screeny,TILE_WIDTH,TILE_WIDTH
);
143 }
144
145 mapx
++;
146 screenx
+=TILE_WIDTH
;
147 }
148 mapy
++;
149 screeny
+=TILE_WIDTH
;
150 }
151}
152
153// do all sort of things that need to run at
154// a constant time, like user input,
155// processing of objects...
156void process
() {
157 int k
;
158 int xm,ym
;
159
160 while(keypressed()) {
161 k
=readkey();
162 }
163
164 if(key[KEY_LEFT
]) scrollx-
=4;
165 if(key[KEY_RIGHT
]) scrollx
+=4;
166 if(key[KEY_UP
]) scrolly-
=4;
167 if(key[KEY_DOWN
]) scrolly
+=4;
168
169
170 get_mouse_mickeys(&xm,
&ym
);
171 if(mouse_b) {
172 scrollx-
=xm
;
173 scrolly-
=ym
;
174 }
175
176
177 if (mouse_x >= WIN_R-1
) scrollx
+=8;
178 if (mouse_x <= WIN_L
+1) scrollx-
=8;
179 if (mouse_y >= SCREEN_H-1
) scrolly
+=8;
180 if (mouse_y <= WIN_T
) scrolly-
=8;
181
182 if(scrollx
<0) scrollx
=0;
183 if(scrolly
<0) scrolly
=0;
184 if(scrollx>MAP_WIDTH
*TILE_WIDTH-
(WIN_R-WIN_L
+1))
185 scrollx
=MAP_WIDTH
*TILE_WIDTH-
(WIN_R-WIN_L
+1);
186 if(scrolly>MAP_HEIGHT
*TILE_WIDTH-
(WIN_B-WIN_T
+1))
187 scrolly
=MAP_HEIGHT
*TILE_WIDTH-
(WIN_B-WIN_T
+1);
188
189}
190
191void grafix
(BITMAP *myscreen
) {
192 BITMAP *win
;
193 win
=create_sub_bitmap(myscreen,
194 WIN_L,WIN_T,WIN_R,WIN_B
);
195
196 displaymap
(win
);
197
198 destroy_bitmap(win
);
199
200 textprintf_ex(screen,
font,
0,
360,
makecol(255,
255,
255),
makecol(0,
0,
0),
"fps %2d ",fps
);
201}
202
203
204// the main program
205int main
() {
206 BITMAP *double_buffer
;
207
208 allegro_init();
209 install_keyboard();
210 install_timer();
211 install_int(gametimer,
10);
212 install_mouse();
213
214 set_color_depth(COLOR_BITS
);
215 {int s
=set_gfx_mode(GFX_AUTODETECT,
640,
480,
0,
0);
216 if(s
) {
217 printf("Allegro couldnt set %d bit mode\n",COLOR_BITS
);
218 printf("recompile and use another setting\n");
219 printf("sorry\n");
220 return 1;
221 }
222 }
223 double_buffer
= create_video_bitmap(WIN_R-WIN_L, WIN_B-WIN_T
);
224 clear
(double_buffer
);
225
226 loadtiles
();
227 loadmap
();
228
229 {
230 starttime
=second_ago_gframetime
=gametime
;
231 pframes
=gframes
=second_ago_gframes
=0;
232 while(!key[KEY_ESC
]) {
233
234 if(pframes
*100<(gametime-starttime
)*FPS
) {
235 process
();
236 pframes
++;
237 } else {
238
239// don't pass screen in a real program here, but
240// use a doublebuffer or pageflipping or something
241// to avoid bad display quality
242
243 grafix
(double_buffer
);
244 vsync();
245 show_mouse(double_buffer
);
246 blit(double_buffer,
screen,
0,
0, WIN_L, WIN_T, WIN_R-WIN_L, WIN_B-WIN_T
);
247 show_mouse(screen);
248 gframes
++;
249 }
250
251 // fps->how many grafix frames in last second ?
252 if(gametime-second_ago_gframetime>
=100) {
253 second_ago_gframetime
+=100;
254 fps
=gframes-second_ago_gframes
;
255 second_ago_gframes
=gframes
;
256 }
257
258 }
259 }
260
261 destroy_bitmap(double_buffer
);
262
263 printf("email: eliaspschernig@geocities.com? LOL\n");
264 return 0;
265}
266
267END_OF_MAIN();