1 /*
2 * Zaz
3 * Copyright (C) Remigiusz Dybka 2009 <remigiusz.dybka@gmail.com>
4 *
5 Zaz is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Zaz is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "mainmenu.h"
20 #include "textureloader.h"
21 #include "game.h"
22 #include "sample.h"
23 #include "gameloop.h"
24 #include "profile.h"
25 #include "directorylister.h"
26 #include <cstdio>
27
MainMenu(SDL_Surface * surf,uint fps)28 MainMenu::MainMenu(SDL_Surface *surf, uint fps)
29 :Scenes::Scene(surf, fps), currentMenu(&startMenu),
30 menuLev(settings.getCFilename("menu.lvl")), nBallPaths(menuLev.paths.size() - 1), music(NULL),
31 renderHiscores(true), showCredits(false), showBrowser(false), showProfiles(false), showNewProfile(false), showSets(false),
32 oldFullscreen(settings.getb("fullscreen", false)),
33 oldRes(settings.get("resolution", "")), oldMusicVol(atoi(settings.get("musicVolume", "50").c_str())),
34 oldLanguage(settings.get("language", "")),startup(true), browserSelectedLevel(-1), browserUsedKeyboard(false)
35 {
36 startMenu.Add(new GenericMenuItem(_("Start game"), startMenuStartHandler, this));
37 startMenu.Add(new GenericMenuItem(_("Options"), startMenuOptionsHandler, this));
38 startMenu.Add(new GenericMenuItem(_("Credits"), startMenuCreditsHandler, this));
39 startMenu.Add(new GenericMenuItem(_("Exit"), startMenuExitHandler, this));
40 startMenu.Add(new GenericMenuItem(_("Profile:") + profile.getName(), startMenuShowProfilesHandler, this));
41
42 startMenu.SetDimensions(60, 40, 40);
43
44 startMenu.items[4]->width = 80;
45 startMenu.items[4]->y = 6;
46 startMenu.items[4]->x = 10;
47
48 creditsMenu.Add(new GenericMenuItem(_("Back"), menuBackHandler, this));
49 creditsMenu.SetDimensions(30, 10, 40);
50
51 std::vector<std::string>game_types;
52
53 game_types.push_back(_("Sequential"));
54 game_types.push_back(_("Survival"));
55
56 browserMenu.Add(new GenericMenuItem(_("Back"), menuBackHandler, this));
57 browserMenu.Add(new GenericMenuItem("<<", browserMenuRightHandler, this));
58 browserMenu.Add(new GenericMenuItem(">>", browserMenuLeftHandler, this));
59 browserMenu.Add(new OptionMenuItem(_("Game type:"), game_types, "game_type"));
60
61 browserMenu.SetDimensions(30, 6, 40);
62
63 browserMenu.items[1]->x = 10;
64 browserMenu.items[1]->width = 10;
65 browserMenu.items[1]->y = 11;
66
67 browserMenu.items[2]->x = 80;
68 browserMenu.items[2]->width = 10;
69 browserMenu.items[2]->y = 11;
70
71 browserMenu.items[3]->x = 20;
72 browserMenu.items[3]->width = 60;
73 browserMenu.items[3]->y = 45;
74
75 profileActionsMenu.Add(new GenericMenuItem(_("New profile"), profileActionsMenuNewHandler, this));
76 profileActionsMenu.Add(new GenericMenuItem(_("Delete"), profileActionsMenuDeleteHandler, this));
77 // profileActionsMenu.Add(new GenericMenuItem(_("Use"), profileActionsMenuUseHandler, this));
78
79 profileActionsMenu.SetDimensions(0, 10, 30);
80
81 profileActionsMenu.items[0]->y = 10;
82 profileActionsMenu.items[0]->x = 30;
83 profileActionsMenu.items[0]->width = 40;
84
85 for (int p = 0; p < nBallPaths; p++)
86 {
87 bp.push_back(BallPath(menuLev.paths[p + 1], ballText, 0));
88 bp[p].state.feedRate = 2;
89 bp[p].state.colors = 16;
90 bp[p].state.ballsToDraw = -1;
91 bp[p].state.ballsFromStart = 0;
92 }
93
94 lmx = lmy = 0;
95
96 setNames = LevelSet::getSetNames();
97 nleveldesc = 0;
98
99 hiScoreRep = hiScores.GenerateReport(linesPerHiScorePage);
100 hiScorePage = 0;
101 hiScoreTimeout = hiScoreWaitPageSec * desiredFPS;
102
103 CreateOptionsMenu();
104 CreateCredits();
105 creditsScroll = creditsScrollClearance * -1;
106 }
107
CreateCredits()108 void MainMenu::CreateCredits()
109 {
110 credits.push_back(CreditsLine(string("Zaz ") + VERSION, true));
111 credits.push_back(CreditsLine("-"));
112 credits.push_back(CreditsLine(_("code, gfx, snd & design:")));
113 credits.push_back(CreditsLine(_("Remigiusz Dybka"), true));
114 credits.push_back(CreditsLine(_("[remigiusz.dybka@gmail.com] Released under GPLv3 License")));
115 credits.push_back(CreditsLine("-"));
116 credits.push_back(CreditsLine(_("music:")));
117 credits.push_back(CreditsLine(_("paniq - Leonard Ritter"), true));
118 credits.push_back(CreditsLine(_("[http://www.paniq.org] Released under CC BY-SA License")));
119 credits.push_back(CreditsLine("-"));
120 credits.push_back(CreditsLine(_("quality assurance:")));
121 credits.push_back(CreditsLine(_("Kinga Dybka"), true));
122 credits.push_back(CreditsLine(_("Michael Sterrett"), true));
123 credits.push_back(CreditsLine("-"));
124 credits.push_back(CreditsLine("-"));
125 credits.push_back(CreditsLine(_("translations:"), true));
126 credits.push_back(CreditsLine("-"));
127 credits.push_back(CreditsLine(_("German:")));
128 credits.push_back(CreditsLine(_("Frederik Schwarzer"), true));
129 credits.push_back(CreditsLine("-"));
130 credits.push_back(CreditsLine(_("Spanish:")));
131 credits.push_back(CreditsLine(_("Dámaso Domínguez (AmiSpaTra)"), true));
132 credits.push_back(CreditsLine("-"));
133 credits.push_back(CreditsLine(_("French:")));
134 credits.push_back(CreditsLine(_("Nouvel Hugues"), true));
135 credits.push_back(CreditsLine("-"));
136 credits.push_back(CreditsLine(_("Hungarian:")));
137 credits.push_back(CreditsLine(_("Gabor Kmetyko"), true));
138 credits.push_back(CreditsLine("-"));
139 credits.push_back(CreditsLine(_("Italian:")));
140 credits.push_back(CreditsLine(_("Andrea Musuruane"), true));
141 credits.push_back(CreditsLine("-"));
142 credits.push_back(CreditsLine(_("Russian:")));
143 credits.push_back(CreditsLine(_("Николай Рощупкин"), true));
144 credits.push_back(CreditsLine("-"));
145 credits.push_back(CreditsLine(_("Turkish:")));
146 credits.push_back(CreditsLine(_("Anıl Özbek"), true));
147 credits.push_back(CreditsLine("-"));
148 credits.push_back(CreditsLine("-"));
149 credits.push_back(CreditsLine(_("additional coding:")));
150 credits.push_back(CreditsLine(_("Nouvel Hugues"), true));
151 credits.push_back(CreditsLine("-"));
152 credits.push_back(CreditsLine(_("additional testing:")));
153 credits.push_back(CreditsLine(_("Irena Klon"), true));
154 credits.push_back(CreditsLine(_("Kamil Krzyspiak"), true));
155 credits.push_back(CreditsLine(_("Mateusz Jakubowski"), true));
156 credits.push_back(CreditsLine("-"));
157 credits.push_back(CreditsLine("Copyright (C) Remigiusz Dybka 2009-2010 <remigiusz.dybka@gmail.com>"));
158 credits.push_back(CreditsLine("-"));
159 credits.push_back(CreditsLine("Zaz is free software: you can redistribute it and/or modify it"));
160 credits.push_back(CreditsLine("under the terms of the GNU General Public License as published by the"));
161 credits.push_back(CreditsLine("Free Software Foundation, either version 3 of the License, or"));
162 credits.push_back(CreditsLine("(at your option) any later version."));
163 credits.push_back(CreditsLine("-"));
164 credits.push_back(CreditsLine("Zaz is distributed in the hope that it will be useful, but"));
165 credits.push_back(CreditsLine("WITHOUT ANY WARRANTY; without even the implied warranty of"));
166 credits.push_back(CreditsLine("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."));
167 credits.push_back(CreditsLine("See the GNU General Public License for more details."));
168 credits.push_back(CreditsLine("-"));
169 credits.push_back(CreditsLine("You should have received a copy of the GNU General Public License along"));
170 credits.push_back(CreditsLine("with this program. If not, see <http://www.gnu.org/licenses/>."));
171 }
172
CreateOptionsMenu()173 void MainMenu::CreateOptionsMenu()
174 {
175 optionsMenu.Clear();
176
177 std::vector<std::string>resolutions;
178 std::vector<std::string>tempRes;
179
180 for (uint m = 0; screenModes[m]; ++m)
181 {
182 stringstream sm;
183 sm << screenModes[m]->w << "x" << screenModes[m]->h;
184
185 tempRes.push_back(sm.str());
186 }
187
188 // reverse the resolutions
189 for (int m = (unsigned int)tempRes.size() - 1; m >= 0; m--)
190 {
191 resolutions.push_back(tempRes[m]);
192 }
193
194 int y = 9;
195
196 #ifdef ENABLE_NLS
197 y++;
198 std::vector<std::string>languages;
199 std::vector<std::string>descriptions;
200 std::map<std::string, std::string>::iterator iter;
201
202 for (iter = settings.languages.begin(); iter != settings.languages.end(); ++iter)
203 {
204 languages.push_back(iter->first);
205 descriptions.push_back(iter->second);
206 }
207
208 optionsMenu.Add(new OptionMenuItem(_("Language"), languages, "language", &settings, descriptions));
209 #endif
210
211 optionsMenu.Add(new OptionMenuItem(_("Resolution"), resolutions, "resolution", &settings));
212 optionsMenu.Add(new BooleanMenuItem(_("Fullscreen"), &settings, "fullscreen"));
213 optionsMenu.Add(new BooleanMenuItem(_("Show FPS"), &settings, "showFps"));
214 optionsMenu.Add(new BooleanMenuItem(_("Colour hints"), &settings, "colourHints"));
215 optionsMenu.Add(new BooleanMenuItem(_("Disable speed-up"), &settings, "disableSpeedup"));
216 optionsMenu.Add(new ValueMenuItem(_("Mouse sensivity"), 1, 10, &settings, "mouseSensivity"));
217 optionsMenu.Add(new ValueMenuItem(_("Keyb. sensivity"), 1, 10, &settings, "keyboardSensivity"));
218 optionsMenu.Add(new ValueMenuItem(_("SFX volume"), 0, 100, &settings, "sfxVolume"));
219 optionsMenu.Add(new ValueMenuItem(_("Music volume"), 0, 100, &settings, "musicVolume"));
220 optionsMenu.Add(new GenericMenuItem(_("Cancel"), optionsMenuCancelHandler, this));
221 optionsMenu.Add(new GenericMenuItem(_("Apply"), optionsMenuApplyHandler, this));
222 optionsMenu.SetDimensions(10, 80, 80);
223
224 optionsMenu.items[y]->width = 29;
225 optionsMenu.items[y+1]->width = 29;
226 optionsMenu.items[y+1]->x = 61;
227 optionsMenu.items[y+1]->y = optionsMenu.items[y]->y;
228 }
229
RenderStartupProgress()230 void MainMenu::RenderStartupProgress()
231 {
232 float pbarwidth = 80;
233 float pbarheight = 5;
234
235 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
236 glMatrixMode( GL_MODELVIEW );
237 glLoadIdentity( );
238 glTranslated((100 - pbarwidth) / 2, (vheight + pbarheight) / 2, 0);
239
240 glBegin(GL_QUADS);
241 glColor3d( .1, .1, .7);
242 glVertex3d(0, 0, 0);
243 glVertex3d(0, -pbarheight, 0);
244 glColor3d( 0, 0, 0.5);
245 glVertex3d((startupProgress / startupProgressSteps) * pbarwidth, -pbarheight, 0);
246 glVertex3d((startupProgress / startupProgressSteps) * pbarwidth, 0, 0);
247 glEnd();
248
249 glColor3d( 0, 0, 0.5);
250 glBegin(GL_LINE_STRIP);
251 glVertex3d(0, 0, 0);
252 glVertex3d(0, -pbarheight, 0);
253 glVertex3d(pbarwidth, -pbarheight, 0);
254 glVertex3d(pbarwidth, 0, 0);
255 glVertex3d(0, 0, 0);
256 glEnd();
257
258 startupProgress++;
259 glFlush();
260 SDL_GL_SwapBuffers();
261 }
262
LoadLevelSets()263 void MainMenu::LoadLevelSets()
264 {
265 vector<string>::iterator i;
266 for (i = setNames.begin(); i!= setNames.end(); ++i)
267 {
268 LevelSet s = LevelSet(*i);
269 sets.push_back(s);
270 setTex.push_back(LoadTextureFile (settings.getCFilename(s.thumbTexFilename)));
271 RenderStartupProgress();
272 }
273
274 RenderStartupProgress();
275 }
276
LoadTextures()277 void MainMenu::LoadTextures()
278 {
279 startupProgress = 0;
280
281 bool useColourHints = settings.getb("colourHints", false);
282
283 for (int b = 0; b < 16; b++)
284 {
285 BallDesc bd = BallDescriptions[b];
286 ballText[b] = LoadBallsTexture(bd.fileName, bd.r, bd.g, bd.b, useColourHints?bd.overlay:0);
287 RenderStartupProgress();
288 }
289
290 ballText[16] = LoadTexture("bonus1.png");
291 RenderStartupProgress();
292 ballText[17] = LoadTexture("bonus2.png");
293 RenderStartupProgress();
294 ballText[18] = LoadTexture("bonus3.png");
295 RenderStartupProgress();
296 ballText[19] = LoadTexture("bonus4.png");
297 RenderStartupProgress();
298 ballText[20] = LoadTexture("bonus5.png");
299 RenderStartupProgress();
300 ballText[21] = LoadTexture("explosion.png");
301 RenderStartupProgress();
302
303 logoTex = LoadTexture("logo.png");
304 RenderStartupProgress();
305 logoGpl = LoadTexture ("gpl3.png");
306 RenderStartupProgress();
307
308 pointer = LoadTexture("ptr.png");
309 }
310
311
StartMusic()312 void MainMenu::StartMusic()
313 {
314 int musicVol = atoi(settings.get("musicVolume", "50").c_str());
315
316 music = (Scenes::Sample *)new Scenes::StreamingOggSample(Game::getRandomMusic());
317 mixer->EnqueueSample(music, musicVol, 0, true);
318 }
319
StopMusic()320 void MainMenu::StopMusic()
321 {
322 mixer->DisposeSample(music);
323 }
324
profileActionsMenuNewHandler(void * ptr)325 void profileActionsMenuNewHandler(void *ptr)
326 {
327 MainMenu *p = (MainMenu *)ptr;
328 p->showNewProfile = true;
329 p->newProfileEditor = new LineEditor("", 60, 16, 30);
330 }
331
profileActionsMenuDeleteHandler(void * ptr)332 void profileActionsMenuDeleteHandler(void *ptr)
333 {
334 MainMenu *p = (MainMenu *)ptr;
335 // delete the profile file
336 string ph = p->profileNames[p->profileListMenu.getHoverItem()];
337 ph = settings.getDefaultDirectory() + SEPARATOR + ph + ".profile";
338 #ifdef WIN32
339 DeleteFile(Settings::W32_GetFileName(ph).c_str());
340 #else
341 remove(ph.c_str());
342 #endif
343
344 startMenuShowProfilesHandler(ptr);
345 }
346
profileActionsMenuUseHandler(void * ptr)347 void profileActionsMenuUseHandler(void *ptr)
348 {
349 MainMenu *p = (MainMenu *)ptr;
350 profile.Save();
351 profile = Profile(p->profileNames[p->profileListMenu.getHoverItem()]);
352
353 p->startMenu.items[4] = new GenericMenuItem(_("Profile:") + profile.getName(), startMenuShowProfilesHandler, p);
354 p->startMenu.SetDimensions(60, 40, 40);
355 p->startMenu.items[4]->width = 80;
356 p->startMenu.items[4]->y = 6;
357 p->startMenu.items[4]->x = 10;
358
359 settings.set("last_profile", profile.getName());
360
361 profile.Save();
362 p->showProfiles = false;
363 p->renderHiscores = true;
364 p->currentMenu = &p->startMenu;
365 }
366
browserMenuLeftHandler(void * ptr)367 void browserMenuLeftHandler(void *ptr)
368 {
369 MainMenu *p = (MainMenu *)ptr;
370 int sz;
371
372 if (p->showBrowser)
373 {
374 sz = p->nleveldesc; //p->levels.size();
375 }
376 else
377 {
378 sz = p->sets.size();
379 }
380
381 if (p->browserScrollOffsetDest >= sz - p->browserNLevelsPerPage)
382 return;
383
384 p->browserScrollOffsetDest+=p->browserNLevelsPerPage;
385
386 if (p->browserScrollOffsetDest > (int)(sz - p->browserNLevelsPerPage))
387 p->browserScrollOffsetDest = sz - p->browserNLevelsPerPage;
388 }
389
browserMenuRightHandler(void * ptr)390 void browserMenuRightHandler(void *ptr)
391 {
392 MainMenu *p = (MainMenu *)ptr;
393 p->browserScrollOffsetDest-=p->browserNLevelsPerPage;
394 if (p->browserScrollOffsetDest < 0)
395 p->browserScrollOffsetDest = 0;
396
397 }
398
optionsMenuApplyHandler(void * ptr)399 void optionsMenuApplyHandler(void *ptr)
400 {
401 MainMenu *p = (MainMenu *)ptr;
402
403 menuBackHandler (ptr);
404
405 wantReinit = false;
406 #ifdef ENABLE_NLS
407 if (p->oldLanguage != settings.get("language", ""))
408 {
409 settings.setLanguage(settings.get("language", ""));
410 wantReinit = true;
411 }
412 #endif
413 if (p->oldFullscreen != settings.getb("fullscreen", false))
414 wantReinit = true;
415
416 if (p->oldRes != settings.get("resolution", ""))
417 wantReinit = true;
418
419 if (p->oldColourHints != settings.getb("colourHints", false))
420 wantReinit = true;
421
422 if (p->oldMusicVol != atoi(settings.get("musicVolume", "50").c_str()))
423 wantReinit = true;
424
425 if (wantReinit)
426 {
427 p->quit = true;
428 p->StopMusic();
429 }
430
431 ((Scene *)p)->show_fps = settings.getb("showFps", false);
432 };
433
optionsMenuCancelHandler(void * ptr)434 void optionsMenuCancelHandler(void *ptr)
435 {
436 MainMenu *p = (MainMenu *)ptr;
437
438 menuBackHandler (ptr);
439
440 int y = 9;
441
442 #ifdef ENABLE_NLS
443 y++;
444 #endif
445 for (int f = 0; f < y; f++)
446 p->optionsMenu.items[f]->Revert();
447 }
448
menuBackHandler(void * ptr)449 void menuBackHandler(void *ptr)
450 {
451 MainMenu *p = (MainMenu *)ptr;
452 if (p->showBrowser)
453 {
454 p->showBrowser = false;
455 p->showSets = true;
456 p->browserScrollOffset = -5.0;
457 p->browserScrollOffsetDest = 0;
458 p->browserSelectedLevel = -1;
459 return;
460 }
461
462 ((MainMenu*)ptr)->currentMenu = &((MainMenu*)ptr)->startMenu;
463 ((MainMenu*)ptr)->renderHiscores = true;
464 ((MainMenu*)ptr)->showCredits = false;
465 ((MainMenu*)ptr)->showBrowser = false;
466 ((MainMenu*)ptr)->showSets = false;
467 }
468
startMenuOptionsHandler(void * ptr)469 void startMenuOptionsHandler(void *ptr)
470 {
471 ((MainMenu*)ptr)->oldFullscreen = settings.getb("fullscreen", false);
472 ((MainMenu*)ptr)->oldRes = settings.get("resolution", "");
473 ((MainMenu*)ptr)->oldColourHints = settings.getb("colourHints", "");
474 ((MainMenu*)ptr)->oldLanguage = settings.get("language", "");
475 ((MainMenu*)ptr)->oldMusicVol = atoi(settings.get("musicVolume", "50").c_str());
476
477 ((MainMenu*)ptr)->currentMenu = &((MainMenu*)ptr)->optionsMenu;
478 ((MainMenu*)ptr)->renderHiscores = false;
479 };
480
startMenuCreditsHandler(void * ptr)481 void startMenuCreditsHandler(void *ptr)
482 {
483 ((MainMenu*)ptr)->currentMenu = &((MainMenu*)ptr)->creditsMenu;
484 ((MainMenu*)ptr)->renderHiscores = false;
485 ((MainMenu*)ptr)->showCredits = true;
486 ((MainMenu*)ptr)->creditsScroll = ((MainMenu*)ptr)->creditsScrollClearance * -1;
487 };
488
startMenuExitHandler(void * ptr)489 void startMenuExitHandler(void *ptr)
490 {
491 ((MainMenu*)ptr)->quit = true;
492 ((MainMenu*)ptr)->StopMusic();
493 };
494
startMenuShowProfilesHandler(void * ptr)495 void startMenuShowProfilesHandler(void *ptr)
496 {
497 profile.Save();
498 MainMenu *p = (MainMenu *)ptr;
499 p->currentMenu = &p->profileActionsMenu;
500
501 // regenerate profile list
502 p->profileListMenu.items.clear();
503
504 p->profileNames = ListFiles(settings.getDefaultDirectory(), ".profile");
505
506 for (uint f = 0; f < p->profileNames.size(); f++)
507 {
508 string n = p->profileNames[f];
509 n = n.substr(0, n.find(".profile"));
510
511 p->profileNames[f] = n;
512 }
513
514 for (uint f = 0; f < p->profileNames.size() && f < 5; f++)
515 p->profileListMenu.Add(new GenericMenuItem(p->profileNames[f], profileActionsMenuUseHandler, ptr));
516
517 p->profileListMenu.SetDimensions(25, 45, 50);
518
519 p->profileActionsMenu.items[0]->show = true;
520 if (p->profileNames.size() > 4)
521 p->profileActionsMenu.items[0]->show = false;
522
523 p->profileActionsMenu.items[1]->show = true;
524
525 if (p->profileNames.empty())
526 {
527 p->profileActionsMenu.items[1]->show = false;
528 }
529
530 p->showProfiles = true;
531 p->renderHiscores = false;
532 if (p->profileListMenu.getHoverItem() >= p->profileListMenu.items.size())
533 {
534 p->profileListMenu.setHoverItem(p->profileListMenu.items.size() - 1);
535 }
536 }
537
startMenuStartHandler(void * ptr)538 void startMenuStartHandler(void *ptr)
539 {
540 MainMenu *p = (MainMenu *)ptr;
541 p->browserScrollOffset = -5.0;
542 p->browserScrollOffsetDest = 0;
543 p->browserSelectedLevel = -1;
544 p->showSets = true;
545 p->showBrowser = false;
546 p->renderHiscores = false;
547 p->currentMenu = &((MainMenu*)ptr)->browserMenu;
548 p->browserUsedKeyboard = false;
549 };
550
~MainMenu()551 MainMenu::~MainMenu()
552 {
553 glDeleteTextures(1, &logoTex);
554 glDeleteTextures(1, &logoGpl);
555 glDeleteTextures(1, &pointer);
556 glDeleteTextures(14, ballText);
557
558 for (uint f = 0; f < setTex.size(); f++)
559 glDeleteTextures(1, &setTex[f]);
560
561 if (nleveldesc)
562 delete [] levels;
563 }
564
GLSetup()565 void MainMenu::GLSetup()
566 {
567 int width = surface->w;
568 int height = surface->h;
569
570 SDL_ShowCursor(0);
571
572 /* Our shading model--Gouraud (smooth). */
573 glShadeModel( GL_SMOOTH );
574
575 /* Culling. */
576 glCullFace( GL_BACK );
577 glFrontFace( GL_CCW );
578 glEnable( GL_CULL_FACE );
579 glEnable(GL_DEPTH_TEST);
580 glEnable( GL_ALPHA_TEST );
581 glAlphaFunc(GL_GREATER, 0.0);
582 glEnable(GL_LINE_SMOOTH);
583
584 glEnable(GL_BLEND);
585 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
586
587 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
588 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
589 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
590
591 glClearColor( .1f, .1f, .7f, 1.0f );
592 glViewport( 0, 0, width, height);
593 glMatrixMode( GL_PROJECTION );
594 glLoadIdentity( );
595
596 glOrtho(vleft, vwidth + vleft, 0, 100, -100, 100);
597 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
598 }
599
Render(ulong frame)600 void MainMenu::Render(ulong frame)
601 {
602 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
603 glColor3f(1.0, 1.0, 1.0);
604 glMatrixMode( GL_MODELVIEW );
605 glLoadIdentity( );
606
607 for (int p = 0; p < nBallPaths; ++p)
608 {
609 bp[p].Render();
610 }
611
612 // logo
613 glLoadIdentity( );
614 glPushMatrix();
615 glEnable(GL_TEXTURE_2D);
616 glTranslated(vleft + 5, 95, 5);
617 glBindTexture(GL_TEXTURE_2D, logoTex);
618 glScalef(80, 48, 5);
619 glBegin(GL_QUADS);
620 glTexCoord2d(0, 0);
621 glVertex3d(0, 0, 0);
622 glTexCoord2d(0, 1);
623 glVertex3d(0, -1, 0);
624 glTexCoord2d(1, 1);
625 glVertex3d(1, -1, 0);
626 glTexCoord2d(1, 0);
627 glVertex3d(1, 0, 0);
628 glEnd();
629 glDisable(GL_TEXTURE_2D);
630 glPopMatrix();
631
632 currentMenu->Render();
633
634 if (renderHiscores && !hiScoreRep.empty())
635 {
636 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
637
638 glPushMatrix();
639 glTranslatef(18, 42, 5);
640 glScalef(0.15f, 0.15f, 0.15f);
641 glColor4d(1.0, 1.0, 1.0, 1.0);
642
643 font->Render(_("Hall of Fame"), -1);
644 glPopMatrix();
645
646
647 double alpha = 1.0;
648 int a = (hiScoreWaitPageSec * desiredFPS) - hiScoreTimeout;
649 int b = (hiScoreWaitPageSec * desiredFPS) / 5;
650 int c = (hiScoreWaitPageSec * desiredFPS);
651
652 if (a < b)
653 { // fadein
654 alpha = (double)a / (double)b;
655 }
656
657 if (a > (c - b))
658 { // fadeout
659 alpha = 1.0 - ((double)(a - (c - b)) / (double)b);
660 }
661
662
663 float y = 37;
664 glPushMatrix();
665 glTranslatef(-5, y, 5);
666 glScalef(0.1f, 0.1f, 0.1f);
667 glColor4d(1.0, 0.0, 1.0, alpha);
668
669 font->Render(hiScoreRep[hiScorePage].header.c_str(), -1);
670 glPopMatrix();
671
672 y-= 3;
673
674 uint nHigh = hiScoreRep[hiScorePage].lines.size();
675 for (uint f = 0; f < nHigh; f++)
676 {
677 glPushMatrix();
678 glTranslatef(-3, y, 5);
679 glScalef(0.1f, 0.1f, 0.1f);
680 glColor4d(1.0, 1.0, 1.0, alpha);
681
682 font4->Render(hiScoreRep[hiScorePage].lines[f].c_str(), -1);
683 glPopMatrix();
684
685 y-=2.5;
686 }
687 }
688
689 if (showProfiles)
690 {
691 profileListMenu.Render();
692 if (showNewProfile)
693 newProfileEditor->Render();
694 }
695
696 if (showCredits)
697 {
698 double creditsY = 45;
699 double scrollLength = 21;
700 int pos = creditsScroll / 100;
701
702 double starty = creditsY + ((creditsScroll%100) / 100.0) * 2.5;
703 double y = starty;
704
705 while (y > (starty - scrollLength))
706 {
707 if (pos < 0)
708 {
709 y = y - 2.5;
710 pos++;
711 continue;
712 }
713
714 if (pos >= credits.size())
715 {
716 y = y - 2.5;
717 continue;
718 }
719
720 if (creditsY - y < (scrollLength) / 2)
721 {
722 glColor4f(1.0, 1.0, 1.0, (creditsY - y) / (scrollLength / 4));
723 }
724 else
725 {
726 glColor4f(1.0, 1.0, 1.0, (scrollLength - (creditsY - y)) / (scrollLength / 4) - 0.2);
727 }
728
729 double size = 0.08;
730 if (credits[pos].fat)
731 size = 0.12;
732 if (credits[pos].txt != "-")
733 CenterMsg(_(credits[pos].txt.c_str()), y, font, size);
734
735 pos++;
736
737 y = y - 2.5;
738 }
739
740 glLoadIdentity();
741 glEnable(GL_TEXTURE_2D);
742 glTranslatef(50, 18, 5);
743 glBindTexture(GL_TEXTURE_2D, logoGpl);
744 glScalef(20, 10, 1);
745 glBegin(GL_QUADS);
746 glTexCoord2d(0, 0);
747 glVertex3d(-.5, .5, 0);
748 glTexCoord2d(0, 1);
749 glVertex3d(-.5, -.5, 0);
750 glTexCoord2d(1, 1);
751 glVertex3d(.5, -.5, 0);
752 glTexCoord2d(1, 0);
753 glVertex3d(.5, .5, 0);
754 glEnd();
755 glDisable(GL_TEXTURE_2D);
756 }
757
758 if (showSets)
759 {
760 glColor4f(1.0, 1.0, 1.0, 1.0);
761 CenterMsg(_("choose a level set"), 37, font, 0.1);
762 int lstart = (int)iround(browserScrollOffset) - 1;
763 if (lstart < 0)
764 lstart = 0;
765
766 int lend = lstart + browserNLevelsPerPage + browserNLevelsPerPage;
767 if (lend > (int)sets.size())
768 lend = sets.size();
769
770 double tw = (100.0 - double((browserThumbSpacing * (browserNLevelsPerPage - 1)))) / browserNLevelsPerPage;
771 double th = tw / (640.0/480.0);
772
773 double xmv = -(browserScrollOffset - lstart) * (tw + browserThumbSpacing);
774
775 double xx = 0;
776 double spc = 0;
777
778 if (!browserUsedKeyboard)
779 browserSelectedLevel = -1;
780
781 browserMouseOverLevel = -1;
782
783 for (int f = lstart; f < lend; f++)
784 {
785 glLoadIdentity();
786 glTranslated(xx * tw + spc + xmv, 25 - (th / 2), 5);
787
788 if ((mx > xx * tw + spc + xmv) &&
789 (mx < xx * tw + spc + xmv + tw) &&
790 (my > 25 - (th / 2)) &&
791 (my < 25 + (th / 2)))
792 {
793 if (!browserUsedKeyboard)
794 browserSelectedLevel = f;
795 browserMouseOverLevel = f;
796
797 }
798
799 glColor4d(.7, .7, .7, 1.0);
800 if (browserSelectedLevel == f)
801 {
802 glColor4d(1.0, 1.0, 1.0, 1.0);
803 }
804
805 glEnable(GL_TEXTURE_2D);
806 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
807 glBindTexture(GL_TEXTURE_2D, setTex[f]);
808 glBegin(GL_QUADS);
809 glTexCoord2d(0, 0);
810 glVertex3d(0, th, 0);
811 glTexCoord2d(0, 1);
812 glVertex3d(0, 0, 0);
813 glTexCoord2d(1, 1);
814 glVertex3d(tw, 0, 0);
815 glTexCoord2d(1, 0);
816 glVertex3d(tw, th, 0);
817 glEnd();
818
819 glDisable(GL_TEXTURE_2D);
820 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
821
822 glLoadIdentity();
823 glTranslated(xx * tw + spc + xmv, 25 - (th / 2), 7);
824 glColor4d(0, 0, 0, 1);
825 glLineWidth(2.0);
826 glBegin(GL_LINE_STRIP);
827 glVertex3d(0, 0, 0);
828 glVertex3d(0, th, 0);
829 glVertex3d(tw, th, 0);
830 glVertex3d(tw, 0, 0);
831 glVertex3d(0, 0, 0);
832 glEnd();
833
834 double size = 0.08;
835 glLoadIdentity( );
836 glColor4d(1.0, 1.0, 1.0, 1);
837 char levelName[256];
838 sprintf(levelName, "%s", sets[f].getDesc().c_str());
839
840 FTBBox b = font->BBox(gettext(levelName));
841 double txtw = b.Upper().X() / (1.0 / size);
842 glTranslated((xx * tw + spc) + (tw / 2) - (txtw / 2) + xmv, 11.5, 5);
843 glScaled(size, size, size);
844
845 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
846 font->Render(gettext(levelName));
847
848 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
849
850 spc += browserThumbSpacing;
851 xx += 1.0;
852 }
853 }
854
855 if (showBrowser)
856 {
857 glColor4f(1.0, 1.0, 1.0, 1.0);
858 CenterMsg(_(sets[selectedSet].description.c_str()), 37, font, 0.1);
859
860 int lstart = (int)iround(browserScrollOffset) - 1;
861 if (lstart < 0)
862 lstart = 0;
863
864 int lend = lstart + browserNLevelsPerPage + browserNLevelsPerPage;
865 if (lend > nleveldesc)
866 lend = nleveldesc;
867
868 double tw = (100.0 - double((browserThumbSpacing * (browserNLevelsPerPage - 1)))) / browserNLevelsPerPage;
869 double th = tw / (640.0/480.0);
870
871 double xmv = -(browserScrollOffset - lstart) * (tw + browserThumbSpacing);
872
873 double xx = 0;
874 double spc = 0;
875
876 if (!browserUsedKeyboard)
877 browserSelectedLevel = -1;
878
879 browserMouseOverLevel = -1;
880
881 for (int f = lstart; f < lend; f++)
882 {
883 glLoadIdentity();
884 glTranslated(xx * tw + spc + xmv, 25 - (th / 2), 5);
885
886
887 if ((mx > xx * tw + spc + xmv) &&
888 (mx < xx * tw + spc + xmv + tw) &&
889 (my > 25 - (th / 2)) &&
890 (my < 25 + (th / 2)))
891 {
892 if (!levels[f].locked && iround(browserScrollOffset) >= 0)
893 {
894 if (!browserUsedKeyboard)
895 browserSelectedLevel = f;
896
897 browserMouseOverLevel = f;
898 }
899 }
900
901 glColor4d(.7, .7, .7, 1.0);
902 if (browserSelectedLevel == f)
903 {
904 glColor4d(1.0, 1.0, 1.0, 1.0);
905 }
906
907 glEnable(GL_TEXTURE_2D);
908 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
909 glBindTexture(GL_TEXTURE_2D, levels[f].tex);
910
911 XY tl(0,0);
912 XY tr(1,0);
913 XY bl(0,1);
914 XY br(1,1);
915
916 if (levels[f].lev.mirrorX)
917 {
918 XY t = tl;
919 tl = tr;
920 tr = t;
921
922 t = bl;
923 bl = br;
924 br = t;
925 }
926
927 if (levels[f].lev.mirrorY)
928 {
929 XY t = tl;
930 tl = bl;
931 bl = t;
932
933 t = br;
934 br = tr;
935 tr = t;
936 }
937
938 glBegin(GL_QUADS);
939 glTexCoord2d(tl.x, tl.y);
940 glVertex3d(0, th, 0);
941 glTexCoord2d(bl.x, bl.y);
942 glVertex3d(0, 0, 0);
943 glTexCoord2d(br.x, br.y);
944 glVertex3d(tw, 0, 0);
945 glTexCoord2d(tr.x, tr.y);
946 glVertex3d(tw, th, 0);
947 glEnd();
948
949 glDisable(GL_TEXTURE_2D);
950 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
951
952 glLoadIdentity();
953 glTranslated(xx * tw + spc + xmv, 25 - (th / 2), 7);
954 glColor4d(0, 0, 0, 1);
955 glLineWidth(2.0);
956 glBegin(GL_LINE_STRIP);
957 glVertex3d(0, 0, 0);
958 glVertex3d(0, th, 0);
959 glVertex3d(tw, th, 0);
960 glVertex3d(tw, 0, 0);
961 glVertex3d(0, 0, 0);
962 glEnd();
963
964 double size = 0.08;
965 glLoadIdentity( );
966 glColor4d(1.0, 1.0, 1.0, 1);
967 char levelName[256];
968 sprintf(levelName, "%s", levels[f].lev.name.c_str());
969
970 FTBBox b = font->BBox(gettext(levelName));
971 double txtw = b.Upper().X() / (1.0 / size);
972 glTranslated((xx * tw + spc) + (tw / 2) - (txtw / 2) + xmv, 11.5, 5);
973 glScaled(size, size, size);
974
975 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
976 font->Render(gettext(levelName));
977 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
978
979 if (levels[f].locked)
980 {
981 char lockedTxt[256];
982
983 sprintf(lockedTxt, "%s", _("locked"));
984 size = 0.3;
985 glLoadIdentity( );
986 glColor4d(1.0, 0, 0, 1);
987 b = font->BBox(lockedTxt);
988 txtw = b.Upper().X() / (1.0 / size);
989 glTranslated((xx * tw + spc) + (tw / 2) - (txtw / 2) + xmv, 28, 7);
990 glScaled(size, size, size);
991
992 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
993 font->Render(lockedTxt);
994 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
995 }
996
997 spc += browserThumbSpacing;
998 xx += 1.0;
999 }
1000 }
1001
1002 // render pointer
1003 glLoadIdentity();
1004 glEnable(GL_TEXTURE_2D);
1005 glTranslatef(mx, my, 20);
1006 glColor4f(1.0, 1.0, 1.0, 1.0);
1007 glBindTexture(GL_TEXTURE_2D, pointer);
1008 glScalef(5, 5, 5);
1009 glBegin(GL_QUADS);
1010 glTexCoord2d(0, 0);
1011 glVertex3d(0, 0, 0);
1012 glTexCoord2d(0, 1);
1013 glVertex3d(0, -1, 0);
1014 glTexCoord2d(1, 1);
1015 glVertex3d(1, -1, 0);
1016 glTexCoord2d(1, 0);
1017 glVertex3d(1, 0, 0);
1018 glEnd();
1019 glDisable(GL_TEXTURE_2D);
1020
1021 int pf = pointerFrame / 2;
1022 double ts = 1.0 / double(BALLTEXTURECOUNT);
1023 double tx = (double)((pf % BALLTEXTURECOUNT)) * ts;
1024 double ty = (double)((pf / BALLTEXTURECOUNT)) * ts;
1025
1026 glLoadIdentity();
1027 glEnable(GL_TEXTURE_2D);
1028 glTranslated(mx, my, 20);
1029 glBindTexture(GL_TEXTURE_2D, ballText[1]);
1030 glTranslated(3.5, -3.5, 0);
1031 glScalef(3, 3, 3);
1032 glRotated(pointerRot, 0, 0, 1.0);
1033
1034 glBegin(GL_QUADS);
1035 glTexCoord2d(tx, ty);
1036 glVertex3d(-0.5, 0.5, 0);
1037 glTexCoord2d(tx, ty + ts);
1038 glVertex3d(-0.5, -0.5, 0);
1039 glTexCoord2d(tx + ts, ty + ts);
1040 glVertex3d(0.5, -0.5, 0);
1041 glTexCoord2d(tx + ts, ty);
1042 glVertex3d(0.5, 0.5, 0);
1043 glEnd();
1044 glDisable(GL_TEXTURE_2D);
1045 }
1046
FixLevelLocks()1047 void MainMenu::FixLevelLocks()
1048 {
1049 if (currentLevelSet.getEmpty())
1050 return;
1051
1052
1053 }
1054
Logic(ulong frame)1055 void MainMenu::Logic(ulong frame)
1056 {
1057 pointerFrame++;
1058 if (pointerFrame >= BALLTEXTURECOUNT*BALLTEXTURECOUNT*2)
1059 pointerFrame = 0;
1060
1061 pointerRot = pointerRot + 0.1;
1062
1063 if (startup)
1064 {
1065 // handle LCTRL to reset screenmode
1066 if (!resReset && (SDL_GetModState() & KMOD_LCTRL))
1067 {
1068 settings.setb("fullscreen", false);
1069 settings.set("resolution", "640x480");
1070
1071 wantReinit = true;
1072 quit = true;
1073 StopMusic();
1074 resReset = true;
1075 return;
1076 }
1077
1078 startupProgressSteps = (float)(25 + setNames.size());
1079 GLSetup();
1080 LoadTextures();
1081 LoadLevelSets();
1082 resync = true;
1083 startup = false;
1084 return;
1085 }
1086
1087 if (music == NULL)
1088 StartMusic ();
1089
1090 if (showNewProfile)
1091 {
1092 newProfileEditor->Logic(events);
1093 }
1094
1095 bool click = false;
1096
1097 if (!events.empty)
1098 {
1099 if (events.keyDown.size() > 0)
1100 for (vector<SDLKey>::iterator i = events.keyDown.begin(); i != events.keyDown.end(); ++i)
1101 {
1102 if (*i == SDLK_ESCAPE && !showNewProfile)
1103 {
1104 if (currentMenu == &startMenu)
1105 {
1106 quit = true;
1107 }
1108 else
1109 {
1110 if (currentMenu == &optionsMenu)
1111 {
1112 optionsMenuCancelHandler(this);
1113 return;
1114 }
1115
1116 if (showBrowser)
1117 {
1118 showBrowser = false;
1119 showSets = true;
1120 browserScrollOffset = -5.0;
1121 browserScrollOffsetDest = 0;
1122 browserSelectedLevel = -1;
1123 return;
1124 }
1125 else
1126 {
1127 currentMenu = &startMenu;
1128 renderHiscores = true;
1129 showBrowser = false;
1130 showCredits = false;
1131 showSets = false;
1132 if (showProfiles)
1133 { // we could have deleted current profile and escaped
1134 profile.Save();
1135 showProfiles = false;
1136 renderHiscores = true;
1137 }
1138 }
1139 }
1140 }
1141
1142 if (*i == SDLK_ESCAPE && showNewProfile)
1143 {
1144 showNewProfile = false;
1145 delete(newProfileEditor);
1146 }
1147
1148 if (!showNewProfile)
1149 if (showProfiles && (*i == SDLK_RETURN || *i == SDLK_KP_ENTER))
1150 {
1151 profileActionsMenuUseHandler(this);
1152 return;
1153 }
1154
1155 if (showNewProfile && (*i == SDLK_RETURN || *i == SDLK_KP_ENTER))
1156 {
1157 showNewProfile = false;
1158 if (!newProfileEditor->txt.empty())
1159 {
1160 #ifndef WIN32
1161 string ph = settings.getDefaultDirectory() + SEPARATOR + newProfileEditor->txt + ".profile";
1162 FILE *phile = fopen(ph.c_str(), "wb");
1163 if (phile)
1164 fclose(phile);
1165 #endif
1166
1167 #ifdef WIN32
1168 Settings::W32_CreateFile(settings.getDefaultDirectory() + SEPARATOR + newProfileEditor->txt + ".profile");
1169 #endif
1170 startMenuShowProfilesHandler(this);
1171 }
1172
1173 delete(newProfileEditor);
1174 return;
1175 }
1176
1177 if (showBrowser || showSets)
1178 {
1179 if (*i == SDLK_LEFT)
1180 {
1181 browserSelectedLevel--;
1182 browserUsedKeyboard = true;
1183 }
1184
1185 if (*i == SDLK_RIGHT)
1186 {
1187 browserSelectedLevel++;
1188 browserUsedKeyboard = true;
1189 }
1190
1191 if (*i == SDLK_TAB)
1192 {
1193 browserMenu.items[3]->Key(SDLK_RIGHT);
1194 }
1195
1196 if (showSets)
1197 {
1198 clamp(browserSelectedLevel, 0, (int)(sets.size() - 1))
1199 }
1200 else
1201 {
1202 clamp(browserSelectedLevel, 0, (int)(currentLevelSet.levels.size() - 1))
1203 }
1204
1205 if (browserUsedKeyboard)
1206 {
1207 browserScrollOffsetDest=(browserSelectedLevel/browserNLevelsPerPage) * browserNLevelsPerPage;
1208 }
1209
1210 if (*i == SDLK_RETURN || *i == SDLK_KP_ENTER)
1211 {
1212 click = true;
1213 }
1214 }
1215 }
1216
1217 if (lmx != mx || lmy != my)
1218 browserUsedKeyboard = false;
1219
1220 lmx = mx;
1221 lmy = my;
1222
1223 if (events.buttDown[0])
1224 {
1225 if (browserMouseOverLevel != -1)
1226 click = true;
1227 }
1228
1229 // we have to translate mouse events to local coords for the menu
1230 FrameEvents tempEvents = events;
1231 tempEvents.mouseX = mx;
1232 tempEvents.mouseY = my;
1233
1234 if (showProfiles)
1235 {
1236 if (!showNewProfile)
1237 profileListMenu.Logic(tempEvents);
1238
1239 // move menuactions to hovered item in profilelist
1240 int h = profileListMenu.getHoverItem();
1241
1242 if (profileListMenu.items.size())
1243 {
1244 profileActionsMenu.items[1]->x = 0;
1245 profileActionsMenu.items[1]->y = profileListMenu.items[h]->y;
1246 profileActionsMenu.items[1]->width = 25;
1247
1248 profileActionsMenu.items[1]->show = true;
1249 string ph = profileNames[profileListMenu.getHoverItem()];
1250 if (ph == profile.getName())
1251 {
1252 profileActionsMenu.items[1]->show = false;
1253 }
1254
1255
1256 /*profileActionsMenu.items[2]->x = 70;
1257 profileActionsMenu.items[2]->y = profileListMenu.items[h]->y;
1258 profileActionsMenu.items[2]->width = 30;*/
1259 }
1260 }
1261
1262 // have to strip the key events from browser menu
1263 if (!showBrowser && !showProfiles && !showSets)
1264 {
1265 currentMenu->Logic(tempEvents);
1266 }
1267 else
1268 {
1269 tempEvents.keyUp.clear();
1270 tempEvents.keyDown.clear();
1271 if (!showNewProfile)
1272 currentMenu->Logic(tempEvents);
1273 }
1274
1275
1276 if (showBrowser && browserSelectedLevel >= 0 && click)
1277 {
1278 currentMenu = &startMenu;
1279 renderHiscores = true;
1280 showBrowser = false;
1281
1282 StopMusic();
1283 currentLevelSet = sets[selectedSet];
1284
1285 bool survival = false;
1286 if (((OptionMenuItem*)browserMenu.items[3])->getV() == 1)
1287 survival = true;
1288
1289 GameLoop(surface, ballText, browserSelectedLevel, Scenes::DEFAULT_FPS, survival).Run();
1290 resync = true;
1291 RecalculateMousePos();
1292
1293 StartMusic();
1294 GLSetup();
1295 SDL_ShowCursor(SDL_ENABLE);
1296 SDL_WM_GrabInput(SDL_GRAB_OFF);
1297 hiScoreRep = hiScores.GenerateReport(linesPerHiScorePage);
1298 hiScorePage = 0;
1299 hiScoreTimeout = hiScoreWaitPageSec * desiredFPS;
1300 }
1301
1302 if (showSets && browserSelectedLevel >= 0 && click)
1303 {
1304 showSets = false;
1305 showBrowser = true;
1306 browserScrollOffset = -5.0;
1307 browserScrollOffsetDest = 0;
1308 selectedSet = browserSelectedLevel;
1309 browserSelectedLevel = -1;
1310 currentLevelSet = sets[selectedSet];
1311 FillLevelDesc();
1312 }
1313 }
1314
1315 for (int p = 0; p < nBallPaths; ++p)
1316 {
1317 bp[p].state.ballOut = false;
1318 bp[p].Logic();
1319 }
1320
1321 if (showBrowser || showSets)
1322 {
1323 browserScrollOffset = browserScrollOffset + (browserScrollOffsetDest - browserScrollOffset) / 20.0;
1324 }
1325
1326 if (renderHiscores)
1327 {
1328 if (hiScoreTimeout)
1329 hiScoreTimeout--;
1330
1331 if (hiScoreTimeout == 0)
1332 {
1333 hiScorePage++;
1334 hiScoreTimeout = hiScoreWaitPageSec * desiredFPS;
1335 if (hiScorePage >= hiScoreRep.size())
1336 {
1337 hiScorePage = 0;
1338 }
1339 }
1340 }
1341
1342 if (showCredits)
1343 {
1344 creditsScroll++;
1345 if (creditsScroll > (int)((credits.size() * 100)))
1346 creditsScroll = -creditsScrollClearance;
1347 }
1348 }
1349
FillLevelDesc()1350 void MainMenu::FillLevelDesc()
1351 {
1352 if (nleveldesc > 0)
1353 delete [] levels;
1354
1355 nleveldesc = sets[selectedSet].levels.size();
1356 levels = new LevelDesc[nleveldesc];
1357 if (nleveldesc > 0)
1358 levels[0].locked = false;
1359
1360 for (int f = 0; f < nleveldesc; f++)
1361 {
1362 levels[f].lev = sets[selectedSet].levels[f];
1363 levels[f].tex = LoadTextureFile(sets[selectedSet].levels[f].thumbTexFilename.c_str());
1364
1365 stringstream setname;
1366 setname << sets[selectedSet].filename << ":" << (f + 1) << ":completed";
1367
1368 if (f < nleveldesc - 1)
1369 {
1370 levels[f + 1].locked = true;
1371
1372 if (profile.getb(setname.str(), false))
1373 {
1374 levels[f+1].locked = false;
1375 }
1376 }
1377 }
1378 }
1379
CenterMsg(string msg,double y,FTFont * font,double size)1380 void MainMenu::CenterMsg(string msg, double y, FTFont *font, double size)
1381 {
1382 glLoadIdentity( );
1383 FTBBox b = font->BBox(msg.c_str());
1384 double tw = b.Upper().X() / (1.0 / size);
1385 glTranslated((100 - tw) / 2, y, 5);
1386 glScaled(size, size, size);
1387
1388 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1389 font->Render(msg.c_str());
1390 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1391 }
1392
1393