1 | /******************************************************************************************* |
2 | * |
3 | * raylib - sample game: pang |
4 | * |
5 | * Sample game developed by Ian Eito and Albert Martos and Ramon Santamaria |
6 | * |
7 | * This game has been created using raylib v1.3 (www.raylib.com) |
8 | * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) |
9 | * |
10 | * Copyright (c) 2015 Ramon Santamaria (@raysan5) |
11 | * |
12 | ********************************************************************************************/ |
13 | |
14 | #include "raylib.h" |
15 | |
16 | #include <math.h> |
17 | |
18 | #if defined(PLATFORM_WEB) |
19 | #include <emscripten/emscripten.h> |
20 | #endif |
21 | |
22 | //---------------------------------------------------------------------------------- |
23 | // Some Defines |
24 | //---------------------------------------------------------------------------------- |
25 | #define PLAYER_BASE_SIZE 20.0f |
26 | #define PLAYER_SPEED 5.0f |
27 | #define PLAYER_MAX_SHOOTS 1 |
28 | |
29 | #define MAX_BIG_BALLS 2 |
30 | #define BALLS_SPEED 2.0f |
31 | |
32 | //---------------------------------------------------------------------------------- |
33 | // Types and Structures Definition |
34 | //---------------------------------------------------------------------------------- |
35 | typedef struct Player { |
36 | Vector2 position; |
37 | Vector2 speed; |
38 | Vector3 collider; |
39 | float rotation; |
40 | } Player; |
41 | |
42 | typedef struct Shoot { |
43 | Vector2 position; |
44 | Vector2 speed; |
45 | float radius; |
46 | float rotation; |
47 | int lifeSpawn; |
48 | bool active; |
49 | } Shoot; |
50 | |
51 | typedef struct Ball { |
52 | Vector2 position; |
53 | Vector2 speed; |
54 | float radius; |
55 | int points; |
56 | bool active; |
57 | } Ball; |
58 | |
59 | typedef struct Points { |
60 | Vector2 position; |
61 | int value; |
62 | float alpha; |
63 | } Points; |
64 | |
65 | //------------------------------------------------------------------------------------ |
66 | // Global Variables Declaration |
67 | //------------------------------------------------------------------------------------ |
68 | static const int screenWidth = 800; |
69 | static const int screenHeight = 450; |
70 | |
71 | static int framesCounter = 0; |
72 | static bool gameOver = false; |
73 | static bool pause = false; |
74 | static int score = 0; |
75 | |
76 | static Player player = { 0 }; |
77 | static Shoot shoot[PLAYER_MAX_SHOOTS] = { 0 }; |
78 | static Ball bigBalls[MAX_BIG_BALLS] = { 0 }; |
79 | static Ball mediumBalls[MAX_BIG_BALLS*2] = { 0 }; |
80 | static Ball smallBalls[MAX_BIG_BALLS*4] = { 0 }; |
81 | static Points points[5] = { 0 }; |
82 | |
83 | // NOTE: Defined triangle is isosceles with common angles of 70 degrees. |
84 | static float shipHeight = 0.0f; |
85 | static float gravity = 0.0f; |
86 | |
87 | static int countmediumBallss = 0; |
88 | static int countsmallBallss = 0; |
89 | static int meteorsDestroyed = 0; |
90 | static Vector2 linePosition = { 0 }; |
91 | |
92 | static bool victory = false; |
93 | static bool lose = false; |
94 | static bool awake = false; |
95 | |
96 | //------------------------------------------------------------------------------------ |
97 | // Module Functions Declaration (local) |
98 | //------------------------------------------------------------------------------------ |
99 | static void InitGame(void); // Initialize game |
100 | static void UpdateGame(void); // Update game (one frame) |
101 | static void DrawGame(void); // Draw game (one frame) |
102 | static void UnloadGame(void); // Unload game |
103 | static void UpdateDrawFrame(void); // Update and Draw (one frame) |
104 | |
105 | //------------------------------------------------------------------------------------ |
106 | // Program main entry point |
107 | //------------------------------------------------------------------------------------ |
108 | int main(void) |
109 | { |
110 | // Initialization (Note windowTitle is unused on Android) |
111 | //--------------------------------------------------------- |
112 | InitWindow(screenWidth, screenHeight, "sample game: pang" ); |
113 | |
114 | InitGame(); |
115 | |
116 | #if defined(PLATFORM_WEB) |
117 | emscripten_set_main_loop(UpdateDrawFrame, 0, 1); |
118 | #else |
119 | SetTargetFPS(60); |
120 | //-------------------------------------------------------------------------------------- |
121 | |
122 | // Main game loop |
123 | while (!WindowShouldClose()) // Detect window close button or ESC key |
124 | { |
125 | // Update and Draw |
126 | //---------------------------------------------------------------------------------- |
127 | UpdateDrawFrame(); |
128 | //---------------------------------------------------------------------------------- |
129 | } |
130 | #endif |
131 | // De-Initialization |
132 | //-------------------------------------------------------------------------------------- |
133 | UnloadGame(); // Unload loaded data (textures, sounds, models...) |
134 | |
135 | CloseWindow(); // Close window and OpenGL context |
136 | //-------------------------------------------------------------------------------------- |
137 | |
138 | return 0; |
139 | } |
140 | |
141 | //------------------------------------------------------------------------------------ |
142 | // Module Functions Definitions (local) |
143 | //------------------------------------------------------------------------------------ |
144 | |
145 | // Initialize game variables |
146 | static void InitGame(void) |
147 | { |
148 | int posx, posy; |
149 | int velx = 0; |
150 | int vely = 0; |
151 | |
152 | framesCounter = 0; |
153 | gameOver = false; |
154 | pause = false; |
155 | score = 0; |
156 | |
157 | victory = false; |
158 | lose = false; |
159 | awake = true; |
160 | gravity = 0.25f; |
161 | |
162 | linePosition = (Vector2){ 0.0f , 0.0f }; |
163 | shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD); |
164 | |
165 | // Initialization player |
166 | player.position = (Vector2){ screenWidth/2, screenHeight }; |
167 | player.speed = (Vector2){ PLAYER_SPEED, PLAYER_SPEED }; |
168 | player.rotation = 0; |
169 | player.collider = (Vector3){ player.position.x, player.position.y - shipHeight/2.0f, 12.0f }; |
170 | |
171 | meteorsDestroyed = 0; |
172 | |
173 | // Initialize shoots |
174 | for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) |
175 | { |
176 | shoot[i].position = (Vector2){ 0, 0 }; |
177 | shoot[i].speed = (Vector2){ 0, 0 }; |
178 | shoot[i].radius = 2; |
179 | shoot[i].active = false; |
180 | shoot[i].lifeSpawn = 0; |
181 | } |
182 | |
183 | // Initialize big meteors |
184 | for (int i = 0; i < MAX_BIG_BALLS; i++) |
185 | { |
186 | bigBalls[i].radius = 40.0f; |
187 | posx = GetRandomValue(0 + bigBalls[i].radius, screenWidth - bigBalls[i].radius); |
188 | posy = GetRandomValue(0 + bigBalls[i].radius, screenHeight/2); |
189 | |
190 | bigBalls[i].position = (Vector2){ posx, posy }; |
191 | |
192 | while ((velx == 0) || (vely == 0)) |
193 | { |
194 | velx = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); |
195 | vely = GetRandomValue(-BALLS_SPEED, BALLS_SPEED); |
196 | } |
197 | |
198 | bigBalls[i].speed = (Vector2){ velx, vely }; |
199 | bigBalls[i].points = 200; |
200 | bigBalls[i].active = true; |
201 | } |
202 | |
203 | // Initialize medium meteors |
204 | for (int i = 0; i < MAX_BIG_BALLS*2; i++) |
205 | { |
206 | mediumBalls[i].position = (Vector2){-100, -100}; |
207 | mediumBalls[i].speed = (Vector2){0,0}; |
208 | mediumBalls[i].radius = 20.0f; |
209 | mediumBalls[i].points = 100; |
210 | mediumBalls[i].active = false; |
211 | } |
212 | |
213 | // Initialize small meteors |
214 | for (int i = 0; i < MAX_BIG_BALLS*4; i++) |
215 | { |
216 | smallBalls[i].position = (Vector2){ -100, -100 }; |
217 | smallBalls[i].speed = (Vector2){ 0, 0 }; |
218 | smallBalls[i].radius = 10.0f; |
219 | smallBalls[i].points = 50; |
220 | smallBalls[i].active = false; |
221 | } |
222 | |
223 | // Initialize animated points |
224 | for (int i = 0; i < 5; i++) |
225 | { |
226 | points[i].position = (Vector2){ 0, 0 }; |
227 | points[i].value = 0; |
228 | points[i].alpha = 0.0f; |
229 | } |
230 | |
231 | countmediumBallss = 0; |
232 | countsmallBallss = 0; |
233 | } |
234 | |
235 | // Update game (one frame) |
236 | void UpdateGame(void) |
237 | { |
238 | if (!gameOver && !victory) |
239 | { |
240 | if (IsKeyPressed('P')) pause = !pause; |
241 | |
242 | if (!pause) |
243 | { |
244 | // Player logic |
245 | if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x; |
246 | if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x; |
247 | |
248 | // Player vs wall collision logic |
249 | if (player.position.x + PLAYER_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - PLAYER_BASE_SIZE/2; |
250 | else if (player.position.x - PLAYER_BASE_SIZE/2 < 0) player.position.x = 0 + PLAYER_BASE_SIZE/2; |
251 | |
252 | // Player shot logic |
253 | if (IsKeyPressed(KEY_SPACE)) |
254 | { |
255 | for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) |
256 | { |
257 | if (!shoot[i].active) |
258 | { |
259 | shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight }; |
260 | shoot[i].speed.y = PLAYER_SPEED; |
261 | shoot[i].active = true; |
262 | |
263 | linePosition = (Vector2){ player.position.x, player.position.y}; |
264 | |
265 | break; |
266 | } |
267 | } |
268 | } |
269 | |
270 | // Shoot life timer |
271 | for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) |
272 | { |
273 | if (shoot[i].active) shoot[i].lifeSpawn++; |
274 | } |
275 | |
276 | // Shot logic |
277 | for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) |
278 | { |
279 | if (shoot[i].active) |
280 | { |
281 | shoot[i].position.y -= shoot[i].speed.y; |
282 | |
283 | // Shot vs walls collision logic |
284 | if ((shoot[i].position.x > screenWidth + shoot[i].radius) || (shoot[i].position.x < 0 - shoot[i].radius) || |
285 | (shoot[i].position.y > screenHeight + shoot[i].radius) || (shoot[i].position.y < 0 - shoot[i].radius)) |
286 | { |
287 | shoot[i].active = false; |
288 | shoot[i].lifeSpawn = 0; |
289 | } |
290 | |
291 | // Player shot life spawn |
292 | if (shoot[i].lifeSpawn >= 120) |
293 | { |
294 | shoot[i].position = (Vector2){ 0.0f, 0.0f }; |
295 | shoot[i].speed = (Vector2){ 0.0f, 0.0f }; |
296 | shoot[i].lifeSpawn = 0; |
297 | shoot[i].active = false; |
298 | } |
299 | } |
300 | } |
301 | |
302 | // Player vs meteors collision logic |
303 | player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12}; |
304 | |
305 | for (int i = 0; i < MAX_BIG_BALLS; i++) |
306 | { |
307 | if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigBalls[i].position, bigBalls[i].radius) && bigBalls[i].active) |
308 | { |
309 | gameOver = true; |
310 | } |
311 | } |
312 | |
313 | for (int i = 0; i < MAX_BIG_BALLS*2; i++) |
314 | { |
315 | if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumBalls[i].position, mediumBalls[i].radius) && mediumBalls[i].active) |
316 | { |
317 | gameOver = true; |
318 | } |
319 | } |
320 | |
321 | for (int i = 0; i < MAX_BIG_BALLS*4; i++) |
322 | { |
323 | if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallBalls[i].position, smallBalls[i].radius) && smallBalls[i].active) |
324 | { |
325 | gameOver = true; |
326 | } |
327 | } |
328 | |
329 | // Meteors logic (big) |
330 | for (int i = 0; i < MAX_BIG_BALLS; i++) |
331 | { |
332 | if (bigBalls[i].active) |
333 | { |
334 | // Meteor movement logic |
335 | bigBalls[i].position.x += bigBalls[i].speed.x; |
336 | bigBalls[i].position.y += bigBalls[i].speed.y; |
337 | |
338 | // Meteor vs wall collision logic |
339 | if (((bigBalls[i].position.x + bigBalls[i].radius) >= screenWidth) || ((bigBalls[i].position.x - bigBalls[i].radius) <= 0)) bigBalls[i].speed.x *= -1; |
340 | if ((bigBalls[i].position.y - bigBalls[i].radius) <= 0) bigBalls[i].speed.y *= -1.5; |
341 | |
342 | if ((bigBalls[i].position.y + bigBalls[i].radius) >= screenHeight) |
343 | { |
344 | bigBalls[i].speed.y *= -1; |
345 | bigBalls[i].position.y = screenHeight - bigBalls[i].radius; |
346 | } |
347 | |
348 | bigBalls[i].speed.y += gravity; |
349 | } |
350 | } |
351 | |
352 | // Meteors logic (medium) |
353 | for (int i = 0; i < MAX_BIG_BALLS*2; i++) |
354 | { |
355 | if (mediumBalls[i].active) |
356 | { |
357 | // Meteor movement logic |
358 | mediumBalls[i].position.x += mediumBalls[i].speed.x; |
359 | mediumBalls[i].position.y += mediumBalls[i].speed.y; |
360 | |
361 | // Meteor vs wall collision logic |
362 | if (mediumBalls[i].position.x + mediumBalls[i].radius >= screenWidth || mediumBalls[i].position.x - mediumBalls[i].radius <= 0) mediumBalls[i].speed.x *= -1; |
363 | if (mediumBalls[i].position.y - mediumBalls[i].radius <= 0) mediumBalls[i].speed.y *= -1; |
364 | if (mediumBalls[i].position.y + mediumBalls[i].radius >= screenHeight) |
365 | { |
366 | mediumBalls[i].speed.y *= -1; |
367 | mediumBalls[i].position.y = screenHeight - mediumBalls[i].radius; |
368 | } |
369 | |
370 | mediumBalls[i].speed.y += gravity + 0.12f; |
371 | } |
372 | } |
373 | |
374 | // Meteors logic (small) |
375 | for (int i = 0; i < MAX_BIG_BALLS*4; i++) |
376 | { |
377 | if (smallBalls[i].active) |
378 | { |
379 | // Meteor movement logic |
380 | smallBalls[i].position.x += smallBalls[i].speed.x; |
381 | smallBalls[i].position.y += smallBalls[i].speed.y; |
382 | |
383 | // Meteor vs wall collision logic |
384 | if (smallBalls[i].position.x + smallBalls[i].radius >= screenWidth || smallBalls[i].position.x - smallBalls[i].radius <= 0) smallBalls[i].speed.x *= -1; |
385 | if (smallBalls[i].position.y - smallBalls[i].radius <= 0) smallBalls[i].speed.y *= -1; |
386 | if (smallBalls[i].position.y + smallBalls[i].radius >= screenHeight) |
387 | { |
388 | smallBalls[i].speed.y *= -1; |
389 | smallBalls[i].position.y = screenHeight - smallBalls[i].radius; |
390 | } |
391 | |
392 | smallBalls[i].speed.y += gravity + 0.25f; |
393 | } |
394 | } |
395 | |
396 | // Player-shot vs meteors logic |
397 | for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) |
398 | { |
399 | if ((shoot[i].active)) |
400 | { |
401 | for (int a = 0; a < MAX_BIG_BALLS; a++) |
402 | { |
403 | if (bigBalls[a].active && (bigBalls[a].position.x - bigBalls[a].radius <= linePosition.x && bigBalls[a].position.x + bigBalls[a].radius >= linePosition.x) |
404 | && (bigBalls[a].position.y + bigBalls[a].radius >= shoot[i].position.y)) |
405 | { |
406 | shoot[i].active = false; |
407 | shoot[i].lifeSpawn = 0; |
408 | bigBalls[a].active = false; |
409 | meteorsDestroyed++; |
410 | score += bigBalls[a].points; |
411 | |
412 | for (int z = 0; z < 5; z++) |
413 | { |
414 | if (points[z].alpha == 0.0f) |
415 | { |
416 | points[z].position = bigBalls[a].position; |
417 | points[z].value = bigBalls[a].points; |
418 | points[z].alpha = 1.0f; |
419 | z = 5; |
420 | } |
421 | } |
422 | |
423 | for (int j = 0; j < 2; j ++) |
424 | { |
425 | if ((countmediumBallss%2) == 0) |
426 | { |
427 | mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; |
428 | mediumBalls[countmediumBallss].speed = (Vector2){ -1*BALLS_SPEED, BALLS_SPEED }; |
429 | } |
430 | else |
431 | { |
432 | mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y}; |
433 | mediumBalls[countmediumBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED }; |
434 | } |
435 | |
436 | mediumBalls[countmediumBallss].active = true; |
437 | countmediumBallss ++; |
438 | } |
439 | |
440 | a = MAX_BIG_BALLS; |
441 | } |
442 | } |
443 | } |
444 | |
445 | if ((shoot[i].active)) |
446 | { |
447 | for (int b = 0; b < MAX_BIG_BALLS*2; b++) |
448 | { |
449 | if (mediumBalls[b].active && (mediumBalls[b].position.x - mediumBalls[b].radius <= linePosition.x && mediumBalls[b].position.x + mediumBalls[b].radius >= linePosition.x) |
450 | && (mediumBalls[b].position.y + mediumBalls[b].radius >= shoot[i].position.y)) |
451 | { |
452 | shoot[i].active = false; |
453 | shoot[i].lifeSpawn = 0; |
454 | mediumBalls[b].active = false; |
455 | meteorsDestroyed++; |
456 | score += mediumBalls[b].points; |
457 | |
458 | for (int z = 0; z < 5; z++) |
459 | { |
460 | if (points[z].alpha == 0.0f) |
461 | { |
462 | points[z].position = mediumBalls[b].position; |
463 | points[z].value = mediumBalls[b].points; |
464 | points[z].alpha = 1.0f; |
465 | z = 5; |
466 | } |
467 | } |
468 | |
469 | for (int j = 0; j < 2; j ++) |
470 | { |
471 | if (countsmallBallss%2 == 0) |
472 | { |
473 | smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; |
474 | smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED*-1, BALLS_SPEED*-1}; |
475 | } |
476 | else |
477 | { |
478 | smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y}; |
479 | smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED*-1}; |
480 | } |
481 | |
482 | smallBalls[countsmallBallss].active = true; |
483 | countsmallBallss ++; |
484 | } |
485 | |
486 | b = MAX_BIG_BALLS*2; |
487 | } |
488 | } |
489 | } |
490 | |
491 | if ((shoot[i].active)) |
492 | { |
493 | for (int c = 0; c < MAX_BIG_BALLS*4; c++) |
494 | { |
495 | if (smallBalls[c].active && (smallBalls[c].position.x - smallBalls[c].radius <= linePosition.x && smallBalls[c].position.x + smallBalls[c].radius >= linePosition.x) |
496 | && (smallBalls[c].position.y + smallBalls[c].radius >= shoot[i].position.y)) |
497 | { |
498 | shoot[i].active = false; |
499 | shoot[i].lifeSpawn = 0; |
500 | smallBalls[c].active = false; |
501 | meteorsDestroyed++; |
502 | score += smallBalls[c].points; |
503 | |
504 | for (int z = 0; z < 5; z++) |
505 | { |
506 | if (points[z].alpha == 0.0f) |
507 | { |
508 | points[z].position = smallBalls[c].position; |
509 | points[z].value = smallBalls[c].points; |
510 | points[z].alpha = 1.0f; |
511 | z = 5; |
512 | } |
513 | } |
514 | |
515 | c = MAX_BIG_BALLS*4; |
516 | } |
517 | } |
518 | } |
519 | } |
520 | |
521 | if (meteorsDestroyed == (MAX_BIG_BALLS + MAX_BIG_BALLS*2 + MAX_BIG_BALLS*4)) victory = true; |
522 | } |
523 | } |
524 | else |
525 | { |
526 | if (IsKeyPressed(KEY_ENTER)) |
527 | { |
528 | InitGame(); |
529 | gameOver = false; |
530 | } |
531 | } |
532 | |
533 | // Points move-up and fade logic |
534 | for (int z = 0; z < 5; z++) |
535 | { |
536 | if (points[z].alpha > 0.0f) |
537 | { |
538 | points[z].position.y -= 2; |
539 | points[z].alpha -= 0.02f; |
540 | } |
541 | |
542 | if (points[z].alpha < 0.0f) points[z].alpha = 0.0f; |
543 | } |
544 | } |
545 | |
546 | // Draw game (one frame) |
547 | void DrawGame(void) |
548 | { |
549 | BeginDrawing(); |
550 | |
551 | ClearBackground(RAYWHITE); |
552 | |
553 | if (!gameOver) |
554 | { |
555 | // Draw player |
556 | Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) }; |
557 | Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; |
558 | Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) }; |
559 | DrawTriangle(v1, v2, v3, MAROON); |
560 | |
561 | // Draw meteors (big) |
562 | for (int i = 0;i < MAX_BIG_BALLS; i++) |
563 | { |
564 | if (bigBalls[i].active) DrawCircleV(bigBalls[i].position, bigBalls[i].radius, DARKGRAY); |
565 | else DrawCircleV(bigBalls[i].position, bigBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); |
566 | } |
567 | |
568 | // Draw meteors (medium) |
569 | for (int i = 0;i < MAX_BIG_BALLS*2; i++) |
570 | { |
571 | if (mediumBalls[i].active) DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, GRAY); |
572 | else DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); |
573 | } |
574 | |
575 | // Draw meteors (small) |
576 | for (int i = 0;i < MAX_BIG_BALLS*4; i++) |
577 | { |
578 | if (smallBalls[i].active) DrawCircleV(smallBalls[i].position, smallBalls[i].radius, GRAY); |
579 | else DrawCircleV(smallBalls[i].position, smallBalls[i].radius, Fade(LIGHTGRAY, 0.3f)); |
580 | } |
581 | |
582 | // Draw shoot |
583 | for (int i = 0; i < PLAYER_MAX_SHOOTS; i++) |
584 | { |
585 | if (shoot[i].active) DrawLine(linePosition.x, linePosition.y, shoot[i].position.x, shoot[i].position.y, RED); |
586 | } |
587 | |
588 | // Draw score points |
589 | for (int z = 0; z < 5; z++) |
590 | { |
591 | if (points[z].alpha > 0.0f) |
592 | { |
593 | DrawText(TextFormat("+%02i" , points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha)); |
594 | } |
595 | } |
596 | |
597 | // Draw score (UI) |
598 | DrawText(TextFormat("SCORE: %i" , score), 10, 10, 20, LIGHTGRAY); |
599 | |
600 | if (victory) |
601 | { |
602 | DrawText("YOU WIN!" , screenWidth/2 - MeasureText("YOU WIN!" , 60)/2, 100, 60, LIGHTGRAY); |
603 | DrawText("PRESS [ENTER] TO PLAY AGAIN" , GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN" , 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); |
604 | } |
605 | |
606 | if (pause) DrawText("GAME PAUSED" , screenWidth/2 - MeasureText("GAME PAUSED" , 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY); |
607 | } |
608 | else DrawText("PRESS [ENTER] TO PLAY AGAIN" , GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN" , 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY); |
609 | |
610 | EndDrawing(); |
611 | } |
612 | |
613 | // Unload game variables |
614 | void UnloadGame(void) |
615 | { |
616 | // TODO: Unload all dynamic loaded data (textures, sounds, models...) |
617 | } |
618 | |
619 | // Update and Draw (one frame) |
620 | void UpdateDrawFrame(void) |
621 | { |
622 | UpdateGame(); |
623 | DrawGame(); |
624 | } |
625 | |