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.

492 line
20 KiB

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