1 /*
2   Copyright (C) 2009 Facundo Domínguez
3 
4   This file is part of Spacejunk.
5 
6   Spacejunk 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   Foobar 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <guichan.hpp>
21 #include <guichan/sdl.hpp>
22 #include "graphic.h"
23 #include "screens.h"
24 #include "scorelist.h"
25 #include <sge.h>
26 #include "gcnlayouts.h"
27 #include "soundcollection.h"
28 #include "music.h"
29 #include "bar.h"
30 #include <sstream>
31 #include "parsercombinators.h"
32 #include "fade.h"
33 #include "debugmsg.h"
34 #include "clipping.h"
35 #include "imagescroller.h"
36 
37 extern SoundCollection * sounds;
38 
39 using namespace std;
40 
41 extern int mousePositionX;
42 extern int mousePositionY;
43 
44 const int initwait=1000;
45 int waitdelay=0;
46 int laststep;
47 
48 /**
49  * @returns false if the event loop must finish.
50  */
GUI_process_events(gcn::SDLInput * input,gcn::SDLGraphics * graphics)51 bool GUI_process_events(gcn::SDLInput * input,gcn::SDLGraphics * graphics) {
52     SDL_Event e;
53     while (SDL_PollEvent(&e)) {
54         if (waitdelay>0) continue;
55         input->pushInput(e);
56         switch (e.type) {
57         case SDL_KEYDOWN:
58             switch (e.key.keysym.sym) {
59             case SDLK_ESCAPE:
60                 return false;
61             default:
62                 ;
63             }
64             break;
65         case SDL_MOUSEMOTION:
66             mousePositionX=Graphic::fromScreenx(e.motion.x);
67             mousePositionY=Graphic::fromScreeny(e.motion.y);
68             break;
69         case SDL_ACTIVEEVENT: {
70             Uint8 st=SDL_GetAppState();
71             if (st & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) {
72                 if (!e.active.gain)
73                     Music::pause();
74                 else
75                     Music::resume();
76             }
77             break;
78             }
79         case SDL_QUIT:
80             throw 0;
81             return false;
82         default:
83             ;
84         }
85     };
86     return true;
87 };
88 
89 class MainScreenAction : public gcn::ActionListener {
90 private:
91     ButtonPress * st;
92     bool * quit;
93     int * levelcount;
94     int leveltotal;
95 public:
MainScreenAction(ButtonPress * st,bool * q,int * levelcount,int leveltotal)96     MainScreenAction(ButtonPress * st,bool * q,int * levelcount,int leveltotal) :
97             st(st),quit(q),levelcount(levelcount),leveltotal(leveltotal) {};
action(const gcn::ActionEvent & actionEvent)98     void  action (const gcn::ActionEvent& actionEvent) {
99         const string id = actionEvent.getId();
100         if (sounds && id!="quit" && id!="play" && id!="levelup" && id!="leveldown") sounds->mainScreenMenuButtons.play();
101         if (id=="play") {
102             if (sounds) sounds->playButton.play();
103             *st=PLAYBT;
104             *quit=true;
105         } else if (id=="quit") {
106             *quit=true;
107         } else if (id=="scores") {
108             *st=SCORESBT;
109             *quit=true;
110         } else if (id=="levelup") {
111             if (leveltotal>0) {
112                 (*levelcount)++;
113                 *levelcount%=leveltotal;
114             }
115         } else if (id=="leveldown") {
116             if (leveltotal>0) {
117                 (*levelcount)+=leveltotal-1;
118                 *levelcount%=leveltotal;
119             }
120         } else if (id=="story") {
121             *st=STORYBT;
122             *quit=true;
123         } else if (id=="credits") {
124             *st=CREDITSBT;
125             *quit=true;
126         } else if (id=="scores") {
127             *st=SCORESBT;
128             *quit=true;
129         } else if (id=="options") {
130             *st=OPTIONSBT;
131             *quit=true;
132         } else if (id=="editor") {
133             *st=EDITORBT;
134             *quit=true;
135         } else if (id=="multiplayer") {
136             *st=MULTIPLAYERBT;
137             *quit=true;
138         }
139     }
140 };
141 
142 extern int mousePositionX;
143 extern int mousePositionY;
144 
145 class ImageButton : public gcn::Button {
146 public:
147     ImageButton(const std::string & label,const std::string & imgid);
148 
draw(gcn::Graphics * g)149     void draw(gcn::Graphics *g) {
150         int x=g->getCurrentClipArea().xOffset;
151         int y=g->getCurrentClipArea().yOffset;
152         img.setFrame(isPressed()?1:0);
153         img.draw(x,y);
154     }
155 private:
156     Graphic img;
157 };
158 
ImageButton(const std::string & label,const std::string & imgid)159 ImageButton::ImageButton(const std::string & label,const std::string & imgid) :
160         gcn::Button(label), img(imgid,false) {
161     setDimension(gcn::Rectangle(0,0,img.getWidth(),img.getHeight()));
162     setFrameSize(0);
163 };
164 
165 
166 class FontButton : public gcn::Button {
167 public:
168     FontButton(const std::string & label,const std::string & fontid,const std::string & fontgrayid);
169 
draw(gcn::Graphics * g)170     void draw(gcn::Graphics *g) {
171         int x=g->getCurrentClipArea().xOffset;
172         int y=g->getCurrentClipArea().yOffset;
173         if (isPressed()) font->draw(x,y,getCaption());
174         else fontgray->draw(x,y,getCaption());
175     }
176 
177 private:
178     RMFONTRef font;
179     RMFONTRef fontgray;
180 };
181 
FontButton(const std::string & label,const std::string & fontid,const std::string & fontgrayid)182 FontButton::FontButton(const std::string & label,const std::string & fontid,const std::string & fontgrayid) :
183         gcn::Button(label), font(fontid), fontgray(fontgrayid) {
184     setDimension(gcn::Rectangle(0,0,font->getWidth(label)+1,font->getHeight()));
185     setFrameSize(0);
186 };
187 
188 
mainScreen(int & levelcount,int leveltotal)189 ButtonPress mainScreen(int & levelcount,int leveltotal) {
190 
191     SDL_WM_SetCaption("Spacejunk","Spacejunk");
192     Graphic::setPalette("title",SDL_LOGPAL);
193 
194     gcn::SDLImageLoader imageLoader;
195     gcn::Image::setImageLoader(&imageLoader);
196 
197     gcn::SDLGraphics graphics;
198     graphics.setTarget(Graphic::getScreen());
199     RMFONTRef font("asimovgray20");
200 
201     //ImageFont font("fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
202     gcn::Widget::setGlobalFont(&*font);
203 
204     gcn::SDLInput input;
205     ButtonPress state=QUITBT;
206     bool quit=false;
207 
208     MainScreenAction a(&state,&quit,&levelcount,leveltotal);
209     //EditorControl ec;
210     LeftVerticalLayout c;
211     Graphic titlescreen("titlescreen",false,true);
212     Graphic mousepointer("mousepointer",false);
213     gcn::Label numlevel(getText("numlevelbt"));
214 
215     char s[5];
216     snprintf(s,5,"%2d",levelcount+1);
217     gcn::Label numl("00");
218     numl.setCaption(s);
219     FontButton ldown("<<","asimov20","asimovgray20"), lup(">>","asimov20","asimovgray20");
220     CenterHorizontalLayout levell(5);
221     ldown.setActionEventId("leveldown");
222     ldown.addActionListener(&a);
223     lup.setActionEventId("levelup");
224     lup.addActionListener(&a);
225     levell.add(&numlevel);
226     levell.add(&ldown);
227     levell.add(&numl);
228     levell.add(&lup);
229     levell.fitWidgets();
230 
231     FontButton bt(getText("playbt"),"asimov20","asimovgray20"),
232     btStory(getText("storybt"),"asimov20","asimovgray20"),
233     bt3(getText("scoresbt"),"asimov20","asimovgray20"),
234     bt5(getText("optionsbt"),"asimov20","asimovgray20"),
235     bt2(getText("quitbt"),"asimov20","asimovgray20"),
236     bt7(getText("creditsbt"),"asimov20","asimovgray20");
237     FontButton bt6(getText("leveleditorbt"),"asimov20","asimovgray20");
238     bt.setActionEventId("play");
239     bt.addActionListener(&a);
240     bt3.setActionEventId("scores");
241     bt3.addActionListener(&a);
242     bt6.setActionEventId("editor");
243     bt6.addActionListener(&a);
244     bt5.setActionEventId("options");
245     bt5.addActionListener(&a);
246     bt7.setActionEventId("credits");
247     bt7.addActionListener(&a);
248     bt2.setActionEventId("quit");
249     bt2.addActionListener(&a);
250     btStory.setActionEventId("story");
251     btStory.addActionListener(&a);
252     c.add(&bt);
253     c.add(&levell);
254     c.add(&btStory);
255     c.add(&bt5);
256     c.add(&bt3);
257     c.add(&bt6);
258     c.add(&bt7);
259     c.add(&bt2);
260     c.setOpaque(false);
261     c.fitWidgets();
262     c.setPosition(Graphic::toScreenx(395),Graphic::toScreeny(148));
263     gcn::Gui gui;
264     gui.setGraphics(&graphics);
265     gui.setInput(&input);
266     gui.setTop(&c);
267 
268     int nx,ny;
269     numl.getAbsolutePosition(nx,ny);
270     SDL_Rect numlrect = {Graphic::fromScreenx(nx),Graphic::fromScreeny(ny),
271                          int(numl.getWidth()/Graphic::getBaseScaleFactorX()),int(numl.getHeight()/Graphic::getBaseScaleFactorY())};
272     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
273     Fade fade;
274     fade.setMode(Fade::IN,1000);
275     bool endfade=false;
276     while (!quit && GUI_process_events(&input,&graphics)) {
277         titlescreen.draw(0,0);
278         gui.logic();
279         gui.draw();
280         if (!fade.step()) {
281             endfade=true;
282             break;
283         }
284         mousepointer.draw(mousePositionX,mousePositionY);
285 
286         Graphic::flip();
287         Graphic::sleep(20);
288     }
289     if (endfade) {
290         UPDATEbegin;
291         bool first=true;
292         while (!quit && GUI_process_events(&input,&graphics)) {
293             UPDATEOFF(titlescreen.draw(0,0));
294             gui.logic();
295 
296             char s[5];
297             snprintf(s,5,"%2d",levelcount+1);
298             numl.setCaption(s);
299             Graphic::updateRect(&numlrect);
300 
301             gui.draw();
302             mousepointer.draw(mousePositionX,mousePositionY);
303 
304             Graphic::flip(first);
305             first=false;
306             Graphic::sleep(20);
307         }
308         UPDATEend;
309     }
310     fade.setMode(Fade::OUT,state==PLAYBT?1000:500);
311     while (fade.getMode()!=Fade::NONE) {
312         GUI_process_events(&input,&graphics);
313         titlescreen.draw(0,0);
314         gui.logic();
315         gui.draw();
316         mousepointer.draw(mousePositionX,mousePositionY);
317         if (!fade.step()) break;
318 
319         Graphic::flip();
320         Graphic::sleep(20);
321     }
322 
323     return state;
324 };
325 
326 
fallen_process_events(int * state)327 bool fallen_process_events(int * state) {
328     SDL_Event e;
329     while (SDL_PollEvent(&e)) {
330         if (waitdelay>0) continue;
331         switch (e.type) {
332         case SDL_KEYDOWN:
333             switch (e.key.keysym.sym) {
334             case SDLK_ESCAPE:
335                 *state=0;
336                 return false;
337             default:
338                 *state=1;
339                 return false;
340             }
341             break;
342         case SDL_MOUSEBUTTONDOWN:
343             *state=1;
344             return false;
345         case SDL_ACTIVEEVENT: {
346             Uint8 st=SDL_GetAppState();
347             if (st & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) {
348                 if (!e.active.gain)
349                     Music::pause();
350                 else
351                     Music::resume();
352             }
353             break;
354             }
355         case SDL_QUIT:
356             throw 0;
357             *state=0;
358             return false;
359         default:
360             ;
361         }
362     };
363     return true;
364 }
365 
fallenScreen()366 bool fallenScreen() {
367 
368     RMFONTRef fr("24p");
369     Graphic planet("star3",false);
370     int state=0;
371     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
372     Graphic::flip();
373     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
374 
375     string text=getText("leveldied");
376     laststep=Graphic::ticks();
377     waitdelay=initwait;
378 
379     Fade f;
380     f.setMode(Fade::IN,1000);
381     while (fallen_process_events(&state)) {
382         planet.draw(Graphic::screencenter-Vector2d(125,325));
383         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y),text,FontRenderer::CENTER);
384         f.step();
385         Graphic::flip();
386         Graphic::sleep(40);
387 
388         int delta=Graphic::ticks()-laststep;
389         if (waitdelay<delta) waitdelay=0;
390         else waitdelay-=delta;
391         laststep+=delta;
392     }
393 
394     f.setMode(Fade::OUT,1000);
395     while (f.getMode()!=Fade::NONE) {
396         planet.draw(Graphic::screencenter-Vector2d(125,325));
397         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y),text,FontRenderer::CENTER);
398         f.step();
399         Graphic::flip();
400         Graphic::sleep(40);
401     }
402 
403     return state;
404 };
405 
406 
lastLevelScreen()407 void lastLevelScreen() {
408 
409     Music::play("final");
410 
411     RMFONTRef fr("24p");
412     Graphic ship("starship1",false);
413     Graphic trash("trash8");
414     Graphic trash1("trash6");
415     Graphic trash2("trash2");
416     Graphic g1("galaxia1",false);
417     Graphic g2("galaxia0grande",false);
418     Graphic g3("galaxia3",false);
419     Graphic s1("farstargroup1",false);
420     Graphic s2("farstargroup2",false);
421     Graphic s3("farstargroup3",false);
422     int state=0;
423     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
424     Graphic::flip();
425     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
426     string text=getText("endcongratulation");
427     int init=laststep=Graphic::ticks();
428     waitdelay=initwait;
429 
430     Fade f;
431     f.setMode(Fade::IN,1000);
432     while (fallen_process_events(&state)) {
433         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
434         g1.draw(50,400);
435         g2.draw(400,0);
436         g3.draw(50,50);
437         s1.draw(450,250);
438         s2.draw(100,350);
439         s2.draw(50,120);
440         s3.draw(250,250);
441         ship.draw(Graphic::screencenter-Vector2d(16,100+(laststep-init)*0.03));
442         trash.draw(int(Graphic::screencenter.x),int(Graphic::screencenter.y+100),1,(laststep-init)*0.05);
443         trash1.draw(100,50,1,(laststep-init)*0.1);
444         trash2.draw(500,100,1,(laststep-init)*0.2);
445         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y)-50,text,FontRenderer::CENTER);
446 
447         if (f.step()) break;
448         Graphic::flip();
449         Graphic::sleep(30);
450 
451         int delta=Graphic::ticks()-laststep;
452         if (waitdelay<delta) waitdelay=0;
453         else waitdelay-=delta;
454         laststep+=delta;
455     }
456 
457     UPDATEbegin;
458     while (fallen_process_events(&state)) {
459         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
460         UPDATEOFF(g1.draw(50,400));
461         UPDATEOFF(g2.draw(400,0));
462         UPDATEOFF(g3.draw(50,50));
463         UPDATEOFF(s1.draw(450,250));
464         UPDATEOFF(s2.draw(100,350));
465         UPDATEOFF(s2.draw(50,120));
466         UPDATEOFF(s3.draw(250,250));
467         ship.draw(Graphic::screencenter-Vector2d(16,100+(laststep-init)*0.03));
468         trash.draw(int(Graphic::screencenter.x),int(Graphic::screencenter.y+100),1,(laststep-init)*0.05);
469         trash1.draw(100,50,1,(laststep-init)*0.1);
470         trash2.draw(500,100,1,(laststep-init)*0.2);
471         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y)-50,text,FontRenderer::CENTER);
472 
473         Graphic::flip();
474         Graphic::sleep(30);
475 
476         int delta=Graphic::ticks()-laststep;
477         if (waitdelay<delta) waitdelay=0;
478         else waitdelay-=delta;
479         laststep+=delta;
480     }
481     UPDATEend;
482 
483     f.setMode(Fade::OUT,500);
484     while (f.getMode()!=Fade::NONE) {
485         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
486         g1.draw(50,400);
487         g2.draw(400,0);
488         g3.draw(50,50);
489         s1.draw(450,250);
490         s2.draw(100,350);
491         s2.draw(50,120);
492         s3.draw(250,250);
493         ship.draw(Graphic::screencenter-Vector2d(16,100+(laststep-init)*0.03));
494         trash.draw(int(Graphic::screencenter.x),int(Graphic::screencenter.y)+100,1,(laststep-initwait)*0.05);
495         trash1.draw(100,50,1,(laststep-init)*0.1);
496         trash2.draw(500,100,1,(laststep-init)*0.2);
497         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y)-50,text,FontRenderer::CENTER);
498         f.step();
499         Graphic::flip();
500         Graphic::sleep(40);
501 
502         int delta=Graphic::ticks()-laststep;
503         laststep+=delta;
504     }
505 };
506 
scoreScreen(const ScoreList & scorelist)507 void scoreScreen(const ScoreList &scorelist) {
508     RMFONTRef fr("12p");
509     RMFONTRef fr2("asimov27");
510     fr->linespacing=15;
511     int state=0;
512     Graphic background("scorescreen",false);
513     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
514     string names=scorelist.getNames();
515     string points=scorelist.getPoints();
516     string title=getText("scoresbt");
517 
518     Fade f;
519     f.setMode(Fade::IN,1000);
520     while (fallen_process_events(&state)) {
521         background.draw(0,0);
522         fr->drawL(195,125,names);
523         fr->drawL(450,125,points,FontRenderer::RIGHT);
524         fr2->drawL((640-fr2->getWidth(title))/2,50,title);
525         f.step();
526         Graphic::flip();
527         Graphic::sleep(40);
528     }
529     f.setMode(Fade::OUT,500);
530     while (f.getMode()!=Fade::NONE) {
531         background.draw(0,0);
532         fr->drawL(195,125,names);
533         fr->drawL(450,125,points,FontRenderer::RIGHT);
534         fr2->drawL((640-fr2->getWidth(title))/2,50,title);
535         f.step();
536         Graphic::flip();
537         Graphic::sleep(40);
538     }
539 };
540 
enter_score_process_events(sge_TextEditor & text)541 bool enter_score_process_events(sge_TextEditor & text) {
542     SDL_Event e;
543     while (SDL_PollEvent(&e)) {
544         switch (e.type) {
545         case SDL_KEYDOWN:
546             switch (e.key.keysym.sym) {
547             case SDLK_QUOTEDBL:
548                 break;
549             case SDLK_RETURN:
550                 if (sounds) sounds->typeEnter.play();
551             case SDLK_ESCAPE:
552                 if (text.get_string(false).length()>0 && sounds)
553                     sounds->typeEnter.play();
554                 return false;
555             case SDLK_DELETE:
556             case SDLK_BACKSPACE:
557             case SDLK_RSHIFT:
558             case SDLK_LSHIFT:
559             case SDLK_LEFT:
560             case SDLK_RIGHT:
561                 text.check(&e);
562                 break;
563             default:
564                 if (text.get_string(false).length()<30) {
565                     if (sounds && e.key.keysym.unicode!=0)
566                         sounds->typeNotEnter.play();
567                     text.check(&e);
568                 }
569             }
570             break;
571         case SDL_ACTIVEEVENT: {
572             Uint8 st=SDL_GetAppState();
573             if (st & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) {
574                 if (!e.active.gain)
575                     Music::pause();
576                 else
577                     Music::resume();
578             }
579             break;
580             }
581         case SDL_QUIT:
582             throw 0;
583             return false;
584         default:
585             text.check(&e);
586         }
587     };
588     return true;
589 }
590 
remapwsUint16(Uint16 * str)591 string remapwsUint16(Uint16*str) {
592     basic_string<wchar_t> s;
593     for (;*str;str++)
594         s+=*str;
595     return wstos(s);
596 }
597 
enterScoreScreen(ScoreList * scorelist,int playerPoints)598 void enterScoreScreen(ScoreList * scorelist,int playerPoints) {
599     if (playerPoints<=0 || (!scorelist->inside(playerPoints) && scorelist->size()>=14)) return;
600 
601     Graphic background("scorescreen",false);
602     RMFONTRef fr("12p");
603     fr->linespacing=15;
604     SDL_Rect r={0,0,LOGICAL_WIDTH,LOGICAL_HEIGHT};
605     ScoreList::iterator i=scorelist->setScore("",playerPoints);
606     int posy=scorelist->position(i)*(fr->getHeight()+fr->linespacing);
607     while (scorelist->size()>14) {
608         scorelist->erase_last();
609     }
610 
611     string names=scorelist->getNames();
612     string points=scorelist->getPoints();
613     sge_TextEditor text;
614 
615     Uint16 * t;
616     Fade f;
617     f.setMode(Fade::IN,1000);
618     while (enter_score_process_events(text)) {
619         SDL_FillRect(Graphic::getScreen(),&r,SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
620         background.draw(0,0);
621         fr->drawL(195,125,names);
622         t=text.get_ucstring((Graphic::ticks()/300)%2);
623         fr->drawLine(Graphic::toScreenx(195),Graphic::toScreeny(125)+posy,remapwsUint16(t));
624         delete t;
625         fr->drawL(450,125,points,FontRenderer::RIGHT);
626         f.step();
627         Graphic::flip();
628         Graphic::sleep(40);
629     }
630     t=text.get_ucstring(false);
631     if (*t!=L'\0')
632         scorelist->setName(remapwsUint16(t),i);
633     else
634         scorelist->erase(i);
635     delete t;
636 
637     f.setMode(Fade::OUT,500);
638     while (f.getMode()!=Fade::NONE) {
639         SDL_FillRect(Graphic::getScreen(),&r,SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
640         background.draw(0,0);
641         fr->drawL(195,125,names);
642         t=text.get_ucstring();
643         fr->drawLine(Graphic::toScreenx(195),Graphic::toScreeny(125)+posy,remapwsUint16(t));
644         delete t;
645         fr->drawL(450,125,points,FontRenderer::RIGHT);
646         f.step();
647         Graphic::flip();
648         Graphic::sleep(40);
649     }
650 };
651 
652 
countLines(const std::string & text)653 int countLines(const std::string& text) {
654     int count=0;
655     for(unsigned int i=0;i<text.length();i++) {
656         if (text[i]=='\n')
657             count++;
658     }
659     return count;
660 }
661 
662 
storyScreen()663 void storyScreen() {
664     RMFONTRef fr("24p");
665     RMFONTRef fr2("asimov27");
666     int state=0;
667     Graphic background("storyscreen",false);
668     string story=getText("story");
669     string title=getText("storybt");
670 
671     /*******************************************
672      Get the text on a temporal surface
673     *******************************************/
674     SDL_Surface * screen=Graphic::getScreen();
675     SDL_Surface * temp=Graphic::createSurface(Graphic::toScreenw(400),Graphic::toScreenh(520));
676     SDL_FillRect(temp,NULL,SDL_MapRGB(screen->format, 0x00, 0x00, 0x00));
677     fr->s=temp;
678     fr->draw(0,0,story);
679     fr->s=NULL;
680 
681     const int textheight = (fr->getHeight()+fr->linespacing)*countLines(story);
682     const int windowheight = LOGICAL_HEIGHT-(150+50);
683     const bool drawfull = textheight/Graphic::getBaseScaleFactorY()<=windowheight;
684     SDL_Rect orig={0,-windowheight,400,windowheight};
685     SDL_Rect dest={175,150,400,windowheight};
686     ImageScroller imgs(temp,orig,0.010);
687 
688 
689     /*******************************************
690       Fade In
691     *******************************************/
692 
693     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
694     Fade f;
695     f.setMode(Fade::IN,1000);
696     while (fallen_process_events(&state)) {
697         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
698         background.draw(0,0);
699         fr2->drawL(265,91,title);
700         if (drawfull)
701             imgs.draw(Graphic::getScreen(),175,dest.y,drawfull);
702         if (!f.step())
703             break;
704         Graphic::flip();
705         Graphic::sleep(30);
706     }
707 
708     imgs.reset();
709     bool first = true;
710     UPDATEbegin
711     while (fallen_process_events(&state)) {
712         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
713         UPDATEOFF(background.draw(0,0);fr2->drawL(265,91,title));
714         imgs.draw(Graphic::getScreen(),175,dest.y,drawfull);
715         Graphic::updateRect(&dest);
716         Graphic::flip(first);
717         first = false;
718         Graphic::sleep(30);
719     }
720     UPDATEend
721 
722     f.setMode(Fade::OUT,500);
723     while (f.getMode()!=Fade::NONE) {
724         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
725         background.draw(0,0);
726         fr2->drawL(265,91,title);
727         imgs.draw(Graphic::getScreen(),175,dest.y,drawfull);
728         f.step();
729         Graphic::flip();
730         Graphic::sleep(30);
731     }
732 
733     SDL_FreeSurface(temp);
734 };
735 
creditsScreen()736 void creditsScreen() {
737     RMFONTRef fr("asimovgray20");
738     RMFONTRef fr2("asimov27");
739     int state=0;
740     Graphic background("storyscreen",false);
741     string credittitles=getText("credittitles");
742     string creditnames=getText("creditnames");
743     string title=getText("creditsbt");
744 
745     /*******************************************
746      Get the text on a temporal surface
747     *******************************************/
748     SDL_Surface * screen=Graphic::getScreen();
749     SDL_Surface * temp=Graphic::createSurface(Graphic::toScreenw(400),Graphic::toScreenh(520));
750     SDL_FillRect(temp,NULL,SDL_MapRGB(screen->format, 0x00, 0x00, 0x00));
751     fr->s=temp;
752     fr->draw(Graphic::toScreenw(175),0,credittitles,FontRenderer::CENTER);
753     fr->s=NULL;
754     fr=RMFONTRef("asimov20");
755     fr->s=temp;
756     fr->draw(Graphic::toScreenw(175),0,creditnames,FontRenderer::CENTER);
757     fr->s=NULL;
758 
759     /*******************************************
760       Fade In
761     *******************************************/
762 
763     Fade f;
764     f.setMode(Fade::IN,1000);
765     while (fallen_process_events(&state)) {
766         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
767         background.draw(0,0);
768         fr2->drawL(275,91,title);
769         if (!f.step()) break;
770         Graphic::flip();
771         Graphic::sleep(30);
772     }
773 
774     const int windowheight = LOGICAL_HEIGHT-(150+50);
775     SDL_Rect orig={0,-windowheight,400,windowheight};
776     SDL_Rect dest={150,150,400,windowheight};
777     ImageScroller imgs(temp,orig,0.015);
778 
779     UPDATEbegin
780     while (fallen_process_events(&state)) {
781         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
782         UPDATEOFF(background.draw(0,0));
783         UPDATEOFF(fr2->drawL(275,91,title));
784         imgs.draw(Graphic::getScreen(),dest.x,dest.y,false);
785         Graphic::updateRect(&dest);
786         Graphic::flip(false);
787         Graphic::sleep(30);
788     }
789     UPDATEend
790 
791     f.setMode(Fade::OUT,500);
792     while (f.getMode()!=Fade::NONE) {
793         Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
794         background.draw(0,0);
795         fr2->drawL(275,91,title);
796         imgs.draw(Graphic::getScreen(),dest.x,dest.y,false);
797         f.step();
798         Graphic::flip();
799         Graphic::sleep(30);
800     }
801 
802     SDL_FreeSurface(temp);
803 };
804 
giveUpScreen()805 bool giveUpScreen() {
806     RMFONTRef fr("24p");
807     Graphic planet("planet1",false);
808     int state=0;
809     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
810     Graphic::flip();
811     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
812     string text=getText("giveup");
813 
814     Fade f;
815     f.setMode(Fade::IN,1000);
816     while (fallen_process_events(&state)) {
817         planet.draw(Graphic::screencenter-Vector2d(50,150));
818         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y),text,FontRenderer::CENTER);
819         f.step();
820         Graphic::flip();
821         Graphic::sleep(40);
822     }
823 
824     f.setMode(Fade::OUT,500);
825     while (f.getMode()!=Fade::NONE) {
826         planet.draw(Graphic::screencenter-Vector2d(50,150));
827         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y),text,FontRenderer::CENTER);
828         f.step();
829         Graphic::flip();
830         Graphic::sleep(40);
831     }
832 
833     return state;
834 };
835 
missionFailedScreen()836 bool missionFailedScreen() {
837     RMFONTRef fr("24p");
838     Graphic planet("nebula1",false);
839     int state=0;
840     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
841     Graphic::flip();
842     Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0));
843 
844     string text=getText("missionFailed");
845     laststep=Graphic::ticks();
846     waitdelay=initwait;
847 
848     Fade f;
849     f.setMode(Fade::IN,1000);
850     while (fallen_process_events(&state)) {
851         planet.draw(Graphic::screencenter-Vector2d(75,175));
852         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y),text,FontRenderer::CENTER);
853         f.step();
854         Graphic::flip();
855         Graphic::sleep(40);
856 
857         int delta=Graphic::ticks()-laststep;
858         if (waitdelay<delta) waitdelay=0;
859         else waitdelay-=delta;
860         laststep+=delta;
861     }
862 
863     f.setMode(Fade::OUT,500);
864     while (f.getMode()!=Fade::NONE) {
865         planet.draw(Graphic::screencenter-Vector2d(75,175));
866         fr->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y),text,FontRenderer::CENTER);
867         f.step();
868         Graphic::flip();
869         Graphic::sleep(40);
870     }
871 
872     return state;
873 };
874 
875 
876 
congratulation_process_events(int * state)877 bool congratulation_process_events(int * state) {
878     SDL_Event e;
879     while (SDL_PollEvent(&e)) {
880         if (waitdelay>0) continue;
881         switch (e.type) {
882         case SDL_KEYDOWN:
883             switch (e.key.keysym.sym) {
884             default:
885                 *state=1;
886                 return false;
887             }
888             break;
889         case SDL_MOUSEBUTTONDOWN:
890             *state=1;
891             return false;
892         case SDL_ACTIVEEVENT: {
893             Uint8 st=SDL_GetAppState();
894             if (st & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) {
895                 if (!e.active.gain)
896                     Music::pause();
897                 else
898                     Music::resume();
899             }
900             break;
901         }
902         case SDL_QUIT:
903             throw 0;
904             *state=0;
905             return false;
906         default:
907             ;
908         }
909     };
910     return true;
911 }
912 
913 
914 #define drawsumary Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0)); \
915   UPDATEOFF(planet.draw(500,250));                  \
916   UPDATEOFF(planet2.draw(200,200));                 \
917   UPDATEOFF(farstar.draw(600,50));                  \
918   UPDATEOFF(farstar.draw(350,150));                 \
919   UPDATEOFF(farstar.draw(100,100));                 \
920   UPDATEOFF(farstar.draw(300,430));                 \
921   fuelbar.draw(units/TOTALFUELPOINTS);                  \
922   UPDATEOFF(scoredisplay.draw((LOGICAL_WIDTH-scoredisplay.getWidth())/2,0)); \
923   UPDATEOFF(shipcontrol.draw(0,LOGICAL_HEIGHT-shipcontrol.getHeight())); \
924   o.str("");                                \
925   o<<bonus;                             \
926   fr->drawL(380,5,o.str(),FontRenderer::RIGHT);             \
927   o.str("");                                \
928   o<<*score;                                \
929   fr->drawL(240,5,o.str(),FontRenderer::RIGHT);             \
930   fr->drawL(520,5,"0",FontRenderer::RIGHT);             \
931   fr2->drawL(int(Graphic::screencenter.x),int(Graphic::screencenter.y)-170,text,FontRenderer::CENTER); \
932   UPDATEOFF(font24pgray->drawL(scorelabelx,1,scorelabel));   \
933   UPDATEOFF(font24pgray->drawL(bonuslabelx,1,bonuslabel));  \
934   UPDATEOFF(font24pgray->drawL(collectlabelx,1,collectlabel));
935 
936 #define TOTALFUELPOINTS (50.0)
937 #define DISCOUNTUNIT (25)
938 
sumaryScreen(real fuel,real maxFuel,int bonus,int * score)939 bool sumaryScreen(real fuel,real maxFuel,int bonus,int * score) {
940 
941     Music::play("success");
942 
943     FuelBar fuelbar;
944     RMFONTRef fr("12p");
945     RMFONTRef fr2("24p");
946     RMFONTRef font24pgray("24pgray");
947 
948     string scorelabel=getText("scorelabel");
949     string bonuslabel=getText("bonuslabel");
950     string collectlabel=getText("collectlabel");
951 
952     Graphic planet("star2",false);
953     Graphic planet2("planet2",false);
954     Graphic farstar("farstar1",false);
955 
956     Graphic scoredisplay("scoredisplay",false);
957     Graphic shipcontrol("controlpanel",false);
958     string text=getText("levelcongratulation");
959 
960     int scorex = (LOGICAL_WIDTH-scoredisplay.getWidth())/2;
961     int scorelabelx = scorex + 59;
962     int bonuslabelx = scorex + 200;
963     int collectlabelx = scorex + 343;
964 
965 
966     int units=int(floor(fuel*TOTALFUELPOINTS/maxFuel));
967     int unitTime=0;
968     int delta;
969     int state=0;
970     waitdelay=initwait;
971 
972     ostringstream o;
973 
974     Fade f;
975     f.setMode(Fade::IN,1000);
976     while (f.getMode()!=Fade::NONE) {
977         drawsumary;
978         f.step();
979         Graphic::flip();
980     }
981 
982     laststep=Graphic::ticks();
983     delta=50;
984 
985     if (sounds) sounds->timeBack.play();
986 
987     while (congratulation_process_events(&state)) {
988         drawsumary;
989         Graphic::flip();
990 
991         if (units>0) {
992             unitTime+=delta;
993             if (unitTime>=DISCOUNTUNIT) {
994                 int addunits=unitTime/DISCOUNTUNIT;
995                 if (units<addunits) addunits=units;
996 
997                 units-=addunits;
998                 *score+=addunits;
999                 unitTime%=DISCOUNTUNIT;
1000             }
1001         } else if (bonus>0) {
1002             unitTime+=delta;
1003             if (unitTime>=DISCOUNTUNIT) {
1004                 int addunits=unitTime/DISCOUNTUNIT;
1005                 if (bonus<addunits) addunits=bonus;
1006 
1007                 bonus-=addunits;
1008                 *score+=addunits;
1009                 unitTime%=DISCOUNTUNIT;
1010             }
1011             if (bonus<=0 && sounds) sounds->timeBack.stop();
1012         }
1013 
1014         delta=Graphic::ticks()-laststep;
1015         if (delta<45) Graphic::sleep(45-delta);
1016         delta=Graphic::ticks()-laststep;
1017         if (waitdelay<delta) waitdelay=0;
1018         else waitdelay-=delta;
1019         laststep+=delta;
1020     }
1021 
1022     *score+=units;
1023     *score+=bonus;
1024 
1025     f.setMode(Fade::OUT,500);
1026     while (f.getMode()!=Fade::NONE) {
1027         drawsumary;
1028         f.step();
1029         Graphic::flip();
1030     }
1031 
1032     return state;
1033 };
1034 
1035 
1036 class ImageSlider : public gcn::Slider {
1037 public:
1038     ImageSlider(float inf,float sup,const std::string & imgid);
1039 
setValue(double value)1040     void setValue(double value) {
1041         if (value>getScaleEnd())
1042             gcn::Slider::setValue(getScaleEnd());
1043         else if (value<getScaleStart())
1044             gcn::Slider::setValue(getScaleStart());
1045         else
1046             gcn::Slider::setValue(value);
1047     }
1048 
drawMarker(gcn::Graphics * g)1049     void drawMarker(gcn::Graphics *g) {
1050         int x=g->getCurrentClipArea().xOffset;
1051         int y=g->getCurrentClipArea().yOffset;
1052         img.draw(int(1+Graphic::fromScreenx(int(x+getMarkerLength()/2+getValue()*(getWidth()-getMarkerLength()-1)/(getScaleEnd()-getScaleStart())))),Graphic::fromScreeny(y));
1053     }
1054 
draw(gcn::Graphics * g)1055     void draw(gcn::Graphics * g) {
1056         drawMarker(g);
1057     };
1058 
1059 private:
1060     Graphic img;
1061 };
1062 
ImageSlider(float inf,float sup,const std::string & imgid)1063 ImageSlider::ImageSlider(float inf,float sup,const std::string & imgid) :
1064         gcn::Slider(inf,sup), img(imgid,false) {
1065     setMarkerLength(Graphic::toScreenw(img.getWidth()+10));
1066     setFrameSize(0);
1067     img.hotspot=Vector2d(img.getWidth()/2,0);
1068 };
1069 
1070 
1071 class SldListener : public gcn::MouseListener {
1072 public:
SldListener()1073     SldListener() {};
mouseReleased(gcn::MouseEvent & e)1074     void mouseReleased(gcn::MouseEvent& e) {
1075         if (sounds)
1076             sounds->typeEnter.play();
1077     }
1078 };
1079 
1080 class OptionsAction : public gcn::ActionListener {
1081 public:
1082     bool * quit;
1083     int * musvol, * fxvol;
1084     ImageSlider fxvolume,musicvolume;
1085     SldListener sldl;
1086 
OptionsAction(bool * q,int * musvol,int * fxvol)1087     OptionsAction(bool * q, int * musvol, int * fxvol) :
1088             quit(q), musvol(musvol), fxvol(fxvol),
1089             fxvolume(0,100,"soundslidermarker"),
1090             musicvolume(0,128,"soundslidermarker") {
1091         fxvolume.setActionEventId("fxvolume");
1092         fxvolume.setValue(Soundfx::getOverallVolume());
1093         fxvolume.addActionListener(this);
1094         fxvolume.addMouseListener(&sldl);
1095         fxvolume.setDimension(gcn::Rectangle(Graphic::toScreenx(344),Graphic::toScreeny(237),
1096                                              Graphic::toScreenw(79),Graphic::toScreenh(16)));
1097         musicvolume.setActionEventId("musicvolume");
1098         musicvolume.setValue(Music::getVolume());
1099         musicvolume.addActionListener(this);
1100         musicvolume.setDimension(gcn::Rectangle(Graphic::toScreenx(344),Graphic::toScreeny(213),
1101                                                 Graphic::toScreenw(79),Graphic::toScreenh(16)));
1102     };
action(const gcn::ActionEvent & e)1103     void  action (const gcn::ActionEvent& e) {
1104         const string id = e.getId();
1105         if (id=="done") {
1106             if (sounds) sounds->mainScreenMenuButtons.play();
1107             *quit=true;
1108         } else if (id=="musicvolume") {
1109             Music::setVolume(Uint8(musicvolume.getValue()));
1110             *musvol=Uint8(musicvolume.getValue());
1111         } else if (id=="fxvolume") {
1112             Soundfx::setOverallVolume(Uint8(fxvolume.getValue()));
1113             *fxvol=Uint8(fxvolume.getValue());
1114         }
1115     }
1116 };
1117 
optionsScreen(int * musvolume,int * fxvolume)1118 void optionsScreen(int * musvolume, int * fxvolume) {
1119 
1120     gcn::SDLImageLoader imageLoader;
1121     gcn::Image::setImageLoader(&imageLoader);
1122 
1123     gcn::SDLGraphics graphics;
1124     graphics.setTarget(Graphic::getScreen());
1125     RMFONTRef font("12p");
1126     RMFONTRef font24("24pgray");
1127     RMFONTRef fr2("asimov27");
1128 
1129     gcn::Widget::setGlobalFont(&*font);
1130 
1131     gcn::SDLInput input;
1132     bool quit=false;
1133 
1134     string title = getText("optionsbt");
1135     string musiclabel = getText("musiclabel");
1136     string fxlabel = getText("fxlabel");
1137 
1138     OptionsAction a(&quit,musvolume,fxvolume);
1139 
1140     Graphic background("soundscreen",false);
1141     Layout c;
1142     Graphic mousepointer("mousepointer",false);
1143     FontButton bt(getText("donebt"),"asimov20","asimovgray20");
1144     bt.setActionEventId("done");
1145     bt.addActionListener(&a);
1146     bt.setPosition(Graphic::toScreenx(285),Graphic::toScreeny(370));
1147     c.add(&a.musicvolume);
1148     c.add(&a.fxvolume);
1149     c.add(&bt);
1150     c.setOpaque(false);
1151     c.fitWidgets();
1152     gcn::Gui gui;
1153     gui.setGraphics(&graphics);
1154     gui.setInput(&input);
1155     gui.setTop(&c);
1156 
1157     Fade f;
1158     bool fullupdate=true;
1159     f.setMode(Fade::IN,1000);
1160     while (!quit && GUI_process_events(&input,&graphics)) {
1161         UPDATEOFF(Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0)));
1162         UPDATEOFF(background.draw(0,0));
1163         fr2->drawL(int(LOGICAL_WIDTH-fr2->getWidth(title)/Graphic::getBaseScaleFactorX())/2,147,title);
1164         font24->drawL(int(LOGICAL_WIDTH/2-10-font24->getWidth(musiclabel)/Graphic::getBaseScaleFactorX()),206,musiclabel);
1165         font24->drawL(int(LOGICAL_WIDTH/2-10-font24->getWidth(fxlabel)/Graphic::getBaseScaleFactorX()),229,fxlabel);
1166         gui.logic();
1167         gui.draw();
1168         f.step();
1169         mousepointer.draw(mousePositionX,mousePositionY);
1170 
1171         Graphic::flip(fullupdate);
1172         fullupdate = f.getMode()!=Fade::NONE;
1173         Graphic::sleep(20);
1174     }
1175 
1176     f.setMode(Fade::OUT,500);
1177     while (f.getMode()!=Fade::NONE) {
1178         UPDATEOFF(Graphic::clearScreen(SDL_MapRGB(Graphic::getScreen()->format, 0, 0,0)));
1179         UPDATEOFF(background.draw(0,0));
1180         fr2->drawL(int(LOGICAL_WIDTH-fr2->getWidth(title)/Graphic::getBaseScaleFactorX())/2,147,title);
1181         font24->drawL(int(LOGICAL_WIDTH/2-10-font24->getWidth(musiclabel)/Graphic::getBaseScaleFactorX()),206,musiclabel);
1182         font24->drawL(int(LOGICAL_WIDTH/2-10-font24->getWidth(fxlabel)/Graphic::getBaseScaleFactorX()),229,fxlabel);
1183         gui.draw();
1184         mousepointer.draw(mousePositionX,mousePositionY);
1185         f.step();
1186         Graphic::flip();
1187     }
1188 };
1189