1 // Brain Party
2 // Copyright (C) 2010 Paul Hudson (http://www.tuxradar.com/brainparty)
3
4 // Brain Party is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 3
7 // of the License, or (at your option) any later version.
8
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 #include <ctime>
19 #include "BPGame.h"
20 #include "SDL.h"
21 #include "SDL_opengl.h"
22 #include "SDL_ttf.h"
23 #include <string>
24
25
26 #include "bombhunt.h"
27 #include "balloonblaster.h"
28 #include "bpsays.h"
29 #include "bubbletrouble.h"
30 #include "cardmatch.h"
31 #include "connex.h"
32 #include "cupsnballs.h"
33 #include "diceoff.h"
34 #include "flashcounting.h"
35 #include "flashlight.h"
36 #include "iqtest.h"
37 #include "jewelflip.h"
38 #include "jeweljam.h"
39 #include "marbledrop.h"
40 #include "memoryblox.h"
41 #include "memorybox.h"
42 #include "memorymaths.h"
43 #include "minesweep.h"
44 #include "moonjump.h"
45 #include "nextinline.h"
46 #include "numbersnake.h"
47 #include "oddoneout.h"
48 #include "patchmatch.h"
49 #include "perfectpaths.h"
50 #include "routefinder.h"
51 #include "rps.h"
52 #include "scrambled.h"
53 #include "setfinder.h"
54 #include "sharpshooter.h"
55 #include "shortcircuitsudoku.h"
56 #include "shufflepuzzler.h"
57 #include "strangerdanger.h"
58 #include "symboliclogic.h"
59 #include "underthehat.h"
60 #include "untangler.h"
61 #include "wordsmash.h"
62
63 Texture* BPGame::sfcLogo;
64 bool BPGame::ShowingMessageBox;
65 bool BPGame::ShowingClearScores;
66 SpriteFont* BPGame::sfcMessageBoxText;
67 SpriteFont* BPGame::sfcMessageBoxTitle;
68
Init(int width,int height)69 void BPGame::Init(int width, int height) {
70 srand(time(0));
71
72 EnableSound = true;
73 EnableMusic = true;
74
75 EmptyPoint = BPPoint(0,0);
76 LastStateChange = 0;
77
78 LastBGObject = 0;
79
80 Black = new Colour(0.0f, 0.0f, 0.0f, 1.0f);
81 White = new Colour(1.0f, 1.0f, 1.0f, 1.0f);
82 TransparentWhite = new Colour(1.0f, 1.0f, 1.0f, 0.0f);
83
84 Blue = new Colour(0.0f, 0.0f, 1.0f, 1.0f);
85 Cyan = new Colour(0.0f, 1.0f, 1.0f, 1.0f);
86 Green = new Colour(0.0f, 1.0f, 0.0f, 1.0f);
87 Orange = new Colour(1.0f, 0.75f, 0.0f, 1.0f);
88 Red = new Colour(1.0f, 0.0f, 0.0f, 1.0f);
89 LightRed = new Colour(1.0f, 0.5f, 0.6f, 1.0f);
90 DarkRed = new Colour(0.5f, 0.0f, 0.0f, 1.0f);
91 Yellow = new Colour(1.0f, 1.0f, 0.0f, 1.0f);
92 DarkGrey = new Colour(0.5f, 0.5f, 0.5f, 1.0f);
93 ConnexGreen = new Colour(0.0f, 0.8f, 0.0f, 0.7f);
94
95 CheatMainTaps = CheatOptionsTaps = 0;
96
97 InTestMode = false;
98
99 TickCount = 0;
100 ElapsedSeconds = 0;
101 AnimCounter = 0.0f;
102 PractiseAnimCounter = 0.0f;
103
104 PractisePageNumber = 0;
105 PractisePageMoveLeft = true;
106
107 sfcTestWeight = NULL;
108 sfcTestJob = NULL;
109 sfcHighestBrainWeight = NULL;
110
111 HighestBrainWeight = -1;
112 CurrentBrainWeight = -1;
113
114 TestBrainJobs.Add("Fast Food Assistant");
115 TestBrainJobs.Add("Fast Food Manager");
116 TestBrainJobs.Add("Bingo Club Manager");
117 TestBrainJobs.Add("Web Designer");
118 TestBrainJobs.Add("Personal Shopper");
119 TestBrainJobs.Add("Aromatherapist");
120 TestBrainJobs.Add("Solicitor");
121 TestBrainJobs.Add("Psychotherapist");
122 TestBrainJobs.Add("Lifestyle Consultant");
123 TestBrainJobs.Add("Librarian");
124 TestBrainJobs.Add("Acupuncturist");
125 TestBrainJobs.Add("Insurance Broker");
126 TestBrainJobs.Add("Bank Manager");
127 TestBrainJobs.Add("Fashion Stylist");
128 TestBrainJobs.Add("Interior Designer");
129 TestBrainJobs.Add("Fashion Consultant");
130 TestBrainJobs.Add("Sales Assistant");
131 TestBrainJobs.Add("Actor");
132 TestBrainJobs.Add("Sales Executive");
133 TestBrainJobs.Add("Movie Director");
134 TestBrainJobs.Add("Hotel Manager");
135 TestBrainJobs.Add("Botanist");
136 TestBrainJobs.Add("Marketing Executive");
137 TestBrainJobs.Add("Economist");
138 TestBrainJobs.Add("Statistician");
139 TestBrainJobs.Add("Theatre Director");
140 TestBrainJobs.Add("Nurse");
141 TestBrainJobs.Add("Police Officer");
142 TestBrainJobs.Add("Meteorologist");
143 TestBrainJobs.Add("Art Valuer");
144 TestBrainJobs.Add("Museum Curator");
145 TestBrainJobs.Add("Marine Biologist");
146 TestBrainJobs.Add("School Teacher");
147 TestBrainJobs.Add("Dentist");
148 TestBrainJobs.Add("Software Engineer");
149 TestBrainJobs.Add("Forensic Scientist");
150 TestBrainJobs.Add("Psychiatrist");
151 TestBrainJobs.Add("Archaeologist");
152 TestBrainJobs.Add("Engineer");
153 TestBrainJobs.Add("Investment Analyst");
154 TestBrainJobs.Add("Physicist");
155 TestBrainJobs.Add("Sculptor");
156 TestBrainJobs.Add("Painter");
157 TestBrainJobs.Add("Poet");
158 TestBrainJobs.Add("Doctor");
159 TestBrainJobs.Add("Composer");
160 TestBrainJobs.Add("Fighter Pilot");
161 TestBrainJobs.Add("Architect");
162 TestBrainJobs.Add("Brain Surgeon");
163 TestBrainJobs.Add("Professor");
164 TestBrainJobs.Add("Philosopher");
165 TestBrainJobs.Add("Astronaut");
166 TestBrainJobs.Add("Nobel Prize Winner");
167 TestBrainJobs.Add("Genius");
168 TestBrainJobs.Add("Super Genius");
169 TestBrainJobs.Add("Albert Einstein");
170
171 PeopleNames.Add("Andrea");
172 PeopleNames.Add("Andrew");
173 PeopleNames.Add("Bob");
174 PeopleNames.Add("Catherine");
175 PeopleNames.Add("Dawn");
176 PeopleNames.Add("Diana");
177 PeopleNames.Add("Esther");
178 PeopleNames.Add("Graham");
179 PeopleNames.Add("Hannah");
180 PeopleNames.Add("Jack");
181 PeopleNames.Add("James");
182 PeopleNames.Add("Jeff");
183 PeopleNames.Add("Jeremy");
184 PeopleNames.Add("John");
185 PeopleNames.Add("Kathryn");
186 PeopleNames.Add("Laura");
187 PeopleNames.Add("Louise");
188 PeopleNames.Add("Lyn");
189 PeopleNames.Add("Mark");
190 PeopleNames.Add("Matthew");
191 PeopleNames.Add("Mike");
192 PeopleNames.Add("Paul");
193 PeopleNames.Add("Rebecca");
194 PeopleNames.Add("Richard");
195 PeopleNames.Add("Sandra");
196 PeopleNames.Add("Scott");
197 PeopleNames.Add("Tanya");
198 PeopleNames.Add("Terry");
199 PeopleNames.Add("Tim");
200 PeopleNames.Add("William");
201
202
203 sfcMiniGameUnknown = LoadBitmap("minigame_unknown", 90, 90);
204 MiniGames[BALLOONBLASTER] = new BPMiniGame_Container(BALLOONBLASTER, "balloonblaster", "Balloon Blaster!", LoadBitmap("minigame_balloonblaster", 90, 90), false);
205 MiniGames[BOMBHUNT] = new BPMiniGame_Container(BOMBHUNT, "bombhunt", "Bomb Hunt", LoadBitmap("minigame_bombhunt", 90, 90), false);
206 MiniGames[BPSAYS] = new BPMiniGame_Container(BPSAYS, "bpsays", "Brain Party says...", LoadBitmap("minigame_bpsays", 90, 90), false);
207 MiniGames[BUBBLETROUBLE] = new BPMiniGame_Container(BUBBLETROUBLE, "bubbletrouble", "Bubble Trouble", LoadBitmap("minigame_bubbletrouble", 90, 90), false);
208 MiniGames[CARDMATCH] = new BPMiniGame_Container(CARDMATCH, "cardmatch", "Card Match", LoadBitmap("minigame_cardmatch", 90, 90), false);
209 MiniGames[CUPSNBALLS] = new BPMiniGame_Container(CUPSNBALLS, "cupsnballs", "Cups 'n' Balls", LoadBitmap("minigame_cupsnballs", 90, 90), false);
210 MiniGames[CONNEX] = new BPMiniGame_Container(CONNEX, "connex", "Connex", LoadBitmap("minigame_connex", 90, 90), false);
211 MiniGames[DICEOFF] = new BPMiniGame_Container(DICEOFF, "diceoff", "Dice Off", LoadBitmap("minigame_unknown", 90, 90), true);
212 MiniGames[FLASHCOUNTING] = new BPMiniGame_Container(FLASHCOUNTING, "flashcounting", "Flash Counting", LoadBitmap("minigame_flashcounting", 90, 90), false);
213 MiniGames[FLASHLIGHT] = new BPMiniGame_Container(FLASHLIGHT, "flashlight", "Flashlight", LoadBitmap("minigame_flashlight", 90, 90), false);
214 MiniGames[IQTEST] = new BPMiniGame_Container(IQTEST, "iqtest", "IQ Test", LoadBitmap("minigame_iqtest", 90, 90), false);
215 MiniGames[JEWELFLIP] = new BPMiniGame_Container(JEWELFLIP, "jewelflip", "Jewel Flip", LoadBitmap("minigame_jewelflip", 90, 90), false);
216 MiniGames[JEWELJAM] = new BPMiniGame_Container(JEWELJAM, "jeweljam", "Jewel Jam", LoadBitmap("minigame_jeweljam", 90, 90), false);
217 MiniGames[MARBLEDROP] = new BPMiniGame_Container(MARBLEDROP, "marbledrop", "Marble Drop", LoadBitmap("minigame_marbledrop", 90, 90), false);
218 MiniGames[MEMORYBLOX] = new BPMiniGame_Container(MEMORYBLOX, "memoryblox", "MemoryBlox", LoadBitmap("minigame_memoryblox", 90, 90), false);
219 MiniGames[MEMORYBOX] = new BPMiniGame_Container(MEMORYBOX, "memorybox", "Memory Box", LoadBitmap("minigame_memorybox", 90, 90), false);
220 MiniGames[MEMORYMATHS] = new BPMiniGame_Container(MEMORYMATHS, "memorymaths", "Memory Maths", LoadBitmap("minigame_memorymaths", 90, 90), false);
221 MiniGames[MINESWEEP] = new BPMiniGame_Container(MINESWEEP, "minesweep", "Mine Sweep", LoadBitmap("minigame_minesweep", 90, 90), false);
222 MiniGames[MOONJUMP] = new BPMiniGame_Container(MOONJUMP, "moonjump", "Moon Jump", LoadBitmap("minigame_moonjump", 90, 90), false);
223 MiniGames[NEXTINLINE] = new BPMiniGame_Container(NEXTINLINE, "nextinline", "Next in Line", LoadBitmap("minigame_nextinline", 90, 90), false);
224 MiniGames[NUMBERSNAKE] = new BPMiniGame_Container(NUMBERSNAKE, "numbersnake", "Number Snake", LoadBitmap("minigame_numbersnake", 90, 90), false);
225 MiniGames[ODDONEOUT] = new BPMiniGame_Container(ODDONEOUT, "oddoneout", "Odd One Out", LoadBitmap("minigame_oddoneout", 90, 90), false);
226 MiniGames[PATCHMATCH] = new BPMiniGame_Container(PATCHMATCH, "patchmatch", "Patch Match", LoadBitmap("minigame_patchmatch", 90, 90), false);
227 MiniGames[PERFECTPATHS] = new BPMiniGame_Container(PERFECTPATHS, "perfectpaths", "Perfect Paths", LoadBitmap("minigame_perfectpaths", 90, 90), false);
228 MiniGames[ROUTEFINDER] = new BPMiniGame_Container(ROUTEFINDER, "routefinder", "Route Finder", LoadBitmap("minigame_routefinder", 90, 90), false);
229 MiniGames[RPS] = new BPMiniGame_Container(RPS, "rockpaperscissors", "Rock, Paper, Scissors", LoadBitmap("minigame_rps", 90, 90), false);
230 MiniGames[SCRAMBLED] = new BPMiniGame_Container(SCRAMBLED, "scrambled", "Scrambled", LoadBitmap("minigame_scrambled", 90, 90), false);
231 MiniGames[SETFINDER] = new BPMiniGame_Container(SETFINDER, "setfinder", "Set Finder", LoadBitmap("minigame_setfinder", 90, 90), false);
232 MiniGames[SHARPSHOOTER] = new BPMiniGame_Container(SHARPSHOOTER, "sharpshooter", "Sharpshooter", LoadBitmap("minigame_sharpshooter", 90, 90), true);
233 MiniGames[SHORTCIRCUITSUDOKU] = new BPMiniGame_Container(SHORTCIRCUITSUDOKU, "shortcircuitsudoku", "Short-circuit Sudoku", LoadBitmap("minigame_shortcircuitsudoku", 90, 90), false);
234 MiniGames[SHUFFLEPUZZLER] = new BPMiniGame_Container(SHUFFLEPUZZLER, "shufflepuzzler", "Shuffle Puzzler", LoadBitmap("minigame_shufflepuzzler", 90, 90), true);
235 MiniGames[STRANGERDANGER] = new BPMiniGame_Container(STRANGERDANGER, "strangerdanger", "Stranger Danger", LoadBitmap("minigame_unknown", 90, 90), true);
236 MiniGames[SYMBOLICLOGIC] = new BPMiniGame_Container(SYMBOLICLOGIC, "symboliclogic", "Symbolic Logic", LoadBitmap("minigame_symboliclogic", 90, 90), false);
237 MiniGames[UNDERTHEHAT] = new BPMiniGame_Container(UNDERTHEHAT, "underthehat", "Under the Hat", LoadBitmap("minigame_underthehat", 90, 90), true);
238 MiniGames[UNTANGLER] = new BPMiniGame_Container(UNTANGLER, "untangler", "Untangler", LoadBitmap("minigame_untangler", 90, 90), false);
239 MiniGames[WORDSMASH] = new BPMiniGame_Container(WORDSMASH, "wordsmash", "Word Smash", LoadBitmap("minigame_unknown", 90, 90), true);
240
241 sfcLogo = LoadBitmap("brainparty", 312, 227);
242 ShowingMessageBox = false;
243 ShowingClearScores = false;
244 sfcMessageBoxTitle = NULL;
245 sfcMessageBoxText = NULL;
246
247 sfcTestStatus.Add(LoadBitmap("teststatus1", 320, 75));
248 sfcTestStatus.Add(LoadBitmap("teststatus2", 320, 75));
249 sfcTestStatus.Add(LoadBitmap("teststatus3", 320, 75));
250 sfcTestStatus.Add(LoadBitmap("teststatus4", 320, 75));
251 sfcTestStatus.Add(LoadBitmap("teststatus5", 320, 75));
252
253 sfcResults90[FAIL] = LoadBitmap("results_fail_90", 90, 90);
254 sfcResults90[BRONZE] = LoadBitmap("results_bronze_90", 90, 90);
255 sfcResults90[SILVER] = LoadBitmap("results_silver_90", 90, 90);
256 sfcResults90[GOLD] = LoadBitmap("results_gold_90", 90, 90);
257 sfcResults90[PLATINUM] = LoadBitmap("results_platinum_90", 90, 90);
258
259 sfcFirstRun = LoadBitmap("firstrun", 320, 480);
260 sfcHelp = LoadBitmap("menu_help", 320, 480);
261 sfcLoading = LoadBitmap("loading", 320, 480);
262
263 sfcOptions = LoadBitmap("menu_options", 320, 480);
264 sfcOptionsSoundsOff = LoadBitmap("sound_off", 320, 48);
265 sfcOptionsMusicOff = LoadBitmap("music_off", 320, 48);
266
267 sfcTestBackground = LoadBitmap("bg_test", 512, 512);
268 sfcResultsBackground = LoadBitmap("bg_results", 512, 512);
269 sfcResultsBackground2 = LoadBitmap("bg_results2", 320, 480);
270 sfcHistoryBackground = LoadBitmap("history", 320, 480);
271
272 sfcMarathonMode = LoadBitmap("menu_marathonmode", 320, 480);
273 sfcBrainBoost = LoadBitmap("menu_brainboost", 320, 480);
274
275 sfcBGObjectTypes.Add(LoadBitmap("emptycircle", 256, 256));
276 sfcBGObjectTypes.Add(LoadBitmap("doubleemptycircle", 256, 256));
277 sfcBGObjectTypes.Add(LoadBitmap("doublecircle", 256, 256));
278 sfcBGObjectTypes.Add(LoadBitmap("circlering", 256, 256));
279 sfcBGObjectTypes.Add(LoadBitmap("filledcircle", 256, 256));
280
281 sfcSecretLo = LoadBitmap("secret_lo", 71, 66);
282 sfcSecretHi = LoadBitmap("secret_hi", 71, 66);
283
284 sfcStarTypes.Add(LoadBitmap("star_dark", 3, 3));
285 sfcStarTypes.Add(LoadBitmap("star_medium", 3, 3));
286 sfcStarTypes.Add(LoadBitmap("star_bright", 3, 3));
287
288 Sounds["baa"] = LoadSound("baa");
289 Sounds["baa2"] = LoadSound("baa2");
290 Sounds["baa3"] = LoadSound("baa3");
291 Sounds["balloon_pop"] = LoadSound("balloon_pop");
292 Sounds["beep_hi"] = LoadSound("beep_hi");
293 Sounds["bubble"] = LoadSound("bubble");
294 Sounds["card_flip"] = LoadSound("card_flip");
295 Sounds["card_flip2"] = LoadSound("card_flip2");
296 Sounds["click"] = LoadSound("click");
297 Sounds["correct"] = LoadSound("correct");
298 Sounds["down"] = LoadSound("down");
299 Sounds["explosion"] = LoadSound("explosion");
300 Sounds["gem_select"] = LoadSound("gem_select");
301 Sounds["glass_break"] = LoadSound("glass_break");
302 Sounds["gun1"] = LoadSound("gun1");
303 Sounds["gun2"] = LoadSound("gun2");
304 Sounds["happy_ring"] = LoadSound("happy_ring");
305 Sounds["meow"] = LoadSound("meow");
306 Sounds["mouse_click"] = LoadSound("mouse_click");
307 Sounds["result"] = LoadSound("result");
308 Sounds["slide"] = LoadSound("slide");
309 Sounds["soft_boom"] = LoadSound("soft_boom");
310 Sounds["swoosh_long"] = LoadSound("swoosh_long");
311 Sounds["whack"] = LoadSound("whack");
312 Sounds["wrong"] = LoadSound("wrong");
313 Sounds["wrong2"] = LoadSound("wrong2");
314 Sounds["wrong3"] = LoadSound("wrong3");
315 Sounds["zap"] = LoadSound("zap");
316
317 PlaySound("mouse_click", true, false);
318
319 Music = NULL;
320
321 sfcMainMenu = LoadBitmap("menu_main", 320, 480);
322 sfcPlayMenu = LoadBitmap("menu_play", 320, 480);
323 sfcPractiseMenu = LoadBitmap("menu_practise", 320, 480);
324 sfcPractiseMenuHider = LoadBitmap("menu_practise_hider", 134, 34);
325 sfcProfessorTalk = LoadBitmap("professor_talk", 320, 480);
326 sfcCredits = LoadBitmap("menu_credits", 320, 480);
327
328 sfcBottomBar = LoadBitmap("bottombar", 320, 64);
329
330 sfcQuitTest = LoadBitmap("quit_test", 320, 480);
331
332 sfcResultsFail = LoadBitmap("results_fail", 320, 480);
333 sfcResultsBronze = LoadBitmap("results_bronze", 320, 480);
334 sfcResultsSilver = LoadBitmap("results_silver", 320, 480);
335 sfcResultsGold = LoadBitmap("results_gold", 320, 480);
336 sfcResultsPlatinum = LoadBitmap("results_platinum", 320, 480);
337
338 sfcWhite = LoadBitmap("white", 64, 64);
339
340 sfcCorrect = LoadBitmap("correct", 320, 92);
341 sfcWrong = LoadBitmap("wrong", 320, 92);
342
343 ActiveMiniGame = NULL;
344
345 LoadSettings();
346
347 if (FirstRun) {
348 SetGameState(FIRST_RUN);
349 } else {
350 SetGameState(MAIN_MENU);
351 }
352
353 PlayMusic("theme");
354
355
356 // Hackage for stress testing!
357
358 // for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
359 // for (int i = 0; i < 1000000; ++i) {
360 // NSLog("Creating %", it->second->ShortName);
361 // CreateMiniGame(UNTANGLER, false, true);
362 // ActiveMiniGame->Start();
363 // }
364 // }
365 }
366
Update(float elapsed)367 void BPGame::Update(float elapsed) {
368 ElapsedSeconds = elapsed;
369 ElapsedTickCount = floor(elapsed * 1000);
370 TickCount += ElapsedTickCount;
371
372 if (ShowingMessageBox) {
373 return;
374 }
375
376 if (!GameStateJustChanged) {
377 // some gamestates need to increment the animcounter - do that now!
378 switch (GameState) {
379 case MAIN_MENU_PLAY:
380 case PLAY_MAIN_MENU:
381 case PRACTISE_PROFESSOR:
382 case MAIN_MENU_OPTIONS:
383 case OPTIONS_MAIN_MENU:
384 case PLAY_HISTORY:
385 case HISTORY_CREDITS:
386 case CREDITS_HISTORY:
387 case HISTORY_PLAY:
388 case TEST_RESULTS_PLAY:
389 case MAIN_MENU_HELP:
390 case HELP_MAIN_MENU:
391 if (AnimCounter < 1.0f) {
392 AnimCounter += 3.5f * elapsed;
393 if (AnimCounter > 1.0f) {
394 AnimCounter = 1.0f;
395 }
396 }
397
398 break;
399
400 case PLAY_PRACTISE:
401 case PRACTISE_PLAY:
402 if (AnimCounter < 1.0f) {
403 AnimCounter += 3.5f * elapsed;
404 if (AnimCounter > 1.0f) {
405 AnimCounter = 1.0f;
406 }
407 }
408
409 // don't break - we need to execute the following one too!
410
411 case PRACTISE_MENU:
412 if (PractiseAnimCounter < 1.0f) {
413 PractiseAnimCounter += 3.5f * elapsed;
414 if (PractiseAnimCounter > 1.0f) {
415 PractiseAnimCounter = 1.0f;
416 }
417 }
418
419 break;
420
421 case TEST_STATUS:
422 if (LastStateChange + 5000 < TickCount) {
423 NextTest();
424 }
425
426 if (LastBGObject + 1000 < TickCount) {
427 BGObject* obj = new BGObject();
428 obj->Scale = 0.0f;
429 obj->Pos = BPPoint(RandomRange(0, 320), RandomRange(0, 480));
430
431 switch (RandomRange(0, 17)) {
432 case 0:
433 case 1:
434 case 2:
435 case 3:
436 case 4:
437 case 5:
438 case 6:
439 case 7:
440 obj->Type = sfcBGObjectTypes[0];
441 break;
442
443 case 8:
444 case 9:
445 case 10:
446 case 11:
447 obj->Type = sfcBGObjectTypes[1];
448 break;
449
450 case 12:
451 case 13:
452 case 14:
453 obj->Type = sfcBGObjectTypes[2];
454 break;
455
456 case 15:
457 case 16:
458 obj->Type = sfcBGObjectTypes[3];
459 break;
460
461 default:
462 obj->Type = sfcBGObjectTypes[4];
463 break;
464 }
465
466 BackgroundObjects.Add(obj);
467 LastBGObject = TickCount;
468 }
469
470
471 for (int i = BackgroundObjects.Count - 1; i >= 0; --i) {
472 BackgroundObjects[i]->Scale += 0.3f * ElapsedSeconds;
473
474 if (BackgroundObjects[i]->Scale >= 1.0f) {
475 BackgroundObjects.RemoveAt(i);
476 }
477 }
478
479
480 break;
481
482 case TEST_RESULTS:
483 for (int i = 0; i < TestResultContainers.Count; ++i) {
484 TestResultContainer* result = TestResultContainers[i];
485
486 if (result->GoingUp) {
487 result->FadeUpAnim += 0.2f * ElapsedSeconds;
488 if (result->FadeUpAnim > 1.0f) {
489 result->FadeUpAnim = 1.0f;
490 result->GoingUp = false;
491 }
492 } else {
493 result->FadeUpAnim -= 0.4f * ElapsedSeconds;
494 if (result->FadeUpAnim < -1.0f) {
495 result->FadeUpAnim = -1.0f;
496 result->GoingUp = true;
497 }
498 }
499 }
500
501 break;
502
503 }
504 } else {
505 GameStateJustChanged = false; // we skipped our animcounter update - now continue as normal
506 }
507
508 switch (GameState) {
509 case PLAY_PRACTISE:
510 case PRACTISE_PLAY:
511 if (AnimCounter == 1.0f) {
512 if (GameState == PLAY_PRACTISE) {
513 SetGameState(PRACTISE_MENU);
514 } else {
515 SetGameState(PLAY_MENU);
516 }
517 }
518 // don't break - we need to update the practise screen behind the scenes too
519
520 case PRACTISE_MENU:
521 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
522 it->second->X = SmoothStep(it->second->StartX, it->second->DestX, PractiseAnimCounter);
523 it->second->Y = SmoothStep(it->second->StartY, it->second->DestY, PractiseAnimCounter);
524 }
525
526 break;
527
528 case PLAYING:
529 ActiveMiniGame->TickMiniGame();
530 break;
531
532 case MAIN_MENU_PLAY:
533 if (AnimCounter == 1.0f) SetGameState(PLAY_MENU);
534 break;
535
536 case PLAY_MAIN_MENU:
537 if (AnimCounter == 1.0f) SetGameState(MAIN_MENU);
538 break;
539
540 case PLAY_HISTORY:
541 if (AnimCounter == 1.0f) SetGameState(HISTORY);
542 break;
543
544 case HISTORY_CREDITS:
545 if (AnimCounter == 1.0f) SetGameState(CREDITS);
546 break;
547
548 case CREDITS_HISTORY:
549 if (AnimCounter == 1.0f) SetGameState(HISTORY);
550 break;
551
552 case HISTORY_PLAY:
553 if (AnimCounter == 1.0f) SetGameState(PLAY_MENU);
554 break;
555
556 case PRACTISE_PROFESSOR:
557 if (AnimCounter == 1.0f) SetGameState(PROFESSOR);
558 break;
559
560 case MAIN_MENU_OPTIONS:
561 if (AnimCounter == 1.0f) SetGameState(OPTIONS);
562 break;
563
564 case OPTIONS_MAIN_MENU:
565 if (AnimCounter == 1.0f) SetGameState(MAIN_MENU);
566 break;
567
568 case TEST_RESULTS_PLAY:
569 if (AnimCounter == 1.0f) SetGameState(PLAY_MENU);
570 break;
571
572 case MAIN_MENU_HELP:
573 if (AnimCounter == 1.0f) SetGameState(HELP);
574 break;
575
576 case HELP_MAIN_MENU:
577 if (AnimCounter == 1.0f) SetGameState(MAIN_MENU);
578 break;
579 }
580 }
581
Draw()582 void BPGame::Draw() {
583 Clear(Black);
584
585 switch (GameState) {
586 case FIRST_RUN:
587 sfcFirstRun->Draw(0, 0);
588 break;
589
590 case MAIN_MENU:
591 RenderMainMenu(0, 0);
592 break;
593
594 case MAIN_MENU_PLAY:
595 {
596 float offval = SmoothStep(0, -320, AnimCounter);
597 float onval = SmoothStep(320, 0, AnimCounter);
598
599 RenderMainMenu(offval, 0.0f);
600 RenderPlayMenu(onval, 0.0f);
601 }
602
603 break;
604
605 case PLAY_MAIN_MENU:
606 {
607 float offval = SmoothStep(-320, 0, AnimCounter);
608 float onval = SmoothStep(0, 320, AnimCounter);
609
610 RenderMainMenu(offval, 0.0f);
611 RenderPlayMenu(onval, 0.0f);
612 }
613
614 break;
615
616 case PLAY_HISTORY:
617 {
618 float offval = SmoothStep(0, -480, AnimCounter);
619 float onval = SmoothStep(480, 0, AnimCounter);
620
621 RenderPlayMenu(0.0f, offval);
622 RenderHistory(0.0f, onval);
623 }
624
625 break;
626
627 case HISTORY_CREDITS:
628 {
629 float offval = SmoothStep(0, -480, AnimCounter);
630 float onval = SmoothStep(480, 0, AnimCounter);
631
632 RenderHistory(0.0f, offval);
633 RenderCredits(0.0f, onval);
634 }
635
636 break;
637
638 case CREDITS_HISTORY:
639 {
640 float offval = SmoothStep(0, 480, AnimCounter);
641 float onval = SmoothStep(-480, 0, AnimCounter);
642
643 RenderCredits(0.0f, offval);
644 RenderHistory(0.0f, onval);
645 }
646
647 break;
648
649 case HISTORY_PLAY:
650 {
651 float offval = SmoothStep(0, 480, AnimCounter);
652 float onval = SmoothStep(-480, 0, AnimCounter);
653
654 RenderHistory(0.0f, offval);
655 RenderPlayMenu(0.0f, onval);
656 }
657
658 break;
659
660 case MAIN_MENU_OPTIONS:
661 RenderOptionsMenu();
662
663 glColor4f(1.0f, 1.0f, 1.0f, 1 - AnimCounter);
664 RenderMainMenu(0.0f, 0.0f);
665 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
666
667 break;
668
669 case OPTIONS_MAIN_MENU:
670 RenderMainMenu(0.0f, 0.0f);
671
672 glColor4f(1.0f, 1.0f, 1.0f, 1 - AnimCounter);
673 RenderOptionsMenu();
674 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
675
676 break;
677
678 case MAIN_MENU_HELP:
679 {
680 float onval = SmoothStep(480, 0, AnimCounter);
681
682 RenderMainMenu(0.0f, 0.0f);
683 RenderHelp(0.0f, onval);
684 }
685
686 break;
687
688 case HELP_MAIN_MENU:
689 {
690 float offval = SmoothStep(0, 480, AnimCounter);
691
692 RenderMainMenu(0.0f, 0.0f);
693 RenderHelp(0.0f, offval);
694 }
695
696 break;
697
698 case TEST_RESULTS_PLAY:
699 {
700 float offval = SmoothStep(0, 480, AnimCounter);
701 float onval = SmoothStep(-480, 0, AnimCounter);
702
703 RenderTestResults(0.0f, offval);
704 RenderPlayMenu(0.0f, onval);
705 }
706
707 break;
708
709 case PLAY_MENU:
710 RenderPlayMenu(0.0f, 0.0f);
711 break;
712
713 case PRACTISE_PLAY:
714 RenderPractiseMenu();
715
716 glColor4f(1.0f, 1.0f, 1.0f, AnimCounter);
717 RenderPlayMenu(0.0f, 0.0f);
718 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
719
720 break;
721
722 case PLAY_PRACTISE:
723 RenderPractiseMenu();
724
725 glColor4f(1.0f, 1.0f, 1.0f, 1 - AnimCounter);
726 RenderPlayMenu(0.0f, 0.0f);
727 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
728
729 break;
730
731 case PRACTISE_MENU:
732 RenderPractiseMenu();
733 break;
734
735 case PROFESSOR:
736 RenderProfessor();
737 break;
738
739 case PRACTISE_PROFESSOR:
740 RenderPractiseMenu();
741
742 glColor4f(1.0f, 1.0f, 1.0f, AnimCounter);
743 RenderProfessor();
744 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
745 break;
746
747 case PLAYING:
748 RenderPlaying();
749 break;
750
751 case TEST_STATUS:
752 RenderTestStatus();
753 break;
754
755 case TEST_RESULTS:
756 RenderTestResults(0.0f, 0.0f);
757 break;
758
759 case OPTIONS:
760 RenderOptionsMenu();
761 break;
762
763 case HISTORY:
764 RenderHistory(0.0f, 0.0f);
765 break;
766
767 case BRAINBOOST:
768 RenderBrainBoost();
769 break;
770
771 case MARATHON:
772 RenderMarathon();
773 break;
774
775 case CREDITS:
776 RenderCredits(0.0f, 0.0f);
777 break;
778
779 case HELP:
780 RenderHelp(0.0f, 0.0f);
781 break;
782 }
783
784 if (ShowingMessageBox) {
785 FillRectangle(Colour(0.0f, 0.0f, 0.0f, 0.85f), 0, 0, 320, 480);
786
787 Colour col = Colour(1.0f, 1.0f, 1.0f, 1.0f);
788 sfcLogo->Draw(160, 90, 0.0f, 0.6f, col);
789 sfcMessageBoxTitle->drawAtPoint(0, 170);
790
791 glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
792 sfcMessageBoxText->drawAtPoint(10, 205);
793 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
794 }
795 }
796
LoadBitmap(const char * filename,int actualwidth,int actualheight)797 Texture* BPGame::LoadBitmap(const char* filename, int actualwidth, int actualheight) {
798 return new Texture(filename, actualwidth, actualheight);
799 }
800
AddTestScore(int score)801 void BPGame::AddTestScore(int score) {
802 if (InTestMode) {
803 TestScores.Add(score);
804
805 if (TestScores.Count == TestMiniGames.Count) {
806 // that was the last game in this test run!
807 CalculateTestResults();
808 SetGameState(TEST_RESULTS);
809 InTestMode = false;
810 PlayMusic("results");
811 } else {
812 SetGameState(TEST_STATUS);
813 }
814 }
815 }
816
FillRectangle(Colour col,float x,float y,float width,float height)817 void BPGame::FillRectangle(Colour col, float x, float y, float width, float height) {
818 glColor4f(col.R, col.G, col.B, col.A);
819 sfcWhite->Draw(x, y, width, height);
820 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
821 }
822
DrawImage(Texture * tex,float x,float y)823 void BPGame::DrawImage(Texture* tex, float x, float y) {
824 tex->Draw(x, y);
825 }
826
DrawImage(Texture * tex,float x,float y,Colour & col)827 void BPGame::DrawImage(Texture* tex, float x, float y, Colour &col) {
828 tex->Draw(x, y, col);
829 }
830
831
DrawImage(Texture * tex,float x,float y,float rotation,float scale,Colour & col)832 void BPGame::DrawImage(Texture* tex, float x, float y, float rotation, float scale, Colour &col) {
833 tex->Draw(x, y, rotation, scale, col);
834 }
835
Clear(Colour * col)836 void BPGame::Clear(Colour* col) {
837 glClearColor(col->R, col->G, col->B, col->A);
838 glClear(GL_COLOR_BUFFER_BIT);
839 }
840
PointOverRect(int x1,int y1,int x2,int y2,int width,int height)841 bool BPGame::PointOverRect(int x1, int y1, int x2, int y2, int width, int height) {
842 if (x1 >= x2 && x1 <= x2 + width) {
843 if (y1 >= y2 && y1 <= y2 + height) {
844 return true;
845 }
846 }
847
848 return false;
849 }
850
RectOverRect(int x1,int y1,int width1,int height1,int x2,int y2,int width2,int height2)851 bool BPGame::RectOverRect(int x1, int y1, int width1, int height1, int x2, int y2, int width2, int height2) {
852 if (x1 + width1 < x2) return false;
853 if (x1 > x2 + width2) return false;
854 if (y1 + height1 < y2) return false;
855 if (y1 > y2 + height2) return false;
856
857 return true;
858 }
859
TouchStart(float x,float y)860 void BPGame::TouchStart(float x, float y) {
861 if (ShowingMessageBox) {
862 return;
863 }
864
865 TouchEvent.X = x;
866 TouchEvent.Y = y;
867
868 switch (GameState) {
869 case PLAYING:
870 if (ActiveMiniGame != NULL) {
871 ActiveMiniGame->HandleMouseDown(TouchEvent);
872 }
873
874 break;
875 }
876 }
877
TouchStop(float x,float y)878 void BPGame::TouchStop(float x, float y) {
879 if (ShowingMessageBox) {
880 ShowingMessageBox = false;
881 ShowingClearScores = false;
882 return;
883 }
884
885 TouchEvent.X = x;
886 TouchEvent.Y = y;
887
888 switch (GameState) {
889 case FIRST_RUN:
890 SetGameState(MAIN_MENU);
891 PlaySound("mouse_click");
892 break;
893
894 case MAIN_MENU:
895 if (PointOverRect(TouchEvent.X, TouchEvent.Y, 37, 207, 248, 78)) {
896 SetGameState(MAIN_MENU_PLAY);
897 PlaySound("mouse_click");
898 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 22, 309, 272, 58)) {
899 SetGameState(MAIN_MENU_OPTIONS);
900 PlaySound("mouse_click");
901 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 73, 370, 170, 58)) {
902 SetGameState(MAIN_MENU_HELP);
903 PlaySound("mouse_click");
904 } else if (TouchEvent.Y < 207) {
905 ++CheatMainTaps;
906 }
907
908 break;
909
910 case PLAY_MENU:
911 if (PointOverRect(TouchEvent.X, TouchEvent.Y, 0, 48, 320, 128)) {
912 if (AllTestScores.Count == 0) {
913 MessageBox::Show("Once you have completed your first test, this will show your brain weight.", "Brain weight");
914 } else {
915 MessageBox::Show("This is your current brain weight, as measured by the last test you did.", "Brain weight");
916 }
917 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 16, 192, 288, 48)) {
918 RunTest();
919 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 15, 252, 289, 48)) {
920 if (NumUnlockedGames > 0) {
921 SetGameState(PLAY_PRACTISE);
922 PlaySound("mouse_click");
923 } else {
924 MessageBox::Show("You can't practise any games until you have completed at least one test. Go on, it won't take long!", "No games to practise");
925 }
926 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 28, 312, 264, 48)) {
927 SetGameState(PLAY_HISTORY);
928 PlaySound("mouse_click");
929 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 74, 410, 172, 48)) {
930 SetGameState(PLAY_MAIN_MENU);
931 PlaySound("mouse_click");
932 }
933 break;
934
935 case PRACTISE_MENU:
936 if (PointOverRect(TouchEvent.X, TouchEvent.Y, 91, 437, 137, 27)) {
937 SetGameState(PRACTISE_PLAY);
938 PlaySound("mouse_click");
939 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 15, 384, 134, 34)) {
940 // back
941 if (PractiseAnimCounter == 1.0f) {
942 if (PractisePageNumber != 0) {
943 PractisePageNumber -= 9;
944 if (PractisePageNumber < 0) PractisePageNumber = 0;
945 PractisePageMoveLeft = false;
946 PositionPractiseGames();
947 PlaySound("mouse_click");
948 }
949 }
950 } else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 173, 383, 134, 34)) {
951 // more
952 if (PractiseAnimCounter == 1.0f) {
953 if (PractisePageNumber + 9 < NumUnlockedGames) {
954 PractisePageNumber += 9;
955 PractisePageMoveLeft = true;
956 PositionPractiseGames();
957 PlaySound("mouse_click");
958 }
959 }
960 } else {
961 // did the player ask to play a minigame?
962 int i = 0;
963 int j = 0;
964 int xpos = 0;
965
966 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
967 if (it->second->IsSecret) continue;
968 if (!it->second->Unlocked) continue;
969
970 if (i < PractisePageNumber) {
971 ++i;
972 continue;
973 }
974
975 xpos = i - PractisePageNumber;
976
977 y = 75 + (xpos * 100);
978 x = 15 + (j * 100);
979
980 if (PointOverRect(TouchEvent.X, TouchEvent.Y, x, y, 90, 90)) {
981 if (it->second->Unlocked) {
982 PlaySound("mouse_click");
983 CreateMiniGame((MiniGameType)it->second->GameCode, false, true);
984 }
985
986 break;
987 }
988
989 ++j;
990
991 if (j == 3) {
992 j = 0;
993 ++i;
994 }
995
996 if (i > PractisePageNumber + 2) break;
997 }
998 }
999 break;
1000
1001 case PROFESSOR:
1002 ActiveMiniGame->PlayMusic();
1003 ActiveMiniGame->Start();
1004 SetGameState(PLAYING);
1005 break;
1006
1007 case PLAYING:
1008 ActiveMiniGame->HandleMouseUp(TouchEvent);
1009 break;
1010
1011 case TEST_STATUS:
1012 NextTest();
1013 break;
1014
1015 case TEST_RESULTS:
1016 if (LastStateChange + 1600 < TickCount) {
1017 SetGameState(TEST_RESULTS_PLAY);
1018 PlayMusic("theme");
1019 }
1020
1021 break;
1022
1023 case OPTIONS:
1024 if (PointOverRect(x, y, 21, 193, 277, 39)) {
1025 EnableSound = !EnableSound;
1026 PlaySound("click", false, true);
1027 SaveSettings();
1028 } else if (PointOverRect(x, y, 29, 259, 262, 37)) {
1029 EnableMusic = !EnableMusic;
1030 PlaySound("click");
1031
1032 if (EnableMusic == false) {
1033 StopMusic();
1034 } else {
1035 PlayMusic("theme");
1036 }
1037
1038 SaveSettings();
1039 } else if (PointOverRect(x, y, 15, 353, 290, 31)) {
1040 PromptResetScores();
1041 PlaySound("click");
1042
1043 } else if (PointOverRect(x, y, 0, 416, 320, 64)) {
1044 SetGameState(OPTIONS_MAIN_MENU);
1045 PlaySound("mouse_click");
1046 } else if (TouchEvent.Y < 193) {
1047 ++CheatOptionsTaps;
1048 }
1049
1050 break;
1051
1052 case HISTORY:
1053 if (PointOverRect(x, y, 17, 45, 285, 161)) {
1054 MessageBox::Show("This graph shows your most recent test results.", "Your test history");
1055 } else if (PointOverRect(x, y, 21, 251, 285, 57)) {
1056 MessageBox::Show("This is the highest brain weight you have scored in any test. Each minigame is worth up to 500g, and you get five in a test, so the maximum brain weight is 2500g.", "Highest Brain Weight");
1057 } else if (PointOverRect(x, y, 0, 349, 74, 66)) {
1058 if (Secret1) {
1059 CreateMiniGame(DICEOFF, false, false);
1060 } else {
1061 MessageBox::Show("This secret game is unlocked when you get a Platinum score in Balloon Blaster.", "Secret locked!");
1062 }
1063 } else if (PointOverRect(x, y, 82, 349, 74, 66)) {
1064 if (Secret2) {
1065 CreateMiniGame(WORDSMASH, false, false);
1066 } else {
1067 MessageBox::Show("This secret game is unlocked when you get a Platinum score in Jewel Jam.", "Secret locked!");
1068 }
1069 } else if (PointOverRect(x, y, 162, 349, 74, 66)) {
1070 if (Secret3) {
1071 SetGameState(MARATHON);
1072 PlaySound("mouse_click");
1073 } else {
1074 MessageBox::Show("This secret area is unlocked when you get a Platinum score in Odd One Out.", "Secret locked!");
1075 }
1076 } else if (PointOverRect(x, y, 245, 349, 74, 66)) {
1077 if (Secret4) {
1078 SetGameState(BRAINBOOST);
1079 PlaySound("mouse_click");
1080 } else {
1081 MessageBox::Show("This secret area is unlocked when you get a Platinum score in Untangler.", "Secret locked!");
1082 }
1083 } else if (PointOverRect(x, y, 2, 418, 110, 54)) {
1084 SetGameState(HISTORY_PLAY);
1085 PlaySound("mouse_click");
1086 } else if (PointOverRect(x, y, 182, 418, 136, 54)) {
1087 SetGameState(HISTORY_CREDITS);
1088 PlaySound("mouse_click");
1089 }
1090
1091 break;
1092
1093 case CREDITS:
1094 if (PointOverRect(x, y, 193, 203, 126, 148)) {
1095 // clicked on the professor!
1096 if (CheatMainTaps >= 5 && CheatOptionsTaps >= 5) {
1097 MessageBox::Show("Hey, it looks like you activated the cheat code - all the minigames and secrets have been unlocked. We hope you're proud of yourself!", "Cheat activated!");
1098
1099 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1100 it->second->Unlocked = true;
1101 }
1102
1103 Secret1 = Secret2 = Secret3 = Secret4 = true;
1104
1105 SaveSettings();
1106
1107 PlaySound("meow");
1108 }
1109 }
1110
1111 SetGameState(CREDITS_HISTORY);
1112 PlaySound("mouse_click");
1113 break;
1114
1115 case MARATHON:
1116 if (PointOverRect(x, y, 12, 201, 90, 90)) {
1117 CreateMiniGame(BALLOONBLASTER, true, false);
1118 } else if (PointOverRect(x, y, 116, 201, 90, 90)) {
1119 CreateMiniGame(BPSAYS, true, false);
1120 } else if (PointOverRect(x, y, 220, 201, 90, 90)) {
1121 CreateMiniGame(JEWELJAM, true, false);
1122 } else if (PointOverRect(x, y, 12, 305, 90, 90)) {
1123 CreateMiniGame(SHORTCIRCUITSUDOKU, true, false);
1124 } else if (PointOverRect(x, y, 116, 305, 90, 90)) {
1125 CreateMiniGame(SYMBOLICLOGIC, true, false);
1126 } else if (PointOverRect(x, y, 220, 305, 90, 90)) {
1127 CreateMiniGame(UNTANGLER, true, false);
1128 } else if (PointOverRect(x, y, 0, 423, 320, 64)) {
1129 SetGameState(HISTORY);
1130 PlaySound("mouse_click");
1131 }
1132
1133 break;
1134
1135 case BRAINBOOST:
1136 if (PointOverRect(x, y, 53, 184, 90, 90)) {
1137 CreateMiniGame(SHARPSHOOTER, true, false);
1138 } else if (PointOverRect(x, y, 179, 184, 90, 90)) {
1139 CreateMiniGame(SHUFFLEPUZZLER, true, false);
1140 } else if (PointOverRect(x, y, 53, 305, 90, 90)) {
1141 CreateMiniGame(STRANGERDANGER, true, false);
1142 } else if (PointOverRect(x, y, 179, 305, 90, 90)) {
1143 CreateMiniGame(UNDERTHEHAT, true, false);
1144 } else if (PointOverRect(x, y, 0, 423, 320, 64)) {
1145 SetGameState(HISTORY);
1146 PlaySound("mouse_click");
1147 }
1148
1149 break;
1150
1151 case HELP:
1152 SetGameState(HELP_MAIN_MENU);
1153 PlaySound("mouse_click");
1154 break;
1155 }
1156 }
1157
TouchDrag(float x,float y)1158 void BPGame::TouchDrag(float x, float y) {
1159 if (ShowingMessageBox) {
1160 return;
1161 }
1162
1163 TouchEvent.X = x;
1164 TouchEvent.Y = y;
1165
1166 switch (GameState) {
1167 case PLAYING:
1168 if (ActiveMiniGame != NULL) {
1169 ActiveMiniGame->HandleMouseMove(TouchEvent);
1170 }
1171
1172 break;
1173 }
1174 }
1175
TrimString(const std::string & str)1176 const string TrimString(const std::string& str) {
1177 string::size_type First = str.find_first_not_of( ' ' );
1178
1179 if (First == string::npos) {
1180 First = 0;
1181 }
1182
1183 string::size_type Last = str.find_last_not_of( ' ' );
1184 if (Last != string::npos) {
1185 Last = (Last + 1) - First;
1186 }
1187
1188 return str.substr(First, Last);
1189 }
1190
1191
AllocString(SpriteFont ** tex,const char * str,FontSizes size,float width,float height,Alignments align,bool bold)1192 void BPGame::AllocString(SpriteFont** tex, const char* str, FontSizes size, float width, float height, Alignments align, bool bold) {
1193 SAFE_DELETE((*tex));
1194
1195 // it's incredibly lazy to open and close the font each time - hurray!
1196 TTF_Font* fnt = TTF_OpenFont("/usr/local/share/brainparty/freesans.ttf", size - 3); // NB: the -3 is here because the freesans.ttf font we're using is a big chunkier than the iPhone font
1197
1198 static SDL_Color white = { 255, 255, 255, 255 };
1199
1200 vector<string> lines; // we'll store the split lines here
1201 string temp(str); // the current text we're working on
1202 temp += " "; // always add a space to the end of the text to enable wrapping - this gets removed later
1203 int n = 0; // current index
1204 int p = 0; // previous space
1205
1206 while (n != -1) {
1207 std::string strSub;
1208 n = temp.find(" ", p + 1 ); // -- Find the next " "
1209
1210 std::string line_so_far = temp.substr(0, n);
1211 int w,h;
1212
1213 const char* c_str = line_so_far.c_str();
1214 TTF_SizeText(fnt, c_str, &w, &h);
1215
1216 if (w >= width) {
1217 strSub = temp.substr(0, p);
1218 lines.push_back(strSub);
1219
1220 if (n != -1) temp = temp.substr( p+1, string::npos );
1221 p = 0;
1222 } else {
1223 p = n;
1224 }
1225 }
1226
1227 // do the last line too
1228 string strSub = temp.substr(0, p);
1229 lines.push_back(strSub);
1230
1231
1232 // create a SpriteFont to hold all the information - this is used for drawing later
1233 (*tex) = new SpriteFont();
1234 (*tex)->Width = width;
1235 (*tex)->Height = height;
1236 (*tex)->Align = align;
1237
1238 // render all the text
1239 for (int i = 0; i < lines.size(); ++i) {
1240 SDL_Surface* sfc = TTF_RenderText_Blended(fnt, TrimString(lines[i]).c_str(), white);
1241
1242 if (sfc != NULL) {
1243 (*tex)->Surfaces.Add(new Texture(sfc));
1244 SDL_FreeSurface(sfc);
1245 }
1246 }
1247
1248 TTF_CloseFont(fnt);
1249 }
1250
DrawString(SpriteFont * tex,Colour & col,float x,float y)1251 void BPGame::DrawString(SpriteFont* tex, Colour &col, float x, float y) {
1252 if (tex == NULL) return;
1253
1254 glColor4f(col.R, col.G, col.B, col.A);
1255 tex->drawAtPoint(x,y);
1256 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1257 }
1258
DrawString(SpriteFont * tex,Colours col,float x,float y)1259 void BPGame::DrawString(SpriteFont* tex, Colours col, float x, float y) {
1260 if (tex == NULL) return;
1261
1262 if (col == WHITE) {
1263 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1264 } else if (col == BLACK) {
1265 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1266 }
1267
1268 tex->drawAtPoint(x,y);
1269
1270 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1271 }
1272
DrawString(SpriteFont * tex,float x,float y)1273 void BPGame::DrawString(SpriteFont* tex, float x, float y) {
1274 if (tex == NULL) return;
1275
1276 tex->drawAtPoint(x,y);
1277 }
1278
RandomRange(int min,int max)1279 int BPGame::RandomRange(int min, int max) {
1280 if (max < min) return min;
1281
1282 int value = rand();
1283 return (value % ((max - min) + 1) + min);
1284 }
1285
RandomRangeExcept(int min,int max,int except)1286 int BPGame::RandomRangeExcept(int min, int max, int except) {
1287 int val = RandomRange(min, max);
1288
1289 while (val == except) {
1290 val = RandomRange(min, max);
1291 }
1292
1293 return val;
1294 }
1295
LoadSettings()1296 void BPGame::LoadSettings() {
1297 Secret1 = Secret2 = Secret3 = Secret4 = false;
1298 NumUnlockedGames = 0;
1299
1300 ifstream ifs;
1301 ifs.open((string(getenv("HOME")) + "/.brainparty").c_str());
1302
1303 FirstRun = false;
1304
1305 if (ifs.is_open()) {
1306 string temp;
1307
1308 int loading_stage = 0;
1309 int line_number = 0;
1310 int secret_num = 1;
1311
1312 while (getline(ifs, temp)) {
1313 ++line_number;
1314
1315 if (temp.size() == 0) {
1316 ++loading_stage;
1317 } else {
1318 switch (loading_stage) {
1319 case 0:
1320 // loading whether we have music and sound
1321 if (line_number == 1) {
1322 if (temp.compare("1") == 0) {
1323 EnableSound = true;
1324 } else {
1325 EnableSound = false;
1326 }
1327 } else {
1328 if (temp.compare("1") == 0) {
1329 EnableMusic = true;
1330 } else {
1331 EnableMusic = false;
1332 }
1333 }
1334 break;
1335
1336 case 1:
1337 // loading secrets
1338 switch (secret_num) {
1339 case 1:
1340 if (temp.compare("1") == 0) {
1341 Secret1 = true;
1342 } else {
1343 Secret1 = false;
1344 }
1345
1346 break;
1347
1348 case 2:
1349 if (temp.compare("1") == 0) {
1350 Secret2 = true;
1351 } else {
1352 Secret2 = false;
1353 }
1354 break;
1355
1356 case 3:
1357 if (temp.compare("1") == 0) {
1358 Secret3 = true;
1359 } else {
1360 Secret3 = false;
1361 }
1362 break;
1363
1364 case 4:
1365 if (temp.compare("1") == 0) {;
1366
1367 Secret4 = true;
1368 } else {
1369 Secret4 = false;
1370 }
1371 break;
1372 }
1373
1374 ++secret_num;
1375
1376 break;
1377
1378 case 2:
1379 {
1380 // loading test scores
1381 CurrentBrainWeight = atoi(temp.c_str());
1382 AllTestScores.Add(CurrentBrainWeight);
1383
1384 if (CurrentBrainWeight > HighestBrainWeight) {
1385 HighestBrainWeight = CurrentBrainWeight;
1386 }
1387
1388 break;
1389 }
1390
1391
1392 case 3:
1393 const char* gamename = temp.c_str();
1394
1395 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1396 if (it->second->IsSecret) continue;
1397
1398 if (strcmp(gamename, it->second->ShortName) == 0) {
1399 it->second->Unlocked = true;
1400 ++NumUnlockedGames;
1401 continue;
1402 }
1403 }
1404
1405 break;
1406 }
1407 }
1408 }
1409 } else {
1410 FirstRun = true;
1411 }
1412
1413 if (CurrentBrainWeight != -1) {
1414 ostringstream output;
1415 output << CurrentBrainWeight << "g";
1416 AllocString(&sfcTestWeight, output.str().c_str(), BRAINWEIGHT, 320, 100, CENTRED, true);
1417 } else {
1418 AllocString(&sfcTestWeight, "???", BRAINWEIGHT, 320, 100, CENTRED, true);
1419 }
1420
1421 if (HighestBrainWeight != -1) {
1422 ostringstream output;
1423 output << HighestBrainWeight << "g";
1424 AllocString(&sfcHighestBrainWeight, output.str().c_str(), XXLARGE, 320, 100, CENTRED, true);
1425 } else {
1426 AllocString(&sfcHighestBrainWeight, "N/A", XXLARGE, 320, 100, CENTRED, true);
1427 }
1428 }
1429
SaveSettings()1430 void BPGame::SaveSettings() {
1431 ofstream savefile;
1432 savefile.open((string(getenv("HOME")) + "/.brainparty").c_str());
1433 savefile << EnableSound << endl;
1434 savefile << EnableMusic << endl;
1435 savefile << endl;
1436
1437 savefile << Secret1 << endl;
1438 savefile << Secret2 << endl;
1439 savefile << Secret3 << endl;
1440 savefile << Secret4 << endl;
1441 savefile << endl;
1442
1443 for (int i = 0; i < AllTestScores.Count; ++i) {
1444 savefile << AllTestScores[i] << endl;
1445 }
1446
1447 savefile << endl;
1448
1449 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1450 if (it->second->Unlocked) {
1451 savefile << it->second->ShortName << endl;
1452 }
1453 }
1454
1455 savefile.close();
1456
1457 LoadSettings();
1458 }
1459
SeparateThousands(int number)1460 string BPGame::SeparateThousands(int number) {
1461 char buffer[20];
1462
1463 int i, digit, out_index = 0;
1464
1465 for (i = number; i != 0; i /= 10) {
1466 digit = i % 10;
1467
1468 if ((out_index + 1) % 4 == 0) {
1469 buffer[out_index++] = ',';
1470 }
1471
1472 buffer[out_index++] = digit + '0';
1473 }
1474
1475 buffer[out_index] = '\0';
1476
1477 string retval = string(buffer);
1478 reverse(retval.begin(), retval.end());
1479 return retval;
1480 }
1481
TicksToTime(int ticks)1482 string* BPGame::TicksToTime(int ticks) {
1483 int seconds_elapsed = floor(ticks / 1000);
1484 int minutes = floor(seconds_elapsed / 60.0);
1485 int seconds = seconds_elapsed % 60;
1486
1487 ostringstream output;
1488
1489 if (seconds < 10) {
1490 output << minutes << ":0" << seconds;
1491 } else {
1492 output << minutes << ":" << seconds;
1493 }
1494
1495 string* retval = new string(output.str());
1496 return retval;
1497 }
1498
DivRem(int Num,int Div,int * Rem)1499 int BPGame::DivRem(int Num, int Div, int* Rem) {
1500 (*Rem) = Num % Div;
1501 return floor(Num / Div);
1502 }
1503
DrawLine(int fromx,int fromy,int tox,int toy,Colour * col,float width)1504 void BPGame::DrawLine(int fromx, int fromy, int tox, int toy, Colour* col, float width) {
1505 GLfloat vertices[] = { fromx, fromy, tox, toy };
1506
1507 glDisable(GL_TEXTURE_2D);
1508 glLineWidth(width);
1509 glColor4f(col->R, col->G, col->B, col->A);
1510 glLoadIdentity();
1511
1512 glVertexPointer(2, GL_FLOAT, 0, vertices);
1513 glDrawArrays(GL_LINES, 0, 2);
1514
1515 glEnable(GL_TEXTURE_2D);
1516 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1517 }
1518
Clamp(float value,float minval,float maxval)1519 float BPGame::Clamp(float value, float minval, float maxval) {
1520 if (value > maxval) {
1521 value = maxval;
1522 } else if (value < minval) {
1523 value = minval;
1524 }
1525
1526 return value;
1527 }
1528
Hermite(float value1,float tangent1,float value2,float tangent2,float amount)1529 float BPGame::Hermite(float value1, float tangent1, float value2, float tangent2, float amount) {
1530 float AmountSquared = amount * amount;
1531 float AmountCubed = AmountSquared * amount;
1532
1533 float result = 0.0f;
1534
1535 if (amount == 0.0f) {
1536 result = value1;
1537 } else if (amount == 1.0f) {
1538 result = value2;
1539 } else {
1540 result = (2 * value1 - 2 * value2 + tangent2 + tangent1) * AmountCubed + (3 * value2 - 3 * value1 - 2 * tangent1 - tangent2) * AmountSquared + tangent1 * amount + value1;
1541 }
1542
1543 return result;
1544 }
1545
Lerp(float value1,float value2,float amount)1546 float BPGame::Lerp(float value1, float value2, float amount) {
1547 float result = Clamp(amount, 0.0f, 1.0f);
1548 return value1 + (value2 - value1) * result;
1549 }
1550
SmoothStep(float value1,float value2,float amount)1551 float BPGame::SmoothStep(float value1, float value2, float amount) {
1552 float result = Clamp(amount, 0.0f, 1.0f);
1553 result = Hermite(value1, 0.0, value2, 0.0, result);
1554 return result;
1555 }
1556
SmoothStep2(float value1,float value2,float amount)1557 float BPGame::SmoothStep2(float value1, float value2, float amount) {
1558 float result = Clamp(amount, 0.0f, 1.0f);
1559
1560 if (result > 0.5f) {
1561 result = Hermite(value2, 0.0f, value1, 0.0f, (result - 0.5f) * 2.0f);
1562 } else {
1563 result = Hermite(value1, 0.0f, value2, 0.0f, result * 2.0f);
1564 }
1565
1566 return result;
1567 }
1568
ColourSmoothStep(Colour & from,Colour & to,float amount)1569 Colour BPGame::ColourSmoothStep(Colour &from, Colour &to, float amount) {
1570 return Colour(SmoothStep(from.R, to.R, amount), SmoothStep(from.G, to.G, amount), SmoothStep(from.B, to.B, amount), SmoothStep(from.A, to.A, amount));
1571 }
1572
1573
StartsWithVowel(string * word)1574 bool BPGame::StartsWithVowel(string* word) {
1575 char chr = (*word)[0];
1576 if (chr == 'a' || chr == 'e' || chr == 'i' || chr == 'o' || chr == 'u'){
1577 return true;
1578 }
1579
1580 return false;
1581 }
1582
GetName()1583 const char* BPGame::GetName() {
1584 return PeopleNames[RandomRange(0, PeopleNames.Count - 1)];
1585 }
1586
RenderMainMenu(float xoff,float yoff)1587 void BPGame::RenderMainMenu(float xoff, float yoff) {
1588 DrawImage(sfcMainMenu, xoff, yoff);
1589 }
1590
RenderOptionsMenu()1591 void BPGame::RenderOptionsMenu() {
1592 DrawImage(sfcOptions, 0, 0);
1593
1594 if (!EnableSound) {
1595 DrawImage(sfcOptionsSoundsOff, 0, 188);
1596 }
1597
1598 if (!EnableMusic) {
1599 DrawImage(sfcOptionsMusicOff, 0, 254);
1600 }
1601 }
1602
RenderPlayMenu(float xoff,float yoff)1603 void BPGame::RenderPlayMenu(float xoff, float yoff) {
1604 DrawImage(sfcPlayMenu, xoff, yoff);
1605 DrawString(sfcTestWeight, xoff, yoff + 58.0f);
1606 }
1607
RenderPractiseMenu()1608 void BPGame::RenderPractiseMenu() {
1609 DrawImage(sfcPractiseMenu, 0, 0);
1610
1611 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1612 if (!it->second->IsShowing) {
1613 glColor4f(1.0f, 1.0f, 1.0f, 1.0f - PractiseAnimCounter);
1614 }
1615
1616 if (it->second->Pic == NULL) {
1617 DrawImage(sfcMiniGameUnknown, it->second->X, it->second->Y);
1618 } else {
1619 DrawImage(it->second->Pic, it->second->X, it->second->Y);
1620 }
1621
1622 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1623 }
1624
1625 if (PractisePageNumber == 0) {
1626 // hide Back
1627 glColor4f(1.0f, 1.0f, 1.0f, 0.85f);
1628 DrawImage(sfcPractiseMenuHider, 15, 384);
1629 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1630 }
1631
1632 if (PractisePageNumber + 9 >= NumUnlockedGames) {
1633 glColor4f(1.0f, 1.0f, 1.0f, 0.85f);
1634 DrawImage(sfcPractiseMenuHider, 173, 383);
1635 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1636 }
1637 }
1638
RenderProfessor()1639 void BPGame::RenderProfessor() {
1640 DrawImage(sfcProfessorTalk, 0, 0);
1641
1642 ActiveMiniGame->DrawProfessorText();
1643 }
1644
RenderPlaying()1645 void BPGame::RenderPlaying() {
1646 ActiveMiniGame->RenderMiniGame();
1647 }
1648
RenderTestStatus()1649 void BPGame::RenderTestStatus() {
1650 static float rotation = 0.0f;
1651 rotation += 15 * ElapsedSeconds;
1652
1653 Clear(Black);
1654 DrawImage(sfcTestBackground, 160.0f, 240.0f, rotation, 1.2f, (*White));
1655 Colour col = Colour(1.0f, 1.0f, 1.0f, 0.2f);
1656 DrawImage(sfcTestBackground, 160.0f, 240.0f, -rotation, 1.2f, col);
1657
1658 for (int i = 0; i < BackgroundObjects.Count; ++i) {
1659 BGObject* obj = BackgroundObjects[i];
1660
1661 float alpha;
1662
1663 if (obj->Scale < 0.5f) {
1664 // fading in
1665 alpha = (obj->Scale / 2.5f);
1666 } else {
1667 // fading out
1668 alpha = 0.4f - (obj->Scale / 2.5f);
1669 }
1670
1671 alpha = Clamp(alpha, 0.0f, 1.0f);
1672 Colour col = Colour(1.0f, 1.0f, 1.0f, alpha);
1673
1674 DrawImage(obj->Type, obj->Pos.X, obj->Pos.Y, 0.0f, obj->Scale, col);
1675 }
1676
1677 DrawImage(sfcTestStatus[TestPosition], 0.0f, 208.0f);
1678 }
1679
RenderTestResults(float xoff,float yoff)1680 void BPGame::RenderTestResults(float xoff, float yoff) {
1681 if (LastStateChange + 200 > TickCount) {
1682 // plain background
1683 DrawImage(sfcResultsBackground, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1684 } else if (LastStateChange + 1000 > TickCount) {
1685 // fade in Your Brain Weighs text
1686 DrawImage(sfcResultsBackground, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1687 Colour col = Colour(1.0f, 1.0, 1.0f, 1 - (((LastStateChange + 1000) - TickCount) / 800.0f));
1688 DrawImage(sfcResultsBackground2, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, col);
1689 } else if (LastStateChange + 1600 > TickCount) {
1690 // fade in brain weight
1691 DrawImage(sfcResultsBackground2, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1692 float alpha = 1 - (((LastStateChange + 1600) - TickCount) / 600.0f);
1693
1694 glColor4f(1.0f, 1.0f, 1.0f, alpha);
1695 DrawString(sfcTestWeight, xoff + 0.0f, yoff + 93.0f);
1696 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1697 } else {
1698 // show everything
1699 DrawImage(sfcResultsBackground2, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1700 DrawString(sfcTestWeight, xoff + 0.0f, yoff + 93.0f);
1701 DrawString(sfcTestJob, xoff + 0.0f, yoff + 200.0f);
1702 }
1703
1704 float diff = 1 - (((LastStateChange + 500) - TickCount) / 500.0f);
1705
1706 for (int i = 0; i < TestResultContainers.Count; ++i) {
1707 TestResultContainer* result = TestResultContainers[i];
1708
1709 int x, y, rot;
1710
1711 if (LastStateChange + 500 > TickCount) {
1712 // fading in
1713 x = SmoothStep(160, result->Pos.X, diff);
1714 y = SmoothStep(525, result->Pos.Y, diff);
1715 rot = SmoothStep(60 + (i * 60), 0, diff);
1716 Colour col = Colour(1.0f, 1.0f, 1.0f, SmoothStep(0.0f, 1.0f, diff));
1717 DrawImage(MiniGames[(MiniGameType)result->MiniGame]->Pic, xoff + x, yoff + y, rot, 1.0f, col);
1718 } else {
1719 x = result->Pos.X;
1720 y = result->Pos.Y;
1721 rot = 0;
1722 DrawImage(MiniGames[(MiniGameType)result->MiniGame]->Pic, xoff + x, yoff + y, rot, 1.0f, (*White));
1723 Colour col = Colour(1.0f, 1.0f, 1.0f, SmoothStep(0.0f, 1.0f, result->FadeUpAnim));
1724 DrawImage(sfcResults90[result->Rank], xoff + x, yoff + y, 0.0f, 1.0f, col);
1725 }
1726 }
1727 }
1728
RenderHistory(float xoff,float yoff)1729 void BPGame::RenderHistory(float xoff, float yoff) {
1730 DrawImage(sfcHistoryBackground, xoff, yoff);
1731
1732 DrawString(sfcHighestBrainWeight, xoff, 246.0f + yoff);
1733
1734 if (Secret1) {
1735 DrawImage(sfcSecretHi, 2 + xoff, 349 + yoff);
1736 } else {
1737 DrawImage(sfcSecretLo, 2 + xoff, 349 + yoff);
1738 }
1739
1740 if (Secret2) {
1741 DrawImage(sfcSecretHi, 83 + xoff, 349 + yoff);
1742 } else {
1743 DrawImage(sfcSecretLo, 83 + xoff, 349 + yoff);
1744 }
1745
1746 if (Secret3) {
1747 DrawImage(sfcSecretHi, 164 + xoff, 349 + yoff);
1748 } else {
1749 DrawImage(sfcSecretLo, 164 + xoff, 349 + yoff);
1750 }
1751
1752 if (Secret4) {
1753 DrawImage(sfcSecretHi, 246 + xoff, 349 + yoff);
1754 } else {
1755 DrawImage(sfcSecretLo, 246 + xoff, 349 + yoff);
1756 }
1757
1758 int graph_height = 148;
1759 int last_score = -1;
1760
1761 if (ShowScores.Count == 1) {
1762 // just one score - draw a dot!
1763 int this_score = round(ShowScores[0] / 2500.0f * graph_height);
1764 DrawLine(52 + xoff, 201 - this_score + yoff, 56 + xoff, 201 - this_score + yoff, Red, 4.0f);
1765 } else {
1766 for (int i = 0; i < ShowScores.Count; ++i) {
1767 int this_score = round(ShowScores[i] / 2500.0f * graph_height);
1768
1769 if (last_score != -1) {
1770 // connect the last dot to this dot
1771 DrawLine(54 + ((i - 1) * 30) + xoff, 201 - last_score + yoff, 54 + (i * 30) + xoff, 201 - this_score + yoff, Red, 3.0f);
1772 }
1773
1774 last_score = this_score;
1775 }
1776 }
1777 }
1778
RenderBrainBoost()1779 void BPGame::RenderBrainBoost() {
1780 DrawImage(sfcBrainBoost, 0, 0);
1781 }
1782
RenderMarathon()1783 void BPGame::RenderMarathon() {
1784 DrawImage(sfcMarathonMode, 0, 0);
1785 }
1786
RenderHelp(float xoff,float yoff)1787 void BPGame::RenderHelp(float xoff, float yoff) {
1788 DrawImage(sfcHelp, xoff, yoff);
1789 }
1790
RenderCredits(float xoff,float yoff)1791 void BPGame::RenderCredits(float xoff, float yoff) {
1792 DrawImage(sfcCredits, xoff, yoff);
1793 }
1794
CalculateTestResults()1795 void BPGame::CalculateTestResults() {
1796 // add up all our scores and see how well we did...
1797 TestBrainWeight = 0;
1798
1799 for (int i = 0; i < TestScores.Count; ++i) {
1800 TestBrainWeight += TestScores[i];
1801 }
1802
1803 if (TestBrainWeight < 500) {
1804 TestBrainJob = TestBrainJobs[0];
1805 } else if (TestBrainWeight < 600) {
1806 TestBrainJob = TestBrainJobs[1];
1807 } else if (TestBrainWeight < 650) {
1808 TestBrainJob = TestBrainJobs[2];
1809 } else if (TestBrainWeight < 700) {
1810 TestBrainJob = TestBrainJobs[3];
1811 } else if (TestBrainWeight < 750) {
1812 TestBrainJob = TestBrainJobs[4];
1813 } else if (TestBrainWeight < 800) {
1814 TestBrainJob = TestBrainJobs[5];
1815 } else if (TestBrainWeight < 850) {
1816 TestBrainJob = TestBrainJobs[6];
1817 } else if (TestBrainWeight < 900) {
1818 TestBrainJob = TestBrainJobs[7];
1819 } else if (TestBrainWeight < 950) {
1820 TestBrainJob = TestBrainJobs[8];
1821 } else if (TestBrainWeight < 1000) {
1822 TestBrainJob = TestBrainJobs[9];
1823 } else if (TestBrainWeight < 1050) {
1824 TestBrainJob = TestBrainJobs[10];
1825 } else if (TestBrainWeight < 1100) {
1826 TestBrainJob = TestBrainJobs[11];
1827 } else if (TestBrainWeight < 1150) {
1828 TestBrainJob = TestBrainJobs[12];
1829 } else if (TestBrainWeight < 1175) {
1830 TestBrainJob = TestBrainJobs[13];
1831 } else if (TestBrainWeight < 1200) {
1832 TestBrainJob = TestBrainJobs[14];
1833 } else if (TestBrainWeight < 1225) {
1834 TestBrainJob = TestBrainJobs[15];
1835 } else if (TestBrainWeight < 1250) {
1836 TestBrainJob = TestBrainJobs[16];
1837 } else if (TestBrainWeight < 1275) {
1838 TestBrainJob = TestBrainJobs[17];
1839 } else if (TestBrainWeight < 1300) {
1840 TestBrainJob = TestBrainJobs[18];
1841 } else if (TestBrainWeight < 1325) {
1842 TestBrainJob = TestBrainJobs[19];
1843 } else if (TestBrainWeight < 1350) {
1844 TestBrainJob = TestBrainJobs[20];
1845 } else if (TestBrainWeight < 1375) {
1846 TestBrainJob = TestBrainJobs[21];
1847 } else if (TestBrainWeight < 1400) {
1848 TestBrainJob = TestBrainJobs[22];
1849 } else if (TestBrainWeight < 1425) {
1850 TestBrainJob = TestBrainJobs[23];
1851 } else if (TestBrainWeight < 1450) {
1852 TestBrainJob = TestBrainJobs[24];
1853 } else if (TestBrainWeight < 1475) {
1854 TestBrainJob = TestBrainJobs[25];
1855 } else if (TestBrainWeight < 1500) {
1856 TestBrainJob = TestBrainJobs[26];
1857 } else if (TestBrainWeight < 1525) {
1858 TestBrainJob = TestBrainJobs[27];
1859 } else if (TestBrainWeight < 1550) {
1860 TestBrainJob = TestBrainJobs[28];
1861 } else if (TestBrainWeight < 1575) {
1862 TestBrainJob = TestBrainJobs[29];
1863 } else if (TestBrainWeight < 1600) {
1864 TestBrainJob = TestBrainJobs[30];
1865 } else if (TestBrainWeight < 1625) {
1866 TestBrainJob = TestBrainJobs[31];
1867 } else if (TestBrainWeight < 1650) {
1868 TestBrainJob = TestBrainJobs[32];
1869 } else if (TestBrainWeight < 1675) {
1870 TestBrainJob = TestBrainJobs[33];
1871 } else if (TestBrainWeight < 1700) {
1872 TestBrainJob = TestBrainJobs[34];
1873 } else if (TestBrainWeight < 1725) {
1874 TestBrainJob = TestBrainJobs[35];
1875 } else if (TestBrainWeight < 1750) {
1876 TestBrainJob = TestBrainJobs[36];
1877 } else if (TestBrainWeight < 1775) {
1878 TestBrainJob = TestBrainJobs[37];
1879 } else if (TestBrainWeight < 1800) {
1880 TestBrainJob = TestBrainJobs[38];
1881 } else if (TestBrainWeight < 1825) {
1882 TestBrainJob = TestBrainJobs[39];
1883 } else if (TestBrainWeight < 1850) {
1884 TestBrainJob = TestBrainJobs[40];
1885 } else if (TestBrainWeight < 1875) {
1886 TestBrainJob = TestBrainJobs[41];
1887 } else if (TestBrainWeight < 1900) {
1888 TestBrainJob = TestBrainJobs[42];
1889 } else if (TestBrainWeight < 1925) {
1890 TestBrainJob = TestBrainJobs[43];
1891 } else if (TestBrainWeight < 1950) {
1892 TestBrainJob = TestBrainJobs[44];
1893 } else if (TestBrainWeight < 1975) {
1894 TestBrainJob = TestBrainJobs[45];
1895 } else if (TestBrainWeight < 2000) {
1896 TestBrainJob = TestBrainJobs[46];
1897 } else if (TestBrainWeight < 2025) {
1898 TestBrainJob = TestBrainJobs[47];
1899 } else if (TestBrainWeight < 2050) {
1900 TestBrainJob = TestBrainJobs[48];
1901 } else if (TestBrainWeight < 2075) {
1902 TestBrainJob = TestBrainJobs[49];
1903 } else if (TestBrainWeight < 2100) {
1904 TestBrainJob = TestBrainJobs[50];
1905 } else if (TestBrainWeight < 2125) {
1906 TestBrainJob = TestBrainJobs[51];
1907 } else if (TestBrainWeight < 2150) {
1908 TestBrainJob = TestBrainJobs[52];
1909 } else if (TestBrainWeight < 2175) {
1910 TestBrainJob = TestBrainJobs[53];
1911 } else if (TestBrainWeight < 2200) {
1912 TestBrainJob = TestBrainJobs[54];
1913 } else {
1914 TestBrainJob = TestBrainJobs[55];
1915 }
1916
1917 AllocString(&sfcTestJob, TestBrainJob, NORMAL, 320.0f, 80.0f, CENTRED, false);
1918
1919 // add the new score to the array
1920 AllTestScores.Add(TestBrainWeight);
1921 CurrentBrainWeight = TestBrainWeight;
1922
1923 // unlock the games we just played
1924 for (int i = 0; i < TestMiniGames.Count; ++i) {
1925 MiniGames[TestMiniGames[i]]->Unlocked = true;
1926 }
1927
1928 // now prepare the results screen
1929 TestResultContainers.Clear();
1930
1931 for (int i = 0; i < TestMiniGames.Count; ++i) {
1932 TestResultContainer* result = new TestResultContainer();
1933
1934 ostringstream brainweight;
1935 brainweight << TestScores[i] << "g";
1936 AllocString(&result->sfcBrainWeight, brainweight.str().c_str(), NORMAL, 90.0f, 30.0f, CENTRED, true);
1937
1938 result->MiniGame = TestMiniGames[i];
1939 result->Rank = BPMiniGame::GetRank(TestScores[i]);
1940 result->GoingUp = false;
1941
1942 if (i < 2) {
1943 // first row
1944 result->Pos = BPPoint(110 + (i * 100), 325);
1945 } else {
1946 // second row
1947 result->Pos = BPPoint(60 + ((i - 2) * 100), 425);
1948 }
1949
1950 result->FadeUpAnim = Lerp(-1.0f, 0.0f, i / (float)(TestMiniGames.Count - 1));
1951 TestResultContainers.Add(result);
1952 }
1953
1954 SaveSettings();
1955 }
1956
CreateMiniGame(MiniGameType game,bool marathon,bool practise)1957 void BPGame::CreateMiniGame(MiniGameType game, bool marathon, bool practise) {
1958 if (ActiveMiniGame != NULL) {
1959 SAFE_DELETE(ActiveMiniGame);
1960 }
1961
1962 switch (game) {
1963 case BALLOONBLASTER:
1964 ActiveMiniGame = new BPMiniGame_BalloonBlaster(this);
1965 break;
1966
1967 case BOMBHUNT:
1968 ActiveMiniGame = new BPMiniGame_BombHunt(this);
1969 break;
1970
1971 case BPSAYS:
1972 ActiveMiniGame = new BPMiniGame_BPSays(this);
1973 break;
1974
1975 case BUBBLETROUBLE:
1976 ActiveMiniGame = new BPMiniGame_BubbleTrouble(this);
1977 break;
1978
1979 case CARDMATCH:
1980 ActiveMiniGame = new BPMiniGame_CardMatch(this);
1981 break;
1982
1983 case CONNEX:
1984 ActiveMiniGame = new BPMiniGame_Connex(this);
1985 break;
1986
1987 case CUPSNBALLS:
1988 ActiveMiniGame = new BPMiniGame_CupsNBalls(this);
1989 break;
1990
1991 case DICEOFF:
1992 ActiveMiniGame = new BPMiniGame_DiceOff(this);
1993 break;
1994
1995 case FLASHCOUNTING:
1996 ActiveMiniGame = new BPMiniGame_FlashCounting(this);
1997 break;
1998
1999 case FLASHLIGHT:
2000 ActiveMiniGame = new BPMiniGame_Flashlight(this);
2001 break;
2002
2003 case IQTEST:
2004 ActiveMiniGame = new BPMiniGame_IQTest(this);
2005 break;
2006
2007 case JEWELFLIP:
2008 ActiveMiniGame = new BPMiniGame_JewelFlip(this);
2009 break;
2010
2011 case JEWELJAM:
2012 ActiveMiniGame = new BPMiniGame_JewelJam(this);
2013 break;
2014
2015 case MARBLEDROP:
2016 ActiveMiniGame = new BPMiniGame_MarbleDrop(this);
2017 break;
2018
2019 case MEMORYBLOX:
2020 ActiveMiniGame = new BPMiniGame_MemoryBlox(this);
2021 break;
2022
2023 case MEMORYBOX:
2024 ActiveMiniGame = new BPMiniGame_MemoryBox(this);
2025 break;
2026
2027 case MEMORYMATHS:
2028 ActiveMiniGame = new BPMiniGame_MemoryMaths(this);
2029 break;
2030
2031 case MINESWEEP:
2032 ActiveMiniGame = new BPMiniGame_MineSweep(this);
2033 break;
2034
2035 case MOONJUMP:
2036 ActiveMiniGame = new BPMiniGame_MoonJump(this);
2037 break;
2038
2039 case NEXTINLINE:
2040 ActiveMiniGame = new BPMiniGame_NextInLine(this);
2041 break;
2042
2043 case NUMBERSNAKE:
2044 ActiveMiniGame = new BPMiniGame_NumberSnake(this);
2045 break;
2046
2047 case ODDONEOUT:
2048 ActiveMiniGame = new BPMiniGame_OddOneOut(this);
2049 break;
2050
2051 case PATCHMATCH:
2052 ActiveMiniGame = new BPMiniGame_PatchMatch(this);
2053 break;
2054
2055 case PERFECTPATHS:
2056 ActiveMiniGame = new BPMiniGame_PerfectPaths(this);
2057 break;
2058
2059 case ROUTEFINDER:
2060 ActiveMiniGame = new BPMiniGame_RouteFinder(this);
2061 break;
2062
2063 case RPS:
2064 ActiveMiniGame = new BPMiniGame_RPS(this);
2065 break;
2066
2067 case SCRAMBLED:
2068 ActiveMiniGame = new BPMiniGame_Scrambled(this);
2069 break;
2070
2071 case SETFINDER:
2072 ActiveMiniGame = new BPMiniGame_SetFinder(this);
2073 break;
2074
2075 case SHARPSHOOTER:
2076 ActiveMiniGame = new BPMiniGame_Sharpshooter(this);
2077 break;
2078
2079 case SHORTCIRCUITSUDOKU:
2080 ActiveMiniGame = new BPMiniGame_ShortCircuitSudoku(this);
2081 break;
2082
2083 case SHUFFLEPUZZLER:
2084 ActiveMiniGame = new BPMiniGame_ShufflePuzzler(this);
2085 break;
2086
2087 case STRANGERDANGER:
2088 ActiveMiniGame = new BPMiniGame_StrangerDanger(this);
2089 break;
2090
2091 case SYMBOLICLOGIC:
2092 ActiveMiniGame = new BPMiniGame_SymbolicLogic(this);
2093 break;
2094
2095 case UNDERTHEHAT:
2096 ActiveMiniGame = new BPMiniGame_UnderTheHat(this);
2097 break;
2098
2099 case UNTANGLER:
2100 ActiveMiniGame = new BPMiniGame_Untangler(this);
2101 break;
2102
2103 case WORDSMASH:
2104 ActiveMiniGame = new BPMiniGame_WordSmash(this);
2105 break;
2106 }
2107
2108 ActiveMiniGame->Init();
2109
2110 if (marathon) ActiveMiniGame->SetMarathon();
2111
2112 if (GameState == HISTORY) {
2113 ActiveMiniGame->ReturnType = RT_SECRET;
2114 } else if (GameState == BRAINBOOST) {
2115 ActiveMiniGame->ReturnType = RT_BRAINBOOST;
2116 }
2117
2118 if (practise) {
2119 SetGameState(PRACTISE_PROFESSOR);
2120 } else {
2121 SetGameState(PROFESSOR);
2122 }
2123 }
2124
SetGameState(GameStates state)2125 void BPGame::SetGameState(GameStates state) {
2126 GameState = state;
2127 AnimCounter = 0.0f;
2128 GameStateJustChanged = true;
2129
2130 if (state != TEST_RESULTS_PLAY) {
2131 // don't reset LastStateChange when going from test results back to the play menu, as that resets the
2132 // animation on the results screen
2133 LastStateChange = TickCount;
2134 }
2135
2136 switch (state) {
2137 case PLAY_PRACTISE:
2138 PractisePageNumber = 0;
2139 PractisePageMoveLeft = true;
2140
2141 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2142 it->second->IsShowing = false;
2143 }
2144
2145 PositionPractiseGames();
2146
2147 break;
2148
2149 case HISTORY:
2150 ShowScores.Clear();
2151
2152 if (AllTestScores.Count > 8) {
2153 for (int i = AllTestScores.Count - 8; i < AllTestScores.Count; ++i) {
2154 ShowScores.Add(AllTestScores[i]);
2155 }
2156 } else {
2157 for (int i = 0; i < AllTestScores.Count; ++i) {
2158 ShowScores.Add(AllTestScores[i]);
2159 }
2160 }
2161
2162 break;
2163
2164 case PROFESSOR:
2165 PlayMusic("professor");
2166 break;
2167
2168 case TEST_STATUS:
2169 PlaySound("happy_ring");
2170 break;
2171 }
2172 }
2173
PositionPractiseGames()2174 void BPGame::PositionPractiseGames() {
2175 PractiseAnimCounter = 0.0f;
2176
2177 // get all minigames off the screen
2178 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2179 if (it->second->IsShowing) {
2180 // these are visible - make them scroll offscreen neatly
2181 it->second->StartX = it->second->X;
2182 it->second->StartY = it->second->Y;
2183
2184 if (PractisePageMoveLeft) {
2185 it->second->DestX = -100;
2186 } else {
2187 it->second->DestX = 320;
2188 }
2189
2190 it->second->DestY = 175;
2191 } else {
2192 it->second->Y = it->second->StartY = it->second->DestY = 175;
2193
2194 if (PractisePageMoveLeft) {
2195 it->second->X = it->second->StartX = it->second->DestX = -100;
2196 } else {
2197 it->second->X = it->second->StartX = it->second->DestX = 320;
2198 }
2199 }
2200
2201 it->second->IsShowing = false;
2202 }
2203
2204 BPPList<BPPoint*> PractisePositions;
2205
2206 for (int row = 0; row < 3; ++row) {
2207 for (int col = 0; col < 3; ++col) {
2208 PractisePositions.Add(new BPPoint(15 + (col * 100), 75 + (row * 100)));
2209 }
2210 }
2211
2212 int i = 0;
2213 int j = 0;
2214
2215 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2216 if (it->second->IsSecret) continue;
2217 if (!it->second->Unlocked) continue;
2218
2219 if (i < PractisePageNumber) {
2220 ++i;
2221 it->second->IsShowing = false;
2222 continue;
2223 }
2224
2225 it->second->DestX = PractisePositions[j]->X;
2226 it->second->DestY = PractisePositions[j]->Y;
2227
2228 it->second->StartY = PractisePositions[j]->Y;
2229
2230 if (PractisePageMoveLeft) {
2231 it->second->StartX = 320;
2232 } else {
2233 it->second->StartX = -100;
2234 }
2235
2236 it->second->IsShowing = true;
2237
2238 ++i;
2239 ++j;
2240
2241 if (i >= PractisePageNumber + 9) break;
2242 }
2243
2244 PractisePositions.Clear();
2245 }
2246
RunTest()2247 void BPGame::RunTest() {
2248 StopMusic();
2249
2250 TestMiniGames.Clear();
2251 TestScores.Clear();
2252 TestPosition = 0;
2253
2254 BPList<MiniGameType> SeenMiniGames;
2255 BPList<MiniGameType> UnseenMiniGames;
2256
2257 // add them all to an array, then shuffle the array
2258 for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2259 if (it->second->IsSecret) continue; // don't allow hidden minigames into the test
2260
2261 if (it->second->Unlocked) {
2262 SeenMiniGames.Add(it->first);
2263 } else {
2264 UnseenMiniGames.Add(it->first);
2265 }
2266 }
2267
2268 SeenMiniGames.Shuffle();
2269 UnseenMiniGames.Shuffle();
2270
2271 int to_add;
2272
2273 if (SeenMiniGames.Count == 0) {
2274 // we've seen no games yet; add five unseen games
2275 to_add = 5;
2276 } else {
2277 to_add = min(UnseenMiniGames.Count, 4);
2278 }
2279
2280 for (int i = 0; i < to_add; ++i) {
2281 TestMiniGames.Add(UnseenMiniGames[i]);
2282 }
2283
2284 // figure out how many seen games we need to add, and add them
2285 to_add = 5 - to_add;
2286 for (int i = 0; i < to_add; ++i) {
2287 TestMiniGames.Add(SeenMiniGames[i]);
2288 }
2289
2290 // shuffle the list so that the seen/unseen games come in any order
2291 TestMiniGames.Shuffle();
2292
2293 InTestMode = true;
2294 SetGameState(TEST_STATUS);
2295 }
2296
NextTest()2297 void BPGame::NextTest() {
2298 if (TestPosition == TestMiniGames.Count) {
2299 // use this for quick testing
2300 // if (true) {
2301 // TestScores.Add(150);
2302 // TestScores.Add(250);
2303 // TestScores.Add(350);
2304 // TestScores.Add(450);
2305 // TestScores.Add(500);
2306 CalculateTestResults();
2307 SetGameState(TEST_RESULTS);
2308
2309 InTestMode = false;
2310
2311 PlayMusic("results");
2312
2313 return;
2314 }
2315
2316 CreateMiniGame(TestMiniGames[TestPosition], false, false);
2317 ++TestPosition;
2318 }
2319
PlaySound(const char * sound,bool preload_only,bool force_play)2320 void BPGame::PlaySound(const char* sound, bool preload_only, bool force_play) {
2321
2322 if (!EnableSound && !force_play) return;
2323
2324 if (Sounds.find(sound) != Sounds.end()) {
2325 if (preload_only) {
2326 // do nothing - this is only for iPhone
2327 } else {
2328 Mix_PlayChannel(-1, Sounds[sound], 0);
2329 }
2330 } else {
2331 printf("Error: sound %s doesn't exist.\n", sound);
2332 }
2333 }
2334
PlayMusic(const char * name)2335 void BPGame::PlayMusic(const char* name) {
2336 if (!EnableMusic) return;
2337
2338 if (Music != NULL) {
2339 Mix_HaltMusic();
2340 Mix_FreeMusic(Music);
2341 Music = NULL;
2342 }
2343
2344 string* file = new string(name);
2345 file->insert(0, "/usr/local/share/brainparty/");
2346 file->append(".ogg");
2347
2348 Music = Mix_LoadMUS(file->c_str());
2349 Mix_PlayMusic(Music, -1);
2350
2351 delete(file);
2352 }
2353
StopMusic()2354 void BPGame::StopMusic() {
2355 if (Music != NULL) {
2356 Mix_HaltMusic();
2357 Mix_FreeMusic(Music);
2358 Music = NULL;
2359 }
2360 }
2361
FileExists(const char * filename)2362 bool BPGame::FileExists(const char * filename) {
2363 if (FILE * file = fopen(filename, "r")) {
2364 fclose(file);
2365 return true;
2366 }
2367 return false;
2368 }
2369
LoadSound(const char * filename,const char * extension)2370 Mix_Chunk* BPGame::LoadSound(const char* filename, const char* extension) {
2371 string* file = new string(filename);
2372 file->insert(0, "/usr/local/share/brainparty/");
2373 file->append(".wav");
2374
2375 Mix_Chunk* retval = Mix_LoadWAV(file->c_str());
2376 if (retval == NULL) printf("Warning: couldn't load file %s.\n", filename);
2377 delete file;
2378
2379 return retval;
2380 }
2381
CancelTest()2382 void BPGame::CancelTest() {
2383 GameState = PLAY_MENU;
2384 TestMiniGames.Clear();
2385 TestScores.Clear();
2386 TestPosition = 0;
2387
2388 InTestMode = false;
2389
2390 PlayMusic("theme");
2391 }
2392
Accelerate(float x,float y,float z)2393 void BPGame::Accelerate(float x, float y, float z) {
2394 Acceleration[0] = x;
2395 Acceleration[1] = y;
2396 Acceleration[2] = z;
2397 }
2398
PromptResetScores()2399 void BPGame::PromptResetScores() {
2400 ShowingClearScores = true;
2401 MessageBox::Show("Are you sure you want to wipe all your test scores so far? Press Y on your keyboard now to wipe your scores. Click the mouse or press any other key cancel.", "Clear scores?");
2402 }
2403
ExecuteResetScores()2404 void BPGame::ExecuteResetScores() {
2405 AllTestScores.Clear();
2406 SaveSettings();
2407 MessageBox::Show("Your test scores have been wiped and you have a clean slate - good luck!", "Scores wiped!");
2408 }
2409
ColorLerp(Colour * from,Colour * to,float amount)2410 Colour* BPGame::ColorLerp(Colour* from, Colour* to, float amount) {
2411 Colour* col = new Colour(Lerp(from->R, to->R, amount), Lerp(from->G, to->G, amount), Lerp(from->B, to->B, amount), Lerp(from->A, to->A, amount));
2412 return col;
2413 }
2414