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.

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