1 /* Penguin Command: a clone of the famous Missile Command game
2 Copyright (C) 2000 Karl Bartel
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 Karl Bartel
19 Cecilienstr. 14
20 12307 Berlin
21 GERMANY
22 karlb@gmx.net
23 */
24 #include <main.h>
25 #include <time.h> /* For seeding rand() */
26 #include <string.h>
27 #ifdef JOYSTICK
28 #include "joystick.h"
29 #endif
30 #ifndef VERSION
31 #define VERSION "1.6.?"
32 #endif
33
34
35 int fullscreen=1, CityDestroyed[6]={0,0,0,0,0,0},
36 CannonDestroyed[3]={0,0,0}, Score=0, HWCursor=0, NoAlpha=0, ArcadeMode=0, MusicVol=10, SoundVol=10;
37 //images
38 SDL_Surface *ShotPic,*CityPic,*BackPic,*CityHitPic,*Cannon[21],*Font,
39 *BombPic[10],*CannonHitPic,*TitlePic,*ExplosionPic[21],
40 *CursorPic[10],*FlyerPic[16];
41 //event handling
42 SDL_Event event;
43 //other
44 int Quit=0, Loaded=0, StartLevel=0;
45 Uint32 WaitStart=0;
46 int LowDetail=0, MediumDetail=0, HighDetail=1;
47
Wait(int time_in_ms)48 int Wait( int time_in_ms )
49 {
50 if (WaitStart==0)
51 WaitStart=SDL_GetTicks();
52 if (WaitStart+time_in_ms <= SDL_GetTicks()) {
53 WaitStart=0;
54 return 0;
55 }
56 return 1;
57 }
58
LoadImages()59 void LoadImages()
60 {
61 int i;
62 char text[200];
63
64 BackPic = LoadImage("back.jpg",0);
65 SDL_FreeSurface(ShotPic);
66 ShotPic = LoadImage("shot.png",3);
67 CityPic = LoadImage("city.png",4);
68 CityHitPic = LoadImage("cityhit.png",4);
69 CannonHitPic = LoadImage("cannonhit.png",4);
70 for (i=0;i<21;i++) {
71 sprintf(text,"cannon%d.png",i+1);
72 SDL_FreeSurface(Cannon[i]);
73 Cannon[i] = LoadImage(text,3);
74 }
75 for (i=0;i<10;i++) {
76 sprintf(text,"bomb%d.png",i+1);
77 SDL_FreeSurface(BombPic[i]);
78 BombPic[i] = LoadImage(text,3);
79 }
80 for (i=0;i<20;i++) {
81 sprintf(text,"%dexplo.png",i+1);
82 SDL_FreeSurface(ExplosionPic[i]);
83 ExplosionPic[i] = LoadImage(text,3);
84 }
85 for (i=0;i<9;i++) {
86 sprintf(text,"%dcursor.png",i+1);
87 SDL_FreeSurface(CursorPic[i]);
88 CursorPic[i] = LoadImage(text,3);
89 }
90 CursorPic[9] = CursorPic[0];
91 for (i=0;i<16;i++) {
92 sprintf(text,"%dflyer.png",i+1);
93 SDL_FreeSurface(FlyerPic[i]);
94 FlyerPic[i] = LoadImage(text,3);
95 }
96 }
97
Button(int x,int y,char * String,int prev,SDL_Surface * Background)98 int Button(int x, int y, char *String, int prev, SDL_Surface *Background)
99 {
100 SDL_Rect rect;
101 int MouseX,MouseY;
102
103 rect.x=x;
104 rect.y=y;
105 rect.w=SFont_TextWidth(String);
106 rect.h=Font->h;
107
108 SDL_GetMouseState(&MouseX, &MouseY);
109 if ((MouseX>x)&&(MouseY>y)
110 &&(MouseX<x+SFont_TextWidth(String))
111 &&(MouseY<y+Font->h))
112 {
113 if (prev!=1) {
114 // clear
115 SDL_SetAlpha(Background,0,0);
116 SDL_BlitSurface(Background, &rect, Screen, &rect);
117 // draw
118 PutString(Screen, x, y, String);
119 AddThisRect(rect);
120 SDL_BlitSurface(Screen, &rect, BackBuffer, &rect);
121 PlaySound(ClickSound);
122 }
123 return 1;
124 } else if (prev!=0) {
125 // clear
126 SDL_SetAlpha(Background,0,0);
127 SDL_BlitSurface(Background, &rect, Screen, &rect);
128 // draw
129 PutString(Screen, x, y, String);
130 AddThisRect(rect);
131 // darken
132 SDL_SetAlpha(Background,SDL_SRCALPHA,100);
133 SDL_BlitSurface(Background, &rect, Screen, &rect);
134 SDL_SetAlpha(Background,0,0);
135 SDL_BlitSurface(Screen, &rect, BackBuffer, &rect);
136 }
137
138 return 0;
139 }
140
SetDetail()141 void SetDetail()
142 {
143 if (LowDetail) {
144 HWCursor=1;
145 NoAlpha=1;
146 }
147 if (MediumDetail) {
148 HWCursor=0;
149 NoAlpha=1;
150 }
151 if (HighDetail) {
152 HWCursor=0;
153 NoAlpha=0;
154 }
155 }
156
ShowHelp()157 void ShowHelp()
158 {
159 float anim=0;
160 SDL_Rect rect;
161 SDL_Event WaitEvent;
162 char DetailString[100],LevelString[100],text[100];
163 int Level=3,SoundV=3,MusicV=3;
164
165 Blit(0,0,BackPic);
166 ExplosionCount=0;
167 XCenteredString(Screen,10,"< Penguin Command Help & Options >");
168 PutString(Screen,20,60,"Objective: Defend cities!");
169 PutString(Screen,20,100,"Controls: Mouse, or mouse + a,s,d keys");
170 PutString(Screen,20,140,"Score:");
171 PutString(Screen,150,185,"10 Remaining Shot");
172 PutString(Screen,150,220,"20 Destroyed Missile");
173 PutString(Screen,150,255,"30 Destroyed Smartbomb");
174 PutString(Screen,150,290,"80 Remaining City");
175 Blit(80-ShotPic->w/2,200-ShotPic->h/2,ShotPic);
176 Blit(80-CityPic->w/2,310-CityPic->h/2,CityPic);
177 XCenteredString(Screen,380,"< Settings >");
178 SDL_BlitSurface(Screen,NULL,BackBuffer,NULL);
179 SDL_BlitSurface(Screen,NULL,FadeBuffer,NULL);
180 Update();
181 Now=SDL_GetTicks();
182 while (Level || SoundV || MusicV) {
183 SDL_PollEvent(&WaitEvent);
184 while ( (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(1))
185 ||(SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(2))
186 ||(SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(3)) )
187 {SDL_PollEvent(&WaitEvent);}
188 while (WaitEvent.type!=SDL_KEYDOWN && WaitEvent.type!=SDL_MOUSEBUTTONDOWN) {
189 SDL_PollEvent(&WaitEvent);
190 UndrawMouse();
191 // Explosion
192 UndrawExplosion();
193 if (ExplosionCount<1) CreateExplosion(80,235);
194 HandleExplosion(0);
195 DrawExplosion();
196 // Bomb
197 anim+=Speed/100;
198 if ((int)anim>=10) anim-=10;
199 rect.x=80-BombPic[0]->w/2; rect.y=270-BombPic[0]->h/2;
200 rect.w=BombPic[0]->w; rect.h=BombPic[0]->h;
201 SDL_BlitSurface( BackBuffer, &rect, Screen, &rect);
202 Blit(rect.x,rect.y,BombPic[(int)anim]);
203 AddThisRect(blitrect);
204 // detail button
205 if (LowDetail) strcpy(DetailString,"Low Detail");
206 if (MediumDetail) strcpy(DetailString,"Medium Detail");
207 if (HighDetail) strcpy(DetailString,"High Detail");
208 // Detail=Button(400-SFont_TextWidth(DetailString)/2,430,DetailString,Detail,FadeBuffer);
209 // level start button
210 sprintf(LevelString,"Starting at Wave %d", StartLevel+1);
211 Level=Button(400-SFont_TextWidth(LevelString)/2,430,LevelString,Level,FadeBuffer);
212 // sound buttons
213 sprintf(text,"Music Volume: %d", MusicVol);
214 MusicV=Button(390-SFont_TextWidth(text),490,text,MusicV,FadeBuffer);
215 sprintf(text,"Sound Volume: %d", SoundVol);
216 SoundV=Button(410,490,text,SoundV,FadeBuffer);
217 // display
218 GetSpeed();
219 DrawMouse();
220 Update();
221 }
222 if (SoundV) {
223 if (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(1))
224 if (SoundVol<15) SoundVol++;
225 if (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(3))
226 if (SoundVol>0) SoundVol--;
227 SoundV=3;
228 rect.x=400;
229 rect.y=490;
230 rect.w=400;
231 rect.h=Font->h;
232 AddThisRect(rect);
233 SDL_SetAlpha( FadeBuffer, 0, 0);
234 SDL_BlitSurface( FadeBuffer, &rect, BackBuffer, &rect);
235 SDL_BlitSurface( FadeBuffer, &rect, Screen, &rect);
236 SetVol();
237 }
238 if (MusicV) {
239 if (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(1))
240 if (MusicVol<15) MusicVol++;
241 if (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(3))
242 if (MusicVol>0) MusicVol--;
243 MusicV=3;
244 rect.x=0;
245 rect.y=490;
246 rect.w=400;
247 rect.h=Font->h;
248 AddThisRect(rect);
249 SDL_SetAlpha( FadeBuffer, 0, 0);
250 SDL_BlitSurface( FadeBuffer, &rect, BackBuffer, &rect);
251 SDL_BlitSurface( FadeBuffer, &rect, Screen, &rect);
252 #ifdef USE_SOUND
253 Mix_VolumeMusic(MusicVol*7);
254 #endif
255 }
256 if (Level) {
257 if (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(1))
258 if (StartLevel<30) StartLevel+=5;
259 if (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(3))
260 if (StartLevel>0) StartLevel-=5;
261 Level=3;
262 rect.x=100;
263 rect.y=430;
264 rect.w=600;
265 rect.h=Font->h;
266 SDL_SetAlpha( FadeBuffer, 0, 0);
267 SDL_BlitSurface( FadeBuffer, &rect, BackBuffer, &rect);
268 SDL_BlitSurface( FadeBuffer, &rect, Screen, &rect);
269 AddThisRect(rect);
270 }
271 SDL_Delay(10);
272 while (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(1)) {SDL_PollEvent(&WaitEvent);SDL_Delay(10);}
273 }
274 // SetDetail();
275 // LoadImages();
276 // SDL_ShowCursor(HWCursor);
277 }
278
ShowCredits()279 void ShowCredits()
280 {
281 float MusicDown=110;
282
283 BlitToBB(0,0,BackPic);
284 XCenteredString(BackBuffer,10,"<Penguin Command Credits>");
285 PutString(BackBuffer,20,60 ,"Code:");
286 PutString(BackBuffer,20,90,"- Karl Bartel <karlb@gmx.net>");
287 PutString(BackBuffer,20,140,"Graphics:");
288 PutString(BackBuffer,20,170,"- Karl Bartel");
289 PutString(BackBuffer,20,200,"- Shane Simmons");
290 PutString(BackBuffer,20,140+MusicDown,"Music:");
291 PutString(BackBuffer,20,170+MusicDown,"- Skaven of the Future Crew");
292 PutString(BackBuffer,100,200+MusicDown,"Data Jack");
293 PutString(BackBuffer,100,230+MusicDown,"Ice Frontier");
294 PutString(BackBuffer,100,260+MusicDown,"Rama Gardens");
295 PutString(BackBuffer,20,310+MusicDown,"- Seth Peelle");
296 PutString(BackBuffer,100,340+MusicDown,"Penguin Night");
297 XCenteredString(BackBuffer,560,"http://www.linux-games.com/");
298 FadeScreen(1);
299 Now=SDL_GetTicks();
300 while (SDL_GetMouseState(NULL,NULL)==SDL_BUTTON(1)) {SDL_PollEvent(&event);SDL_Delay(10);}
301 while ((event.type!=SDL_KEYDOWN)&&(event.type!=SDL_MOUSEBUTTONDOWN)) {
302 SDL_PollEvent(&event);
303 UndrawMouse();
304 DrawMouse();
305 GetSpeed();
306 Update();
307 }
308 }
309
ShowTitle()310 void ShowTitle()
311 {
312 int start=3,help=3,hiscore=3,quit=3,delay=0,credits=3,arcade=3;
313 float NewExplosion=0;
314
315 // show Title
316 printf ("** Blit Background **\n");
317 Blit(0,0,TitlePic);
318 printf ("** Background image drawn **\n");
319 if (!Loaded) {
320 printf("** Loading Font **\n");
321 Font = LoadImage("abc.png",4);
322 printf("** Init Font **\n");
323 InitFont( Font );
324 //SDL_EventState(SDL_KEYUP, SDL_IGNORE);
325 printf("** Loading Images **\n");
326 // load...
327 LoadImages();
328 Loaded=1;
329 MenuEvents();
330 }
331 SDL_SetAlpha(Font, SDL_SRCALPHA, 0);
332 ExplosionCount=0;CursorAnim=0;
333 SDL_BlitSurface(TitlePic,NULL,BackBuffer,NULL);
334 // menu
335 while (!Quit) {
336 if (delay) {
337 Blit(0,0,TitlePic);
338 SDL_BlitSurface(TitlePic,NULL,BackBuffer,NULL);
339 while (event.type==SDL_MOUSEBUTTONDOWN)
340 SDL_PollEvent(&event);
341 Now=SDL_GetTicks();
342 start=3;help=3;hiscore=3;quit=3;credits=3;arcade=3;
343 }
344 UndrawMouse();
345 hiscore=Button(50,300,"Hiscores",hiscore,TitlePic);
346 start=Button(400-SFont_TextWidth("Normal Game")/2,300,"Normal Game",start,TitlePic);
347 arcade=Button(400-SFont_TextWidth("Arcade Game")/2,340,"Arcade Game",arcade,TitlePic);
348 help=Button(750-SFont_TextWidth("Help&Conf"),300,"Help&Conf",help,TitlePic);
349 credits=Button(750-SFont_TextWidth("Credits"),450,"Credits",credits,TitlePic);
350 quit=Button(50,450,"Quit",quit,TitlePic);
351 // Fancy explosions
352 UndrawExplosion();
353 if ((ExplosionCount<10)&&(NewExplosion<0)) {
354 CreateExplosion(abrand(0,799),abrand(0,280));
355 NewExplosion+=abrand(0,600)+50;
356 }
357 NewExplosion-=Speed;
358 HandleExplosion(0);
359 DrawExplosion();
360 GetSpeed();
361 // Explosions end
362 DrawMouse();
363 Update();
364 delay=0;
365 SDL_PollEvent(&event);
366 if (event.type==SDL_MOUSEBUTTONDOWN) {
367 if (hiscore) {
368 ShowHiscore();
369 SDL_WaitEvent(&event);
370 }
371 if (start) {
372 ArcadeMode=0;
373 break;
374 }
375 if (arcade) {
376 ArcadeMode=1;
377 break;
378 }
379 if (help) ShowHelp();
380 if (credits) ShowCredits();
381 if (quit) Quit=1;
382 delay=1;
383 }
384 }
385 ExplosionCount=0;
386 // SDL_WaitEvent(&event);
387 }
388
TextHelp(char * argv[])389 void TextHelp(char *argv[])
390 {
391 printf("\nPenguin Command Version %s\n",VERSION);
392 puts("The newest version can be obtained at http://www.linux-games.com/\n");
393 printf("Usage: %s [options]\n",argv[0]);
394 puts(" [-f, --fullscreen] start in fullscreen mode (default)");
395 puts(" [-w, --windowed] start in windowed mode");
396 puts(" [-s, --nosound] start without sound");
397 puts(" [-l, --lefthandedmouse] swaps left and right mouse buttons");
398 puts(" [-h, --help] this text\n");
399
400 exit(0);
401 }
402
ReadCommandLine(char * argv[])403 void ReadCommandLine(char *argv[])
404 {
405 int i;
406 for ( i=1;argv[i];i++ ) {
407 if ((strcmp(argv[i],"--fullscreen")==0)||(strcmp(argv[i],"-f")==0)) fullscreen=1; else
408 if ((strcmp(argv[i],"--windowed")==0)||(strcmp(argv[i],"-w")==0)) fullscreen=0; else
409 if ((strcmp(argv[i],"--nosound")==0)||(strcmp(argv[i],"-s")==0)) sound=0; else
410 if ((strcmp(argv[i],"--lefthandedmouse")==0)||(strcmp(argv[i],"-l")==0)) LeftHandedMouse=1; else
411 if ((strcmp(argv[i],"--help")==0)||(strcmp(argv[i],"-h")==0)) TextHelp(argv);
412 else {
413 printf("\nUnknown parameter: \"%s\" \n", argv[i]);
414 TextHelp(argv);
415 }
416 }
417 }
418
main(int argc,char * argv[])419 int main(int argc, char *argv[])
420 {
421 // intialisation
422 // if ( SDL_Init(SDL_INIT_AUDIO ) < 0 ) ComplainAndExit();
423 ReadCommandLine(argv);
424 printf("** Starting SDL init **\n");
425 init_SDL();
426 SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
427 SDL_WM_SetCaption("Penguin Command","Penguin Command");
428 srand((unsigned)time(NULL));
429 #ifdef JOYSTICK
430 /* joystick */
431 printf("** Finding Joysticks **\n");
432 JoystickInit();
433 #endif
434 // load data
435 printf("** Loading Title Screen **\n");
436 TitlePic = LoadImage("title.jpg",0);
437 InitSound();
438 // set volume
439 ReadOptions();
440 // show title screen
441 printf("** Playing Music **\n");
442 SetVol();
443 SDL_EnableUNICODE(1);
444 // LoadCursor();
445 // SetDetail();
446 SDL_ShowCursor(HWCursor);
447 printf("** Ready to enter Menu **\n");
448 // start game
449 PlayMusic();
450 while (!Quit) {
451 #ifdef USE_SOUND
452 if (sound) {
453 printf("** Fade in Music **\n");
454 //Mix_FadeInMusic(Music[abrand(0,MUSICNUM-1)],0,5000);
455 }
456 #endif
457 printf("** Showing Title Screen **\n");
458 ShowTitle();
459 if (Quit) break;
460 StartGame();
461 FinalScore();
462 ShowHiscore();
463 }
464 // user wants to quit
465 #ifdef USE_SOUND
466 Mix_FadeOutMusic(1000);
467 #endif
468 {SDL_Rect rect; rect.x=0;rect.y=0;rect.w=800;rect.h=600; SDL_FillRect(BackBuffer,&rect,0);}
469 FadeScreen(0.9);
470 WriteOptions();
471 // printf("Awaiting SDL_Quit()\n");
472 SDL_Quit();
473 // printf("SDL_Quit() finished.\n");
474 return 0;
475 }
476