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.

447 lines
18 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib game - Dr. Turtle & Mr. Gamera
  4. *
  5. * Welcome to raylib!
  6. *
  7. * To test examples, just press F6 and execute raylib_compile_execute script
  8. * Note that compiled executable is placed in the same folder as .c file
  9. *
  10. * You can find all basic examples on C:\raylib\raylib\examples folder or
  11. * raylib official webpage: www.raylib.com
  12. *
  13. * Enjoy using raylib. :)
  14. *
  15. * This game has been created using raylib 1.1 (www.raylib.com)
  16. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  17. *
  18. * Copyright (c) 2014 Ramon Santamaria (@raysan5)
  19. *
  20. ********************************************************************************************/
  21. #include "raylib.h"
  22. #define MAX_ENEMIES 10
  23. typedef enum { TITLE, GAMEPLAY, ENDING } GameScreen;
  24. int main()
  25. {
  26. // Initialization
  27. //--------------------------------------------------------------------------------------
  28. const int screenWidth = 1280;
  29. const int screenHeight = 720;
  30. // Init window
  31. InitWindow(screenWidth, screenHeight, "Dr. Turtle & Mr. GAMERA");
  32. // Load game resources: textures
  33. Texture2D sky = LoadTexture("resources/sky.png");
  34. Texture2D mountains = LoadTexture("resources/mountains.png");
  35. Texture2D sea = LoadTexture("resources/sea.png");
  36. Texture2D title = LoadTexture("resources/title.png");
  37. Texture2D turtle = LoadTexture("resources/turtle.png");
  38. Texture2D gamera = LoadTexture("resources/gamera.png");
  39. Texture2D shark = LoadTexture("resources/shark.png");
  40. Texture2D orca = LoadTexture("resources/orca.png");
  41. Texture2D swhale = LoadTexture("resources/swhale.png");
  42. Texture2D fish = LoadTexture("resources/fish.png");
  43. Texture2D gframe = LoadTexture("resources/gframe.png");
  44. // Load game resources: fonts
  45. Font font = LoadFont("resources/komika.png");
  46. // Define scrolling variables
  47. int backScrolling = 0;
  48. int seaScrolling = 0;
  49. // Define current screen
  50. GameScreen currentScreen = TITLE;
  51. // Define player variables
  52. int playerRail = 1;
  53. Rectangle playerBounds = { 30 + 14, playerRail*120 + 90 + 14, 100, 100 };
  54. bool gameraMode = false;
  55. // Define enemies variables
  56. Rectangle enemyBounds[MAX_ENEMIES];
  57. int enemyRail[MAX_ENEMIES];
  58. int enemyType[MAX_ENEMIES];
  59. bool enemyActive[MAX_ENEMIES];
  60. float enemySpeed = 10;
  61. // Init enemies variables
  62. for (int i = 0; i < MAX_ENEMIES; i++)
  63. {
  64. // Define enemy type (all same probability)
  65. //enemyType[i] = GetRandomValue(0, 3);
  66. // Probability system for enemies type
  67. int enemyProb = GetRandomValue(0, 100);
  68. if (enemyProb < 30) enemyType[i] = 0;
  69. else if (enemyProb < 60) enemyType[i] = 1;
  70. else if (enemyProb < 90) enemyType[i] = 2;
  71. else enemyType[i] = 3;
  72. // Define enemy rail
  73. enemyRail[i] = GetRandomValue(0, 4);
  74. enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
  75. enemyActive[i] = false;
  76. }
  77. // Define additional game variables
  78. int score = 0;
  79. float distance = 0.0f;
  80. int hiscore = 0;
  81. float hidistance = 0.0f;
  82. int foodBar = 0;
  83. int framesCounter = 0;
  84. SetTargetFPS(60); // Setup game frames per second
  85. //--------------------------------------------------------------------------------------
  86. // Main game loop
  87. while (!WindowShouldClose()) // Detect window close button or ESC key
  88. {
  89. // Update
  90. //----------------------------------------------------------------------------------
  91. framesCounter++;
  92. // Game screens management
  93. switch (currentScreen)
  94. {
  95. case TITLE:
  96. {
  97. // Sea scrolling
  98. seaScrolling -= 2;
  99. if (seaScrolling <= -screenWidth) seaScrolling = 0;
  100. // Press enter to change to gameplay screen
  101. if (IsKeyPressed(KEY_ENTER))
  102. {
  103. currentScreen = GAMEPLAY;
  104. framesCounter = 0;
  105. }
  106. } break;
  107. case GAMEPLAY:
  108. {
  109. // Background scrolling logic
  110. backScrolling--;
  111. if (backScrolling <= -screenWidth) backScrolling = 0;
  112. // Sea scrolling logic
  113. seaScrolling -= (enemySpeed - 2);
  114. if (seaScrolling <= -screenWidth) seaScrolling = 0;
  115. // Player movement logic
  116. if (IsKeyPressed(KEY_DOWN)) playerRail++;
  117. else if (IsKeyPressed(KEY_UP)) playerRail--;
  118. // Check player not out of rails
  119. if (playerRail > 4) playerRail = 4;
  120. else if (playerRail < 0) playerRail = 0;
  121. // Update player bounds
  122. playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 };
  123. // Enemies activation logic (every 40 frames)
  124. if (framesCounter > 40)
  125. {
  126. for (int i = 0; i < MAX_ENEMIES; i++)
  127. {
  128. if (enemyActive[i] == false)
  129. {
  130. enemyActive[i] = true;
  131. i = MAX_ENEMIES;
  132. }
  133. }
  134. framesCounter = 0;
  135. }
  136. // Enemies logic
  137. for (int i = 0; i < MAX_ENEMIES; i++)
  138. {
  139. if (enemyActive[i])
  140. {
  141. enemyBounds[i].x -= enemySpeed;
  142. }
  143. // Check enemies out of screen
  144. if (enemyBounds[i].x <= 0 - 128)
  145. {
  146. enemyActive[i] = false;
  147. enemyType[i] = GetRandomValue(0, 3);
  148. enemyRail[i] = GetRandomValue(0, 4);
  149. enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
  150. }
  151. }
  152. if (!gameraMode) enemySpeed += 0.005;
  153. // Check collision player vs enemies
  154. for (int i = 0; i < MAX_ENEMIES; i++)
  155. {
  156. if (enemyActive[i])
  157. {
  158. if (CheckCollisionRecs(playerBounds, enemyBounds[i]))
  159. {
  160. if (enemyType[i] < 3) // Bad enemies
  161. {
  162. if (gameraMode)
  163. {
  164. if (enemyType[i] == 0) score += 50;
  165. else if (enemyType[i] == 1) score += 150;
  166. else if (enemyType[i] == 2) score += 300;
  167. foodBar += 15;
  168. enemyActive[i] = false;
  169. // After enemy deactivation, reset enemy parameters to be reused
  170. enemyType[i] = GetRandomValue(0, 3);
  171. enemyRail[i] = GetRandomValue(0, 4);
  172. // Make sure not two consecutive enemies in the same row
  173. if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
  174. enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
  175. }
  176. else
  177. {
  178. // Player die logic
  179. currentScreen = ENDING;
  180. framesCounter = 0;
  181. // Save hiscore and hidistance for next game
  182. if (score > hiscore) hiscore = score;
  183. if (distance > hidistance) hidistance = distance;
  184. }
  185. }
  186. else // Sweet fish
  187. {
  188. enemyActive[i] = false;
  189. enemyType[i] = GetRandomValue(0, 3);
  190. enemyRail[i] = GetRandomValue(0, 4);
  191. // Make sure not two consecutive enemies in the same row
  192. if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
  193. enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
  194. if (!gameraMode) foodBar += 80;
  195. else foodBar += 25;
  196. score += 10;
  197. if (foodBar == 400)
  198. {
  199. gameraMode = true;
  200. }
  201. }
  202. }
  203. }
  204. }
  205. // Gamera mode logic
  206. if (gameraMode)
  207. {
  208. foodBar--;
  209. if (foodBar <= 0)
  210. {
  211. gameraMode = false;
  212. enemySpeed -= 2;
  213. if (enemySpeed < 10) enemySpeed = 10;
  214. }
  215. }
  216. // Update distance counter
  217. distance += 0.5f;
  218. } break;
  219. case ENDING:
  220. {
  221. // Press enter to play again
  222. if (IsKeyPressed(KEY_ENTER))
  223. {
  224. currentScreen = GAMEPLAY;
  225. // Reset player
  226. playerRail = 1;
  227. playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 };
  228. gameraMode = false;
  229. // Reset enemies data
  230. for (int i = 0; i < MAX_ENEMIES; i++)
  231. {
  232. int enemyProb = GetRandomValue(0, 100);
  233. if (enemyProb < 30) enemyType[i] = 0;
  234. else if (enemyProb < 60) enemyType[i] = 1;
  235. else if (enemyProb < 90) enemyType[i] = 2;
  236. else enemyType[i] = 3;
  237. //enemyType[i] = GetRandomValue(0, 3);
  238. enemyRail[i] = GetRandomValue(0, 4);
  239. enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
  240. enemyActive[i] = false;
  241. }
  242. enemySpeed = 10;
  243. // Reset game variables
  244. score = 0;
  245. distance = 0.0;
  246. foodBar = 0;
  247. framesCounter = 0;
  248. }
  249. } break;
  250. default: break;
  251. }
  252. //----------------------------------------------------------------------------------
  253. // Draw
  254. //----------------------------------------------------------------------------------
  255. BeginDrawing();
  256. ClearBackground(RAYWHITE);
  257. // Draw background (common to all screens)
  258. DrawTexture(sky, 0, 0, WHITE);
  259. DrawTexture(mountains, backScrolling, 0, WHITE);
  260. DrawTexture(mountains, screenWidth + backScrolling, 0, WHITE);
  261. if (!gameraMode)
  262. {
  263. DrawTexture(sea, seaScrolling, 0, (Color){ 16, 189, 227, 255});
  264. DrawTexture(sea, screenWidth + seaScrolling, 0, (Color){ 16, 189, 227, 255});
  265. }
  266. else
  267. {
  268. DrawTexture(sea, seaScrolling, 0, (Color){ 255, 113, 66, 255});
  269. DrawTexture(sea, screenWidth + seaScrolling, 0, (Color){ 255, 113, 66, 255});
  270. }
  271. switch (currentScreen)
  272. {
  273. case TITLE:
  274. {
  275. // Draw title
  276. DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE);
  277. // Draw blinking text
  278. if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.baseSize, 0, WHITE);
  279. } break;
  280. case GAMEPLAY:
  281. {
  282. // Draw water lines
  283. for (int i = 0; i < 5; i++) DrawRectangle(0, i*120 + 120, screenWidth, 110, Fade(SKYBLUE, 0.1f));
  284. // Draw player
  285. if (!gameraMode) DrawTexture(turtle, playerBounds.x - 14, playerBounds.y - 14, WHITE);
  286. else DrawTexture(gamera, playerBounds.x - 64, playerBounds.y - 64, WHITE);
  287. // Draw player bounding box
  288. //if (!gameraMode) DrawRectangleRec(playerBounds, Fade(GREEN, 0.4f));
  289. //else DrawRectangleRec(playerBounds, Fade(ORANGE, 0.4f));
  290. // Draw enemies
  291. for (int i = 0; i < MAX_ENEMIES; i++)
  292. {
  293. if (enemyActive[i])
  294. {
  295. // Draw enemies
  296. switch(enemyType[i])
  297. {
  298. case 0: DrawTexture(shark, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
  299. case 1: DrawTexture(orca, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
  300. case 2: DrawTexture(swhale, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
  301. case 3: DrawTexture(fish, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
  302. default: break;
  303. }
  304. // Draw enemies bounding boxes
  305. /*
  306. switch(enemyType[i])
  307. {
  308. case 0: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break;
  309. case 1: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break;
  310. case 2: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break;
  311. case 3: DrawRectangleRec(enemyBounds[i], Fade(GREEN, 0.5f)); break;
  312. default: break;
  313. }
  314. */
  315. }
  316. }
  317. // Draw gameplay interface
  318. DrawRectangle(20, 20, 400, 40, Fade(GRAY, 0.4f));
  319. DrawRectangle(20, 20, foodBar, 40, ORANGE);
  320. DrawRectangleLines(20, 20, 400, 40, BLACK);
  321. DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.baseSize, -2, ORANGE);
  322. DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.baseSize, -2, ORANGE);
  323. if (gameraMode)
  324. {
  325. DrawText("GAMERA MODE", 60, 22, 40, GRAY);
  326. DrawTexture(gframe, 0, 0, Fade(WHITE, 0.5f));
  327. }
  328. } break;
  329. case ENDING:
  330. {
  331. // Draw a transparent black rectangle that covers all screen
  332. DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f));
  333. DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.baseSize*3, -2, MAROON);
  334. DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.baseSize, -2, GOLD);
  335. DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.baseSize, -2, GOLD);
  336. DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.baseSize, -2, ORANGE);
  337. DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.baseSize, -2, ORANGE);
  338. // Draw blinking text
  339. if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.baseSize, -2, LIGHTGRAY);
  340. } break;
  341. default: break;
  342. }
  343. EndDrawing();
  344. //----------------------------------------------------------------------------------
  345. }
  346. // De-Initialization
  347. //--------------------------------------------------------------------------------------
  348. // Unload textures
  349. UnloadTexture(sky);
  350. UnloadTexture(mountains);
  351. UnloadTexture(sea);
  352. UnloadTexture(gframe);
  353. UnloadTexture(title);
  354. UnloadTexture(turtle);
  355. UnloadTexture(shark);
  356. UnloadTexture(orca);
  357. UnloadTexture(swhale);
  358. UnloadTexture(fish);
  359. UnloadTexture(gamera);
  360. // Unload font texture
  361. UnloadFont(font);
  362. CloseWindow(); // Close window and OpenGL context
  363. //--------------------------------------------------------------------------------------
  364. return 0;
  365. }