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.

496 lines
20 KiB

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