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.

413 line
14 KiB

  1. /*******************************************************************************************
  2. *
  3. * RE_PAIR [GLOBAL GAME JAM 2020]
  4. *
  5. * Let's find your perfect match!
  6. * Ready for dating? Do you need some face tweaks? Choose wisely!
  7. *
  8. * This game has been created using raylib 3.0 (www.raylib.com)
  9. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  10. *
  11. * Copyright (c) 2020 Ramon Santamaria (@raysan5)
  12. *
  13. ********************************************************************************************/
  14. #include "raylib.h"
  15. #include "screens/screens.h" // NOTE: Defines global variable: currentScreen
  16. #if defined(PLATFORM_WEB)
  17. #include <emscripten/emscripten.h>
  18. #endif
  19. GameScreen currentScreen = 0;
  20. Font font = { 0 };
  21. Music music = { 0 };
  22. Sound fxCoin = { 0 };
  23. Texture2D background = { 0 };
  24. Texture2D texNPatch = { 0 };
  25. NPatchInfo npInfo = { 0 };
  26. Texture2D texHead, texHair, texNose, texMouth, texEyes, texComp;
  27. Character playerBase = { 0 };
  28. Character datingBase = { 0 };
  29. Character player = { 0 };
  30. Character dating = { 0 };
  31. //----------------------------------------------------------------------------------
  32. // Global Variables Definition (local to this module)
  33. //----------------------------------------------------------------------------------
  34. const int screenWidth = 1280;
  35. const int screenHeight = 720;
  36. // Required variables to manage screen transitions (fade-in, fade-out)
  37. static float transAlpha = 0.0f;
  38. static bool onTransition = false;
  39. static bool transFadeOut = false;
  40. static int transFromScreen = -1;
  41. static int transToScreen = -1;
  42. // NOTE: Some global variables that require to be visible for all screens,
  43. // are defined in screens.h (i.e. currentScreen)
  44. //----------------------------------------------------------------------------------
  45. // Local Functions Declaration
  46. //----------------------------------------------------------------------------------
  47. static void ChangeToScreen(int screen); // No transition effect
  48. static void TransitionToScreen(int screen);
  49. static void UpdateTransition(void);
  50. static void DrawTransition(void);
  51. static void UpdateDrawFrame(void); // Update and Draw one frame
  52. //----------------------------------------------------------------------------------
  53. // Main entry point
  54. //----------------------------------------------------------------------------------
  55. int main(void)
  56. {
  57. // Initialization (Note windowTitle is unused on Android)
  58. //---------------------------------------------------------
  59. InitWindow(screenWidth, screenHeight, "RE-PAIR [GGJ2020]");
  60. // Global data loading (assets that must be available in all screens, i.e. fonts)
  61. InitAudioDevice();
  62. font = LoadFont("resources/font.png");
  63. SetTextureFilter(font.texture, FILTER_BILINEAR);
  64. music = LoadMusicStream("resources/elevator_romance.ogg");
  65. fxCoin = LoadSound("resources/coin.wav");
  66. background = LoadTexture("resources/background.png");
  67. texNPatch = LoadTexture("resources/npatch.png");
  68. npInfo.sourceRec = (Rectangle){ 0, 0, 80, texNPatch.height },
  69. npInfo.left = 24;
  70. npInfo.top = 24;
  71. npInfo.right = 24;
  72. npInfo.bottom = 24;
  73. // Load required textures
  74. texHead = LoadTexture("resources/head_models.png");
  75. texHair = LoadTexture("resources/hair_models.png");
  76. texNose = LoadTexture("resources/nose_models.png");
  77. texMouth = LoadTexture("resources/mouth_models.png");
  78. texEyes = LoadTexture("resources/eyes_models.png");
  79. //texComp = LoadTexture("resources/comp_models.png");
  80. SetMusicVolume(music, 0.5f);
  81. //PlayMusicStream(music);
  82. // Setup and Init first screen
  83. currentScreen = LOGO;
  84. InitLogoScreen();
  85. #if defined(PLATFORM_WEB)
  86. emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
  87. #else
  88. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  89. //--------------------------------------------------------------------------------------
  90. // Main game loop
  91. while (!WindowShouldClose()) // Detect window close button or ESC key
  92. {
  93. UpdateDrawFrame();
  94. }
  95. #endif
  96. // De-Initialization
  97. //--------------------------------------------------------------------------------------
  98. // Unload current screen data before closing
  99. switch (currentScreen)
  100. {
  101. case LOGO: UnloadLogoScreen(); break;
  102. case TITLE: UnloadTitleScreen(); break;
  103. case GAMEPLAY: UnloadGameplayScreen(); break;
  104. case ENDING: UnloadEndingScreen(); break;
  105. default: break;
  106. }
  107. // Unload all global loaded data (i.e. fonts) here!
  108. UnloadFont(font);
  109. UnloadMusicStream(music);
  110. UnloadSound(fxCoin);
  111. UnloadTexture(background);
  112. UnloadTexture(texNPatch);
  113. UnloadTexture(texHead);
  114. UnloadTexture(texHair);
  115. UnloadTexture(texNose);
  116. UnloadTexture(texMouth);
  117. UnloadTexture(texEyes);
  118. //UnloadTexture(texComp);
  119. CloseAudioDevice(); // Close audio context
  120. CloseWindow(); // Close window and OpenGL context
  121. //--------------------------------------------------------------------------------------
  122. return 0;
  123. }
  124. //----------------------------------------------------------------------------------
  125. // Public Functions Definition
  126. //----------------------------------------------------------------------------------
  127. Character GenerateCharacter(void)
  128. {
  129. Character character = { 0 };
  130. // Generate player character!
  131. character.head = GetRandomValue(0, texHead.width/BASE_HEAD_WIDTH - 1);
  132. character.colHead = headColors[GetRandomValue(0, 5)];
  133. character.hair = GetRandomValue(0, texHair.width/BASE_HAIR_WIDTH - 1);
  134. character.colHair = hairColors[GetRandomValue(0, 9)];
  135. character.eyes = GetRandomValue(0, texEyes.width/BASE_EYES_WIDTH - 1);
  136. character.nose = GetRandomValue(0, texNose.width/BASE_NOSE_WIDTH - 1);
  137. character.mouth = GetRandomValue(0, texMouth.width/BASE_MOUTH_WIDTH - 1);
  138. // NOTE: No character customization at this point
  139. return character;
  140. }
  141. void CustomizeCharacter(Character *character)
  142. {
  143. if (GetRandomValue(0, 1)) character->hair = GetRandomValue(0, texHair.width/BASE_HAIR_WIDTH - 1);
  144. if (GetRandomValue(0, 1)) character->colHair = hairColors[GetRandomValue(0, 9)];
  145. if (GetRandomValue(0, 1)) character->eyes = GetRandomValue(0, texEyes.width/BASE_EYES_WIDTH - 1);
  146. if (GetRandomValue(0, 1)) character->nose = GetRandomValue(0, texNose.width/BASE_NOSE_WIDTH - 1);
  147. if (GetRandomValue(0, 1)) character->mouth = GetRandomValue(0, texMouth.width/BASE_MOUTH_WIDTH - 1);
  148. }
  149. void DrawCharacter(Character character, Vector2 position)
  150. {
  151. DrawTextureRec(texHair, (Rectangle){ BASE_HAIR_WIDTH*character.hair, 240, BASE_HAIR_WIDTH, texHair.height - 240 }, (Vector2){ position.x + (250 - BASE_HAIR_WIDTH)/2, position.y + 240 }, GetColor(character.colHair));
  152. DrawTextureRec(texHead, (Rectangle){ BASE_HEAD_WIDTH*character.head, 0, BASE_HEAD_WIDTH, texHead.height }, (Vector2){ position.x + (250 - BASE_HEAD_WIDTH)/2, position.y + 60 }, GetColor(character.colHead));
  153. DrawTextureRec(texHair, (Rectangle){ BASE_HAIR_WIDTH*character.hair, 0, BASE_HAIR_WIDTH, 240 }, (Vector2){ position.x + (250 - BASE_HAIR_WIDTH)/2, position.y }, GetColor(character.colHair));
  154. DrawTextureRec(texEyes, (Rectangle){ BASE_EYES_WIDTH*character.eyes, 0, BASE_EYES_WIDTH, texEyes.height }, (Vector2){ position.x + (250 - BASE_EYES_WIDTH)/2, position.y + 190 }, WHITE);
  155. DrawTextureRec(texNose, (Rectangle){ BASE_NOSE_WIDTH*character.nose, 0, BASE_NOSE_WIDTH, texNose.height }, (Vector2){ position.x + (250 - BASE_NOSE_WIDTH)/2, position.y + 275 }, GetColor(character.colHead));
  156. DrawTextureRec(texMouth, (Rectangle){ BASE_MOUTH_WIDTH*character.mouth, 0, BASE_MOUTH_WIDTH, texMouth.height }, (Vector2){ position.x + (250 - BASE_MOUTH_WIDTH)/2, position.y + 370 }, GetColor(character.colHead));
  157. }
  158. // Gui Button
  159. bool GuiButton(Rectangle bounds, const char *text, int forcedState)
  160. {
  161. static const int textColor[4] = { 0xeff6ffff, 0x78e782ff, 0xb04d5fff, 0xd6d6d6ff };
  162. int state = (forcedState >= 0)? forcedState : 0; // NORMAL
  163. bool pressed = false;
  164. Vector2 textSize = MeasureTextEx(font, text, font.baseSize, 1);
  165. // Update control
  166. //--------------------------------------------------------------------
  167. if ((state < 3) && (forcedState < 0))
  168. {
  169. Vector2 mousePoint = GetMousePosition();
  170. // Check button state
  171. if (CheckCollisionPointRec(mousePoint, bounds))
  172. {
  173. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = 2; // PRESSED
  174. else state = 1; // FOCUSED
  175. if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON) || IsGestureDetected(GESTURE_TAP))
  176. {
  177. pressed = true;
  178. PlaySound(fxCoin);
  179. }
  180. }
  181. }
  182. npInfo.sourceRec.x = 80*state;
  183. //--------------------------------------------------------------------
  184. // Draw control
  185. //--------------------------------------------------------------------
  186. //DrawRectangleRec(bounds, GREEN);
  187. //DrawRectangleLinesEx(bounds, 4, DARKGREEN);
  188. DrawTextureNPatch(texNPatch, npInfo, bounds, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
  189. DrawTextEx(font, text, (Vector2){ bounds.x + bounds.width/2 - textSize.x/2, bounds.y + bounds.height/2 - textSize.y/2 + 4 }, font.baseSize, 1, GetColor(textColor[state]));
  190. //------------------------------------------------------------------
  191. return pressed;
  192. }
  193. //----------------------------------------------------------------------------------
  194. // Module specific Functions Definition
  195. //----------------------------------------------------------------------------------
  196. // Change to next screen, no transition
  197. static void ChangeToScreen(int screen)
  198. {
  199. // Unload current screen
  200. switch (currentScreen)
  201. {
  202. case LOGO: UnloadLogoScreen(); break;
  203. case TITLE: UnloadTitleScreen(); break;
  204. case GAMEPLAY: UnloadGameplayScreen(); break;
  205. case ENDING: UnloadEndingScreen(); break;
  206. default: break;
  207. }
  208. // Init next screen
  209. switch (screen)
  210. {
  211. case LOGO: InitLogoScreen(); break;
  212. case TITLE: InitTitleScreen(); break;
  213. case GAMEPLAY: InitGameplayScreen(); break;
  214. case ENDING: InitEndingScreen(); break;
  215. default: break;
  216. }
  217. currentScreen = screen;
  218. }
  219. // Define transition to next screen
  220. static void TransitionToScreen(int screen)
  221. {
  222. onTransition = true;
  223. transFadeOut = false;
  224. transFromScreen = currentScreen;
  225. transToScreen = screen;
  226. transAlpha = 0.0f;
  227. }
  228. // Update transition effect
  229. static void UpdateTransition(void)
  230. {
  231. if (!transFadeOut)
  232. {
  233. transAlpha += 0.05f;
  234. // NOTE: Due to float internal representation, condition jumps on 1.0f instead of 1.05f
  235. // For that reason we compare against 1.01f, to avoid last frame loading stop
  236. if (transAlpha > 1.01f)
  237. {
  238. transAlpha = 1.0f;
  239. // Unload current screen
  240. switch (transFromScreen)
  241. {
  242. case LOGO: UnloadLogoScreen(); break;
  243. case TITLE: UnloadTitleScreen(); break;
  244. case GAMEPLAY: UnloadGameplayScreen(); break;
  245. case ENDING: UnloadEndingScreen(); break;
  246. default: break;
  247. }
  248. // Load next screen
  249. switch (transToScreen)
  250. {
  251. case LOGO: InitLogoScreen(); break;
  252. case TITLE: InitTitleScreen(); break;
  253. case GAMEPLAY: InitGameplayScreen(); break;
  254. case ENDING: InitEndingScreen(); break;
  255. default: break;
  256. }
  257. currentScreen = transToScreen;
  258. // Activate fade out effect to next loaded screen
  259. transFadeOut = true;
  260. }
  261. }
  262. else // Transition fade out logic
  263. {
  264. transAlpha -= 0.02f;
  265. if (transAlpha < -0.01f)
  266. {
  267. transAlpha = 0.0f;
  268. transFadeOut = false;
  269. onTransition = false;
  270. transFromScreen = -1;
  271. transToScreen = -1;
  272. }
  273. }
  274. }
  275. // Draw transition effect (full-screen rectangle)
  276. static void DrawTransition(void)
  277. {
  278. DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha));
  279. }
  280. // Update and draw game frame
  281. static void UpdateDrawFrame(void)
  282. {
  283. // Update
  284. //----------------------------------------------------------------------------------
  285. UpdateMusicStream(music); // NOTE: Music keeps playing between screens
  286. if (!onTransition)
  287. {
  288. switch(currentScreen)
  289. {
  290. case LOGO:
  291. {
  292. UpdateLogoScreen();
  293. if (FinishLogoScreen())
  294. {
  295. TransitionToScreen(TITLE);
  296. PlayMusicStream(music);
  297. }
  298. } break;
  299. case TITLE:
  300. {
  301. UpdateTitleScreen();
  302. if (FinishTitleScreen() == 1) TransitionToScreen(GAMEPLAY);
  303. //else if (FinishTitleScreen() == 2) TransitionToScreen(GAMEPLAY);
  304. } break;
  305. case GAMEPLAY:
  306. {
  307. UpdateGameplayScreen();
  308. if (FinishGameplayScreen() == 1) TransitionToScreen(ENDING);
  309. //else if (FinishGameplayScreen() == 2) TransitionToScreen(TITLE);
  310. } break;
  311. case ENDING:
  312. {
  313. UpdateEndingScreen();
  314. if (FinishEndingScreen() == 1) TransitionToScreen(TITLE);
  315. } break;
  316. default: break;
  317. }
  318. }
  319. else UpdateTransition(); // Update transition (fade-in, fade-out)
  320. //----------------------------------------------------------------------------------
  321. // Draw
  322. //----------------------------------------------------------------------------------
  323. BeginDrawing();
  324. ClearBackground(RAYWHITE);
  325. switch(currentScreen)
  326. {
  327. case LOGO: DrawLogoScreen(); break;
  328. case TITLE: DrawTitleScreen(); break;
  329. case GAMEPLAY: DrawGameplayScreen(); break;
  330. case ENDING: DrawEndingScreen(); break;
  331. default: break;
  332. }
  333. // Draw full screen rectangle in front of everything
  334. if (onTransition) DrawTransition();
  335. //DrawFPS(10, 10);
  336. EndDrawing();
  337. //----------------------------------------------------------------------------------
  338. }