1 /*
2 * IceBreaker
3 * Copyright (c) 2000-2002 Matthew Miller <mattdm@mattdm.org> and
4 * Enrico Tassi <gareuselesinge@infinito.it>
5 *
6 * <http://www.mattdm.org/icebreaker/>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24 #include <SDL.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "icebreaker.h"
28 #include "globals.h"
29 #include "text.h"
30 #include "laundry.h"
31 #include "dialog.h"
32 #include "sound.h"
33 #include "hiscore.h"
34 #include "options.h"
35 #include "fullscreen.h"
36 #include "themes.h"
37 #include "grid.h"
38 #include "status.h"
39 #include "level.h"
40 #include "event.h"
41
42
gethighusername(int highest)43 PopupReturnType gethighusername(int highest)
44 {
45 SDL_Rect tmprect,namerect,okayrect;
46 SDL_Event event;
47 int done=false;
48 PopupReturnType rc=POPUPDONOTHING;
49 int okayglow=false;
50 int okaypressed=false;
51 int clearname=true;
52
53 char keypressed;
54 int insertionpoint=0;
55
56 tmprect.w=282;
57 tmprect.h=92;
58 tmprect.x=(WIDTH/2)-(tmprect.w/2)-1;
59 tmprect.y=(HEIGHT/2)+31;
60 SDL_FillRect(screen,&tmprect,color.gridline);
61
62 tmprect.w-=2; tmprect.h-=2;
63 tmprect.x++; tmprect.y++;
64 SDL_FillRect(screen,&tmprect,color.background);
65
66 if (highest)
67 puttext(tmprect.x+7,tmprect.y+7,2,color.normaltext,"NEW TOP SCORE!");
68 else
69 puttext(tmprect.x+7,tmprect.y+7,2,color.normaltext,"NEW HIGH SCORE.");
70 puttext(tmprect.x+7,tmprect.y+7+16,2,color.normaltext,"ENTER YOUR NAME:");
71
72 namerect.w=268;
73 namerect.h=29;
74 namerect.x=tmprect.x+6;
75 namerect.y=tmprect.y+7+32;
76
77 SDL_FillRect(screen,&namerect,color.textentrybox);
78
79 // this makes sure username fits. maybe a bit gross to have this
80 // truncated here, but hey.
81 while(strlen(username)>1 && gettextwidth(4,username) > namerect.w-8)
82 {
83 username[strlen(username)-1]='\0';
84 }
85
86 puttext(namerect.x+4,namerect.y+5,4,color.textentrytext,username);
87
88 okayrect.x=tmprect.x+tmprect.w-32;
89 okayrect.y=tmprect.y+7+64;
90 okayrect.h=CHARHEIGHT*2+3;
91 okayrect.w=CHARWIDTH*2*2+1;
92
93 //SDL_FillRect(screen,&okayrect,color.textentrybox);
94 puttext(okayrect.x+3,okayrect.y+3,2,color.normaltext,"OK");
95
96
97 updateall(); // fix -- is this really needed? we should soil() the
98 // above rectangles instead, i think
99
100
101 SDL_EnableUNICODE(1);
102 SDL_EnableKeyRepeat(500,90);
103
104 clean();
105 do
106 {
107 SDL_WaitEvent(NULL); // no new CPU cooler needed. :)
108 while (pollevent(&event))
109 {
110 if (event.type == SDL_QUIT)
111 {
112 done=true;
113 rc=POPUPQUITGAME;
114 }
115 else if (event.type == SDL_MOUSEBUTTONDOWN)
116 { // fix -- make this left button only
117 if (event.button.x>=okayrect.x
118 && event.button.y>=okayrect.y
119 && event.button.x<okayrect.x+okayrect.w
120 && event.button.y<okayrect.y+okayrect.h)
121 okaypressed=true;
122 }
123 else if (event.type == SDL_MOUSEBUTTONUP)
124 {
125 if (okaypressed
126 && event.button.x>=okayrect.x
127 && event.button.y>=okayrect.y
128 && event.button.x<okayrect.x+okayrect.w
129 && event.button.y<okayrect.y+okayrect.h)
130 {
131 if (username[0]!='\0')
132 {
133 done=true;
134 rc=POPUPOK;
135 }
136 else
137 {
138 playsound(SNDOUCH);
139 }
140 }
141 else if (okayglow)
142 {
143 okayglow=false;
144 SDL_FillRect(screen,&okayrect,color.background);
145 puttext(okayrect.x+3,okayrect.y+3,2,color.normaltext,"OK");
146 soil(okayrect);
147 }
148 okaypressed=false;
149 }
150 else if (event.type == SDL_MOUSEMOTION)
151 {
152 if (event.motion.x>=okayrect.x
153 && event.motion.y>=okayrect.y
154 && event.motion.x<okayrect.x+okayrect.w
155 && event.motion.y<okayrect.y+okayrect.h)
156 {
157 if (!okayglow)
158 {
159 okayglow=true;
160 SDL_FillRect(screen,&okayrect,color.menuhighlight);
161 puttext(okayrect.x+3,okayrect.y+3,2,color.background,"OK");
162 soil(okayrect);
163 }
164
165 }
166 else
167 {
168 if (okayglow && !okaypressed)
169 {
170 okayglow=false;
171 SDL_FillRect(screen,&okayrect,color.background);
172 puttext(okayrect.x+3,okayrect.y+3,2,color.normaltext,"OK");
173 soil(okayrect);
174 }
175 }
176
177 }
178 else if (event.type==SDL_KEYDOWN)
179 {
180
181 if (event.key.keysym.sym==SDLK_BACKSPACE ||
182 event.key.keysym.sym==SDLK_DELETE ||
183 event.key.keysym.sym==SDLK_LEFT)
184 {
185 if (clearname)
186 {
187 insertionpoint=0;
188 username[0]='\0'; // null out username
189 }
190 else if (insertionpoint>0)
191 {
192 insertionpoint--;
193 username[insertionpoint]='\0';
194 }
195 else
196 {
197 playsound(SNDOUCH);
198 }
199 clearname=false;
200 }
201 else if (event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_KP_ENTER)
202 {
203 if (username[0]!='\0')
204 {
205 done=true;
206 rc=POPUPOK;
207 }
208 else
209 {
210 playsound(SNDOUCH);
211 }
212 clearname=false;
213 }
214 else if (event.key.keysym.sym==SDLK_ESCAPE || event.key.keysym.sym==SDLK_CLEAR) // fix -- make ctrl-u work here
215 {
216 insertionpoint=0;
217 username[0]='\0'; // null out username
218 clearname=false;
219 }
220 else if ((event.key.keysym.unicode & 0xFF80) == 0) // make sure it's ascii
221 {
222 keypressed=event.key.keysym.unicode & 0x7F;
223 if (keypressed==32) keypressed=95;
224 if (keypressed>32 && keypressed<127)
225 {
226 if (clearname)
227 {
228 insertionpoint=0;
229 clearname=false;
230 }
231 if (insertionpoint<(50-1) && gettextwidth(4,username)+getletterwidth(4,keypressed) <= namerect.w-8) //(insertionpoint<12)
232 {
233 username[insertionpoint]=keypressed;
234 username[insertionpoint+1]='\0';
235 insertionpoint++;
236 }
237 else
238 {
239 playsound(SNDOUCH);
240 }
241 }
242 }
243 SDL_FillRect(screen,&namerect,color.textentrybox);
244 puttext(namerect.x+4,namerect.y+5,4,color.textentrytext,username);
245 soil(namerect);
246 }
247 }
248 clean();
249 } while (!done);
250
251 // because the game is over, restore of background is unnecessary
252
253 SDL_EnableKeyRepeat(0,0);
254 SDL_EnableUNICODE(0);
255 return(rc);
256 }
257
258
popuphighscores()259 PopupReturnType popuphighscores()
260 {
261 SDL_Rect scorelistrect,borderrect;
262 SDL_Surface * scorelistsave;
263 PopupReturnType rc=POPUPDONOTHING;
264 int i;
265 char buf[30]; // plenty big. :)
266
267 scorelistrect.w=PLAYWIDTH-(BLOCKWIDTH*11);
268 scorelistrect.h=PLAYHEIGHT-(BLOCKHEIGHT*4);
269 scorelistrect.x=BORDERLEFT+PLAYWIDTH/2-scorelistrect.w/2+BLOCKWIDTH*4;
270 scorelistrect.y=BORDERTOP+PLAYHEIGHT/2-scorelistrect.h/2+BLOCKHEIGHT/2;
271
272 borderrect.w=scorelistrect.w+2;
273 borderrect.h=scorelistrect.h+2;
274 borderrect.x=scorelistrect.x-1;
275 borderrect.y=scorelistrect.y-1;
276
277 scorelistsave = SDL_CreateRGBSurface(SDL_SWSURFACE,borderrect.w,borderrect.h,screen->format->BitsPerPixel,0,0,0,0);
278 SDL_BlitSurface(screen, &borderrect, scorelistsave, NULL);
279
280 SDL_FillRect(screen,&borderrect,color.gridline);
281 SDL_FillRect(screen,&scorelistrect,color.background);
282
283 puttext(scorelistrect.x+(scorelistrect.w/2-(CHARWIDTH*2*9)),scorelistrect.y+BLOCKHEIGHT,4,color.bonusscrolltext,"HIGH SCORES");
284
285 // just in case they've changed...
286 readhiscores();
287
288 for (i=0;i<HISCORENUM;i++)
289 {
290 snprintf(buf,sizeof(buf),"%d.",i+1);
291 puttext(scorelistrect.x+BLOCKWIDTH,scorelistrect.y+45+i*(CHARHEIGHT*2+5),2,color.normaltext,buf);
292 puttext(scorelistrect.x+BLOCKWIDTH*4,scorelistrect.y+45+i*(CHARHEIGHT*2+5),2,color.normaltext,hiscorename[i]);
293 snprintf(buf,sizeof(buf),"%ld",hiscoreval[i]);
294 puttext(scorelistrect.x+scorelistrect.w-(BLOCKWIDTH*5),scorelistrect.y+45+i*(CHARHEIGHT*2+5),2,color.normaltext,buf);
295 }
296
297 soil(borderrect);
298
299 clean();
300
301 rc=waitforuser();
302
303 SDL_BlitSurface(scorelistsave, NULL, screen, &borderrect);
304 soil(borderrect);
305 clean();
306
307 SDL_FreeSurface(scorelistsave);
308
309 return(rc);
310 }
311
popuphelp()312 PopupReturnType popuphelp()
313 {
314 SDL_Rect helprect,borderrect;
315 SDL_Surface * helpsave;
316 PopupReturnType rc=POPUPDONOTHING;
317 int i=0;
318 char buf[80];
319
320
321 #ifdef ONEBUTTONMICEARESILLY
322 char helptext[13][50]={
323 "Ok, so there's a bunch of penguins on an",
324 "iceberg in Antarctica. You must catch them",
325 "so they can be shipped to Finland. The",
326 "smaller the area in which they're caught,",
327 "the lower the shipping fees and the higher",
328 "your score - but don't take too long: the",
329 "clock is ticking. Once 80% of the 'berg is",
330 "cleared, it's on to the next shipment.",
331 "",
332 "The left mouse button starts lines; right",
333 "button or [spacebar] toggles direction.",
334 "",
335 "Check the README file for more info."
336 };
337 #else
338 char helptext[13][50]={
339 "Ok, so there's a bunch of penguins on an",
340 "iceberg in Antarctica. You must catch them",
341 "so they can be shipped to Finland. The",
342 "smaller the area in which they're caught,",
343 "the lower the shipping fees and the higher",
344 "your score - but don't take too long: the",
345 "clock is ticking. Once 80% of the 'berg is",
346 "cleared, it's on to the next shipment.",
347 "",
348 "The left mouse button starts lines; right",
349 "button toggles direction. You'll catch on.",
350 "",
351 "Check the README file for more info."
352 };
353 #endif
354
355 helprect.w=PLAYWIDTH-(BLOCKWIDTH*2)+2;
356 helprect.h=PLAYHEIGHT-(BLOCKHEIGHT*3);
357 helprect.x=BORDERLEFT+PLAYWIDTH/2-helprect.w/2;
358 helprect.y=BORDERTOP+PLAYHEIGHT/2-helprect.h/2;
359
360 borderrect.w=helprect.w+2;
361 borderrect.h=helprect.h+2;
362 borderrect.x=helprect.x-1;
363 borderrect.y=helprect.y-1;
364
365 helpsave = SDL_CreateRGBSurface(SDL_SWSURFACE,borderrect.w,borderrect.h,screen->format->BitsPerPixel,0,0,0,0);
366 SDL_BlitSurface(screen, &borderrect, helpsave, NULL);
367
368 SDL_FillRect(screen,&borderrect,color.gridline);
369 SDL_FillRect(screen,&helprect,color.background);
370
371 for (i=0;i<13;i++)
372 {
373 puttext(helprect.x+BLOCKWIDTH/2,helprect.y+BLOCKHEIGHT/2+i*(CHARHEIGHT*2+4),2,color.normaltext,helptext[i]);
374 }
375 snprintf(buf,sizeof(buf),"v%d.%d.%d %s",VERMAJOR,VERMINOR,VERSUB,"Copyright (c) 2000-2002 Matthew Miller. Released under the GPL.");
376 puttext(helprect.x+BLOCKWIDTH/2,helprect.y+helprect.h-CHARHEIGHT*3,1,color.copyrighttext,buf);
377 puttext(helprect.x+BLOCKWIDTH/2,helprect.y+helprect.h-CHARHEIGHT*1-3,1,color.copyrighttext,"Thanks to my wonderful wife Karen for inspiration (and for patience)!");
378
379 soil(borderrect);
380
381 clean();
382
383 rc=waitforuser();
384
385 SDL_BlitSurface(helpsave, NULL, screen, &borderrect);
386 soil(borderrect);
387 clean();
388
389 SDL_FreeSurface(helpsave);
390
391 return(rc);
392 }
393
394
395 /* Wait for the user to hit a key or button or quit; returns true if quit */
waitforuser()396 PopupReturnType waitforuser()
397 {
398 int done=false;
399 PopupReturnType rc=POPUPDONOTHING;
400 SDL_Event event;
401
402 do
403 {
404 SDL_WaitEvent(NULL);
405 while(pollevent(&event))
406 {
407 if ( event.type == SDL_QUIT)
408 {
409 done=true;
410 rc=POPUPQUITGAME;
411 }
412 else if (event.type == SDL_MOUSEBUTTONUP)
413 {
414 done=true;
415 }
416 else if (event.type == SDL_KEYUP)
417 {
418 switch(translatekeyevent(&event))
419 {
420 case KEYCANCEL: // falls through
421 case KEYMENU: // falls through
422 case KEYSWITCHLINE: // falls through
423 case KEYSTARTLINE:
424 done=true;
425 default:
426 break;
427 }
428
429 }
430 }
431 } while (!done);
432 return(rc);
433 }
434
435
436 // fix -- make this more generic (one or two buttons, selectable button text)
yesnodialog(char * text1,char * text2,char * text3)437 PopupReturnType yesnodialog(char* text1, char* text2, char* text3)
438 {
439 SDL_Rect tmprect, yesrect,norect;
440 SDL_Event event;
441 int done=false;
442 int rc=POPUPDONOTHING;
443 int yesglow=false;
444 int yespressed=false;
445 int noglow=false;
446 int nopressed=false;
447 SDL_Surface* bgsave;
448
449 tmprect.w=gettextwidth(2,text1);
450 if (gettextwidth(2,text2)>tmprect.w) tmprect.w=gettextwidth(2,text2);
451 if (gettextwidth(2,text3)>tmprect.w) tmprect.w=gettextwidth(2,text3);
452 tmprect.w+=15;
453 tmprect.h=92; // fix -- make dialog shorter if text3=null. maybe also text2, but that might be too short
454 tmprect.x=(WIDTH/2)-(tmprect.w/2);
455 tmprect.y=(HEIGHT/2)-(tmprect.h/2);
456
457 // fix -- error checking if this fails
458 bgsave = SDL_CreateRGBSurface(SDL_SWSURFACE,tmprect.w,tmprect.h,screen->format->BitsPerPixel,0,0,0,0);
459 SDL_BlitSurface(screen, &tmprect, bgsave, NULL);
460
461 SDL_FillRect(screen,&tmprect,color.gridline);
462
463 tmprect.w-=2; tmprect.h-=2;
464 tmprect.x++; tmprect.y++;
465 SDL_FillRect(screen,&tmprect,color.background);
466 tmprect.w+=2; tmprect.h+=2; // yay kludgy
467 tmprect.x--; tmprect.y--;
468
469
470
471 puttext(tmprect.x+(tmprect.w-gettextwidth(2,text1))/2,tmprect.y+7,2,color.normaltext,text1);
472 puttext(tmprect.x+(tmprect.w-gettextwidth(2,text2))/2,tmprect.y+7+CHARHEIGHT*3,2,color.normaltext,text2);
473 puttext(tmprect.x+(tmprect.w-gettextwidth(2,text3))/2,tmprect.y+7+CHARHEIGHT*6,2,color.normaltext,text3);
474
475 norect.x=tmprect.x+tmprect.w-33;
476 norect.y=tmprect.y+7+64;
477 norect.h=CHARHEIGHT*2+3;
478 norect.w=CHARWIDTH*2*2+1;
479
480 yesrect.x=tmprect.x+7;
481 yesrect.y=tmprect.y+7+64;
482 yesrect.h=CHARHEIGHT*2+3;
483 yesrect.w=CHARWIDTH*2*3+1;
484
485 puttext(norect.x+3,norect.y+3,2,color.normaltext,"NO");
486 puttext(yesrect.x+3,yesrect.y+3,2,color.normaltext,"YES");
487
488
489 soil(tmprect);
490
491 clean();
492 do
493 {
494 SDL_WaitEvent(NULL);
495 while (pollevent(&event))
496 {
497 if (event.type == SDL_QUIT)
498 {
499 done=true;
500 rc=POPUPQUITGAME;
501 }
502 else if (event.type == SDL_MOUSEBUTTONDOWN)
503 { // fix -- make this left button only
504 if (event.button.x>=norect.x
505 && event.button.y>=norect.y
506 && event.button.x<norect.x+norect.w
507 && event.button.y<norect.y+norect.h)
508 nopressed=true;
509 else if (event.button.x>=yesrect.x
510 && event.button.y>=yesrect.y
511 && event.button.x<yesrect.x+yesrect.w
512 && event.button.y<yesrect.y+yesrect.h)
513 yespressed=true;
514 }
515 else if (event.type == SDL_MOUSEBUTTONUP)
516 {
517 if (nopressed
518 && event.button.x>=norect.x
519 && event.button.y>=norect.y
520 && event.button.x<norect.x+norect.w
521 && event.button.y<norect.y+norect.h)
522 {
523 done=true;
524 rc=POPUPNO;
525 }
526 else if (noglow)
527 {
528 noglow=false;
529 SDL_FillRect(screen,&norect,color.background);
530 puttext(norect.x+3,norect.y+3,2,color.normaltext,"NO");
531 soil(norect);
532 }
533 nopressed=false;
534
535 if (yespressed
536 && event.button.x>=yesrect.x
537 && event.button.y>=yesrect.y
538 && event.button.x<yesrect.x+yesrect.w
539 && event.button.y<yesrect.y+yesrect.h)
540 {
541 done=true;
542 rc=POPUPYES;
543 }
544 else if (yesglow)
545 {
546 yesglow=false;
547 SDL_FillRect(screen,&yesrect,color.background);
548 puttext(yesrect.x+3,yesrect.y+3,2,color.normaltext,"YES");
549 soil(yesrect);
550 }
551 yespressed=false;
552 }
553 else if (event.type == SDL_MOUSEMOTION)
554 {
555 if (event.motion.x>=norect.x
556 && event.motion.y>=norect.y
557 && event.motion.x<norect.x+norect.w
558 && event.motion.y<norect.y+norect.h)
559 {
560 if (!noglow)
561 {
562 noglow=true;
563 SDL_FillRect(screen,&norect,color.menuhighlight);
564 puttext(norect.x+3,norect.y+3,2,color.background,"NO");
565 soil(norect);
566 }
567
568 }
569 else
570 {
571 if (noglow && !nopressed)
572 {
573 noglow=false;
574 SDL_FillRect(screen,&norect,color.background);
575 puttext(norect.x+3,norect.y+3,2,color.normaltext,"NO");
576 soil(norect);
577 }
578 }
579 if (event.motion.x>=yesrect.x
580 && event.motion.y>=yesrect.y
581 && event.motion.x<yesrect.x+yesrect.w
582 && event.motion.y<yesrect.y+yesrect.h)
583 {
584 if (!yesglow)
585 {
586 yesglow=true;
587 SDL_FillRect(screen,&yesrect,color.menuhighlight);
588 puttext(yesrect.x+3,yesrect.y+3,2,color.background,"YES");
589 soil(yesrect);
590 }
591
592 }
593 else
594 {
595 if (yesglow && !yespressed)
596 {
597 yesglow=false;
598 SDL_FillRect(screen,&yesrect,color.background);
599 puttext(yesrect.x+3,yesrect.y+3,2,color.normaltext,"YES");
600 soil(yesrect);
601 }
602 }
603
604 }
605 else if (event.type==SDL_KEYDOWN)
606 {
607 if (event.key.keysym.sym==SDLK_n)
608 {
609 done=true;
610 rc=POPUPNO;
611 }
612 else if (event.key.keysym.sym==SDLK_ESCAPE)
613 {
614 // little hack to keep escape key from "bleeding" into
615 // cancelling the whole menu
616 done=true;
617 rc=POPUPYES;
618 SDL_Delay(200);
619 while(pollevent(&event) && (event.type==SDL_KEYDOWN || event.type==SDL_KEYUP));
620 }
621 else if (event.key.keysym.sym==SDLK_y || event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_KP_ENTER)
622 {
623 done=true;
624 rc=POPUPYES;
625 }
626 }
627 }
628 clean();
629 } while (!done);
630
631 SDL_BlitSurface(bgsave, NULL, screen, &tmprect);
632 soil(tmprect);
633 clean();
634
635 return(rc);
636 }
637