1 /* game_lib.c - sprite libs, etc
2 *
3 * copyright 06/26/2001
4 * dave blood - geekd@yahoo.com
5 *
6 * some chunks of code taken from SDL examples
7 * http://www.libsdl.org/
8 *
9 * other code where credited
10 *
11 */
12 
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include "gamelib.h"
17 #include "SDL_image.h"
18 #include "SDL_mixer.h"
19 
20 /* This function may run in a separate event thread */
FilterEvents(const SDL_Event * event)21 int FilterEvents(const SDL_Event *event) {
22 
23     if ( event->type == SDL_MOUSEMOTION ) {
24         return(0);    /* Drop it, we've handled it */
25     }
26     return(1);
27 }
28 
init_sdl(int width,int height,char * title,const char * win_icon)29 SDL_Surface *init_sdl(int width, int height, char *title, const char *win_icon) {
30 
31   SDL_Surface *screen;
32   SDL_Surface *icon;
33   int audio_rate;
34   Uint16 audio_format;
35   int audio_channels;
36 
37 
38   /* Initialize SDL */
39 #ifndef NOSOUND
40   if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
41     fprintf(stderr, "SDL error: %s\n", SDL_GetError());
42     exit(1);
43   }
44 #endif
45 #ifdef NOSOUND
46   if (SDL_Init(SDL_INIT_VIDEO) < 0) {
47     fprintf(stderr, "SDL error: %s\n", SDL_GetError());
48     exit(1);
49   }
50 #endif
51 
52   atexit(CleanUp);
53 
54   icon = IMG_Load(win_icon);
55   SDL_WM_SetIcon(icon, NULL);
56 
57   screen = SDL_SetVideoMode(
58 			    width, height,                  /* width and height */
59 			    16,                             /* color depth */
60 			    SDL_HWSURFACE | SDL_DOUBLEBUF   /* video flags */
61 			    );
62 
63   if (screen == NULL){
64     fprintf(stderr, "Video error: %s\n", SDL_GetError());
65     exit(1);
66   }
67 
68   /* set window title */
69 
70   SDL_WM_SetCaption(title, NULL);
71 
72   /* set input filter */
73   SDL_SetEventFilter(FilterEvents);
74 
75 
76   /* initialize Audio */
77 
78   /* Initialize variables */
79   audio_rate = MIX_DEFAULT_FREQUENCY;
80   audio_format = MIX_DEFAULT_FORMAT;
81   audio_channels = 2;
82 
83 
84   /* Open the audio device */
85   #ifndef NOSOUND
86   if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, 512) < 0) {
87     fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
88     exit(2);
89   } else {
90     Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
91     printf("Opened audio at %d Hz %d bit %s", audio_rate,
92 	   (audio_format&0xFF),
93 	   (audio_channels > 1) ? "stereo" : "mono");
94 
95   }
96   /* done w/ audio */
97   #endif
98 
99   return(screen);
100 
101 }
102 
new_sprite(Sprite * temp,const char * filename,int x,int y,int transparent,int alpha)103 void new_sprite(Sprite *temp, const char *filename, int x, int y, int transparent, int alpha) {
104 
105   SDL_Surface *new;
106 
107   temp->x = x;
108   temp->y = y;
109 
110   /* load image */
111 
112   new = IMG_Load(filename);
113 
114   if (new == NULL ) {
115     fprintf(stderr, "Couldn't load %s: %s\n", filename, SDL_GetError());
116     exit(1);
117   }
118 
119   /* set transparent color */
120 
121   if (transparent == 1){
122     SDL_SetColorKey(new, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
123   }
124 
125   if (alpha){
126         SDL_SetAlpha(new, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
127   }
128 
129   /* convert the images to match the surface for speedier blitting */
130 
131   temp->image = SDL_DisplayFormat(new);
132 
133   SDL_FreeSurface(new);
134 
135   temp->w = (temp->image)->w;
136   temp->h = (temp->image)->h;
137 
138   temp->x_vel = 0;
139   temp->y_vel = 0;
140 
141 }
142 
new_sprite_surface(Sprite * temp,SDL_Surface * screen,int x,int y,int transparent)143 void new_sprite_surface(Sprite *temp, SDL_Surface *screen, int x, int y, int transparent) {
144 
145   SDL_Surface *new;
146 
147   temp->x = x;
148   temp->y = y;
149 
150   /* load image */
151 
152   new = screen;
153 
154   /* set transparent color */
155 
156   if (transparent == 1){
157     SDL_SetColorKey(new, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
158   }
159 
160   /* convert the images to match the surface for speedier blitting */
161 
162   temp->image = SDL_DisplayFormat(new);
163 
164   SDL_FreeSurface(new);
165 
166   temp->w = (temp->image)->w;
167   temp->h = (temp->image)->h;
168 
169   temp->x_vel = 0;
170   temp->y_vel = 0;
171 
172 
173 }
174 
175 #ifndef NOSOUND
new_audio(char * filename)176 Mix_Chunk *new_audio(char *filename){
177 
178   Mix_Chunk *wave;
179 
180   /* Load the requested wave file */
181   wave = Mix_LoadWAV(filename);
182   if ( wave == NULL ) {
183     fprintf(stderr, "Couldn't load %s: %s\n",filename, SDL_GetError());
184     exit(1);
185   }
186 
187   return(wave);
188 
189 
190 }
191 #endif
192 
193 
draw_sprite(SDL_Surface * screen,Sprite obj)194 void draw_sprite(SDL_Surface *screen, Sprite obj) {
195   SDL_Rect dest;
196 
197   dest.x = obj.x;
198   dest.y = obj.y;
199   dest.w = obj.w;
200   dest.h = obj.h;
201 
202   SDL_BlitSurface(obj.image, NULL, screen, &dest);
203 }
204 
205 #ifndef NOSOUND
play_audio(Mix_Chunk * wave,int channel)206 void play_audio(Mix_Chunk *wave, int channel) {
207 
208   Mix_PlayChannel(channel, wave, 0);
209 
210 }
211 #endif
212 
213 /*  Full object-to-object pixel-level collision detector
214  *  from: http://gamedev.net/reference/articles/article735.asp
215  *  by John Amato - adapted to SDL and this game lib by me (geekd)
216  */
collision_detect_perfect(Sprite obj1,Sprite obj2)217 short int collision_detect_perfect(Sprite obj1, Sprite obj2) {
218 
219   int left1, left2, over_left;
220   int right1, right2, over_right;
221   int top1, top2, over_top;
222   int bottom1, bottom2, over_bottom;
223   int over_width, over_height;
224   int i, j;
225   int pixel1x, pixel2x;
226   int pixel1y, pixel2y;
227 
228   left1 = obj1.x;
229   left2 = obj2.x;
230   right1 = obj1.x + obj1.w;
231   right2 = obj2.x + obj2.w;
232   top1 = obj1.y;
233   top2 = obj2.y;
234   bottom1 = obj1.y + obj1.h;
235   bottom2 = obj2.y + obj2.h;
236 
237 
238   // Trivial rejections:
239   if (bottom1 < top2) return(0);
240   if (top1 > bottom2) return(0);
241 
242   if (right1 < left2) return(0);
243   if (left1 > right2) return(0);
244 
245 
246   // Ok, compute the rectangle of overlap:
247   if (bottom1 > bottom2) over_bottom = bottom2;
248   else over_bottom = bottom1;
249 
250   if (top1 < top2) over_top = top2;
251   else over_top = top1;
252 
253   if (right1 > right2) over_right = right2;
254   else over_right = right1;
255 
256   if (left1 < left2) over_left = left2;
257   else over_left = left1;
258 
259   over_width = (over_right - over_left);
260   over_height = (over_bottom - over_top);
261 
262 
263   // Now compute starting offsets into both objects' bitmaps:
264 
265   pixel1y = (over_top - obj1.y);
266   pixel2y = (over_top - obj2.y);
267 
268   pixel1x = (over_left - obj1.x);
269   pixel2x = (over_left - obj2.x);
270 
271 
272   // Now start scanning the whole rectangle of overlap,
273   // checking the corresponding pixel of each object's
274   // bitmap to see if they're both non-zero:
275 
276   SDL_LockSurface(obj1.image);
277   SDL_LockSurface(obj2.image);
278 
279   for (i=0; i < over_height; i++) {
280     for (j=0; j < over_width; j++) {
281       if ( ((getpixel(obj1.image, pixel1x + j, pixel1y + i)) > 0 ) &&
282 	   ((getpixel(obj2.image, pixel2x + j, pixel2y + i)) > 0 ) ) {
283 
284 	SDL_UnlockSurface(obj1.image);
285 	SDL_UnlockSurface(obj2.image);
286 	return(1);
287       }
288     }
289   }
290 
291 
292   // Worst case!  We scanned through the whole darn rectangle of overlap
293   // and couldn't find a single colliding pixel!
294 
295   SDL_UnlockSurface(obj1.image);
296   SDL_UnlockSurface(obj2.image);
297 
298   return(0);
299 
300 }
301 
302 
303 /*
304  * Return the pixel value at (x, y)
305  * NOTE: The surface must be locked before calling this!
306  */
307 
getpixel(SDL_Surface * surface,int x,int y)308 Uint32 getpixel(SDL_Surface *surface, int x, int y) {
309 
310   int bpp = surface->format->BytesPerPixel;
311   /* Here p is the address to the pixel we want to retrieve */
312   Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
313 
314   switch(bpp) {
315   case 1:
316     return *p;
317 
318   case 2:
319     return *(Uint16 *)p;
320 
321   case 3:
322     if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
323       return p[0] << 16 | p[1] << 8 | p[2];
324     else
325       return p[0] | p[1] << 8 | p[2] << 16;
326 
327   case 4:
328     return *(Uint32 *)p;
329 
330   default:
331     return 0;       /* shouldn't happen, but avoids warnings */
332   }
333 
334 
335 }
336 
337 
CleanUp(void)338 void CleanUp(void)
339 {
340 #ifndef NOSOUND
341   Mix_CloseAudio();
342 #endif
343 
344   SDL_Quit();
345 }
346 
press_any_key(SDLKey quit_key)347 void press_any_key(SDLKey quit_key){
348 
349   SDL_Event event;
350   int quit = 0;
351 
352   while (!quit){
353 
354     /* wait for keypress */
355 
356     SDL_WaitEvent(&event);
357 
358     if (event.type == SDL_QUIT) {
359       exit(0);
360     }
361 
362     if (event.type == SDL_KEYDOWN) {
363       quit = 1;
364 
365       if (quit_key != NULL){
366 	if (event.key.keysym.sym == quit_key){
367 	  exit(0);
368 	}
369       }
370     }
371 
372   } /* end while */
373 
374 }
375 
376