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