1 /*
2 * file image.c - maige filenames and sizes
3 *
4 * $Id: image.c,v 1.10 2006/02/09 21:21:24 fzago Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "xblast.h"
25
26 /*
27 * local types
28 */
29 typedef struct _shape_list ShapeList;
30 struct _shape_list
31 {
32 char *name;
33 XBBool valid;
34 ShapeList *next;
35 };
36
37 /*
38 * global variables
39 */
40
41 /* search paths */
42 #ifdef WMS
43 #define GAME_DATADIR "."
44 #endif
45
46 const char *imgPathBlock = GAME_DATADIR "/image/block";
47 const char *imgPathExpl = GAME_DATADIR "/image/explosion";
48 const char *imgPathMisc = GAME_DATADIR "/image/misc";
49 const char *imgPathScore = GAME_DATADIR "/image/score";
50 const char *imgPathSprite = GAME_DATADIR "/image/sprite";
51
52 /* background pixmaps */
53 const char *imgFileTitle = "title";
54 const char *imgFileTextBg = "text_bg";
55 const char *imgFileTextFg = "text_fg";
56 /* score board leds */
57 const char *imgFileScoreLed[] = {
58 "led_off",
59 "led_on",
60 };
61
62 /* score board tiles */
63 const char *imgFileScoreTile[] = {
64 "tile_void",
65 "text_left",
66 "text_middle",
67 "text_right",
68 };
69
70 /* score player stats */
71 const char *imgFileScorePlayer[] = {
72 "player_dead",
73 "player_sick",
74 "player",
75 "player_abort",
76 "player_sick_abort",
77
78 };
79
80 /* bomb images */
81 const char *imgFileBomb[MAX_BOMBS][MAX_BOMB_ANIME] = {
82 {
83 "bomb_0", "bomb_1", "bomb_2", "bomb_3", "bomb_4", "bomb_5", "bomb_6", "bomb_7",
84 "bomb_8", "bomb_9", "bomb_10", "bomb_11", "bomb_12", "bomb_13", "bomb_14", "bomb_15",
85 "bomb_x",
86 },
87 {
88 "mini_0", "mini_1", "mini_2", "mini_3", "mini_4", "mini_5", "mini_6", "mini_7",
89 "mini_8", "mini_9", "mini_10", "mini_11", "mini_12", "mini_13", "mini_14", "mini_15",
90 "mini_x",
91 },
92 };
93
94 /* explosions image */
95 const char *imgFileExpl[MAX_EXPLOSION] = {
96 "expl00",
97 "expl01",
98 "expl02",
99 "expl03",
100 "expl04",
101 "expl05",
102 "expl06",
103 "expl07",
104 "expl08",
105 "expl09",
106 "expl0a",
107 "expl0b",
108 "expl0c",
109 "expl0d",
110 "expl0e",
111 "expl0f",
112 };
113
114 /*
115 * offset and size data for sprites
116 */
117 const BMRectangle imgRectSprite[MAX_ANIME] = {
118 /* down */
119 {0, 3 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
120 {0, 3 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
121 {0, 3 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
122 {0, 3 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
123 {0, 3 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
124 /* up */
125 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
126 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
127 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
128 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
129 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
130 /* right */
131 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
132 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
133 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
134 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
135 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
136 /* left */
137 {0, 4 * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
138 {0, 4 * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
139 {0, 4 * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
140 {0, 4 * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
141 {0, 4 * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
142 /* damaged */
143 {0, (4 - 1) * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
144 {1 * BASE_X, 6 * BASE_Y, 8 * BASE_X, 10 * BASE_Y},
145 {0, (7 + 1) * BASE_Y, 8 * BASE_X, 8 * BASE_Y},
146 {-1 * BASE_X, 6 * BASE_Y, 8 * BASE_X, 10 * BASE_Y},
147 /* looser */
148 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
149 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
150 {0, 4 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
151 /* winner */
152 {0, 2 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
153 {0, 2 * BASE_Y, 8 * BASE_X, 13 * BASE_Y},
154 {0, 3 * BASE_Y, 8 * BASE_X, 12 * BASE_Y},
155 /* big winner */
156 {-4 * BASE_X, (-8 + 5) * BASE_Y, 16 * BASE_X, 25 * BASE_Y},
157 /* skeleton */
158 {0, 5 * BASE_Y, 8 * BASE_X, 10 * BASE_Y},
159 {0, 5 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
160 {0, 5 * BASE_Y, 8 * BASE_X, 9 * BASE_Y},
161 {0, 5 * BASE_Y, 8 * BASE_X, 11 * BASE_Y},
162 /* morphed eyes */
163 {0, 7 * BASE_Y, 8 * BASE_X, 8 * BASE_Y},
164 {0, 5 * BASE_Y, 8 * BASE_X, 10 * BASE_Y}, /* zombie */
165 };
166
167 /* epm file formats */
168 static const char *imgFileSpriteEpm[MAX_ANIME_EPM] = {
169 /* looking down */
170 "%s_D_S", "%s_D_0", "%s_D_1", "%s_D_2", "%s_D_3",
171 /* looking up */
172 "%s_U_S", "%s_U_0", "%s_U_1", "%s_U_2", "%s_U_3",
173 /* looking right */
174 "%s_R_S", "%s_R_0", "%s_R_1", "%s_R_2", "%s_R_3",
175 /* looking left */
176 "%s_L_S", "%s_L_0", "%s_L_1", "%s_L_2", "%s_L_3",
177 /* damaged player */
178 "%s_DD", "%s_DL", "%s_DU", "%s_DR",
179 /* loosing player */
180 "%s_L", "%s_L1", "%s_L2",
181 /* winning player */
182 "%s_W", "%s_W2", "%s_W3",
183 /* big winning player */
184 "%s_B",
185 };
186
187 const char *imgFileSpritePpm[MAX_ANIME_PPM] = {
188 /* skeleton */
189 "skel_D", "skel_L", "skel_U", "skel_R",
190 /* morphed player (eyes only) */
191 "morph", "zombie",
192 };
193
194 /* icon sprites */
195 const char *imgFileIcon[MAX_ICON_SPRITES] = {
196 /* 6 color sprites */
197 "icon_color", "icon_color", "icon_color", "icon_color", "icon_color", "icon_color",
198 /* other icons */
199 "icon_led_on", "icon_led_off", "icon_abort", "icon_default",
200 /* team icons */
201 "icon_led_off", "icon_led_on", "icon_led_on", "icon_led_on",
202 };
203 const BMRectangle imgRectIcon[MAX_ICON_SPRITES] = {
204 /* 6 color sprite */
205 {BASE_X, BASE_Y, 6 * BASE_X, 6 * BASE_Y,},
206 {BASE_X, BASE_Y, 6 * BASE_X, 6 * BASE_Y,},
207 {BASE_X, BASE_Y, 6 * BASE_X, 6 * BASE_Y,},
208 {BASE_X, BASE_Y, 6 * BASE_X, 6 * BASE_Y,},
209 {BASE_X, BASE_Y, 6 * BASE_X, 6 * BASE_Y,},
210 {BASE_X, BASE_Y, 6 * BASE_X, 6 * BASE_Y,},
211 /* other icons */
212 {5 * BASE_X / 2, 3 * BASE_Y, 3 * BASE_X, 3 * BASE_Y,},
213 {5 * BASE_X / 2, 3 * BASE_Y, 3 * BASE_X, 3 * BASE_Y,},
214 {BASE_X, 2 * BASE_Y, 6 * BASE_X, 5 * BASE_Y,},
215 {BASE_X, 2 * BASE_Y, 6 * BASE_X, 5 * BASE_Y,},
216 };
217
218 /*
219 * local variables
220 */
221
222 /* shapes */
223 static int numShapes = 0;
224 static XBAtom *shapeTable = NULL;
225
226 /*
227 * create list with possible shapes
228 */
229 static ShapeList *
CreateShapeList(const XBDir * epmList)230 CreateShapeList (const XBDir * epmList)
231 {
232 const char *s;
233 int len;
234 const XBDir *ptr;
235 ShapeList *item;
236 ShapeList *list = NULL;
237
238 for (ptr = epmList; ptr != NULL; ptr = ptr->next) {
239 s = strstr (ptr->name, "_B");
240 if (NULL != s) {
241 len = s - ptr->name;
242 /* found big player sprite */
243 item = calloc (1, sizeof (ShapeList));
244 assert (item != NULL);
245 item->valid = XBTrue;
246 item->name = calloc (len + 1, sizeof (char));
247 strncpy (item->name, ptr->name, len);
248 /* add to list */
249 item->next = list;
250 list = item;
251 }
252 }
253 return list;
254 } /* CreateShapeList */
255
256 /*
257 * check for invalid items in shape list
258 */
259 static void
CheckShapeList(ShapeList * list,const XBDir * epmList)260 CheckShapeList (ShapeList * list, const XBDir * epmList)
261 {
262 int i;
263 const XBDir *ptr;
264 ShapeList *item;
265 char fileName[80];
266 XBBool valid;
267
268 for (item = list; item != NULL; item = item->next) {
269 for (i = 0; i < MAX_ANIME_EPM; i++) {
270 sprintf (fileName, imgFileSpriteEpm[i], item->name);
271 valid = XBFalse;
272 for (ptr = epmList; ptr != NULL; ptr = ptr->next) {
273 if (0 == strcmp (fileName, ptr->name)) {
274 valid = XBTrue;
275 break;
276 }
277 }
278 if (!valid) {
279 item->valid = XBFalse;
280 break;
281 }
282 }
283 }
284 } /* CheckShapeList */
285
286 /*
287 *
288 */
289 static XBAtom *
CreateShapeArray(const ShapeList * list,int * pNum)290 CreateShapeArray (const ShapeList * list, int *pNum)
291 {
292 int i;
293 XBAtom *table;
294 const ShapeList *item;
295
296 assert (pNum != NULL);
297
298 *pNum = 0;
299 for (item = list; item != NULL; item = item->next) {
300 if (item->valid) {
301 *pNum = *pNum + 1;
302 }
303 }
304 if (0 == *pNum) {
305 return NULL;
306 }
307 table = calloc (*pNum, sizeof (XBAtom));
308 assert (table != NULL);
309 i = 0;
310 #ifdef DEBUG
311 fprintf (stderr, "found shape:");
312 #endif
313 for (item = list; item != NULL; item = item->next) {
314 if (item->valid) {
315 #ifdef DEBUG
316 fputc (' ', stderr);
317 fputs (item->name, stderr);
318 #endif
319 table[i] = GUI_StringToAtom (item->name);
320 }
321 i++;
322 }
323 #ifdef DEBUG
324 fputc ('\n', stderr);
325 #endif
326 return table;
327 } /* CreateShapeArray */
328
329 /*
330 * Delete shape list
331 */
332 static void
DeleteShapeList(ShapeList * list)333 DeleteShapeList (ShapeList * list)
334 {
335 ShapeList *item, *itemNext;
336
337 for (item = list; item != NULL; item = itemNext) {
338 itemNext = item->next;
339 free (item->name);
340 free (item);
341 }
342 } /* DeleteShapeList */
343
344 /*
345 * inititalize valid player shapes
346 */
347 static XBAtom *
InitShapes(int * pNum)348 InitShapes (int *pNum)
349 {
350 XBDir *epmList;
351 XBDir *pbmList;
352 ShapeList *list = NULL;
353 XBAtom *table;
354 #ifdef DEBUG
355 Dbg_StartClock ();
356 #endif
357
358 epmList = CreateFileList (GAME_DATADIR "/image/sprite", "epm", XBFalse);
359 pbmList = CreateFileList (GAME_DATADIR "/image/sprite", "pbm", XBFalse);
360 /* find possible shapes */
361 list = CreateShapeList (epmList);
362 /* check them */
363 CheckShapeList (list, epmList);
364 CheckShapeList (list, pbmList);
365 /* create array and delete list */
366 table = CreateShapeArray (list, pNum);
367 /* delete list */
368 DeleteShapeList (list);
369 /* delete file list */
370 DeleteFileList (epmList);
371 DeleteFileList (pbmList);
372 #ifdef DEBUG
373 fprintf (stderr, "load shapes: %lu msec\n", Dbg_FinishClock ());
374 #endif
375 return table;
376 } /* InitShapes */
377
378 /*
379 * convert shape name to existing shape
380 */
381 static const char *
ShapeToName(XBAtom shape)382 ShapeToName (XBAtom shape)
383 {
384 int i;
385
386 if (NULL == shapeTable) {
387 shapeTable = InitShapes (&numShapes);
388 }
389 assert (shapeTable != NULL);
390 for (i = 0; i < numShapes; i++) {
391 if (shape == shapeTable[i]) {
392 return GUI_AtomToString (shape);
393 }
394 }
395 return "normal";
396 } /* NameToShape */
397
398 /*
399 * create name for sprite
400 */
401 const char *
ImgFileSpriteEpm(XBAtom shape,int anime)402 ImgFileSpriteEpm (XBAtom shape, int anime)
403 {
404 static char tmp[80];
405
406 assert (shape != ATOM_INVALID);
407 assert (anime >= 0);
408 assert (anime < MAX_ANIME_EPM);
409 sprintf (tmp, imgFileSpriteEpm[anime], ShapeToName (shape));
410 return tmp;
411 } /* ImgFileSpriteEpm */
412
413 /*
414 * list all shapes
415 */
416 const XBAtom *
GetShapeList(int * pNum)417 GetShapeList (int *pNum)
418 {
419 if (NULL == shapeTable) {
420 shapeTable = InitShapes (&numShapes);
421 }
422 assert (shapeTable != NULL);
423 *pNum = numShapes;
424 return shapeTable;
425 } /* GetShapeList */
426
427 /*
428 * delete shape list
429 */
430 void
ClearShapeList(void)431 ClearShapeList (void)
432 {
433 if (NULL != shapeTable) {
434 free (shapeTable);
435 shapeTable = NULL;
436 numShapes = 0;
437 }
438 } /* ClearShapeList */
439
440 /*
441 * end of file x11c_data.c
442 */
443