You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
14 KiB

пре 5 година
пре 5 година
пре 5 година
пре 5 година
пре 5 година
пре 5 година
  1. /*******************************************************************************************
  2. *
  3. * TRANSMISSION MISSION [GLOBAL GAME JAM 2018]
  4. *
  5. * Code the different filtration messages to be send to newspaper
  6. * to avoid being understood in case of interception.
  7. *
  8. * This game has been created using raylib 1.8 (www.raylib.com)
  9. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  10. *
  11. * Copyright (c) 2018 Ramon Santamaria (@raysan5)
  12. *
  13. ********************************************************************************************/
  14. #include "raylib.h"
  15. #include "screens/screens.h" // NOTE: Defines global variable: currentScreen
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #if defined(PLATFORM_WEB)
  19. #include <emscripten/emscripten.h>
  20. #endif
  21. //----------------------------------------------------------------------------------
  22. // Global Variables Definition (local to this module)
  23. //----------------------------------------------------------------------------------
  24. const int screenWidth = 1280;
  25. const int screenHeight = 720;
  26. // Required variables to manage screen transitions (fade-in, fade-out)
  27. static float transAlpha = 0.0f;
  28. static bool onTransition = false;
  29. static bool transFadeOut = false;
  30. static int transFromScreen = -1;
  31. static int transToScreen = -1;
  32. // NOTE: Some global variables that require to be visible for all screens,
  33. // are defined in screens.h (i.e. currentScreen)
  34. //----------------------------------------------------------------------------------
  35. // Local Functions Declaration
  36. //----------------------------------------------------------------------------------
  37. static void ChangeToScreen(int screen); // No transition effect
  38. static void TransitionToScreen(int screen);
  39. static void UpdateTransition(void);
  40. static void DrawTransition(void);
  41. static void UpdateDrawFrame(void); // Update and Draw one frame
  42. //----------------------------------------------------------------------------------
  43. // Main entry point
  44. //----------------------------------------------------------------------------------
  45. int main(void)
  46. {
  47. // Initialization (Note windowTitle is unused on Android)
  48. //---------------------------------------------------------
  49. InitWindow(screenWidth, screenHeight, "transmission mission [GGJ18]");
  50. // Global data loading (assets that must be available in all screens, i.e. fonts)
  51. InitAudioDevice();
  52. music = LoadMusicStream("resources/audio/music_title.ogg");
  53. fxButton = LoadSound("resources/audio/fx_newspaper.ogg");
  54. SetMusicVolume(music, 1.0f);
  55. PlayMusicStream(music);
  56. fontMission = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 64, 0, 250);
  57. texButton = LoadTexture("resources/textures/title_ribbon.png");
  58. // UI BUTTON
  59. recButton.width = texButton.width;
  60. recButton.height = texButton.height;
  61. recButton.x = screenWidth - recButton.width;
  62. recButton.y = screenHeight - recButton.height - 50;
  63. fadeButton = 0.8f;
  64. colorButton = RED;
  65. textPositionButton = (Vector2){recButton.x + recButton.width/2, recButton.y + recButton.height/2};
  66. fontSizeButton = 30;
  67. textColorButton = WHITE;
  68. currentMission = 0;
  69. totalMissions = 4;
  70. // Setup and Init first screen
  71. currentScreen = LOGO;
  72. InitLogoScreen();
  73. #if defined(PLATFORM_WEB)
  74. emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
  75. #else
  76. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  77. //--------------------------------------------------------------------------------------
  78. // Main game loop
  79. while (!WindowShouldClose()) // Detect window close button or ESC key
  80. {
  81. UpdateDrawFrame();
  82. }
  83. #endif
  84. // De-Initialization
  85. //--------------------------------------------------------------------------------------
  86. // Unload current screen data before closing
  87. switch (currentScreen)
  88. {
  89. case LOGO: UnloadLogoScreen(); break;
  90. case TITLE: UnloadTitleScreen(); break;
  91. case MISSION: UnloadMissionScreen(); break;
  92. case GAMEPLAY: UnloadGameplayScreen(); break;
  93. case ENDING: UnloadEndingScreen(); break;
  94. default: break;
  95. }
  96. // Unload all global loaded data (i.e. fonts) here!
  97. UnloadMusicStream(music);
  98. UnloadSound(fxButton);
  99. UnloadFont(fontMission);
  100. UnloadTexture(texButton);
  101. CloseAudioDevice(); // Close audio context
  102. CloseWindow(); // Close window and OpenGL context
  103. //--------------------------------------------------------------------------------------
  104. return 0;
  105. }
  106. //----------------------------------------------------------------------------------
  107. // Module specific Functions Definition
  108. //----------------------------------------------------------------------------------
  109. // Change to next screen, no transition
  110. static void ChangeToScreen(int screen)
  111. {
  112. // Unload current screen
  113. switch (currentScreen)
  114. {
  115. case LOGO: UnloadLogoScreen(); break;
  116. case TITLE: UnloadTitleScreen(); break;
  117. case MISSION: UnloadMissionScreen(); break;
  118. case GAMEPLAY: UnloadGameplayScreen(); break;
  119. case ENDING: UnloadEndingScreen(); break;
  120. default: break;
  121. }
  122. // Init next screen
  123. switch (screen)
  124. {
  125. case LOGO: InitLogoScreen(); break;
  126. case TITLE: InitTitleScreen(); break;
  127. case MISSION: InitMissionScreen(); break;
  128. case GAMEPLAY: InitGameplayScreen(); break;
  129. case ENDING: InitEndingScreen(); break;
  130. default: break;
  131. }
  132. currentScreen = screen;
  133. }
  134. // Define transition to next screen
  135. static void TransitionToScreen(int screen)
  136. {
  137. onTransition = true;
  138. transFadeOut = false;
  139. transFromScreen = currentScreen;
  140. transToScreen = screen;
  141. transAlpha = 0.0f;
  142. }
  143. // Update transition effect
  144. static void UpdateTransition(void)
  145. {
  146. if (!transFadeOut)
  147. {
  148. transAlpha += 0.02f;
  149. // NOTE: Due to float internal representation, condition jumps on 1.0f instead of 1.05f
  150. // For that reason we compare against 1.01f, to avoid last frame loading stop
  151. if (transAlpha > 1.01f)
  152. {
  153. transAlpha = 1.0f;
  154. // Unload current screen
  155. switch (transFromScreen)
  156. {
  157. case LOGO: UnloadLogoScreen(); break;
  158. case TITLE: UnloadTitleScreen(); break;
  159. case MISSION: UnloadMissionScreen(); break;
  160. case GAMEPLAY: UnloadGameplayScreen(); break;
  161. case ENDING: UnloadEndingScreen(); break;
  162. default: break;
  163. }
  164. // Load next screen
  165. switch (transToScreen)
  166. {
  167. case LOGO: InitLogoScreen(); break;
  168. case TITLE: InitTitleScreen(); break;
  169. case MISSION: InitMissionScreen(); break;
  170. case GAMEPLAY: InitGameplayScreen(); break;
  171. case ENDING: InitEndingScreen(); break;
  172. default: break;
  173. }
  174. currentScreen = transToScreen;
  175. // Activate fade out effect to next loaded screen
  176. transFadeOut = true;
  177. }
  178. }
  179. else // Transition fade out logic
  180. {
  181. transAlpha -= 0.02f;
  182. if (transAlpha < -0.01f)
  183. {
  184. transAlpha = 0.0f;
  185. transFadeOut = false;
  186. onTransition = false;
  187. transFromScreen = -1;
  188. transToScreen = -1;
  189. }
  190. }
  191. }
  192. // Draw transition effect (full-screen rectangle)
  193. static void DrawTransition(void)
  194. {
  195. DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha));
  196. }
  197. // Update and draw game frame
  198. static void UpdateDrawFrame(void)
  199. {
  200. // Update
  201. //----------------------------------------------------------------------------------
  202. UpdateMusicStream(music); // NOTE: Music keeps playing between screens
  203. if (!onTransition)
  204. {
  205. switch(currentScreen)
  206. {
  207. case LOGO:
  208. {
  209. UpdateLogoScreen();
  210. if (FinishLogoScreen()) TransitionToScreen(TITLE);
  211. } break;
  212. case TITLE:
  213. {
  214. UpdateTitleScreen();
  215. if (FinishTitleScreen())
  216. {
  217. StopMusicStream(music);
  218. TransitionToScreen(MISSION);
  219. }
  220. } break;
  221. case MISSION:
  222. {
  223. UpdateMissionScreen();
  224. if (FinishMissionScreen())
  225. {
  226. StopMusicStream(music);
  227. TransitionToScreen(GAMEPLAY);
  228. }
  229. } break;
  230. case GAMEPLAY:
  231. {
  232. UpdateGameplayScreen();
  233. if (FinishGameplayScreen() == 1) TransitionToScreen(ENDING);
  234. //else if (FinishGameplayScreen() == 2) TransitionToScreen(TITLE);
  235. } break;
  236. case ENDING:
  237. {
  238. UpdateEndingScreen();
  239. if (FinishEndingScreen() == 1) // Continue to next mission
  240. {
  241. TransitionToScreen(MISSION);
  242. }
  243. else if (FinishEndingScreen() == 2) // Replay current mission
  244. {
  245. PlayMusicStream(music);
  246. TransitionToScreen(TITLE);
  247. }
  248. } break;
  249. default: break;
  250. }
  251. }
  252. else UpdateTransition(); // Update transition (fade-in, fade-out)
  253. //----------------------------------------------------------------------------------
  254. // Draw
  255. //----------------------------------------------------------------------------------
  256. BeginDrawing();
  257. ClearBackground(RAYWHITE);
  258. switch(currentScreen)
  259. {
  260. case LOGO: DrawLogoScreen(); break;
  261. case TITLE: DrawTitleScreen(); break;
  262. case MISSION: DrawMissionScreen(); break;
  263. case GAMEPLAY: DrawGameplayScreen(); break;
  264. case ENDING: DrawEndingScreen(); break;
  265. default: break;
  266. }
  267. // Draw full screen rectangle in front of everything
  268. if (onTransition) DrawTransition();
  269. //DrawFPS(10, 10);
  270. EndDrawing();
  271. //----------------------------------------------------------------------------------
  272. }
  273. // Load missions from text file
  274. Mission *LoadMissions(const char *fileName)
  275. {
  276. Mission *missions = NULL;
  277. char buffer[512];
  278. int missionsCount = 0;
  279. FILE *misFile = fopen(fileName, "rt");
  280. if (misFile == NULL) printf("[%s] Missions file could not be opened\n", fileName);
  281. else
  282. {
  283. // First pass to get total missions count
  284. while (!feof(misFile))
  285. {
  286. fgets(buffer, 512, misFile);
  287. switch (buffer[0])
  288. {
  289. case 't': sscanf(buffer, "t %i", &missionsCount); break;
  290. default: break;
  291. }
  292. }
  293. if (missionsCount > 0) missions = (Mission *)malloc(missionsCount*sizeof(Mission));
  294. else return NULL;
  295. rewind(misFile); // Return to the beginning of the file, to read again
  296. int missionNum = 0;
  297. while (!feof(misFile))
  298. {
  299. fgets(buffer, 512, misFile);
  300. if (missionNum < missionsCount)
  301. {
  302. switch (buffer[0])
  303. {
  304. case 'b':
  305. {
  306. // New mission brief starts!
  307. missions[missionNum].id = missionNum;
  308. sscanf(buffer, "b %[^\n]s", missions[missionNum].brief);
  309. } break;
  310. case 'k': sscanf(buffer, "k %[^\n]s", missions[missionNum].key); break;
  311. case 'm':
  312. {
  313. // NOTE: Message is loaded as is, needs to be processed!
  314. sscanf(buffer, "m %[^\n]s", missions[missionNum].msg);
  315. } break;
  316. case 's':
  317. {
  318. sscanf(buffer, "s %i %i %i %i %i %i %i %i",
  319. &missions[missionNum].sols[0],
  320. &missions[missionNum].sols[1],
  321. &missions[missionNum].sols[2],
  322. &missions[missionNum].sols[3],
  323. &missions[missionNum].sols[4],
  324. &missions[missionNum].sols[5],
  325. &missions[missionNum].sols[6],
  326. &missions[missionNum].sols[7]);
  327. missions[missionNum].wordsCount = 0;
  328. for (int i = 0; i < 8; i++)
  329. {
  330. if (missions[missionNum].sols[i] > -1)
  331. {
  332. missions[missionNum].wordsCount++;
  333. }
  334. }
  335. TraceLog(LOG_WARNING, "Mission %i - Words count %i", missionNum, missions[missionNum].wordsCount);
  336. missionNum++;
  337. } break;
  338. default: break;
  339. }
  340. }
  341. }
  342. if (missionsCount != missionNum) TraceLog(LOG_WARNING, "Missions count and loaded missions don't match!");
  343. }
  344. fclose(misFile);
  345. if (missions != NULL)
  346. {
  347. TraceLog(LOG_INFO, "Missions loaded: %i", missionsCount);
  348. TraceLog(LOG_INFO, "Missions loaded successfully!");
  349. }
  350. return missions;
  351. }
  352. bool IsButtonPressed()
  353. {
  354. if (CheckCollisionPointRec(GetMousePosition(), recButton))
  355. {
  356. fadeButton = 1.0f;
  357. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsGestureDetected(GESTURE_TAP))
  358. {
  359. PlaySound(fxButton);
  360. return true;
  361. }
  362. }
  363. else fadeButton = 0.80f;
  364. return false;
  365. }
  366. void DrawButton(const char *text)
  367. {
  368. //DrawRectangleRec(recButton, Fade(colorButton, fadeButton));
  369. DrawTexturePro(texButton, (Rectangle){0,0,texButton.width, texButton.height}, recButton, (Vector2){0,0},0, Fade(WHITE, fadeButton));
  370. Vector2 measure = MeasureTextEx(fontMission, text, fontSizeButton, 0);
  371. Vector2 textPos = {textPositionButton.x - measure.x/2 + 10, textPositionButton.y - measure.y/2 - 10};
  372. DrawTextEx(fontMission, text, textPos , fontSizeButton, 0, textColorButton);
  373. }