1 /*
2     XorGramana Copyright 2009 James W. Morris, james@jwm-art.net
3 
4     This file is part of XorGramana.
5 
6     XorGramana is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     XorGramana is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with XorGramana.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "icons.h"
20 #include "gfx.h"
21 
22 struct xg_icon icon_details[ICON_XXX]=
23 {
24     { "floor",      ' ' },
25     { "wall",       '#' },
26     { "h-field",    '-' },
27     { "v-field",    '|' },
28     { "hash",       '0' },
29     { "star",       '1' },
30     { "map",        'M' },
31     { "teleport",   '+' },
32     { "exit",       'E' },
33     { "mask",       '@' },
34     { "dot",        '.' },
35     { "blank",      '_' },
36     { "a", 'a' },
37     { "b", 'b' },
38     { "c", 'c' },
39     { "d", 'd' },
40     { "e", 'e' },
41     { "f", 'f' },
42     { "g", 'g' },
43     { "h", 'h' },
44     { "i", 'i' },
45     { "j", 'j' },
46     { "k", 'k' },
47     { "l", 'l' },
48     { "m", 'm' },
49     { "n", 'n' },
50     { "o", 'o' },
51     { "p", 'p' },
52     { "q", 'q' },
53     { "r", 'r' },
54     { "s", 's' },
55     { "t", 't' },
56     { "u", 'u' },
57     { "v", 'v' },
58     { "w", 'w' },
59     { "x", 'x' },
60     { "y", 'y' },
61     { "z", 'z' },
62     { "0", '0' },
63     { "1", '1' },
64     { "2", '2' },
65     { "3", '3' },
66     { "4", '4' },
67     { "5", '5' },
68     { "6", '6' },
69     { "7", '7' },
70     { "8", '8' },
71     { "9", '9' },
72 /***** THE FOLLOWING ARE NOT SPECIFIABLE IN MAP FILE *****/
73 /***** (hence '\0' as map character specifier)       *****/
74     { "exit_open",  '\0'},
75     { "space",      '\0'}, /* opaque */
76     { "space",      '\0'}, /* transparent */
77     { "explode01",  '\0'},
78     { "explode02",  '\0'},
79     { "explode03",  '\0'},
80     { "explode04",  '\0'},
81     { "explode05",  '\0'},
82     { "line-l",     '\0'},
83     { "line-r",     '\0'},
84     { "line-t",     '\0'},
85     { "line-b",     '\0'},
86     { "line-tl",    '\0'},
87     { "line-tr",    '\0'},
88     { "line-bl",    '\0'},
89     { "line-br",    '\0'}
90 };
91 
92 char* wall_names[WALL_XXX]=
93 {
94     "wall1",
95     "wall2",
96     "wall3",
97     "wall4",
98     "wall5",
99     "wall6",
100     "wall7",
101     "wall4",
102     "wall1",
103     "wall3",
104     "wall2",
105     "wall5",
106     "wall3",
107     "wall2",
108     "wall7",
109     "wall6",
110 };
111 
112 char* floor_names[WALL_XXX]=
113 {
114     "floor1",
115     "floor2",
116     "floor3",
117     "floor4",
118     "floor5",
119     "floor6",
120     "floor7",
121     "floor1",
122     "floor2",
123     "floor7",
124     "floor3",
125     "floor5",
126     "floor6",
127     "floor4",
128     "floor2",
129     "floor1",
130 };
131 
132 char* edge_names[WALL_XXX][EDGE_XXX]=
133 {
134     {   "edge1_t",  "edge1_b",  "edge1_l",  "edge1_r"   },
135     {   "edge2_t",  "edge2_b",  "edge2_l",  "edge2_r"   },
136     {   "edge3_t",  "edge3_b",  "edge3_l",  "edge3_r"   },
137     {   "edge4_t",  "edge4_b",  "edge4_l",  "edge4_r"   },
138     {   "edge5_t",  "edge5_b",  "edge5_l",  "edge5_r"   },
139     {   "edge6_t",  "edge6_b",  "edge6_l",  "edge6_r"   },
140     {   "edge7_t",  "edge7_b",  "edge7_l",  "edge7_r"   },
141     {   "edge5_t",  "edge5_b",  "edge5_l",  "edge5_r"   },
142     {   "edge4_t",  "edge4_b",  "edge4_l",  "edge4_r"   },
143     {   "edge2_t",  "edge2_b",  "edge2_l",  "edge2_r"   },
144     {   "edge3_t",  "edge3_b",  "edge3_l",  "edge3_r"   },
145     {   "edge1_t",  "edge1_b",  "edge1_l",  "edge1_r"   },
146     {   "edge7_t",  "edge7_b",  "edge7_l",  "edge7_r"   },
147     {   "edge6_t",  "edge6_b",  "edge6_l",  "edge6_r"   },
148     {   "edge7_t",  "edge7_b",  "edge7_l",  "edge7_r"   },
149     {   "edge4_t",  "edge4_b",  "edge4_l",  "edge4_r"   },
150 };
151 
152 char* indicator_names[DIRIND_XXX]=
153 {
154     "grav_u","grav_d","grav_l","grav_r",
155     "push_u","push_d","push_l","push_r",
156     "hard_push_u","hard_push_d","hard_push_l","hard_push_r",
157     "explode_h","explode_v"
158 };
159 
160 SDL_Surface* walls[WALL_XXX]={0};
161 SDL_Surface* floors[WALL_XXX]={0};
162 SDL_Surface* hs_walls[WALL_XXX]={0};
163 SDL_Surface* hs_floors[WALL_XXX]={0};
164 SDL_Surface* wall_edges[WALL_XXX][EDGE_XXX]={{0}};
165 SDL_Surface* indicators[DIRIND_XXX]={0};
166 SDL_Surface* edged_walls[ICON_EDGE_TBLR-ICON_EDGE_T]={0};
167 
168 SDL_Surface* icons[ICON_XXX]={0};
169 SDL_Surface* hs_icons[ICON_XXX]={0};
170 SDL_Surface* icons_with_indicators[ICON_XXX]={0};
171 
172 ss_t current_wall_texture=-1;
173 enum ICON spc_icon=ICON_FLOOR;
174 
175 /* private functions */
176 SDL_Surface* icon_half_assed_size(SDL_Surface* s, bool transparent, int tr_r, int tr_g, int tr_b);
177 void generate_wall_edging(su_t wall);
178 
init_icons(void)179 void init_icons(void)
180 {
181     char buf[256];
182     int i;
183     #ifdef ICON_DEBUG
184     printf("Loading icons...\n");
185     #endif
186     for(i=ICON_WALL+1;i<ICON_LOADED_XXX;i++){
187         strcpy(buf,"/usr/local/share/xorgramana/GFX/");
188         strcat(buf,icon_details[i].fname);
189         strcat(buf,ICON_EXT);
190         switch(i){
191             /* opaque icons */
192             case ICON_FLOOR:
193             case ICON_EXIT_OPEN:
194             case ICON_LINE_L:
195             case ICON_LINE_R:
196             case ICON_LINE_T:
197             case ICON_LINE_B:
198             case ICON_LINE_TL:
199             case ICON_LINE_TR:
200             case ICON_LINE_BL:
201             case ICON_LINE_BR:
202             case ICON_SPACE_OPAQUE:
203                 icons[i]=load_image(buf,FALSE,0,0,0);
204                 hs_icons[i]=icon_half_assed_size(icons[i],FALSE,0,0,0);
205                 break;
206             default:
207                 /* icons with black as transparency */
208                 icons[i]=load_image(buf,TRUE,0,0,0);
209                 hs_icons[i]=icon_half_assed_size(icons[i],TRUE,0,0,0);
210                 break;
211         }
212     }
213     for(i=0;i<WALL_XXX;i++){
214         /* walls */
215         strcpy(buf,"/usr/local/share/xorgramana/GFX/");
216         strcat(buf,wall_names[i]);
217         strcat(buf,ICON_EXT);
218         walls[i]=load_image(buf,FALSE,0,0,0);
219         hs_walls[i]=icon_half_assed_size(walls[i],FALSE,0,0,0);
220         /* floors */
221         strcpy(buf,"/usr/local/share/xorgramana/GFX/");
222         strcat(buf,floor_names[i]);
223         strcat(buf,ICON_EXT);
224         floors[i]=load_image(buf,FALSE,0,0,0);
225         hs_floors[i]=icon_half_assed_size(floors[i],FALSE,0,0,0);
226     }
227     for(i=0;i<DIRIND_XXX;i++){
228         strcpy(buf,"/usr/local/share/xorgramana/GFX/");
229         strcat(buf,indicator_names[i]);
230         strcat(buf,ICON_EXT);
231         indicators[i]=load_image(buf,TRUE,0,0,0);
232     }
233     int j;
234     for(i=0;i<WALL_XXX;i++){
235         for(j=0;j<EDGE_XXX;j++){
236             strcpy(buf,"/usr/local/share/xorgramana/GFX/");
237             strcat(buf,edge_names[i][j]);
238             strcat(buf,ICON_EXT);
239             wall_edges[i][j]=load_image(buf,TRUE,0xff,0xff,0xff);
240         }
241     }
242 }
243 
init_wall(lvl_t level,bool show)244 void init_wall(lvl_t level, bool show)
245 {
246     int w=(level>0?((level-1)%WALL_XXX):0);
247     int n;
248     icons[ICON_FLOOR]=floors[w];
249     hs_icons[ICON_FLOOR]=hs_floors[w];
250     if(!show){
251         icons[ICON_WALL]=icons[ICON_FLOOR];
252         hs_icons[ICON_WALL]=hs_icons[ICON_FLOOR];
253         for(n=ICON_EDGE_T;n<=ICON_EDGE_TBLR;n++)
254             icons[n]=icons[ICON_FLOOR];
255             /* won't bother with half-sized edged walls */
256         return;
257     }
258     icons[ICON_WALL]=walls[w];
259     hs_icons[ICON_WALL]=hs_walls[w];
260     if(current_wall_texture!=level){
261         current_wall_texture=level;
262         generate_wall_edging(w);
263     }
264     for(n=ICON_EDGE_T;n<=ICON_EDGE_TBLR;n++){
265         if(!(icons[n]=edged_walls[n-ICON_EDGE_T]))
266             icons[n]=icons[ICON_WALL];
267     }
268         /* won't bother with half-sized edged walls */
269 }
270 
icons_cleanup()271 void icons_cleanup()
272 {
273     int i,w;
274     for(i=0;i<ICON_LOADED_XXX;i++){
275         if(i!=ICON_WALL&&i!=ICON_FLOOR){
276             if(icons[i]){
277                 SDL_FreeSurface(icons[i]);
278                 SDL_FreeSurface(hs_icons[i]);
279             }
280         }
281     }
282     for(i=0;i<WALL_XXX;i++){
283         if(walls[i]){
284             SDL_FreeSurface(walls[i]);
285             SDL_FreeSurface(hs_walls[i]);
286         }
287         if(floors[i]){
288             SDL_FreeSurface(floors[i]);
289             SDL_FreeSurface(hs_floors[i]);
290         }
291     }
292     for(i=0;i<DIRIND_XXX;i++){
293         if(indicators[i])
294             SDL_FreeSurface(indicators[i]);
295     }
296     for(w=0;w<WALL_XXX;w++){
297         for(i=0;i<EDGE_XXX;i++)
298             if(wall_edges[w][i])
299                 SDL_FreeSurface(wall_edges[w][i]);
300     }
301     for(i=ICON_EDGE_T;i<=ICON_EDGE_TBLR;i++)
302         if(edged_walls[i-ICON_EDGE_T])
303             SDL_FreeSurface(edged_walls[i-ICON_EDGE_T]);
304 }
305 
mapchar_to_icon(char c)306 su_t mapchar_to_icon(char c)
307 {
308     int n;
309     if(c<32)
310         return ICON_FLOOR;
311     for(n=0;n<=ICON_9;n++)
312         if(icon_details[n].mapchar==c)
313             return n;
314     return ICON_FLOOR;
315 }
316 
char_to_icon(char c)317 su_t char_to_icon(char c)
318 {
319     if(c>='A'&&c<='Z')
320         return ICON_A+c-'A';
321     if(c>='a'&&c<='z')
322         return ICON_A+c-'a';
323     if(c>='0'&&c<='9')
324         return ICON_1+c-'1';
325     switch(c){
326         case '#': return ICON_PLAYER0;
327         case '*': return ICON_PLAYER1;
328         case '+': return ICON_TELEPORT;
329         case '-': return ICON_H_FIELD;
330         case '|': return ICON_V_FIELD;
331         case '.': return ICON_DOT;
332         case ' ': return spc_icon;
333         case '_': return ICON_FLOOR;
334         default:  return spc_icon;
335     }
336 }
337 
set_space_icon(enum SPACE_CHAR spc)338 void set_space_icon(enum SPACE_CHAR spc)
339 {
340     switch(spc){
341         case SPC_TRAN:      spc_icon=ICON_SPACE_TRAN;    break;
342         case SPC_OPAQUE:    spc_icon=ICON_SPACE_OPAQUE;  break;
343         default:            spc_icon=ICON_FLOOR;         break;
344     }
345 }
346 
load_image(char * name,bool transparent,int tr_r,int tr_g,int tr_b)347 SDL_Surface *load_image(char *name, bool transparent, int tr_r, int tr_g, int tr_b)
348 {
349     SDL_Surface *temp=IMG_Load(name);
350     SDL_Surface *image;
351     if(!temp){
352         fprintf(stderr,"Failed to load image %s\n",name);
353         return NULL;
354     }
355     if(transparent)
356         SDL_SetColorKey(temp,
357             (SDL_SRCCOLORKEY|SDL_RLEACCEL),
358             SDL_MapRGB(temp->format,
359             tr_r, tr_g, tr_b));
360     else
361         SDL_SetColorKey(temp,
362             (SDL_RLEACCEL),
363             SDL_MapRGB(temp->format,
364             0, 0, 0));
365     image=SDL_DisplayFormat(temp);
366     SDL_FreeSurface(temp);
367     if(!image){
368         fprintf(stderr,"Failed to convert image %s to native format\n", name);
369         return NULL;
370     }
371     return image;
372 }
373 
icon_duplicate(SDL_Surface * s,bool transparent,int tr_r,int tr_g,int tr_b)374 SDL_Surface* icon_duplicate(SDL_Surface* s, bool transparent, int tr_r, int tr_g, int tr_b)
375 {
376     SDL_Surface* temp;
377     SDL_Surface* ret;
378     Sint32 x,y;
379     if(!s)
380         return 0;
381     temp=SDL_CreateRGBSurface(
382             s->flags,s->w,s->h,
383             s->format->BitsPerPixel,
384             s->format->Rmask,s->format->Gmask,
385             s->format->Bmask,s->format->Amask);
386     SDL_LockSurface(s);
387     SDL_LockSurface(temp);
388     for(y=0;y<s->h;y++)
389         for(x=0;x<s->w;x++)
390             putpixel(temp,x,y,getpixel(s,x,y));
391     SDL_UnlockSurface(s);
392     SDL_UnlockSurface(temp);
393     if(transparent)
394         SDL_SetColorKey(temp,
395             (SDL_SRCCOLORKEY|SDL_RLEACCEL),
396             SDL_MapRGB(temp->format,
397             tr_r, tr_g, tr_b));
398     else
399         SDL_SetColorKey(temp,
400             (SDL_RLEACCEL),
401             SDL_MapRGB(temp->format,
402             0, 0, 0));
403     ret=SDL_DisplayFormat(temp);
404     SDL_FreeSurface(temp);
405     return ret;
406 }
407 
icon_half_assed_size(SDL_Surface * s,bool transparent,int tr_r,int tr_g,int tr_b)408 SDL_Surface* icon_half_assed_size(SDL_Surface* s, bool transparent, int tr_r, int tr_g, int tr_b)
409 {
410     SDL_Surface* temp;
411     SDL_Surface* ret;
412     Sint32 x,y;
413     Sint32 hw;
414     Sint32 hh;
415     if(!s)
416         return 0;
417     hw=s->w/2;
418     hh=s->h/2;
419     temp=SDL_CreateRGBSurface(
420             s->flags,hw,hh,
421             s->format->BitsPerPixel,
422             s->format->Rmask,s->format->Gmask,
423             s->format->Bmask,s->format->Amask);
424     SDL_LockSurface(s);
425     SDL_LockSurface(temp);
426     for(y=0;y<hh;y++)
427         for(x=0;x<hw;x++)
428             putpixel(temp,x,y,getpixel(s,x*2,y*2));
429     SDL_UnlockSurface(s);
430     SDL_UnlockSurface(temp);
431     if(transparent)
432         SDL_SetColorKey(temp,
433             (SDL_SRCCOLORKEY|SDL_RLEACCEL),
434             SDL_MapRGB(temp->format,
435             tr_r, tr_g, tr_b));
436     else
437         SDL_SetColorKey(temp,
438             (SDL_RLEACCEL),
439             SDL_MapRGB(temp->format,
440             0, 0, 0));
441     ret=SDL_DisplayFormat(temp);
442     SDL_FreeSurface(temp);
443     return ret;
444 }
445 
446 /* private functions */
447 
generate_wall_edging(su_t wall)448 void generate_wall_edging(su_t wall)
449 {
450     int n;
451     int o;
452     SDL_Surface *temp;
453     if(!icons[ICON_WALL])
454         return;
455     for(n=ICON_EDGE_T;n<=ICON_EDGE_TBLR;n++){
456         int w=n-ICON_EDGE_T;
457         if(edged_walls[w]){
458             SDL_FreeSurface(edged_walls[w]);
459             edged_walls[w]=0;
460         }
461         temp=icon_duplicate(icons[ICON_WALL],FALSE,0,0,0);
462         switch(n){
463             case ICON_EDGE_T:       o=EDGE_T;   break;
464             case ICON_EDGE_B:       o=EDGE_B;   break;
465             case ICON_EDGE_L:       o=EDGE_L;   break;
466             case ICON_EDGE_R:       o=EDGE_R;   break;
467             case ICON_EDGE_TB:      o=EDGE_TB;  break;
468             case ICON_EDGE_LR:      o=EDGE_LR;  break;
469             case ICON_EDGE_TL:      o=EDGE_TL;  break;
470             case ICON_EDGE_TR:      o=EDGE_TR;  break;
471             case ICON_EDGE_BL:      o=EDGE_BL;  break;
472             case ICON_EDGE_BR:      o=EDGE_BR;  break;
473             case ICON_EDGE_TBL:     o=EDGE_TBL; break;
474             case ICON_EDGE_TBR:     o=EDGE_TBR; break;
475             case ICON_EDGE_TLR:     o=EDGE_TLR; break;
476             case ICON_EDGE_BLR:     o=EDGE_BLR; break;
477             default:                o=EDGE_TBLR;break;
478         }
479         if(o&EDGE_T)
480             overlay_image(temp,wall_edges[wall][0],0,0);
481         if(o&EDGE_B)
482             overlay_image(temp,wall_edges[wall][1],0,0);
483         if(o&EDGE_L)
484             overlay_image(temp,wall_edges[wall][2],0,0);
485         if(o&EDGE_R)
486             overlay_image(temp,wall_edges[wall][3],0,0);
487         SDL_SetColorKey(temp,
488             (SDL_SRCCOLORKEY|SDL_RLEACCEL),
489             SDL_MapRGB(temp->format,
490             0, 0, 0));
491         edged_walls[n-ICON_EDGE_T]=SDL_DisplayFormat(temp);
492         SDL_FreeSurface(temp);
493     }
494 }
495