aboutsummaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
Diffstat (limited to 'games')
-rw-r--r--games/arkanoid.c349
-rw-r--r--games/asteroids.c579
-rw-r--r--games/asteroids_survival.c383
-rw-r--r--games/drturtle/04_drturtle_gui.c18
-rw-r--r--games/drturtle/05_drturtle_audio.c18
-rw-r--r--games/drturtle/06_drturtle_final.c22
-rw-r--r--games/drturtle/drturtle_final_web.c541
-rw-r--r--games/drturtle/makefile186
-rw-r--r--games/floppy.c246
-rw-r--r--games/floppy/floppy.c213
-rw-r--r--games/floppy/resources/background.pngbin228930 -> 0 bytes
-rw-r--r--games/floppy/resources/coin.wavbin37396 -> 0 bytes
-rw-r--r--games/floppy/resources/floppy.pngbin2030 -> 0 bytes
-rw-r--r--games/floppy/resources/jump.wavbin14540 -> 0 bytes
-rw-r--r--games/floppy/resources/tubes.pngbin19623 -> 0 bytes
-rw-r--r--games/gold_fever.c288
-rw-r--r--games/gorilas.c571
-rw-r--r--games/just_do/makefile2
-rw-r--r--games/light_my_ritual/light_my_ritual.c271
-rw-r--r--games/light_my_ritual/makefile203
-rw-r--r--games/light_my_ritual/resources/audio/ambient.oggbin0 -> 1274574 bytes
-rw-r--r--games/light_my_ritual/resources/audio/light_off.wavbin0 -> 9291 bytes
-rw-r--r--games/light_my_ritual/resources/audio/light_on.wavbin0 -> 2335 bytes
-rw-r--r--games/light_my_ritual/resources/audio/ritual.oggbin0 -> 2592921 bytes
-rw-r--r--games/light_my_ritual/resources/audio/start.wavbin0 -> 14079 bytes
-rw-r--r--games/light_my_ritual/resources/font_arcadian.pngbin0 -> 97566 bytes
-rw-r--r--games/light_my_ritual/resources/lights_map.pngbin0 -> 430 bytes
-rw-r--r--games/light_my_ritual/resources/textures/back_title.pngbin0 -> 182900 bytes
-rw-r--r--games/light_my_ritual/resources/textures/background.pngbin0 -> 1231218 bytes
-rw-r--r--games/light_my_ritual/resources/textures/book.pngbin0 -> 4402 bytes
-rw-r--r--games/light_my_ritual/resources/textures/circle_level_i_off.pngbin0 -> 15448 bytes
-rw-r--r--games/light_my_ritual/resources/textures/circle_level_i_on.pngbin0 -> 51443 bytes
-rw-r--r--games/light_my_ritual/resources/textures/circle_level_ii_off.pngbin0 -> 27962 bytes
-rw-r--r--games/light_my_ritual/resources/textures/circle_level_ii_on.pngbin0 -> 106608 bytes
-rw-r--r--games/light_my_ritual/resources/textures/circle_level_iii_off.pngbin0 -> 37564 bytes
-rw-r--r--games/light_my_ritual/resources/textures/circle_level_iii_on.pngbin0 -> 160307 bytes
-rw-r--r--games/light_my_ritual/resources/textures/enemy.pngbin0 -> 2812 bytes
-rw-r--r--games/light_my_ritual/resources/textures/foreground_level_i.pngbin0 -> 28111 bytes
-rw-r--r--games/light_my_ritual/resources/textures/foreground_level_ii.pngbin0 -> 36121 bytes
-rw-r--r--games/light_my_ritual/resources/textures/foreground_level_iii.pngbin0 -> 42136 bytes
-rw-r--r--games/light_my_ritual/resources/textures/light.pngbin0 -> 2275 bytes
-rw-r--r--games/light_my_ritual/resources/textures/light_glow.pngbin0 -> 8661 bytes
-rw-r--r--games/light_my_ritual/resources/textures/light_ray.pngbin0 -> 8780 bytes
-rw-r--r--games/light_my_ritual/resources/textures/msg_ritual.pngbin0 -> 114012 bytes
-rw-r--r--games/light_my_ritual/resources/textures/player.pngbin0 -> 2899 bytes
-rw-r--r--games/light_my_ritual/resources/textures/time_over.pngbin0 -> 115874 bytes
-rw-r--r--games/light_my_ritual/resources/textures/title.pngbin0 -> 213549 bytes
-rw-r--r--games/light_my_ritual/screens/screen_gameplay.c842
-rw-r--r--games/light_my_ritual/screens/screen_logo_raylib.c214
-rw-r--r--games/light_my_ritual/screens/screen_title.c105
-rw-r--r--games/light_my_ritual/screens/screens.h78
-rw-r--r--games/makefile254
-rw-r--r--games/missile_commander.c539
-rw-r--r--games/pang.c630
-rw-r--r--games/raylib_demo/makefile116
-rw-r--r--games/raylib_demo/raylib_demo.c64
-rw-r--r--games/skully_escape/makefile254
-rw-r--r--games/skully_escape/monster.c54
-rw-r--r--games/skully_escape/monster.h73
-rw-r--r--games/skully_escape/player.c281
-rw-r--r--games/skully_escape/player.h51
-rw-r--r--games/skully_escape/resources/audio/come_play_with_me.oggbin0 -> 2310768 bytes
-rw-r--r--games/skully_escape/resources/audio/door.oggbin0 -> 32434 bytes
-rw-r--r--games/skully_escape/resources/audio/scream.oggbin0 -> 19696 bytes
-rw-r--r--games/skully_escape/resources/textures/alagard.pngbin0 -> 36659 bytes
-rw-r--r--games/skully_escape/resources/textures/background_aisle01.pngbin0 -> 670481 bytes
-rw-r--r--games/skully_escape/resources/textures/background_aisle02.pngbin0 -> 507254 bytes
-rw-r--r--games/skully_escape/resources/textures/background_armory.pngbin0 -> 252006 bytes
-rw-r--r--games/skully_escape/resources/textures/background_attic.pngbin0 -> 286704 bytes
-rw-r--r--games/skully_escape/resources/textures/background_bathroom.pngbin0 -> 254709 bytes
-rw-r--r--games/skully_escape/resources/textures/background_kitchen.pngbin0 -> 310161 bytes
-rw-r--r--games/skully_escape/resources/textures/background_livingroom.pngbin0 -> 319096 bytes
-rw-r--r--games/skully_escape/resources/textures/doors.pngbin0 -> 82485 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_arc.pngbin0 -> 49342 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_blazon01.pngbin0 -> 47467 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_blazon02.pngbin0 -> 47085 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_blazon03.pngbin0 -> 52593 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_candle.pngbin0 -> 70445 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_chair_left.pngbin0 -> 42529 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_chair_right.pngbin0 -> 46303 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_closet.pngbin0 -> 93494 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_lamp_left.pngbin0 -> 80413 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_lamp_right.pngbin0 -> 148299 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_mirror.pngbin0 -> 67383 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_phone.pngbin0 -> 51545 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_picture.pngbin0 -> 96506 bytes
-rw-r--r--games/skully_escape/resources/textures/monster_window.pngbin0 -> 175595 bytes
-rw-r--r--games/skully_escape/resources/textures/skully.pngbin0 -> 138765 bytes
-rw-r--r--games/skully_escape/resources/textures/skully_icon.pngbin0 -> 3165 bytes
-rw-r--r--games/skully_escape/resources/textures/skully_logo.pngbin0 -> 19137 bytes
-rw-r--r--games/skully_escape/resources/textures/title.pngbin0 -> 120338 bytes
-rw-r--r--games/skully_escape/screens/screen_aisle01.c409
-rw-r--r--games/skully_escape/screens/screen_aisle02.c444
-rw-r--r--games/skully_escape/screens/screen_armory.c404
-rw-r--r--games/skully_escape/screens/screen_attic.c332
-rw-r--r--games/skully_escape/screens/screen_bathroom.c383
-rw-r--r--games/skully_escape/screens/screen_ending.c90
-rw-r--r--games/skully_escape/screens/screen_kitchen.c403
-rw-r--r--games/skully_escape/screens/screen_livingroom.c403
-rw-r--r--games/skully_escape/screens/screen_logo.c108
-rw-r--r--games/skully_escape/screens/screen_logo_raylib.c201
-rw-r--r--games/skully_escape/screens/screen_title.c92
-rw-r--r--games/skully_escape/screens/screens.h164
-rw-r--r--games/skully_escape/skully_escape.c403
-rw-r--r--games/snake.c293
-rw-r--r--games/space_invaders.c406
-rw-r--r--games/tetris.c836
107 files changed, 12517 insertions, 299 deletions
diff --git a/games/arkanoid.c b/games/arkanoid.c
new file mode 100644
index 00000000..f10f9383
--- /dev/null
+++ b/games/arkanoid.c
@@ -0,0 +1,349 @@
+/*******************************************************************************************
+*
+* raylib - sample game: arkanoid
+*
+* Sample game Marc Palau and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+
+#define PLAYER_MAX_LIFE 5
+#define LINES_OF_BRICKS 5
+#define BRICKS_PER_LINE 20
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum GameScreen { LOGO, TITLE, GAMEPLAY, ENDING } GameScreen;
+
+typedef struct Player {
+ Vector2 position;
+ Vector2 size;
+ int life;
+} Player;
+
+typedef struct Ball {
+ Vector2 position;
+ Vector2 speed;
+ int radius;
+ bool active;
+} Ball;
+
+typedef struct Brick {
+ Vector2 position;
+ bool active;
+} Brick;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+
+static Player player;
+static Ball ball;
+static Brick brick[LINES_OF_BRICKS][BRICKS_PER_LINE];
+static Vector2 brickSize;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+// Additional module functions
+static void UpdateBall(void);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: arkanoid");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ brickSize = (Vector2){ GetScreenWidth()/BRICKS_PER_LINE, 40 };
+
+ // Initialize player
+ player.position = (Vector2){ screenWidth/2, screenHeight*7/8 };
+ player.size = (Vector2){ screenWidth/10, 20 };
+ player.life = PLAYER_MAX_LIFE;
+
+ // Initialize ball
+ ball.position = (Vector2){ screenWidth/2, screenHeight*7/8 - 30 };
+ ball.speed = (Vector2){ 0, 0 };
+ ball.radius = 7;
+ ball.active = false;
+
+ // Initialize bricks
+ int initialDownPosition = 50;
+
+ for (int i = 0; i < LINES_OF_BRICKS; i++)
+ {
+ for (int j = 0; j < BRICKS_PER_LINE; j++)
+ {
+ brick[i][j].position = (Vector2){ j*brickSize.x + brickSize.x/2, i*brickSize.y + initialDownPosition };
+ brick[i][j].active = true;
+ }
+ }
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ // Player movement
+ if (IsKeyDown(KEY_LEFT)) player.position.x -= 5;
+ if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2;
+ if (IsKeyDown(KEY_RIGHT)) player.position.x += 5;
+ if ((player.position.x + player.size.x/2) >= screenWidth) player.position.x = screenWidth - player.size.x/2;
+
+ // Launch ball
+ if (!ball.active)
+ {
+ if (IsKeyPressed(KEY_SPACE))
+ {
+ ball.active = true;
+ ball.speed = (Vector2){ 0, -5 };
+ }
+ }
+
+ UpdateBall();
+
+ // Game over logic
+ if (player.life <= 0) gameOver = true;
+ else
+ {
+ gameOver = true;
+
+ for (int i = 0; i < LINES_OF_BRICKS; i++)
+ {
+ for (int j = 0; j < BRICKS_PER_LINE; j++)
+ {
+ if (brick[i][j].active) gameOver = false;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+
+
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw player bar
+ DrawRectangle(player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y, BLACK);
+
+ // Draw player lives
+ for (int i = 0; i < player.life; i++) DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, LIGHTGRAY);
+
+ // Draw ball
+ DrawCircleV(ball.position, ball.radius, MAROON);
+
+ // Draw bricks
+ for (int i = 0; i < LINES_OF_BRICKS; i++)
+ {
+ for (int j = 0; j < BRICKS_PER_LINE; j++)
+ {
+ if (brick[i][j].active)
+ {
+ if ((i + j) % 2 == 0) DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, GRAY);
+ else DrawRectangle(brick[i][j].position.x - brickSize.x/2, brick[i][j].position.y - brickSize.y/2, brickSize.x, brickSize.y, DARKGRAY);
+ }
+ }
+ }
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+}
+
+//--------------------------------------------------------------------------------------
+// Additional module functions
+//--------------------------------------------------------------------------------------
+static void UpdateBall()
+{
+ // Update position
+ if (ball.active)
+ {
+ ball.position.x += ball.speed.x;
+ ball.position.y += ball.speed.y;
+ }
+ else
+ {
+ ball.position = (Vector2){ player.position.x, screenHeight*7/8 - 30 };
+ }
+
+ // Bounce in x
+ if (((ball.position.x + ball.radius) >= screenWidth) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1;
+
+ // Bounce in y
+ if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1;
+
+ // Ball reaches bottom of the screen
+ if ((ball.position.y + ball.radius) >= screenHeight)
+ {
+ ball.speed = (Vector2){ 0, 0 };
+ ball.active = false;
+
+ player.life--;
+ }
+
+ // Collision logic: ball vs player
+ if (CheckCollisionCircleRec(ball.position, ball.radius,
+ (Rectangle){ player.position.x - player.size.x/2, player.position.y - player.size.y/2, player.size.x, player.size.y}))
+ {
+ if (ball.speed.y > 0)
+ {
+ ball.speed.y *= -1;
+ ball.speed.x = (ball.position.x - player.position.x)/(player.size.x/2)*5;
+ }
+ }
+
+ // Collision logic: ball vs bricks
+ for (int i = 0; i < LINES_OF_BRICKS; i++)
+ {
+ for (int j = 0; j < BRICKS_PER_LINE; j++)
+ {
+ if (brick[i][j].active)
+ {
+ // Hit below
+ if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brickSize.y/2)) &&
+ ((ball.position.y - ball.radius) > (brick[i][j].position.y + brickSize.y/2 + ball.speed.y)) &&
+ ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y < 0))
+ {
+ brick[i][j].active = false;
+ ball.speed.y *= -1;
+ }
+ // Hit above
+ else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brickSize.y/2)) &&
+ ((ball.position.y + ball.radius) < (brick[i][j].position.y - brickSize.y/2 + ball.speed.y)) &&
+ ((fabs(ball.position.x - brick[i][j].position.x)) < (brickSize.x/2 + ball.radius*2/3)) && (ball.speed.y > 0))
+ {
+ brick[i][j].active = false;
+ ball.speed.y *= -1;
+ }
+ // Hit left
+ else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brickSize.x/2)) &&
+ ((ball.position.x + ball.radius) < (brick[i][j].position.x - brickSize.x/2 + ball.speed.x)) &&
+ ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x > 0))
+ {
+ brick[i][j].active = false;
+ ball.speed.x *= -1;
+ }
+ // Hit right
+ else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brickSize.x/2)) &&
+ ((ball.position.x - ball.radius) > (brick[i][j].position.x + brickSize.x/2 + ball.speed.x)) &&
+ ((fabs(ball.position.y - brick[i][j].position.y)) < (brickSize.y/2 + ball.radius*2/3)) && (ball.speed.x < 0))
+ {
+ brick[i][j].active = false;
+ ball.speed.x *= -1;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/games/asteroids.c b/games/asteroids.c
new file mode 100644
index 00000000..53ebbd8e
--- /dev/null
+++ b/games/asteroids.c
@@ -0,0 +1,579 @@
+/*******************************************************************************************
+*
+* raylib - sample game: asteroids
+*
+* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define PLAYER_BASE_SIZE 20.0f
+#define PLAYER_SPEED 6.0f
+#define PLAYER_MAX_SHOOTS 10
+
+#define METEORS_SPEED 2
+#define MAX_BIG_METEORS 4
+#define MAX_MEDIUM_METEORS 8
+#define MAX_SMALL_METEORS 16
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+typedef struct Player {
+ Vector2 position;
+ Vector2 speed;
+ float acceleration;
+ float rotation;
+ Vector3 collider;
+ Color color;
+} Player;
+
+typedef struct Shoot {
+ Vector2 position;
+ Vector2 speed;
+ float radius;
+ float rotation;
+ int lifeSpawn;
+ bool active;
+ Color color;
+} Shoot;
+
+typedef struct Meteor {
+ Vector2 position;
+ Vector2 speed;
+ float radius;
+ bool active;
+ Color color;
+} Meteor;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+static bool victory;
+
+// NOTE: Defined triangle is isosceles with common angles of 70 degrees.
+static float shipHeight;
+
+static Player player;
+static Shoot shoot[PLAYER_MAX_SHOOTS];
+static Meteor bigMeteor[MAX_BIG_METEORS];
+static Meteor mediumMeteor[MAX_MEDIUM_METEORS];
+static Meteor smallMeteor[MAX_SMALL_METEORS];
+
+static int countMediumMeteors;
+static int countSmallMeteors;
+static int meteorsDestroyed;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+static void InitShoot(Shoot shoot);
+static void DrawSpaceship(Vector2 position, float rotation, Color color);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: asteroids");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ int posx, posy;
+ int velx, vely;
+ bool correctRange = false;
+ victory = false;
+ pause = false;
+
+ shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD);
+
+ // Initialization player
+ player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2};
+ player.speed = (Vector2){0, 0};
+ player.acceleration = 0;
+ player.rotation = 0;
+ player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12};
+ player.color = LIGHTGRAY;
+
+ meteorsDestroyed = 0;
+
+ // Initialization shoot
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ shoot[i].position = (Vector2){0, 0};
+ shoot[i].speed = (Vector2){0, 0};
+ shoot[i].radius = 2;
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ shoot[i].color = WHITE;
+ }
+
+ for (int i = 0; i < MAX_BIG_METEORS; i++)
+ {
+ posx = GetRandomValue(0, screenWidth);
+
+ while(!correctRange)
+ {
+ if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth);
+ else correctRange = true;
+ }
+
+ correctRange = false;
+
+ posy = GetRandomValue(0, screenHeight);
+
+ while(!correctRange)
+ {
+ if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight);
+ else correctRange = true;
+ }
+
+ bigMeteor[i].position = (Vector2){posx, posy};
+
+ correctRange = false;
+ velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+
+ while(!correctRange)
+ {
+ if (velx == 0 && vely == 0)
+ {
+ velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ }
+ else correctRange = true;
+ }
+
+ bigMeteor[i].speed = (Vector2){velx, vely};
+ bigMeteor[i].radius = 40;
+ bigMeteor[i].active = true;
+ bigMeteor[i].color = BLUE;
+ }
+
+ for (int i = 0; i < MAX_MEDIUM_METEORS; i++)
+ {
+ mediumMeteor[i].position = (Vector2){-100, -100};
+ mediumMeteor[i].speed = (Vector2){0,0};
+ mediumMeteor[i].radius = 20;
+ mediumMeteor[i].active = false;
+ mediumMeteor[i].color = BLUE;
+ }
+
+ for (int i = 0; i < MAX_SMALL_METEORS; i++)
+ {
+ smallMeteor[i].position = (Vector2){-100, -100};
+ smallMeteor[i].speed = (Vector2){0,0};
+ smallMeteor[i].radius = 10;
+ smallMeteor[i].active = false;
+ smallMeteor[i].color = BLUE;
+ }
+
+ countMediumMeteors = 0;
+ countSmallMeteors = 0;
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ // Player logic
+
+ // Rotation
+ if (IsKeyDown(KEY_LEFT)) player.rotation -= 5;
+ if (IsKeyDown(KEY_RIGHT)) player.rotation += 5;
+
+ // Speed
+ player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED;
+ player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED;
+
+ // Controller
+ if (IsKeyDown(KEY_UP))
+ {
+ if (player.acceleration < 1) player.acceleration += 0.04f;
+ }
+ else
+ {
+ if (player.acceleration > 0) player.acceleration -= 0.02f;
+ else if (player.acceleration < 0) player.acceleration = 0;
+ }
+ if (IsKeyDown(KEY_DOWN))
+ {
+ if (player.acceleration > 0) player.acceleration -= 0.04f;
+ else if (player.acceleration < 0) player.acceleration = 0;
+ }
+
+ // Movement
+ player.position.x += (player.speed.x*player.acceleration);
+ player.position.y -= (player.speed.y*player.acceleration);
+
+ // Wall behaviour for player
+ if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight);
+ else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight;
+ if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight);
+ else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight;
+
+ // Activation of shoot
+ if (IsKeyPressed(KEY_SPACE))
+ {
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (!shoot[i].active)
+ {
+ shoot[i].position = (Vector2){ player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight) };
+ shoot[i].active = true;
+ shoot[i].speed.x = 1.5*sin(player.rotation*DEG2RAD)*PLAYER_SPEED;
+ shoot[i].speed.y = 1.5*cos(player.rotation*DEG2RAD)*PLAYER_SPEED;
+ shoot[i].rotation = player.rotation;
+ break;
+ }
+ }
+ }
+
+ // Shoot life timer
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (shoot[i].active) shoot[i].lifeSpawn++;
+ }
+
+ // Shot logic
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (shoot[i].active)
+ {
+ // Movement
+ shoot[i].position.x += shoot[i].speed.x;
+ shoot[i].position.y -= shoot[i].speed.y;
+
+ // Wall behaviour for shoot
+ if (shoot[i].position.x > screenWidth + shoot[i].radius)
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ }
+ else if (shoot[i].position.x < 0 - shoot[i].radius)
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ }
+ if (shoot[i].position.y > screenHeight + shoot[i].radius)
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ }
+ else if (shoot[i].position.y < 0 - shoot[i].radius)
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ }
+
+ // Life of shoot
+ if (shoot[i].lifeSpawn >= 60)
+ {
+ shoot[i].position = (Vector2){0, 0};
+ shoot[i].speed = (Vector2){0, 0};
+ shoot[i].lifeSpawn = 0;
+ shoot[i].active = false;
+ }
+ }
+ }
+
+ // Collision Player to meteors
+ player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12};
+
+ for (int a = 0; a < MAX_BIG_METEORS; a++)
+ {
+ if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, bigMeteor[a].position, bigMeteor[a].radius) && bigMeteor[a].active) gameOver = true;
+ }
+
+ for (int a = 0; a < MAX_MEDIUM_METEORS; a++)
+ {
+ if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true;
+ }
+
+ for (int a = 0; a < MAX_SMALL_METEORS; a++)
+ {
+ if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true;
+ }
+
+ // Meteor logic
+ for (int i = 0; i < MAX_BIG_METEORS; i++)
+ {
+ if (bigMeteor[i].active)
+ {
+ // movement
+ bigMeteor[i].position.x += bigMeteor[i].speed.x;
+ bigMeteor[i].position.y += bigMeteor[i].speed.y;
+
+ // wall behaviour
+ if (bigMeteor[i].position.x > screenWidth + bigMeteor[i].radius) bigMeteor[i].position.x = -(bigMeteor[i].radius);
+ else if (bigMeteor[i].position.x < 0 - bigMeteor[i].radius) bigMeteor[i].position.x = screenWidth + bigMeteor[i].radius;
+ if (bigMeteor[i].position.y > screenHeight + bigMeteor[i].radius) bigMeteor[i].position.y = -(bigMeteor[i].radius);
+ else if (bigMeteor[i].position.y < 0 - bigMeteor[i].radius) bigMeteor[i].position.y = screenHeight + bigMeteor[i].radius;
+ }
+ }
+
+ for (int i = 0; i < MAX_MEDIUM_METEORS; i++)
+ {
+ if (mediumMeteor[i].active)
+ {
+ // movement
+ mediumMeteor[i].position.x += mediumMeteor[i].speed.x;
+ mediumMeteor[i].position.y += mediumMeteor[i].speed.y;
+
+ // wall behaviour
+ if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius);
+ else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius;
+ if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius);
+ else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius;
+ }
+ }
+
+ for (int i = 0; i < MAX_SMALL_METEORS; i++)
+ {
+ if (smallMeteor[i].active)
+ {
+ // movement
+ smallMeteor[i].position.x += smallMeteor[i].speed.x;
+ smallMeteor[i].position.y += smallMeteor[i].speed.y;
+
+ // wall behaviour
+ if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius);
+ else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius;
+ if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius);
+ else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius;
+ }
+ }
+
+ // Collision behaviour
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if ((shoot[i].active))
+ {
+ for (int a = 0; a < MAX_BIG_METEORS; a++)
+ {
+ if (bigMeteor[a].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, bigMeteor[a].position, bigMeteor[a].radius))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ bigMeteor[a].active = false;
+ meteorsDestroyed++;
+ for (int j = 0; j < 2; j ++)
+ {
+ if (countMediumMeteors%2 == 0)
+ {
+ mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y};
+ mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1};
+ }
+ else
+ {
+ mediumMeteor[countMediumMeteors].position = (Vector2){bigMeteor[a].position.x, bigMeteor[a].position.y};
+ mediumMeteor[countMediumMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED};
+ }
+
+ mediumMeteor[countMediumMeteors].active = true;
+ countMediumMeteors ++;
+ }
+ //bigMeteor[a].position = (Vector2){-100, -100};
+ bigMeteor[a].color = RED;
+ a = MAX_BIG_METEORS;
+ }
+ }
+ }
+ if ((shoot[i].active))
+ {
+ for (int b = 0; b < MAX_MEDIUM_METEORS; b++)
+ {
+ if (mediumMeteor[b].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, mediumMeteor[b].position, mediumMeteor[b].radius))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ mediumMeteor[b].active = false;
+ meteorsDestroyed++;
+ for (int j = 0; j < 2; j ++)
+ {
+ if (countSmallMeteors%2 == 0)
+ {
+ smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y};
+ smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED*-1};
+ }
+ else
+ {
+ smallMeteor[countSmallMeteors].position = (Vector2){mediumMeteor[b].position.x, mediumMeteor[b].position.y};
+ smallMeteor[countSmallMeteors].speed = (Vector2){cos(shoot[i].rotation*DEG2RAD)*METEORS_SPEED, sin(shoot[i].rotation*DEG2RAD)*METEORS_SPEED};
+ }
+
+ smallMeteor[countSmallMeteors].active = true;
+ countSmallMeteors ++;
+ }
+ //mediumMeteor[b].position = (Vector2){-100, -100};
+ mediumMeteor[b].color = GREEN;
+ b = MAX_MEDIUM_METEORS;
+ }
+ }
+ }
+ if ((shoot[i].active))
+ {
+ for (int c = 0; c < MAX_SMALL_METEORS; c++)
+ {
+ if (smallMeteor[c].active && CheckCollisionCircles(shoot[i].position, shoot[i].radius, smallMeteor[c].position, smallMeteor[c].radius))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ smallMeteor[c].active = false;
+ meteorsDestroyed++;
+ smallMeteor[c].color = YELLOW;
+ // smallMeteor[c].position = (Vector2){-100, -100};
+ c = MAX_SMALL_METEORS;
+ }
+ }
+ }
+ }
+ }
+
+ if (meteorsDestroyed == MAX_BIG_METEORS + MAX_MEDIUM_METEORS + MAX_SMALL_METEORS) victory = true;
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw spaceship
+ Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) };
+ Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) };
+ Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) };
+ DrawTriangle(v1, v2, v3, MAROON);
+
+ // Draw meteors
+ for (int i = 0; i < MAX_BIG_METEORS; i++)
+ {
+ if (bigMeteor[i].active) DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, DARKGRAY);
+ else DrawCircleV(bigMeteor[i].position, bigMeteor[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ for (int i = 0; i < MAX_MEDIUM_METEORS; i++)
+ {
+ if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY);
+ else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ for (int i = 0; i < MAX_SMALL_METEORS; i++)
+ {
+ if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, GRAY);
+ else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ // Draw shoot
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (shoot[i].active) DrawCircleV(shoot[i].position, shoot[i].radius, BLACK);
+ }
+
+ if (victory) DrawText("VICTORY", screenWidth/2 - MeasureText("VICTORY", 20)/2, screenHeight/2, 20, LIGHTGRAY);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/asteroids_survival.c b/games/asteroids_survival.c
new file mode 100644
index 00000000..aa21112d
--- /dev/null
+++ b/games/asteroids_survival.c
@@ -0,0 +1,383 @@
+/*******************************************************************************************
+*
+* raylib - sample game: asteroids survival
+*
+* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define PLAYER_BASE_SIZE 20.0f
+#define PLAYER_SPEED 6.0f
+#define PLAYER_MAX_SHOOTS 10
+
+#define METEORS_SPEED 2
+#define MAX_MEDIUM_METEORS 8
+#define MAX_SMALL_METEORS 16
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+typedef struct Player {
+ Vector2 position;
+ Vector2 speed;
+ float acceleration;
+ float rotation;
+ Vector3 collider;
+ Color color;
+} Player;
+
+typedef struct Meteor {
+ Vector2 position;
+ Vector2 speed;
+ float radius;
+ bool active;
+ Color color;
+} Meteor;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+
+// NOTE: Defined triangle is isosceles with common angles of 70 degrees.
+static float shipHeight;
+
+static Player player;
+static Meteor mediumMeteor[MAX_MEDIUM_METEORS];
+static Meteor smallMeteor[MAX_SMALL_METEORS];
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: asteroids survival");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ int posx, posy;
+ int velx, vely;
+ bool correctRange = false;
+
+ pause = false;
+
+ framesCounter = 0;
+
+ shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD);
+
+ // Initialization player
+ player.position = (Vector2){screenWidth/2, screenHeight/2 - shipHeight/2};
+ player.speed = (Vector2){0, 0};
+ player.acceleration = 0;
+ player.rotation = 0;
+ player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12};
+ player.color = LIGHTGRAY;
+
+ for (int i = 0; i < MAX_MEDIUM_METEORS; i++)
+ {
+ posx = GetRandomValue(0, screenWidth);
+
+ while(!correctRange)
+ {
+ if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth);
+ else correctRange = true;
+ }
+
+ correctRange = false;
+
+ posy = GetRandomValue(0, screenHeight);
+
+ while(!correctRange)
+ {
+ if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight);
+ else correctRange = true;
+ }
+
+ correctRange = false;
+ velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+
+ while(!correctRange)
+ {
+ if (velx == 0 && vely == 0)
+ {
+ velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ }
+ else correctRange = true;
+ }
+ mediumMeteor[i].position = (Vector2){posx, posy};
+ mediumMeteor[i].speed = (Vector2){velx, vely};
+ mediumMeteor[i].radius = 20;
+ mediumMeteor[i].active = true;
+ mediumMeteor[i].color = GREEN;
+ }
+
+ for (int i = 0; i < MAX_SMALL_METEORS; i++)
+ {
+ posx = GetRandomValue(0, screenWidth);
+
+ while(!correctRange)
+ {
+ if (posx > screenWidth/2 - 150 && posx < screenWidth/2 + 150) posx = GetRandomValue(0, screenWidth);
+ else correctRange = true;
+ }
+
+ correctRange = false;
+
+ posy = GetRandomValue(0, screenHeight);
+
+ while(!correctRange)
+ {
+ if (posy > screenHeight/2 - 150 && posy < screenHeight/2 + 150) posy = GetRandomValue(0, screenHeight);
+ else correctRange = true;
+ }
+
+ correctRange = false;
+ velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+
+ while(!correctRange)
+ {
+ if (velx == 0 && vely == 0)
+ {
+ velx = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ vely = GetRandomValue(-METEORS_SPEED, METEORS_SPEED);
+ }
+ else correctRange = true;
+ }
+ smallMeteor[i].position = (Vector2){posx, posy};
+ smallMeteor[i].speed = (Vector2){velx, vely};
+ smallMeteor[i].radius = 10;
+ smallMeteor[i].active = true;
+ smallMeteor[i].color = YELLOW;
+ }
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ framesCounter++;
+
+ // Player logic
+
+ // Rotation
+ if (IsKeyDown(KEY_LEFT)) player.rotation -= 5;
+ if (IsKeyDown(KEY_RIGHT)) player.rotation += 5;
+
+ // Speed
+ player.speed.x = sin(player.rotation*DEG2RAD)*PLAYER_SPEED;
+ player.speed.y = cos(player.rotation*DEG2RAD)*PLAYER_SPEED;
+
+ // Controller
+ if (IsKeyDown(KEY_UP))
+ {
+ if (player.acceleration < 1) player.acceleration += 0.04f;
+ }
+ else
+ {
+ if (player.acceleration > 0) player.acceleration -= 0.02f;
+ else if (player.acceleration < 0) player.acceleration = 0;
+ }
+ if (IsKeyDown(KEY_DOWN))
+ {
+ if (player.acceleration > 0) player.acceleration -= 0.04f;
+ else if (player.acceleration < 0) player.acceleration = 0;
+ }
+
+ // Movement
+ player.position.x += (player.speed.x*player.acceleration);
+ player.position.y -= (player.speed.y*player.acceleration);
+
+ // Wall behaviour for player
+ if (player.position.x > screenWidth + shipHeight) player.position.x = -(shipHeight);
+ else if (player.position.x < -(shipHeight)) player.position.x = screenWidth + shipHeight;
+ if (player.position.y > (screenHeight + shipHeight)) player.position.y = -(shipHeight);
+ else if (player.position.y < -(shipHeight)) player.position.y = screenHeight + shipHeight;
+
+ // Collision Player to meteors
+ player.collider = (Vector3){player.position.x + sin(player.rotation*DEG2RAD)*(shipHeight/2.5f), player.position.y - cos(player.rotation*DEG2RAD)*(shipHeight/2.5f), 12};
+
+ for (int a = 0; a < MAX_MEDIUM_METEORS; a++)
+ {
+ if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, mediumMeteor[a].position, mediumMeteor[a].radius) && mediumMeteor[a].active) gameOver = true;
+ }
+
+ for (int a = 0; a < MAX_SMALL_METEORS; a++)
+ {
+ if (CheckCollisionCircles((Vector2){player.collider.x, player.collider.y}, player.collider.z, smallMeteor[a].position, smallMeteor[a].radius) && smallMeteor[a].active) gameOver = true;
+ }
+
+ // Meteor logic
+
+ for (int i = 0; i < MAX_MEDIUM_METEORS; i++)
+ {
+ if (mediumMeteor[i].active)
+ {
+ // movement
+ mediumMeteor[i].position.x += mediumMeteor[i].speed.x;
+ mediumMeteor[i].position.y += mediumMeteor[i].speed.y;
+
+ // wall behaviour
+ if (mediumMeteor[i].position.x > screenWidth + mediumMeteor[i].radius) mediumMeteor[i].position.x = -(mediumMeteor[i].radius);
+ else if (mediumMeteor[i].position.x < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.x = screenWidth + mediumMeteor[i].radius;
+ if (mediumMeteor[i].position.y > screenHeight + mediumMeteor[i].radius) mediumMeteor[i].position.y = -(mediumMeteor[i].radius);
+ else if (mediumMeteor[i].position.y < 0 - mediumMeteor[i].radius) mediumMeteor[i].position.y = screenHeight + mediumMeteor[i].radius;
+ }
+ }
+
+ for (int i = 0; i < MAX_SMALL_METEORS; i++)
+ {
+ if (smallMeteor[i].active)
+ {
+ // movement
+ smallMeteor[i].position.x += smallMeteor[i].speed.x;
+ smallMeteor[i].position.y += smallMeteor[i].speed.y;
+
+ // wall behaviour
+ if (smallMeteor[i].position.x > screenWidth + smallMeteor[i].radius) smallMeteor[i].position.x = -(smallMeteor[i].radius);
+ else if (smallMeteor[i].position.x < 0 - smallMeteor[i].radius) smallMeteor[i].position.x = screenWidth + smallMeteor[i].radius;
+ if (smallMeteor[i].position.y > screenHeight + smallMeteor[i].radius) smallMeteor[i].position.y = -(smallMeteor[i].radius);
+ else if (smallMeteor[i].position.y < 0 - smallMeteor[i].radius) smallMeteor[i].position.y = screenHeight + smallMeteor[i].radius;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw spaceship
+ Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) };
+ Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) };
+ Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) };
+ DrawTriangle(v1, v2, v3, MAROON);
+
+ // Draw meteor
+ for (int i = 0;i < MAX_MEDIUM_METEORS; i++)
+ {
+ if (mediumMeteor[i].active) DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, GRAY);
+ else DrawCircleV(mediumMeteor[i].position, mediumMeteor[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ for (int i = 0;i < MAX_SMALL_METEORS; i++)
+ {
+ if (smallMeteor[i].active) DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, DARKGRAY);
+ else DrawCircleV(smallMeteor[i].position, smallMeteor[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ DrawText(FormatText("TIME: %.02f", (float)framesCounter/60), 10, 10, 20, BLACK);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/drturtle/04_drturtle_gui.c b/games/drturtle/04_drturtle_gui.c
index 0e648b5d..bbfd3492 100644
--- a/games/drturtle/04_drturtle_gui.c
+++ b/games/drturtle/04_drturtle_gui.c
@@ -338,7 +338,7 @@ int main()
DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE);
// Draw blinking text
- if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, GetFontBaseSize(font), 0, WHITE);
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 0, WHITE);
} break;
case GAMEPLAY:
@@ -388,8 +388,8 @@ int main()
DrawRectangle(20, 20, foodBar, 40, ORANGE);
DrawRectangleLines(20, 20, 400, 40, BLACK);
- DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, GetFontBaseSize(font), -2, ORANGE);
- DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, GetFontBaseSize(font), -2, ORANGE);
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE);
if (gameraMode)
{
@@ -403,15 +403,15 @@ int main()
// Draw a transparent black rectangle that covers all screen
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f));
- DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, GetFontBaseSize(font)*3, -2, MAROON);
+ DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON);
- DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, GetFontBaseSize(font), -2, GOLD);
- DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, GetFontBaseSize(font), -2, GOLD);
- DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, GetFontBaseSize(font), -2, ORANGE);
- DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, GetFontBaseSize(font), -2, ORANGE);
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE);
// Draw blinking text
- if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, GetFontBaseSize(font), -2, LIGHTGRAY);
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY);
} break;
default: break;
diff --git a/games/drturtle/05_drturtle_audio.c b/games/drturtle/05_drturtle_audio.c
index 7e8cac70..4a36d015 100644
--- a/games/drturtle/05_drturtle_audio.c
+++ b/games/drturtle/05_drturtle_audio.c
@@ -351,7 +351,7 @@ int main()
DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE);
// Draw blinking text
- if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, GetFontBaseSize(font), 0, WHITE);
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 0, WHITE);
} break;
case GAMEPLAY:
@@ -401,8 +401,8 @@ int main()
DrawRectangle(20, 20, foodBar, 40, ORANGE);
DrawRectangleLines(20, 20, 400, 40, BLACK);
- DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, GetFontBaseSize(font), -2, ORANGE);
- DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, GetFontBaseSize(font), -2, ORANGE);
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE);
if (gameraMode)
{
@@ -416,15 +416,15 @@ int main()
// Draw a transparent black rectangle that covers all screen
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f));
- DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, GetFontBaseSize(font)*3, -2, MAROON);
+ DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON);
- DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, GetFontBaseSize(font), -2, GOLD);
- DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, GetFontBaseSize(font), -2, GOLD);
- DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, GetFontBaseSize(font), -2, ORANGE);
- DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, GetFontBaseSize(font), -2, ORANGE);
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE);
// Draw blinking text
- if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, GetFontBaseSize(font), -2, LIGHTGRAY);
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY);
} break;
default: break;
diff --git a/games/drturtle/06_drturtle_final.c b/games/drturtle/06_drturtle_final.c
index a3475de4..128b23a5 100644
--- a/games/drturtle/06_drturtle_final.c
+++ b/games/drturtle/06_drturtle_final.c
@@ -21,6 +21,8 @@
#include "raylib.h"
+#include <math.h> // Used for sinf()
+
#define MAX_ENEMIES 10
typedef enum { TITLE, GAMEPLAY, ENDING } GameScreen;
@@ -128,7 +130,7 @@ int main()
framesCounter++;
// Sea color tint effect
- blue = 210 + 25 * sin(timeCounter);
+ blue = 210 + 25 * sinf(timeCounter);
timeCounter += 0.01;
// Game screens management
@@ -374,7 +376,7 @@ int main()
DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE);
// Draw blinking text
- if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, GetFontBaseSize(font), 0, WHITE);
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 0, WHITE);
} break;
case GAMEPLAY:
@@ -424,8 +426,8 @@ int main()
DrawRectangle(20, 20, foodBar, 40, ORANGE);
DrawRectangleLines(20, 20, 400, 40, BLACK);
- DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, GetFontBaseSize(font), -2, ORANGE);
- DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, GetFontBaseSize(font), -2, ORANGE);
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE);
if (gameraMode)
{
@@ -439,15 +441,15 @@ int main()
// Draw a transparent black rectangle that covers all screen
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f));
- DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, GetFontBaseSize(font)*3, -2, MAROON);
+ DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON);
- DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, GetFontBaseSize(font), -2, GOLD);
- DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, GetFontBaseSize(font), -2, GOLD);
- DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, GetFontBaseSize(font), -2, ORANGE);
- DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, GetFontBaseSize(font), -2, ORANGE);
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE);
// Draw blinking text
- if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, GetFontBaseSize(font), -2, LIGHTGRAY);
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY);
} break;
default: break;
diff --git a/games/drturtle/drturtle_final_web.c b/games/drturtle/drturtle_final_web.c
new file mode 100644
index 00000000..25f4074b
--- /dev/null
+++ b/games/drturtle/drturtle_final_web.c
@@ -0,0 +1,541 @@
+/*******************************************************************************************
+*
+* raylib game - Dr. Turtle & Mr. Gamera
+*
+* Welcome to raylib!
+*
+* To test examples, just press F6 and execute raylib_compile_execute script
+* Note that compiled executable is placed in the same folder as .c file
+*
+* You can find all basic examples on C:\raylib\raylib\examples folder or
+* raylib official webpage: www.raylib.com
+*
+* Enjoy using raylib. :)
+*
+* This game has been created using raylib 1.1 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include <math.h> // Used for sinf()
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+#define MAX_ENEMIES 10
+
+typedef enum { TITLE = 0, GAMEPLAY, ENDING } GameScreen;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+const int screenWidth = 1280;
+const int screenHeight = 720;
+
+Texture2D sky;
+Texture2D mountains;
+Texture2D sea;
+Texture2D title;
+Texture2D turtle;
+Texture2D gamera;
+Texture2D shark;
+Texture2D orca;
+Texture2D swhale;
+Texture2D fish;
+Texture2D gframe;
+
+SpriteFont font;
+
+Sound eat;
+Sound die;
+Sound growl;
+
+// Define scrolling variables
+int backScrolling = 0;
+int seaScrolling = 0;
+
+// Define current screen
+GameScreen currentScreen = 0;
+
+// Define player variables
+int playerRail = 1;
+Rectangle playerBounds;
+bool gameraMode = false;
+
+// Define enemies variables
+Rectangle enemyBounds[MAX_ENEMIES];
+int enemyRail[MAX_ENEMIES];
+int enemyType[MAX_ENEMIES];
+bool enemyActive[MAX_ENEMIES];
+float enemySpeed = 10;
+
+// Define additional game variables
+int score = 0;
+float distance = 0.0f;
+int hiscore = 0;
+float hidistance = 0.0f;
+int foodBar = 0;
+int framesCounter = 0;
+
+unsigned char blue = 200;
+float timeCounter = 0;
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+void UpdateDrawFrame(void); // Update and Draw one frame
+
+//----------------------------------------------------------------------------------
+// Main Enry Point
+//----------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+
+ // Init window
+ InitWindow(screenWidth, screenHeight, "Dr. Turtle & Mr. GAMERA");
+
+ // Initialize audio device
+ InitAudioDevice();
+
+ // Load game resources: textures
+ sky = LoadTexture("resources/sky.png");
+ mountains = LoadTexture("resources/mountains.png");
+ sea = LoadTexture("resources/sea.png");
+ title = LoadTexture("resources/title.png");
+ turtle = LoadTexture("resources/turtle.png");
+ gamera = LoadTexture("resources/gamera.png");
+ shark = LoadTexture("resources/shark.png");
+ orca = LoadTexture("resources/orca.png");
+ swhale = LoadTexture("resources/swhale.png");
+ fish = LoadTexture("resources/fish.png");
+ gframe = LoadTexture("resources/gframe.png");
+
+ // Load game resources: fonts
+ font = LoadSpriteFont("resources/komika.png");
+
+ // Load game resources: sounds
+ eat = LoadSound("resources/eat.wav");
+ die = LoadSound("resources/die.wav");
+ growl = LoadSound("resources/gamera.wav");
+
+ // Start playing streaming music
+ PlayMusicStream("resources/speeding.ogg");
+
+ playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 };
+
+ // Init enemies variables
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ // Define enemy type (all same probability)
+ //enemyType[i] = GetRandomValue(0, 3);
+
+ // Probability system for enemies type
+ int enemyProb = GetRandomValue(0, 100);
+
+ if (enemyProb < 30) enemyType[i] = 0;
+ else if (enemyProb < 60) enemyType[i] = 1;
+ else if (enemyProb < 90) enemyType[i] = 2;
+ else enemyType[i] = 3;
+
+ // define enemy rail
+ enemyRail[i] = GetRandomValue(0, 4);
+
+ // Make sure not two consecutive enemies in the same row
+ if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
+
+ enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
+ enemyActive[i] = false;
+ }
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ UpdateDrawFrame();
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+
+ // Unload textures
+ UnloadTexture(sky);
+ UnloadTexture(mountains);
+ UnloadTexture(sea);
+ UnloadTexture(gframe);
+ UnloadTexture(title);
+ UnloadTexture(turtle);
+ UnloadTexture(shark);
+ UnloadTexture(orca);
+ UnloadTexture(swhale);
+ UnloadTexture(fish);
+ UnloadTexture(gamera);
+
+ // Unload font texture
+ UnloadSpriteFont(font);
+
+ // Unload sounds
+ UnloadSound(eat);
+ UnloadSound(die);
+ UnloadSound(growl);
+
+ StopMusicStream(); // Stop music
+ CloseAudioDevice(); // Close audio device
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+void UpdateDrawFrame(void)
+{
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateMusicStream();
+
+ framesCounter++;
+
+ // Sea color tint effect
+ blue = 210 + 25 * sinf(timeCounter);
+ timeCounter += 0.01;
+
+ // Game screens management
+ switch (currentScreen)
+ {
+ case TITLE:
+ {
+ // Sea scrolling
+ seaScrolling -= 2;
+ if (seaScrolling <= -screenWidth) seaScrolling = 0;
+
+ // Press enter to change to gameplay screen
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ currentScreen = GAMEPLAY;
+ framesCounter = 0;
+ }
+
+ } break;
+ case GAMEPLAY:
+ {
+ // Background scrolling logic
+ backScrolling--;
+ if (backScrolling <= -screenWidth) backScrolling = 0;
+
+ // Sea scrolling logic
+ seaScrolling -= (enemySpeed - 2);
+ if (seaScrolling <= -screenWidth) seaScrolling = 0;
+
+ // Player movement logic
+ if (IsKeyPressed(KEY_DOWN)) playerRail++;
+ else if (IsKeyPressed(KEY_UP)) playerRail--;
+
+ // Check player not out of rails
+ if (playerRail > 4) playerRail = 4;
+ else if (playerRail < 0) playerRail = 0;
+
+ // Update player bounds
+ playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 };
+
+ // Enemies activation logic (every 40 frames)
+ if (framesCounter > 40)
+ {
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ if (enemyActive[i] == false)
+ {
+ enemyActive[i] = true;
+ i = MAX_ENEMIES;
+ }
+ }
+
+ framesCounter = 0;
+ }
+
+ // Enemies logic
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ if (enemyActive[i])
+ {
+ enemyBounds[i].x -= enemySpeed;
+ }
+
+ // Check enemies out of screen
+ if (enemyBounds[i].x <= 0 - 128)
+ {
+ enemyActive[i] = false;
+ enemyType[i] = GetRandomValue(0, 3);
+ enemyRail[i] = GetRandomValue(0, 4);
+
+ // Make sure not two consecutive enemies in the same row
+ if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
+
+ enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
+ }
+ }
+
+ if (!gameraMode) enemySpeed += 0.005;
+
+ // Check collision player vs enemies
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ if (enemyActive[i])
+ {
+ if (CheckCollisionRecs(playerBounds, enemyBounds[i]))
+ {
+ if (enemyType[i] < 3) // Bad enemies
+ {
+ if (gameraMode)
+ {
+ if (enemyType[i] == 0) score += 50;
+ else if (enemyType[i] == 1) score += 150;
+ else if (enemyType[i] == 2) score += 300;
+
+ foodBar += 15;
+
+ enemyActive[i] = false;
+
+ // After enemy deactivation, reset enemy parameters to be reused
+ enemyType[i] = GetRandomValue(0, 3);
+ enemyRail[i] = GetRandomValue(0, 4);
+
+ // Make sure not two consecutive enemies in the same row
+ if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
+
+ enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
+
+ PlaySound(eat);
+ }
+ else
+ {
+ // Player die logic
+ PlaySound(die);
+
+ currentScreen = ENDING;
+ framesCounter = 0;
+
+ // Save hiscore and hidistance for next game
+ if (score > hiscore) hiscore = score;
+ if (distance > hidistance) hidistance = distance;
+ }
+ }
+ else // Sweet fish
+ {
+ enemyActive[i] = false;
+ enemyType[i] = GetRandomValue(0, 3);
+ enemyRail[i] = GetRandomValue(0, 4);
+
+ // Make sure not two consecutive enemies in the same row
+ if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
+
+ enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
+
+ if (!gameraMode) foodBar += 80;
+ else foodBar += 25;
+
+ score += 10;
+
+ if (foodBar == 400)
+ {
+ gameraMode = true;
+
+ PlaySound(growl);
+ }
+
+ PlaySound(eat);
+ }
+ }
+ }
+ }
+
+ // Gamera mode logic
+ if (gameraMode)
+ {
+ foodBar--;
+
+ if (foodBar <= 0)
+ {
+ gameraMode = false;
+ enemySpeed -= 2;
+ if (enemySpeed < 10) enemySpeed = 10;
+ }
+ }
+
+ // Update distance counter
+ distance += 0.5f;
+
+ } break;
+ case ENDING:
+ {
+ // Press enter to play again
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ currentScreen = GAMEPLAY;
+
+ // Reset player
+ playerRail = 1;
+ playerBounds = (Rectangle){ 30 + 14, playerRail*120 + 90 + 14, 100, 100 };
+ gameraMode = false;
+
+ // Reset enemies data
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ int enemyProb = GetRandomValue(0, 100);
+
+ if (enemyProb < 30) enemyType[i] = 0;
+ else if (enemyProb < 60) enemyType[i] = 1;
+ else if (enemyProb < 90) enemyType[i] = 2;
+ else enemyType[i] = 3;
+
+ //enemyType[i] = GetRandomValue(0, 3);
+ enemyRail[i] = GetRandomValue(0, 4);
+
+ // Make sure not two consecutive enemies in the same row
+ if (i > 0) while (enemyRail[i] == enemyRail[i - 1]) enemyRail[i] = GetRandomValue(0, 4);
+
+ enemyBounds[i] = (Rectangle){ screenWidth + 14, 120*enemyRail[i] + 90 + 14, 100, 100 };
+ enemyActive[i] = false;
+ }
+
+ enemySpeed = 10;
+
+ // Reset game variables
+ score = 0;
+ distance = 0.0;
+ foodBar = 0;
+ framesCounter = 0;
+ }
+
+ } break;
+ default: break;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ // Draw background (common to all screens)
+ DrawTexture(sky, 0, 0, WHITE);
+
+ DrawTexture(mountains, backScrolling, 0, WHITE);
+ DrawTexture(mountains, screenWidth + backScrolling, 0, WHITE);
+
+ if (!gameraMode)
+ {
+ DrawTexture(sea, seaScrolling, 0, (Color){ 16, 189, blue, 255});
+ DrawTexture(sea, screenWidth + seaScrolling, 0, (Color){ 16, 189, blue, 255});
+ }
+ else
+ {
+ DrawTexture(sea, seaScrolling, 0, (Color){ 255, 113, 66, 255});
+ DrawTexture(sea, screenWidth + seaScrolling, 0, (Color){ 255, 113, 66, 255});
+ }
+
+ switch (currentScreen)
+ {
+ case TITLE:
+ {
+ // Draw title
+ DrawTexture(title, screenWidth/2 - title.width/2, screenHeight/2 - title.height/2 - 80, WHITE);
+
+ // Draw blinking text
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER", (Vector2){ screenWidth/2 - 150, 480 }, font.size, 1, WHITE);
+
+ } break;
+ case GAMEPLAY:
+ {
+ // Draw water lines
+ for (int i = 0; i < 5; i++) DrawRectangle(0, i*120 + 120, screenWidth, 110, Fade(SKYBLUE, 0.1f));
+
+ // Draw player
+ if (!gameraMode) DrawTexture(turtle, playerBounds.x - 14, playerBounds.y - 14, WHITE);
+ else DrawTexture(gamera, playerBounds.x - 64, playerBounds.y - 64, WHITE);
+
+ // Draw player bounding box
+ //if (!gameraMode) DrawRectangleRec(playerBounds, Fade(GREEN, 0.4f));
+ //else DrawRectangleRec(playerBounds, Fade(ORANGE, 0.4f));
+
+ // Draw enemies
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ if (enemyActive[i])
+ {
+ // Draw enemies
+ switch(enemyType[i])
+ {
+ case 0: DrawTexture(shark, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
+ case 1: DrawTexture(orca, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
+ case 2: DrawTexture(swhale, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
+ case 3: DrawTexture(fish, enemyBounds[i].x - 14, enemyBounds[i].y - 14, WHITE); break;
+ default: break;
+ }
+
+ // Draw enemies bounding boxes
+ /*
+ switch(enemyType[i])
+ {
+ case 0: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break;
+ case 1: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break;
+ case 2: DrawRectangleRec(enemyBounds[i], Fade(RED, 0.5f)); break;
+ case 3: DrawRectangleRec(enemyBounds[i], Fade(GREEN, 0.5f)); break;
+ default: break;
+ }
+ */
+ }
+ }
+
+ // Draw gameplay interface
+ DrawRectangle(20, 20, 400, 40, Fade(GRAY, 0.4f));
+ DrawRectangle(20, 20, foodBar, 40, ORANGE);
+ DrawRectangleLines(20, 20, 400, 40, BLACK);
+
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ screenWidth - 300, 20 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 550, 20 }, font.size, -2, ORANGE);
+
+ if (gameraMode)
+ {
+ DrawText("GAMERA MODE", 60, 22, 40, GRAY);
+ DrawTexture(gframe, 0, 0, Fade(WHITE, 0.5f));
+ }
+
+ } break;
+ case ENDING:
+ {
+ // Draw a transparent black rectangle that covers all screen
+ DrawRectangle(0, 0, screenWidth, screenHeight, Fade(BLACK, 0.4f));
+
+ DrawTextEx(font, "GAME OVER", (Vector2){ 300, 160 }, font.size*3, -2, MAROON);
+
+ DrawTextEx(font, FormatText("SCORE: %04i", score), (Vector2){ 680, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("DISTANCE: %04i", (int)distance), (Vector2){ 290, 350 }, font.size, -2, GOLD);
+ DrawTextEx(font, FormatText("HISCORE: %04i", hiscore), (Vector2){ 665, 400 }, font.size, -2, ORANGE);
+ DrawTextEx(font, FormatText("HIDISTANCE: %04i", (int)hidistance), (Vector2){ 270, 400 }, font.size, -2, ORANGE);
+
+ // Draw blinking text
+ if ((framesCounter/30) % 2) DrawTextEx(font, "PRESS ENTER to REPLAY", (Vector2){ screenWidth/2 - 250, 520 }, font.size, -2, LIGHTGRAY);
+
+ } break;
+ default: break;
+ }
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+} \ No newline at end of file
diff --git a/games/drturtle/makefile b/games/drturtle/makefile
new file mode 100644
index 00000000..f9efd3e8
--- /dev/null
+++ b/games/drturtle/makefile
@@ -0,0 +1,186 @@
+#**************************************************************************************************
+#
+# raylib - makefile to compile Dr.Turtle game
+#
+# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+#
+# This software is provided "as-is", without any express or implied warranty. In no event
+# will the authors be held liable for any damages arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose, including commercial
+# applications, and to alter it and redistribute it freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not claim that you
+# wrote the original software. If you use this software in a product, an acknowledgment
+# in the product documentation would be appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+# as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+#
+#**************************************************************************************************
+
+# define raylib platform if not defined (by default, compile for RPI)
+# Other possible platform: PLATFORM_DESKTOP
+PLATFORM ?= PLATFORM_DESKTOP
+
+# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ LIBPATH=win32
+ else
+ UNAMEOS:=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ LIBPATH=linux
+ else
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ LIBPATH=osx
+ endif
+ endif
+ endif
+endif
+
+# define compiler: gcc for C program, define as g++ for C++
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # define emscripten compiler
+ CC = emcc
+else
+ifeq ($(PLATFORM_OS),OSX)
+ # define llvm compiler for mac
+ CC = clang
+else
+ # define default gcc compiler
+ CC = gcc
+endif
+endif
+
+# define compiler flags:
+# -O2 defines optimization level
+# -Wall turns on most, but not all, compiler warnings
+# -std=c99 use standard C from 1999 revision
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
+else
+ CFLAGS = -O2 -Wall -std=c99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 --shell-file ../../templates/web_shell/shell.html
+ #-s ASSERTIONS=1 --preload-file resources
+ #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
+ #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+endif
+
+# define any directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+else
+ INCLUDES = -I. -I../../src
+# external libraries headers
+# GLFW3
+ INCLUDES += -I../../external/glfw3/include
+# GLEW
+ INCLUDES += -I../../external/glew/include
+# OpenAL Soft
+ INCLUDES += -I../../external/openal_soft/include
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ LFLAGS = -L. -L../../src -L/opt/vc/lib
+else
+ LFLAGS = -L. -L../../src
+ # external libraries to link with
+ # GLFW3
+ LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+ ifneq ($(PLATFORM_OS),OSX)
+ # OpenAL Soft
+ LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+ # GLEW
+ LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+ endif
+endif
+
+# define any libraries to link into executable
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ # libraries for Debian GNU/Linux desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -lGLEW -lGL -lopenal
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ # libraries for OS X 10.9 desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
+ else
+ # libraries for Windows desktop compiling
+ # NOTE: GLFW3 and OpenAL Soft libraries should be installed
+ LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # libraries for Raspberry Pi compiling
+ # NOTE: OpenAL Soft library should be installed (libopenal1 package)
+ LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ LIBS = ../../src/libraylib.bc
+endif
+
+# define additional parameters and flags for windows
+ifeq ($(PLATFORM_OS),WINDOWS)
+ # resources file contains windows exe icon
+ # -Wl,--subsystem,windows hides the console window
+ WINFLAGS = ../../src/resources -Wl,--subsystem,windows
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ EXT = .html
+endif
+
+# define all screen object files required
+SCREENS = \
+
+# typing 'make' will invoke the first target entry in the file,
+# in this case, the 'default' target entry is advance_game
+default: drturtle
+
+# compile template - advance_game
+drturtle: drturtle_final_web.c $(SCREENS)
+ $(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ else
+ ifeq ($(PLATFORM_OS),LINUX)
+ find . -type f -executable -delete
+ rm -f *.o
+ else
+ del *.o *.exe
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
+ rm -f *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
+endif
+ @echo Cleaning done
+
+# instead of defining every module one by one, we can define a pattern
+# this pattern below will automatically compile every module defined on $(OBJS)
+#%.exe : %.c
+# $(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM)
diff --git a/games/floppy.c b/games/floppy.c
new file mode 100644
index 00000000..f48ea235
--- /dev/null
+++ b/games/floppy.c
@@ -0,0 +1,246 @@
+/*******************************************************************************************
+*
+* raylib - sample game: floppy
+*
+* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define MAX_TUBES 100
+#define FLOPPY_RADIUS 24
+#define TUBES_WIDTH 80
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Floppy {
+ Vector2 position;
+ int radius;
+ Color color;
+} Floppy;
+
+typedef struct Tubes {
+ Rectangle rec;
+ Color color;
+ bool active;
+} Tubes;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+static int score;
+static int hiScore = 0;
+
+static Floppy floppy;
+static Tubes tubes[MAX_TUBES*2];
+static Vector2 tubesPos[MAX_TUBES];
+static int tubesSpeedX;
+static bool superfx;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: floppy");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ floppy.radius = FLOPPY_RADIUS;
+ floppy.position = (Vector2){80, screenHeight/2 - floppy.radius};
+ tubesSpeedX = 2;
+
+ for (int i = 0; i < MAX_TUBES; i++)
+ {
+ tubesPos[i].x = 400 + 280*i;
+ tubesPos[i].y = -GetRandomValue(0, 120);
+ }
+
+ for (int i = 0; i < MAX_TUBES*2; i += 2)
+ {
+ tubes[i].rec.x = tubesPos[i/2].x;
+ tubes[i].rec.y = tubesPos[i/2].y;
+ tubes[i].rec.width = TUBES_WIDTH;
+ tubes[i].rec.height = 255;
+
+ tubes[i+1].rec.x = tubesPos[i/2].x;
+ tubes[i+1].rec.y = 600 + tubesPos[i/2].y - 255;
+ tubes[i+1].rec.width = TUBES_WIDTH;
+ tubes[i+1].rec.height = 255;
+
+ tubes[i/2].active = true;
+ }
+
+ score = 0;
+
+ gameOver = false;
+ superfx = false;
+ pause = false;
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX;
+
+ for (int i = 0; i < MAX_TUBES*2; i += 2)
+ {
+ tubes[i].rec.x = tubesPos[i/2].x;
+ tubes[i+1].rec.x = tubesPos[i/2].x;
+ }
+
+ if (IsKeyDown(KEY_SPACE) && !gameOver) floppy.position.y -= 3;
+ else floppy.position.y += 1;
+
+ // Check Collisions
+ for (int i = 0; i < MAX_TUBES*2; i++)
+ {
+ if (CheckCollisionCircleRec(floppy.position, floppy.radius, tubes[i].rec))
+ {
+ gameOver = true;
+ pause = false;
+ }
+ else if ((tubesPos[i/2].x < floppy.position.x) && tubes[i/2].active && !gameOver)
+ {
+ score += 100;
+ tubes[i/2].active = false;
+
+ superfx = true;
+
+ if (score > hiScore) hiScore = score;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ DrawCircle(floppy.position.x, floppy.position.y, floppy.radius, DARKGRAY);
+
+ // Draw tubes
+ for (int i = 0; i < MAX_TUBES; i++)
+ {
+ DrawRectangle(tubes[i*2].rec.x, tubes[i*2].rec.y, tubes[i*2].rec.width, tubes[i*2].rec.height, GRAY);
+ DrawRectangle(tubes[i*2 + 1].rec.x, tubes[i*2 + 1].rec.y, tubes[i*2 + 1].rec.width, tubes[i*2 + 1].rec.height, GRAY);
+ }
+
+ // Draw flashing fx (one frame only)
+ if (superfx)
+ {
+ DrawRectangle(0, 0, screenWidth, screenHeight, WHITE);
+ superfx = false;
+ }
+
+ DrawText(FormatText("%04i", score), 20, 20, 40, GRAY);
+ DrawText(FormatText("HI-SCORE: %04i", hiScore), 20, 70, 20, LIGHTGRAY);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/floppy/floppy.c b/games/floppy/floppy.c
deleted file mode 100644
index 0c0cb5f2..00000000
--- a/games/floppy/floppy.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*******************************************************************************************
-*
-* raylib game - Floppy Bird
-*
-* This game has been created using raylib 1.1 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
-*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
-*
-********************************************************************************************/
-
-#include "raylib.h"
-
-#define MAX_TUBES 100
-
-int main()
-{
- // Initialization
- //--------------------------------------------------------------------------------------
- int screenWidth = 800;
- int screenHeight = 450;
-
- InitWindow(screenWidth, screenHeight, "Floppy Bird");
-
- InitAudioDevice(); // Initialize audio device
-
- Sound coin = LoadSound("resources/coin.wav");
- Sound jump = LoadSound("resources/jump.wav");
-
- Texture2D background = LoadTexture("resources/background.png");
- Texture2D tubes = LoadTexture("resources/tubes.png");
- Texture2D floppy = LoadTexture("resources/floppy.png");
-
- Vector2 floppyPos = { 80, screenHeight/2 - floppy.height/2 };
-
- Vector2 tubesPos[MAX_TUBES];
- int tubesSpeedX = 2;
-
- for (int i = 0; i < MAX_TUBES; i++)
- {
- tubesPos[i].x = 400 + 280*i;
- tubesPos[i].y = -GetRandomValue(0, 120);
- }
-
- Rectangle tubesRecs[MAX_TUBES*2];
- bool tubesActive[MAX_TUBES];
-
- for (int i = 0; i < MAX_TUBES*2; i += 2)
- {
- tubesRecs[i].x = tubesPos[i/2].x;
- tubesRecs[i].y = tubesPos[i/2].y;
- tubesRecs[i].width = tubes.width;
- tubesRecs[i].height = 255;
-
- tubesRecs[i+1].x = tubesPos[i/2].x;
- tubesRecs[i+1].y = 600 + tubesPos[i/2].y - 255;
- tubesRecs[i+1].width = tubes.width;
- tubesRecs[i+1].height = 255;
-
- tubesActive[i/2] = true;
- }
-
- int backScroll = 0;
-
- int score = 0;
- int hiscore = 0;
-
- bool gameover = false;
- bool superfx = false;
-
- SetTargetFPS(60);
- //---------------------------------------------------------------------------------------
-
- // Main game loop
- while (!WindowShouldClose()) // Detect window close button or ESC key
- {
- // Update
- //----------------------------------------------------------------------------------
-
- // Background scroll logic
- backScroll--;
- if (backScroll <= -800) backScroll = 0;
-
- // Player movement logic
- if (!gameover)
- {
- if (IsKeyDown(KEY_SPACE)) floppyPos.y -= 3;
- else floppyPos.y += 1;
-
- if (IsKeyPressed(KEY_SPACE)) PlaySound(jump);
- }
-
- // Tubes moving logic
- for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX;
-
- for (int i = 0; i < MAX_TUBES*2; i += 2)
- {
- tubesRecs[i].x = tubesPos[i/2].x;
- tubesRecs[i+1].x = tubesPos[i/2].x;
- }
-
- // Check collisions player-tubes
- for (int i = 0; i < MAX_TUBES*2; i++)
- {
- if (CheckCollisionCircleRec((Vector2){ floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2 }, floppy.width/2, tubesRecs[i]))
- {
- gameover = true;
- }
- else if ((tubesPos[i/2].x < floppyPos.x) && tubesActive[i/2] && !gameover)
- {
- score += 100;
- tubesActive[i/2] = false;
- PlaySound(coin);
-
- superfx = true;
-
- if (score > hiscore) hiscore = score;
- }
- }
-
- // Gameover logic for reset
- if (gameover && IsKeyPressed(KEY_ENTER))
- {
- for (int i = 0; i < MAX_TUBES; i++)
- {
- tubesPos[i].x = 400 + 280*i;
- tubesPos[i].y = -GetRandomValue(0, 120);
- }
-
- for (int i = 0; i < MAX_TUBES*2; i += 2)
- {
- tubesRecs[i].x = tubesPos[i/2].x;
- tubesRecs[i].y = tubesPos[i/2].y;
-
- tubesRecs[i+1].x = tubesPos[i/2].x;
- tubesRecs[i+1].y = 600 + tubesPos[i/2].y - 255;
-
- tubesActive[i/2] = true;
- }
-
- floppyPos.x = 80;
- floppyPos.y = screenHeight/2 - floppy.height/2;
-
- gameover = false;
- score = 0;
- }
- //----------------------------------------------------------------------------------
-
- // Draw
- //----------------------------------------------------------------------------------
- BeginDrawing();
-
- ClearBackground(RAYWHITE);
-
- // Draw scrolling background
- DrawTexture(background, backScroll, 0, WHITE);
- DrawTexture(background, screenWidth + backScroll, 0, WHITE);
-
- // Draw moving tubes
- for (int i = 0; i < MAX_TUBES; i++)
- {
- if (tubesPos[i].x <= 800) DrawTextureEx(tubes, tubesPos[i], 0, 1.0, WHITE);
-
- // Draw collision recs
- //DrawRectangleLines(tubesRecs[i*2].x, tubesRecs[i*2].y, tubesRecs[i*2].width, tubesRecs[i*2].height, RED);
- //DrawRectangleLines(tubesRecs[i*2 + 1].x, tubesRecs[i*2 + 1].y, tubesRecs[i*2 + 1].width, tubesRecs[i*2 + 1].height, RED);
- }
-
- // Draw scores
- DrawText(FormatText("%04i", score), 20, 20, 40, PINK);
- DrawText(FormatText("HI-SCORE: %04i", hiscore), 20, 70, 20, VIOLET);
-
- // Draw player or game over messages
- if (!gameover)
- {
- DrawTextureEx(floppy, floppyPos, 0, 1.0, WHITE);
-
- // Draw collision circle
- //DrawCircleLines(floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2, floppy.width/2, RED);
- }
- else
- {
- DrawText("GAME OVER", 100, 180, 100, MAROON);
- DrawText("PRESS ENTER to RETRY!", 280, 280, 20, RED);
- }
-
- // Draw screen light flash when passing through a tube
- if (superfx)
- {
- DrawRectangle(0, 0, screenWidth, screenHeight, GOLD);
- superfx = false;
- }
-
- EndDrawing();
- //----------------------------------------------------------------------------------
- }
-
- // De-Initialization
- //--------------------------------------------------------------------------------------
- UnloadTexture(background); // Texture unloading
- UnloadTexture(tubes); // Texture unloading
- UnloadTexture(floppy); // Texture unloading
-
- UnloadSound(coin); // Unload sound data
- UnloadSound(jump); // Unload sound data
-
- CloseAudioDevice(); // Close audio device
-
- CloseWindow(); // Close window and OpenGL context
- //--------------------------------------------------------------------------------------
-
- return 0;
-} \ No newline at end of file
diff --git a/games/floppy/resources/background.png b/games/floppy/resources/background.png
deleted file mode 100644
index eab9d865..00000000
--- a/games/floppy/resources/background.png
+++ /dev/null
Binary files differ
diff --git a/games/floppy/resources/coin.wav b/games/floppy/resources/coin.wav
deleted file mode 100644
index d3b6e93c..00000000
--- a/games/floppy/resources/coin.wav
+++ /dev/null
Binary files differ
diff --git a/games/floppy/resources/floppy.png b/games/floppy/resources/floppy.png
deleted file mode 100644
index 7c851086..00000000
--- a/games/floppy/resources/floppy.png
+++ /dev/null
Binary files differ
diff --git a/games/floppy/resources/jump.wav b/games/floppy/resources/jump.wav
deleted file mode 100644
index 1f68d336..00000000
--- a/games/floppy/resources/jump.wav
+++ /dev/null
Binary files differ
diff --git a/games/floppy/resources/tubes.png b/games/floppy/resources/tubes.png
deleted file mode 100644
index a3ca8e7e..00000000
--- a/games/floppy/resources/tubes.png
+++ /dev/null
Binary files differ
diff --git a/games/gold_fever.c b/games/gold_fever.c
new file mode 100644
index 00000000..5a435027
--- /dev/null
+++ b/games/gold_fever.c
@@ -0,0 +1,288 @@
+/*******************************************************************************************
+*
+* raylib - sample game: gold fever
+*
+* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Player {
+ Vector2 position;
+ Vector2 speed;
+ int radius;
+} Player;
+
+typedef struct Enemy {
+ Vector2 position;
+ Vector2 speed;
+ int radius;
+ int radiusBounds;
+ bool moveRight; // RAY: o__O
+} Enemy;
+
+typedef struct Points {
+ Vector2 position;
+ int radius;
+ int value;
+ bool active;
+} Points;
+
+typedef struct Home {
+ Rectangle rec;
+ bool active;
+ bool save;
+ Color color;
+} Home;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+static int score;
+static int hiScore = 0;
+
+static Player player;
+static Enemy enemy;
+static Points points;
+static Home home;
+static bool follow;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+
+ InitWindow(screenWidth, screenHeight, "sample game: gold fever");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ pause = false;
+ score = 0;
+
+ player.position = (Vector2){50, 50};
+ player.radius = 20;
+ player.speed = (Vector2){5, 5};
+
+ enemy.position = (Vector2){screenWidth - 50, screenHeight/2};
+ enemy.radius = 20;
+ enemy.radiusBounds = 150;
+ enemy.speed = (Vector2){3, 3};
+ enemy.moveRight = true;
+ follow = false;
+
+ points.radius = 10;
+ points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)};
+ points.value = 100;
+ points.active = true;
+
+ home.rec.width = 50;
+ home.rec.height = 50;
+ home.rec.x = GetRandomValue(0, screenWidth - home.rec.width);
+ home.rec.y = GetRandomValue(0, screenHeight - home.rec.height);
+ home.active = false;
+ home.save = false;
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ //Control player
+ if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x;
+ if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x;
+ if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y;
+ if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y;
+
+ //wall behaviour player
+ if (player.position.x - player.radius <= 0) player.position.x = player.radius;
+ if (player.position.x + player.radius >= screenWidth) player.position.x = screenWidth - player.radius;
+ if (player.position.y - player.radius <= 0) player.position.y = player.radius;
+ if (player.position.y + player.radius >= screenHeight) player.position.y = screenHeight - player.radius;
+
+ //IA Enemy
+ if ( (follow || CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radiusBounds)) && !home.save)
+ {
+ if (player.position.x > enemy.position.x) enemy.position.x += enemy.speed.x;
+ if (player.position.x < enemy.position.x) enemy.position.x -= enemy.speed.x;
+
+ if (player.position.y > enemy.position.y) enemy.position.y += enemy.speed.y;
+ if (player.position.y < enemy.position.y) enemy.position.y -= enemy.speed.y;
+ }
+ else
+ {
+ if (enemy.moveRight) enemy.position.x += enemy.speed.x;
+ else enemy.position.x -= enemy.speed.x;
+ }
+
+ //wall behaviour enemy
+ if (enemy.position.x - enemy.radius <= 0) enemy.moveRight = true;
+ if (enemy.position.x + enemy.radius >= screenWidth) enemy.moveRight = false;
+
+ if (enemy.position.x - enemy.radius <= 0) enemy.position.x = enemy.radius;
+ if (enemy.position.x + enemy.radius >= screenWidth) enemy.position.x = screenWidth - enemy.radius;
+ if (enemy.position.y - enemy.radius <= 0) enemy.position.y = enemy.radius;
+ if (enemy.position.y + enemy.radius >= screenHeight) enemy.position.y = screenHeight - enemy.radius;
+
+ //Collisions
+ if (CheckCollisionCircles(player.position, player.radius, points.position, points.radius) && points.active)
+ {
+ follow = true;
+ points.active = false;
+ home.active = true;
+ }
+
+ if (CheckCollisionCircles(player.position, player.radius, enemy.position, enemy.radius) && !home.save)
+ {
+ gameOver = true;
+
+ if (hiScore < score) hiScore = score;
+ }
+
+ if (CheckCollisionCircleRec(player.position, player.radius, home.rec))
+ {
+ follow = false;
+
+ if (!points.active)
+ {
+ score += points.value;
+ points.active = true;
+ enemy.speed.x += 0.5;
+ enemy.speed.y += 0.5;
+ points.position = (Vector2){GetRandomValue(points.radius, screenWidth - points.radius), GetRandomValue(points.radius, screenHeight - points.radius)};
+ }
+
+ home.save = true;
+ }
+ else home.save = false;
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ if (follow)
+ {
+ DrawRectangle(0, 0, screenWidth, screenHeight, RED);
+ DrawRectangle(10, 10, screenWidth - 20, screenHeight - 20, RAYWHITE);
+ }
+
+ DrawRectangleLines(home.rec.x, home.rec.y, home.rec.width, home.rec.height, BLUE);
+
+ DrawCircleLines(enemy.position.x, enemy.position.y, enemy.radiusBounds, RED);
+ DrawCircleV(enemy.position, enemy.radius, MAROON);
+
+ DrawCircleV(player.position, player.radius, GRAY);
+ if (points.active) DrawCircleV(points.position, points.radius, GOLD);
+
+ DrawText(FormatText("SCORE: %04i", score), 20, 15, 20, GRAY);
+ DrawText(FormatText("HI-SCORE: %04i", hiScore), 300, 15, 20, GRAY);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/gorilas.c b/games/gorilas.c
new file mode 100644
index 00000000..86fd3f5b
--- /dev/null
+++ b/games/gorilas.c
@@ -0,0 +1,571 @@
+/*******************************************************************************************
+*
+* raylib - sample game: gorilas
+*
+* Sample game Marc Palau and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define MAX_BUILDINGS 15
+#define MAX_EXPLOSIONS 200
+#define MAX_PLAYERS 2
+
+#define BUILDING_RELATIVE_ERROR 30 // Building size random range %
+#define BUILDING_MIN_RELATIVE_HEIGHT 20 // Minimum height in % of the screenHeight
+#define BUILDING_MAX_RELATIVE_HEIGHT 60 // Maximum height in % of the screenHeight
+#define BUILDING_MIN_GRAYSCALE_COLOR 120 // Minimum gray color for the buildings
+#define BUILDING_MAX_GRAYSCALE_COLOR 200 // Maximum gray color for the buildings
+
+#define MIN_PLAYER_POSITION 5 // Minimum x position %
+#define MAX_PLAYER_POSITION 20 // Maximum x position %
+
+#define GRAVITY 9.81f
+#define DELTA_FPS 60
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Player {
+ Vector2 position;
+ Vector2 size;
+
+ Vector2 aimingPoint;
+ int aimingAngle;
+ int aimingPower;
+
+ Vector2 previousPoint;
+ int previousAngle;
+ int previousPower;
+
+ Vector2 impactPoint;
+
+ bool isLeftTeam; // This player belongs to the left or to the right team
+ bool isPlayer; // If is a player or an AI
+ bool isAlive;
+} Player;
+
+typedef struct Building {
+ Rectangle rectangle;
+ Color color;
+} Building;
+
+typedef struct Explosion {
+ Vector2 position;
+ int radius;
+ bool active;
+} Explosion;
+
+typedef struct Ball {
+ Vector2 position;
+ Vector2 speed;
+ int radius;
+ bool active;
+} Ball;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static bool gameOver = false;
+static bool pause = false;
+
+static Player player[MAX_PLAYERS];
+static Building building[MAX_BUILDINGS];
+static Explosion explosion[MAX_EXPLOSIONS];
+static Ball ball;
+
+static int playerTurn = 0;
+static bool ballOnAir = false;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+// Additional module functions
+static void InitBuildings(void);
+static void InitPlayers(void);
+static bool UpdatePlayer(int playerTurn);
+static bool UpdateBall(int playerTurn);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: gorilas");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ // Init shoot
+ ball.radius = 10;
+ ballOnAir = false;
+ ball.active = false;
+
+ InitBuildings();
+ InitPlayers();
+
+ // Init explosions
+ for (int i = 0; i < MAX_EXPLOSIONS; i++)
+ {
+ explosion[i].position = (Vector2){ 0.0f, 0.0f };
+ explosion[i].radius = 30;
+ explosion[i].active = false;
+ }
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ if (!ballOnAir) ballOnAir = UpdatePlayer(playerTurn); // If we are aiming
+ else
+ {
+ if (UpdateBall(playerTurn)) // If collision
+ {
+ // Game over logic
+ bool leftTeamAlive = false;
+ bool rightTeamAlive = false;
+
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (player[i].isAlive)
+ {
+ if (player[i].isLeftTeam) leftTeamAlive = true;
+ if (!player[i].isLeftTeam) rightTeamAlive = true;
+ }
+ }
+
+ if (leftTeamAlive && rightTeamAlive)
+ {
+ ballOnAir = false;
+ ball.active = false;
+
+ playerTurn++;
+
+ if (playerTurn == MAX_PLAYERS) playerTurn = 0;
+ }
+ else
+ {
+ gameOver = true;
+
+ // if (leftTeamAlive) left team wins
+ // if (rightTeamAlive) right team wins
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw buildings
+ for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(building[i].rectangle, building[i].color);
+
+ // Draw explosions
+ for (int i = 0; i < MAX_EXPLOSIONS; i++)
+ {
+ if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, explosion[i].radius, RAYWHITE);
+ }
+
+ // Draw players
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (player[i].isAlive)
+ {
+ if (player[i].isLeftTeam) DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2,
+ player[i].size.x, player[i].size.y, BLUE);
+ else DrawRectangle(player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2,
+ player[i].size.x, player[i].size.y, RED);
+ }
+ }
+
+ // Draw ball
+ if (ball.active) DrawCircle(ball.position.x, ball.position.y, ball.radius, MAROON);
+
+ // Draw the angle and the power of the aim, and the previous ones
+ if (!ballOnAir)
+ {
+ // Draw shot information
+ /*
+ if (player[playerTurn].isLeftTeam)
+ {
+ DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), 20, 20, 20, DARKBLUE);
+ DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), 20, 50, 20, DARKBLUE);
+ DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), 20, 80, 20, DARKBLUE);
+ DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), 20, 110, 20, DARKBLUE);
+ DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), 20, 140, 20, DARKBLUE);
+ DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), 20, 170, 20, DARKBLUE);
+ }
+ else
+ {
+ DrawText(FormatText("Previous Point %i, %i", (int)player[playerTurn].previousPoint.x, (int)player[playerTurn].previousPoint.y), screenWidth*3/4, 20, 20, DARKBLUE);
+ DrawText(FormatText("Previous Angle %i", player[playerTurn].previousAngle), screenWidth*3/4, 50, 20, DARKBLUE);
+ DrawText(FormatText("Previous Power %i", player[playerTurn].previousPower), screenWidth*3/4, 80, 20, DARKBLUE);
+ DrawText(FormatText("Aiming Point %i, %i", (int)player[playerTurn].aimingPoint.x, (int)player[playerTurn].aimingPoint.y), screenWidth*3/4, 110, 20, DARKBLUE);
+ DrawText(FormatText("Aiming Angle %i", player[playerTurn].aimingAngle), screenWidth*3/4, 140, 20, DARKBLUE);
+ DrawText(FormatText("Aiming Power %i", player[playerTurn].aimingPower), screenWidth*3/4, 170, 20, DARKBLUE);
+ }
+ */
+
+ // Draw aim
+ if (player[playerTurn].isLeftTeam)
+ {
+ // Previous aiming
+ DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 },
+ (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 },
+ player[playerTurn].previousPoint, GRAY);
+
+ // Actual aiming
+ DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 },
+ (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 },
+ player[playerTurn].aimingPoint, DARKBLUE);
+ }
+ else
+ {
+ // Previous aiming
+ DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 },
+ (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 },
+ player[playerTurn].previousPoint, GRAY);
+
+ // Actual aiming
+ DrawTriangle((Vector2){ player[playerTurn].position.x - player[playerTurn].size.x/4, player[playerTurn].position.y + player[playerTurn].size.y/4 },
+ (Vector2){ player[playerTurn].position.x + player[playerTurn].size.x/4, player[playerTurn].position.y - player[playerTurn].size.y/4 },
+ player[playerTurn].aimingPoint, MAROON);
+ }
+ }
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+}
+
+//--------------------------------------------------------------------------------------
+// Additional module functions
+//--------------------------------------------------------------------------------------
+static void InitBuildings(void)
+{
+ // Horizontal generation
+ int currentWidth = 0;
+
+ // We make sure the absolute error randomly generated for each building, has as a minimum value the screenWidth.
+ // This way all the screen will be filled with buildings. Each building will have a different, random width.
+
+ float relativeWidth = 100/(100 - BUILDING_RELATIVE_ERROR);
+ float buildingWidthMean = (screenWidth*relativeWidth/MAX_BUILDINGS) + 1; // We add one to make sure we will cover the whole screen.
+
+ // Vertical generation
+ int currentHeighth = 0;
+ int grayLevel;
+
+ // Creation
+ for (int i = 0; i < MAX_BUILDINGS; i++)
+ {
+ // Horizontal
+ building[i].rectangle.x = currentWidth;
+ building[i].rectangle.width = GetRandomValue(buildingWidthMean*(100 - BUILDING_RELATIVE_ERROR/2)/100 + 1, buildingWidthMean*(100 + BUILDING_RELATIVE_ERROR)/100);
+
+ currentWidth += building[i].rectangle.width;
+
+ // Vertical
+ currentHeighth = GetRandomValue(BUILDING_MIN_RELATIVE_HEIGHT, BUILDING_MAX_RELATIVE_HEIGHT);
+ building[i].rectangle.y = screenHeight - (screenHeight*currentHeighth/100);
+ building[i].rectangle.height = screenHeight*currentHeighth/100 + 1;
+
+ // Color
+ grayLevel = GetRandomValue(BUILDING_MIN_GRAYSCALE_COLOR, BUILDING_MAX_GRAYSCALE_COLOR);
+ building[i].color = (Color){ grayLevel, grayLevel, grayLevel, 255 };
+ }
+}
+
+static void InitPlayers(void)
+{
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ player[i].isAlive = true;
+
+ // Decide the team of this player
+ if (i % 2 == 0) player[i].isLeftTeam = true;
+ else player[i].isLeftTeam = false;
+
+ // Now there is no AI
+ player[i].isPlayer = true;
+
+ // Set size, by default by now
+ player[i].size = (Vector2){ 40, 40 };
+
+ // Set position
+ if (player[i].isLeftTeam) player[i].position.x = GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100);
+ else player[i].position.x = screenWidth - GetRandomValue(screenWidth*MIN_PLAYER_POSITION/100, screenWidth*MAX_PLAYER_POSITION/100);
+
+ for (int j = 0; j < MAX_BUILDINGS; j++)
+ {
+ if (building[j].rectangle.x > player[i].position.x)
+ {
+ // Set the player in the center of the building
+ player[i].position.x = building[j-1].rectangle.x + building[j-1].rectangle.width/2;
+ // Set the player at the top of the building
+ player[i].position.y = building[j-1].rectangle.y - player[i].size.y/2;
+ break;
+ }
+ }
+
+ // Set statistics to 0
+ player[i].aimingPoint = player[i].position;
+ player[i].previousAngle = 0;
+ player[i].previousPower = 0;
+ player[i].previousPoint = player[i].position;
+ player[i].aimingAngle = 0;
+ player[i].aimingPower = 0;
+
+ player[i].impactPoint = (Vector2){ -100, -100 };
+ }
+}
+
+static bool UpdatePlayer(int playerTurn)
+{
+ // If we are aiming at the firing quadrant, we calculate the angle
+ if (GetMousePosition().y <= player[playerTurn].position.y)
+ {
+ // Left team
+ if (player[playerTurn].isLeftTeam && GetMousePosition().x >= player[playerTurn].position.x)
+ {
+ // Distance (calculating the fire power)
+ player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2));
+ // Calculates the angle via arcsin
+ player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG;
+ // Point of the screen we are aiming at
+ player[playerTurn].aimingPoint = GetMousePosition();
+
+ // Ball fired
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ player[playerTurn].previousPoint = player[playerTurn].aimingPoint;
+ player[playerTurn].previousPower = player[playerTurn].aimingPower;
+ player[playerTurn].previousAngle = player[playerTurn].aimingAngle;
+ ball.position = player[playerTurn].position;
+
+ return true;
+ }
+ }
+ // Right team
+ else if (!player[playerTurn].isLeftTeam && GetMousePosition().x <= player[playerTurn].position.x)
+ {
+ // Distance (calculating the fire power)
+ player[playerTurn].aimingPower = sqrt(pow(player[playerTurn].position.x - GetMousePosition().x, 2) + pow(player[playerTurn].position.y - GetMousePosition().y, 2));
+ // Calculates the angle via arcsin
+ player[playerTurn].aimingAngle = asin((player[playerTurn].position.y - GetMousePosition().y)/player[playerTurn].aimingPower)*RAD2DEG;
+ // Point of the screen we are aiming at
+ player[playerTurn].aimingPoint = GetMousePosition();
+
+ // Ball fired
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ player[playerTurn].previousPoint = player[playerTurn].aimingPoint;
+ player[playerTurn].previousPower = player[playerTurn].aimingPower;
+ player[playerTurn].previousAngle = player[playerTurn].aimingAngle;
+ ball.position = player[playerTurn].position;
+
+ return true;
+ }
+ }
+ else
+ {
+ player[playerTurn].aimingPoint = player[playerTurn].position;
+ player[playerTurn].aimingPower = 0;
+ player[playerTurn].aimingAngle = 0;
+ }
+ }
+ else
+ {
+ player[playerTurn].aimingPoint = player[playerTurn].position;
+ player[playerTurn].aimingPower = 0;
+ player[playerTurn].aimingAngle = 0;
+ }
+
+ return false;
+}
+
+static bool UpdateBall(int playerTurn)
+{
+ static int explosionNumber = 0;
+
+ // Activate ball
+ if (!ball.active)
+ {
+ if (player[playerTurn].isLeftTeam)
+ {
+ ball.speed.x = cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS;
+ ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS;
+ ball.active = true;
+ }
+ else
+ {
+ ball.speed.x = -cos(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS;
+ ball.speed.y = -sin(player[playerTurn].previousAngle*DEG2RAD)*player[playerTurn].previousPower*3/DELTA_FPS;
+ ball.active = true;
+ }
+ }
+
+ ball.position.x += ball.speed.x;
+ ball.position.y += ball.speed.y;
+ ball.speed.y += GRAVITY/DELTA_FPS;
+
+ // Collision
+ if (ball.position.x + ball.radius < 0) return true;
+ else if (ball.position.x - ball.radius > screenWidth) return true;
+ else
+ {
+ // Player collision
+ for (int i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (CheckCollisionCircleRec(ball.position, ball.radius, (Rectangle){ player[i].position.x - player[i].size.x/2, player[i].position.y - player[i].size.y/2,
+ player[i].size.x, player[i].size.y }))
+ {
+ // We can't hit ourselves
+ if (i == playerTurn) return false;
+ else
+ {
+ // We set the impact point
+ player[playerTurn].impactPoint.x = ball.position.x;
+ player[playerTurn].impactPoint.y = ball.position.y + ball.radius;
+
+ // We destroy the player
+ player[i].isAlive = false;
+ return true;
+ }
+ }
+ }
+
+ // Building collision
+ // NOTE: We only check building collision if we are not inside an explosion
+ for (int i = 0; i < MAX_BUILDINGS; i++)
+ {
+ if (CheckCollisionCircles(ball.position, ball.radius, explosion[i].position, explosion[i].radius - ball.radius))
+ {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < MAX_BUILDINGS; i++)
+ {
+ if (CheckCollisionCircleRec(ball.position, ball.radius, building[i].rectangle))
+ {
+ // We set the impact point
+ player[playerTurn].impactPoint.x = ball.position.x;
+ player[playerTurn].impactPoint.y = ball.position.y + ball.radius;
+
+ // We create an explosion
+ explosion[explosionNumber].position = player[playerTurn].impactPoint;
+ explosion[explosionNumber].active = true;
+ explosionNumber++;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/games/just_do/makefile b/games/just_do/makefile
index 4c36b154..5cca9df5 100644
--- a/games/just_do/makefile
+++ b/games/just_do/makefile
@@ -72,7 +72,7 @@ else
CFLAGS = -O2 -Wall -std=c99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
- CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --shell-file ../../templates/web_shell/shell.html
#-s ASSERTIONS=1 --preload-file resources
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
diff --git a/games/light_my_ritual/light_my_ritual.c b/games/light_my_ritual/light_my_ritual.c
new file mode 100644
index 00000000..0f1dc47e
--- /dev/null
+++ b/games/light_my_ritual/light_my_ritual.c
@@ -0,0 +1,271 @@
+/*******************************************************************************************
+*
+* GLOBAL GAME JAM 2016 - LIGHT MY RITUAL!
+*
+* Preparing a ritual session is not that easy.
+* You must light all the candles before the astral alignment finishes...
+* but dark creatures move in the shadows to put out all your lights!
+* Be fast! Be smart! Light my ritual!
+*
+* This game has been created using raylib (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "screens/screens.h" // NOTE: Defines global variable: currentScreen
+
+#include <stdlib.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+const int screenWidth = 1280;
+const int screenHeight = 720;
+
+// Required variables to manage screen transitions (fade-in, fade-out)
+float transAlpha = 0;
+bool onTransition = false;
+bool transFadeOut = false;
+int transFromScreen = -1;
+int transToScreen = -1;
+
+//----------------------------------------------------------------------------------
+// Local Functions Declaration
+//----------------------------------------------------------------------------------
+void TransitionToScreen(int screen);
+void ChangeToScreen(int screen); // No transition effect
+void UpdateTransition(void);
+void DrawTransition(void);
+
+void UpdateDrawFrame(void); // Update and Draw one frame
+
+//----------------------------------------------------------------------------------
+// Main entry point
+//----------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //---------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "GGJ16 - LIGHT MY RITUAL!");
+
+ // Global data loading (assets that must be available in all screens, i.e. fonts)
+ InitAudioDevice();
+
+ Image image = LoadImage("resources/lights_map.png"); // Load image in CPU memory (RAM)
+
+ lightsMap = GetImageData(image); // Get image pixels data as an array of Color
+ lightsMapWidth = image.width;
+ lightsMapHeight = image.height;
+
+ UnloadImage(image); // Unload image from CPU memory (RAM)
+
+ //PlayMusicStream("resources/audio/come_play_with_me.ogg");
+
+ font = LoadSpriteFont("resources/font_arcadian.png");
+ //doors = LoadTexture("resources/textures/doors.png");
+ //sndDoor = LoadSound("resources/audio/door.ogg");
+
+ // Setup and Init first screen
+ currentScreen = LOGO_RL;
+ //InitTitleScreen();
+ //InitGameplayScreen();
+ rlInitLogoScreen();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ UpdateDrawFrame();
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ switch (currentScreen)
+ {
+ case LOGO_RL: rlUnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case GAMEPLAY: UnloadGameplayScreen(); break;
+ default: break;
+ }
+
+ // Unload all global loaded data (i.e. fonts) here!
+ UnloadSpriteFont(font);
+ //UnloadSound(sndDoor);
+
+ free(lightsMap);
+
+ CloseAudioDevice();
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+void TransitionToScreen(int screen)
+{
+ onTransition = true;
+ transFromScreen = currentScreen;
+ transToScreen = screen;
+}
+
+void ChangeToScreen(int screen)
+{
+ switch (currentScreen)
+ {
+ case LOGO_RL: rlUnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case GAMEPLAY: UnloadGameplayScreen(); break;
+ default: break;
+ }
+
+ switch (screen)
+ {
+ case LOGO_RL: rlInitLogoScreen(); break;
+ case TITLE: InitTitleScreen(); break;
+ case GAMEPLAY: InitGameplayScreen(); break;
+ default: break;
+ }
+
+ currentScreen = screen;
+}
+
+void UpdateTransition(void)
+{
+ if (!transFadeOut)
+ {
+ transAlpha += 0.05f;
+
+ if (transAlpha >= 1.0)
+ {
+ transAlpha = 1.0;
+
+ switch (transFromScreen)
+ {
+ case LOGO_RL: rlUnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case GAMEPLAY: UnloadGameplayScreen(); break;
+ default: break;
+ }
+
+ switch (transToScreen)
+ {
+ case LOGO_RL:
+ {
+ rlInitLogoScreen();
+ currentScreen = LOGO_RL;
+ } break;
+ case TITLE:
+ {
+ InitTitleScreen();
+ currentScreen = TITLE;
+ } break;
+ case GAMEPLAY:
+ {
+ InitGameplayScreen();
+ currentScreen = GAMEPLAY;
+ } break;
+ default: break;
+ }
+
+ transFadeOut = true;
+ }
+ }
+ else // Transition fade out logic
+ {
+ transAlpha -= 0.05f;
+
+ if (transAlpha <= 0)
+ {
+ transAlpha = 0;
+ transFadeOut = false;
+ onTransition = false;
+ transFromScreen = -1;
+ transToScreen = -1;
+ }
+ }
+}
+
+void DrawTransition(void)
+{
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha));
+}
+
+// Update and draw game frame
+void UpdateDrawFrame(void)
+{
+ // Update
+ //----------------------------------------------------------------------------------
+ if (!onTransition)
+ {
+ switch(currentScreen)
+ {
+ case LOGO_RL:
+ {
+ rlUpdateLogoScreen();
+
+ if (rlFinishLogoScreen()) TransitionToScreen(TITLE);
+
+ } break;
+ case TITLE:
+ {
+ UpdateTitleScreen();
+
+ if (FinishTitleScreen() == 1) TransitionToScreen(GAMEPLAY);
+
+ } break;
+ case GAMEPLAY:
+ {
+ UpdateGameplayScreen();
+
+ if (FinishGameplayScreen() == 1) ChangeToScreen(LOGO_RL);
+ else if (FinishGameplayScreen() == 2) TransitionToScreen(TITLE);
+
+ } break;
+ default: break;
+ }
+ }
+ else
+ {
+ // Update transition (fade-in, fade-out)
+ UpdateTransition();
+ }
+
+ UpdateMusicStream();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ switch(currentScreen)
+ {
+ case LOGO_RL: rlDrawLogoScreen(); break;
+ case TITLE: DrawTitleScreen(); break;
+ case GAMEPLAY: DrawGameplayScreen(); break;
+ default: break;
+ }
+
+ if (onTransition) DrawTransition();
+
+ //DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+}
+
diff --git a/games/light_my_ritual/makefile b/games/light_my_ritual/makefile
new file mode 100644
index 00000000..84d7e994
--- /dev/null
+++ b/games/light_my_ritual/makefile
@@ -0,0 +1,203 @@
+#**************************************************************************************************
+#
+# raylib - Advance Game
+#
+# makefile to compile advance game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
+#
+# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+#
+# This software is provided "as-is", without any express or implied warranty. In no event
+# will the authors be held liable for any damages arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose, including commercial
+# applications, and to alter it and redistribute it freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not claim that you
+# wrote the original software. If you use this software in a product, an acknowledgment
+# in the product documentation would be appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+# as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+#
+#**************************************************************************************************
+
+# define raylib platform if not defined (by default, compile for RPI)
+# Other possible platform: PLATFORM_DESKTOP
+PLATFORM ?= PLATFORM_DESKTOP
+
+# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ LIBPATH=win32
+ else
+ UNAMEOS:=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ LIBPATH=linux
+ else
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ LIBPATH=osx
+ endif
+ endif
+ endif
+endif
+
+# define compiler: gcc for C program, define as g++ for C++
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # define emscripten compiler
+ CC = emcc
+else
+ifeq ($(PLATFORM_OS),OSX)
+ # define llvm compiler for mac
+ CC = clang
+else
+ # define default gcc compiler
+ CC = gcc
+endif
+endif
+
+# define compiler flags:
+# -O2 defines optimization level
+# -Wall turns on most, but not all, compiler warnings
+# -std=c99 use standard C from 1999 revision
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
+else
+ CFLAGS = -O2 -Wall -std=c99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 --shell-file ../../templates/web_shell/shell.html
+ #-s ASSERTIONS=1 --preload-file resources
+ #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
+ #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+endif
+
+# define any directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+else
+ INCLUDES = -I. -I../../src
+# external libraries headers
+# GLFW3
+ INCLUDES += -I../../external/glfw3/include
+# GLEW
+ INCLUDES += -I../../external/glew/include
+# OpenAL Soft
+ INCLUDES += -I../../external/openal_soft/include
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ LFLAGS = -L. -L../../src -L/opt/vc/lib
+else
+ LFLAGS = -L. -L../../src
+ # external libraries to link with
+ # GLFW3
+ LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+ ifneq ($(PLATFORM_OS),OSX)
+ # OpenAL Soft
+ LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+ # GLEW
+ LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+ endif
+endif
+
+# define any libraries to link into executable
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ # libraries for Debian GNU/Linux desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -lGLEW -lGL -lopenal
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ # libraries for OS X 10.9 desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
+ else
+ # libraries for Windows desktop compiling
+ # NOTE: GLFW3 and OpenAL Soft libraries should be installed
+ LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # libraries for Raspberry Pi compiling
+ # NOTE: OpenAL Soft library should be installed (libopenal1 package)
+ LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ LIBS = ../../src/libraylib.bc
+endif
+
+# define additional parameters and flags for windows
+ifeq ($(PLATFORM_OS),WINDOWS)
+ # resources file contains windows exe icon
+ # -Wl,--subsystem,windows hides the console window
+ WINFLAGS = ../../src/resources -Wl,--subsystem,windows
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ EXT = .html
+endif
+
+# define all screen object files required
+SCREENS = \
+ screens/screen_logo_raylib.o \
+ screens/screen_title.o \
+ screens/screen_gameplay.o \
+
+# typing 'make' will invoke the first target entry in the file,
+# in this case, the 'default' target entry is advance_game
+default: light_my_ritual
+
+# compile template - advance_game
+light_my_ritual: light_my_ritual.c $(SCREENS)
+ $(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile screen LOGO raylib
+screens/screen_logo_raylib.o: screens/screen_logo_raylib.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen TITLE
+screens/screen_title.o: screens/screen_title.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen ENDING
+screens/screen_gameplay.o: screens/screen_gameplay.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ else
+ ifeq ($(PLATFORM_OS),LINUX)
+ find . -type f -executable -delete
+ rm -f *.o
+ else
+ del *.o *.exe
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
+ rm -f *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
+endif
+ @echo Cleaning done
+
+# instead of defining every module one by one, we can define a pattern
+# this pattern below will automatically compile every module defined on $(OBJS)
+#%.exe : %.c
+# $(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM)
diff --git a/games/light_my_ritual/resources/audio/ambient.ogg b/games/light_my_ritual/resources/audio/ambient.ogg
new file mode 100644
index 00000000..5828c516
--- /dev/null
+++ b/games/light_my_ritual/resources/audio/ambient.ogg
Binary files differ
diff --git a/games/light_my_ritual/resources/audio/light_off.wav b/games/light_my_ritual/resources/audio/light_off.wav
new file mode 100644
index 00000000..d2203e72
--- /dev/null
+++ b/games/light_my_ritual/resources/audio/light_off.wav
Binary files differ
diff --git a/games/light_my_ritual/resources/audio/light_on.wav b/games/light_my_ritual/resources/audio/light_on.wav
new file mode 100644
index 00000000..38b7ca58
--- /dev/null
+++ b/games/light_my_ritual/resources/audio/light_on.wav
Binary files differ
diff --git a/games/light_my_ritual/resources/audio/ritual.ogg b/games/light_my_ritual/resources/audio/ritual.ogg
new file mode 100644
index 00000000..4674ff7b
--- /dev/null
+++ b/games/light_my_ritual/resources/audio/ritual.ogg
Binary files differ
diff --git a/games/light_my_ritual/resources/audio/start.wav b/games/light_my_ritual/resources/audio/start.wav
new file mode 100644
index 00000000..66ce7ac1
--- /dev/null
+++ b/games/light_my_ritual/resources/audio/start.wav
Binary files differ
diff --git a/games/light_my_ritual/resources/font_arcadian.png b/games/light_my_ritual/resources/font_arcadian.png
new file mode 100644
index 00000000..5c3df51a
--- /dev/null
+++ b/games/light_my_ritual/resources/font_arcadian.png
Binary files differ
diff --git a/games/light_my_ritual/resources/lights_map.png b/games/light_my_ritual/resources/lights_map.png
new file mode 100644
index 00000000..362094cd
--- /dev/null
+++ b/games/light_my_ritual/resources/lights_map.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/back_title.png b/games/light_my_ritual/resources/textures/back_title.png
new file mode 100644
index 00000000..54921247
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/back_title.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/background.png b/games/light_my_ritual/resources/textures/background.png
new file mode 100644
index 00000000..367bdd30
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/background.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/book.png b/games/light_my_ritual/resources/textures/book.png
new file mode 100644
index 00000000..c0bfbdb3
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/book.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/circle_level_i_off.png b/games/light_my_ritual/resources/textures/circle_level_i_off.png
new file mode 100644
index 00000000..7961af7d
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/circle_level_i_off.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/circle_level_i_on.png b/games/light_my_ritual/resources/textures/circle_level_i_on.png
new file mode 100644
index 00000000..1f217734
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/circle_level_i_on.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/circle_level_ii_off.png b/games/light_my_ritual/resources/textures/circle_level_ii_off.png
new file mode 100644
index 00000000..642adc3b
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/circle_level_ii_off.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/circle_level_ii_on.png b/games/light_my_ritual/resources/textures/circle_level_ii_on.png
new file mode 100644
index 00000000..93b71b3a
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/circle_level_ii_on.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/circle_level_iii_off.png b/games/light_my_ritual/resources/textures/circle_level_iii_off.png
new file mode 100644
index 00000000..daf50be9
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/circle_level_iii_off.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/circle_level_iii_on.png b/games/light_my_ritual/resources/textures/circle_level_iii_on.png
new file mode 100644
index 00000000..e2256e95
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/circle_level_iii_on.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/enemy.png b/games/light_my_ritual/resources/textures/enemy.png
new file mode 100644
index 00000000..dc0a911d
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/enemy.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/foreground_level_i.png b/games/light_my_ritual/resources/textures/foreground_level_i.png
new file mode 100644
index 00000000..32b96740
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/foreground_level_i.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/foreground_level_ii.png b/games/light_my_ritual/resources/textures/foreground_level_ii.png
new file mode 100644
index 00000000..44f26003
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/foreground_level_ii.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/foreground_level_iii.png b/games/light_my_ritual/resources/textures/foreground_level_iii.png
new file mode 100644
index 00000000..0fc039d7
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/foreground_level_iii.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/light.png b/games/light_my_ritual/resources/textures/light.png
new file mode 100644
index 00000000..5d08326f
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/light.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/light_glow.png b/games/light_my_ritual/resources/textures/light_glow.png
new file mode 100644
index 00000000..d31356c6
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/light_glow.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/light_ray.png b/games/light_my_ritual/resources/textures/light_ray.png
new file mode 100644
index 00000000..f9f877fa
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/light_ray.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/msg_ritual.png b/games/light_my_ritual/resources/textures/msg_ritual.png
new file mode 100644
index 00000000..73f14d48
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/msg_ritual.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/player.png b/games/light_my_ritual/resources/textures/player.png
new file mode 100644
index 00000000..d6849478
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/player.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/time_over.png b/games/light_my_ritual/resources/textures/time_over.png
new file mode 100644
index 00000000..9f7935be
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/time_over.png
Binary files differ
diff --git a/games/light_my_ritual/resources/textures/title.png b/games/light_my_ritual/resources/textures/title.png
new file mode 100644
index 00000000..55eb593d
--- /dev/null
+++ b/games/light_my_ritual/resources/textures/title.png
Binary files differ
diff --git a/games/light_my_ritual/screens/screen_gameplay.c b/games/light_my_ritual/screens/screen_gameplay.c
new file mode 100644
index 00000000..b91d2545
--- /dev/null
+++ b/games/light_my_ritual/screens/screen_gameplay.c
@@ -0,0 +1,842 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+#include <math.h>
+
+#define MAX_LIGHTS_I 8
+#define MAX_LIGHTS_II 12
+#define MAX_LIGHTS_III 20
+
+#define MAX_ENEMIES 8
+
+#define MAX_PLAYER_ENERGY 40.0f
+#define ENERGY_REFILL_RATIO 0.2f
+
+#define GAMEPAD_SENSITIVITY 4.0f // More sensitivity, more speed :P
+
+#define LIGHT_ANIM_FRAMES 7
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Player {
+ Vector2 position;
+ Vector2 speed;
+ int radius;
+ Color color;
+ float lightEnergy;
+} Player;
+
+typedef struct Enemy {
+ Vector2 position;
+ Vector2 targetPos; // light target position
+ int targetNum; // light target number
+ float speed; // scalar value
+ int radius;
+ int active;
+ int awakeFramesDelay;
+ int framesCounter;
+ Color color;
+} Enemy;
+
+typedef struct Light {
+ Vector2 position;
+ int radius;
+ int requiredEnergy;
+ bool active;
+ Color color;
+
+ int framesCounter;
+ int currentFrame;
+ Rectangle frameRec;
+} Light;
+
+typedef enum { LEVEL_I, LEVEL_II, LEVEL_III, LEVEL_FINISHED } LightedLevel;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+//static Texture2D background;
+
+static bool pause;
+
+static Player player;
+
+static Light lightsI[MAX_LIGHTS_I];
+static Light lightsII[MAX_LIGHTS_II];
+static Light lightsIII[MAX_LIGHTS_III];
+
+static Enemy enemies[MAX_ENEMIES];
+
+static int ritualLevel;
+static int previousLightedLevel;
+static int currentLightedLevel;
+
+static Vector2 lighterPosition;
+
+static int maxLightEnergy;
+static int currentLightEnergy;
+
+static float ritualTime;
+static bool startRitual;
+static float alphaRitual;
+
+static bool timeOver;
+static int nextStarsAlignment;
+
+static Texture2D background;
+static Texture2D foregroundI;
+static Texture2D foregroundII;
+static Texture2D foregroundIII;
+static Texture2D texPlayer;
+static Texture2D texEnemy;
+static Texture2D texLight;
+static Texture2D lightGlow;
+static Texture2D lightRay;
+static Texture2D book;
+static Texture2D texRitual;
+static Texture2D texTimeOver;
+static Texture2D circleIoff, circleIIoff, circleIIIoff;
+static Texture2D circleIon, circleIIon, circleIIIon;
+
+static Rectangle lightOff, lightOn;
+
+static Sound fxLightOn, fxLightOff;
+
+// Debug variables
+static bool enemiesStopped;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static bool ColorEqual(Color col1, Color col2); // Check if two colors are equal
+static Vector2 Vector2Subtract(Vector2 v1, Vector2 v2);
+static void Vector2Normalize(Vector2 *v);
+static void EnemyReset(Enemy *enemy);
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitGameplayScreen(void)
+{
+ framesCounter = 0;
+ finishScreen = 0;
+ pause = false;
+
+ // Textures loading
+ background = LoadTexture("resources/textures/background.png");
+ foregroundI = LoadTexture("resources/textures/foreground_level_i.png");
+ foregroundII = LoadTexture("resources/textures/foreground_level_ii.png");
+ foregroundIII = LoadTexture("resources/textures/foreground_level_iii.png");
+ texPlayer = LoadTexture("resources/textures/player.png");
+ texEnemy = LoadTexture("resources/textures/enemy.png");
+ texLight = LoadTexture("resources/textures/light.png");
+ lightGlow = LoadTexture("resources/textures/light_glow.png");
+ lightRay = LoadTexture("resources/textures/light_ray.png");
+ book = LoadTexture("resources/textures/book.png");
+ texRitual = LoadTexture("resources/textures/msg_ritual.png");
+ texTimeOver = LoadTexture("resources/textures/time_over.png");
+
+ circleIoff = LoadTexture("resources/textures/circle_level_i_off.png");
+ circleIIoff = LoadTexture("resources/textures/circle_level_ii_off.png");
+ circleIIIoff = LoadTexture("resources/textures/circle_level_iii_off.png");
+ circleIon = LoadTexture("resources/textures/circle_level_i_on.png");
+ circleIIon = LoadTexture("resources/textures/circle_level_ii_on.png");
+ circleIIIon = LoadTexture("resources/textures/circle_level_iii_on.png");
+
+ lightOff = (Rectangle){ 0, 0, 64, 64 };
+ lightOn = (Rectangle){ 64, 0, 64, 64 };
+
+ fxLightOn = LoadSound("resources/audio/light_on.wav");
+ fxLightOff = LoadSound("resources/audio/light_off.wav");
+
+ // Initialize player
+ player.position = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 - 40 };
+ player.radius = 20;
+ player.speed = (Vector2){5, 5};
+ player.color = WHITE;
+
+ // Initialize lights positions based on lights map image data
+ int kI = 0, kII = 0, kIII = 0;
+ for (int y = 0; y < lightsMapHeight; y++)
+ {
+ for (int x = 0; x < lightsMapWidth; x++)
+ {
+ if (ColorEqual(lightsMap[y*lightsMapWidth + x], (Color){ 255, 0, 0, 255 }))
+ {
+ // Store light position I
+ lightsI[kI].position.x = (float)x*10;
+ lightsI[kI].position.y = (float)y*10;
+ kI++;
+
+ //printf("Light %02i position: %i, %i\n", kI, (int)lightsI[kI - 1].position.x, (int)lightsI[kI - 1].position.y);
+ }
+ else if (ColorEqual(lightsMap[y*lightsMapWidth + x], (Color){ 0, 255, 0, 255 }))
+ {
+ // Store light position II
+ lightsII[kII].position.x = (float)x*10;
+ lightsII[kII].position.y = (float)y*10;
+ kII++;
+ }
+ else if (ColorEqual(lightsMap[y*lightsMapWidth + x], (Color){ 0, 0, 255, 255 }))
+ {
+ // Store light position III
+ lightsIII[kIII].position.x = (float)x*10;
+ lightsIII[kIII].position.y = (float)y*10;
+ kIII++;
+ }
+ }
+ }
+
+ // Initialize lights I
+ for (int i = 0; i < MAX_LIGHTS_I; i++)
+ {
+ lightsI[i].radius = 12;
+ lightsI[i].requiredEnergy = GetRandomValue(3, 9);
+ lightsI[i].active = false;
+ lightsI[i].color = GOLD;
+
+ lightsI[i].framesCounter = 0;
+ lightsI[i].currentFrame = 0;
+ lightsI[i].frameRec = (Rectangle){ 0, 0, 64, 64 };
+ }
+
+ // Initialize lights II
+ for (int i = 0; i < MAX_LIGHTS_II; i++)
+ {
+ lightsII[i].radius = 8;
+ lightsII[i].requiredEnergy = GetRandomValue(3, 8);
+ lightsII[i].active = false;
+ lightsII[i].color = GOLD;
+
+ lightsII[i].framesCounter = 0;
+ lightsII[i].currentFrame = 0;
+ lightsII[i].frameRec = (Rectangle){ 0, 0, 64, 64 };
+ }
+
+ // Initialize lights III
+ for (int i = 0; i < MAX_LIGHTS_III; i++)
+ {
+ lightsIII[i].radius = 8;
+ lightsIII[i].requiredEnergy = GetRandomValue(4, 10);
+ lightsIII[i].active = false;
+ lightsIII[i].color = GOLD;
+
+ lightsIII[i].framesCounter = 0;
+ lightsIII[i].currentFrame = 0;
+ lightsIII[i].frameRec = (Rectangle){ 0, 0, 64, 64 };
+ }
+
+ // Initialize ritual level
+ ritualLevel = 0;
+ currentLightedLevel = LEVEL_I;
+ lighterPosition = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 };
+
+ // Initialize enemies
+ for (int i = 0; i < MAX_ENEMIES; i++) EnemyReset(&enemies[i]);
+
+ // Initialize max light energy (depends on lights randomness)
+ maxLightEnergy = 0;
+
+ for (int i = 0; i < MAX_LIGHTS_I; i++) maxLightEnergy += lightsI[i].requiredEnergy;
+ for (int i = 0; i < MAX_LIGHTS_II; i++) maxLightEnergy += lightsII[i].requiredEnergy;
+ for (int i = 0; i < MAX_LIGHTS_III; i++) maxLightEnergy += lightsIII[i].requiredEnergy;
+
+ //printf("Max light energy: %i\n", maxLightEnergy);
+
+ // Initialize ritual variables
+ ritualTime = 0.0f;
+ startRitual = false;;
+ alphaRitual = 0.0f;
+
+ timeOver = false;
+ nextStarsAlignment = GetRandomValue(500, 1000);
+
+ enemiesStopped = false;
+
+ PlayMusicStream("resources/audio/ritual.ogg");
+}
+
+// Gameplay Screen Update logic
+void UpdateGameplayScreen(void)
+{
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause && (currentLightedLevel != LEVEL_FINISHED) && !timeOver)
+ {
+ framesCounter++; // Time starts counting to awake enemies
+
+ // Player movement logic
+ if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x;
+ else if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x;
+
+ if (IsKeyDown(KEY_UP)) player.position.y -= player.speed.y;
+ else if (IsKeyDown(KEY_DOWN)) player.position.y += player.speed.y;
+
+ // Debug key to stop enemies
+ if (IsKeyPressed(KEY_S)) enemiesStopped = !enemiesStopped;
+
+ /*
+ if (IsGamepadAvailable(GAMEPAD_PLAYER1))
+ {
+ Vector2 movement = GetGamepadMovement(GAMEPAD_PLAYER1);
+
+ player.position.x += movement.x*GAMEPAD_SENSITIVITY;
+ player.position.y += movement.y*GAMEPAD_SENSITIVITY;
+ }
+ */
+
+ // Player light energy filling logic
+ if (CheckCollisionCircles(player.position, player.radius, lighterPosition, 50))
+ {
+ player.lightEnergy += ENERGY_REFILL_RATIO;
+ player.color = (Color){ 255, 255, 100, 255 };
+ }
+ else player.color = WHITE;
+
+ if (player.lightEnergy > MAX_PLAYER_ENERGY) player.lightEnergy = MAX_PLAYER_ENERGY;
+
+ // Player vs lights collision detection (depends on lighted level)
+ if (currentLightedLevel == LEVEL_I)
+ {
+ for (int i = 0; i < MAX_LIGHTS_I; i++)
+ {
+ // Check player vs lightI collision
+ if (CheckCollisionCircles(player.position, player.radius, lightsI[i].position, lightsI[i].radius))
+ {
+ if (!lightsI[i].active && (player.lightEnergy >= lightsI[i].requiredEnergy))
+ {
+ lightsI[i].active = true;
+ lightsI[i].currentFrame = 1;
+ player.lightEnergy -= lightsI[i].requiredEnergy;
+
+ PlaySound(fxLightOn);
+ }
+ }
+ }
+ }
+ else if (currentLightedLevel == LEVEL_II)
+ {
+ for (int i = 0; i < MAX_LIGHTS_II; i++)
+ {
+ if (CheckCollisionCircles(player.position, player.radius, lightsII[i].position, lightsII[i].radius))
+ {
+ if (!lightsII[i].active && (player.lightEnergy >= lightsII[i].requiredEnergy))
+ {
+ lightsII[i].active = true;
+ player.lightEnergy -= lightsII[i].requiredEnergy;
+
+ PlaySound(fxLightOn);
+ }
+ }
+ }
+ }
+ else if (currentLightedLevel == LEVEL_III)
+ {
+ for (int i = 0; i < MAX_LIGHTS_III; i++)
+ {
+ if (CheckCollisionCircles(player.position, player.radius, lightsIII[i].position, lightsIII[i].radius))
+ {
+ if (!lightsIII[i].active && (player.lightEnergy >= lightsIII[i].requiredEnergy))
+ {
+ lightsIII[i].active = true;
+ player.lightEnergy -= lightsIII[i].requiredEnergy;
+
+ PlaySound(fxLightOn);
+ }
+ }
+ }
+ }
+
+ // Lights animation (it doesn't depend on currentLightedLevel)
+ for (int i = 0; i < MAX_LIGHTS_I; i++)
+ {
+ // Light animation
+ if (lightsI[i].active)
+ {
+ lightsI[i].framesCounter++;
+
+ if (lightsI[i].framesCounter > 10)
+ {
+ lightsI[i].currentFrame++;
+
+ if (lightsI[i].currentFrame > LIGHT_ANIM_FRAMES - 1) lightsI[i].currentFrame = 1;
+
+ lightsI[i].framesCounter = 0;
+ }
+ }
+
+ lightsI[i].frameRec.x = lightsI[i].currentFrame*texLight.width/LIGHT_ANIM_FRAMES;
+ }
+
+ for (int i = 0; i < MAX_LIGHTS_II; i++)
+ {
+ // Light animation
+ if (lightsII[i].active)
+ {
+ lightsII[i].framesCounter++;
+
+ if (lightsII[i].framesCounter > 10)
+ {
+ lightsII[i].currentFrame++;
+
+ if (lightsII[i].currentFrame > LIGHT_ANIM_FRAMES - 1) lightsII[i].currentFrame = 1;
+
+ lightsII[i].framesCounter = 0;
+ }
+ }
+
+ lightsII[i].frameRec.x = lightsII[i].currentFrame*texLight.width/LIGHT_ANIM_FRAMES;
+ }
+
+ for (int i = 0; i < MAX_LIGHTS_III; i++)
+ {
+ // Light animation
+ if (lightsIII[i].active)
+ {
+ lightsIII[i].framesCounter++;
+
+ if (lightsIII[i].framesCounter > 10)
+ {
+ lightsIII[i].currentFrame++;
+
+ if (lightsIII[i].currentFrame > LIGHT_ANIM_FRAMES - 1) lightsIII[i].currentFrame = 1;
+
+ lightsIII[i].framesCounter = 0;
+ }
+ }
+
+ lightsIII[i].frameRec.x = lightsIII[i].currentFrame*texLight.width/LIGHT_ANIM_FRAMES;
+ }
+
+ // Enemies logic
+ if (!enemiesStopped)
+ {
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ if (!enemies[i].active) enemies[i].framesCounter++;
+
+ if (enemies[i].framesCounter > enemies[i].awakeFramesDelay) enemies[i].active = true;
+
+ if (enemies[i].active)
+ {
+ // Move to the target
+ Vector2 dir = Vector2Subtract(enemies[i].targetPos, enemies[i].position);
+ Vector2Normalize(&dir);
+
+ enemies[i].position.x += dir.x*enemies[i].speed;
+ enemies[i].position.y += dir.y*enemies[i].speed;
+
+ if (currentLightedLevel == LEVEL_I)
+ {
+ if (CheckCollisionCircles(enemies[i].position, enemies[i].radius, enemies[i].targetPos, lightsI[enemies[i].targetNum].radius))
+ {
+ lightsI[enemies[i].targetNum].active = false;
+ lightsI[enemies[i].targetNum].framesCounter = 0;
+ lightsI[enemies[i].targetNum].currentFrame = 0;
+ lightsI[enemies[i].targetNum].frameRec = (Rectangle){ 0, 0, 64, 64 };
+
+ EnemyReset(&enemies[i]);
+
+ PlaySound(fxLightOff);
+ }
+ }
+ else if (currentLightedLevel == LEVEL_II)
+ {
+ if (CheckCollisionCircles(enemies[i].position, enemies[i].radius, enemies[i].targetPos, lightsII[enemies[i].targetNum].radius))
+ {
+ lightsII[enemies[i].targetNum].active = false;
+ lightsII[enemies[i].targetNum].framesCounter = 0;
+ lightsII[enemies[i].targetNum].currentFrame = 0;
+ lightsII[enemies[i].targetNum].frameRec = (Rectangle){ 0, 0, 64, 64 };
+
+ EnemyReset(&enemies[i]);
+
+ PlaySound(fxLightOff);
+ }
+ }
+ else if (currentLightedLevel == LEVEL_III)
+ {
+ if (CheckCollisionCircles(enemies[i].position, enemies[i].radius, enemies[i].targetPos, lightsIII[enemies[i].targetNum].radius))
+ {
+ lightsIII[enemies[i].targetNum].active = false;
+ lightsIII[enemies[i].targetNum].framesCounter = 0;
+ lightsIII[enemies[i].targetNum].currentFrame = 0;
+ lightsIII[enemies[i].targetNum].frameRec = (Rectangle){ 0, 0, 64, 64 };
+
+ EnemyReset(&enemies[i]);
+
+ PlaySound(fxLightOff);
+ }
+ }
+ }
+ }
+ }
+
+ // Check current light energy (for right bar)
+ currentLightEnergy = 0;
+
+ for (int i = 0; i < MAX_LIGHTS_I; i++) if (lightsI[i].active) currentLightEnergy += lightsI[i].requiredEnergy;
+ for (int i = 0; i < MAX_LIGHTS_II; i++) if (lightsII[i].active) currentLightEnergy += lightsII[i].requiredEnergy;
+ for (int i = 0; i < MAX_LIGHTS_III; i++) if (lightsIII[i].active) currentLightEnergy += lightsIII[i].requiredEnergy;
+
+ // Check current lighted level
+ // Check ending conditions: all lights off, ritual level reached
+ previousLightedLevel = currentLightedLevel;
+
+ currentLightedLevel = LEVEL_I;
+
+ bool lightedLevel = true;
+ for (int i = 0; i < MAX_LIGHTS_I; i++) if (!lightsI[i].active) lightedLevel = false;
+ if (lightedLevel) currentLightedLevel = LEVEL_II;
+
+ for (int i = 0; i < MAX_LIGHTS_II; i++) if (!lightsII[i].active) lightedLevel = false;
+ if (lightedLevel) currentLightedLevel = LEVEL_III;
+
+ for (int i = 0; i < MAX_LIGHTS_III; i++) if (!lightsIII[i].active) lightedLevel = false;
+ if (lightedLevel)
+ {
+ currentLightedLevel = LEVEL_FINISHED;
+
+ for (int i = 0; i < MAX_ENEMIES; i++) enemies[i].active = false;
+ }
+
+ if (currentLightedLevel != previousLightedLevel) for (int i = 0; i < MAX_ENEMIES; i++) EnemyReset(&enemies[i]);
+
+ ritualTime = (float)framesCounter/60;
+
+ // Check game over condition (time run out)
+ if ((99.0f - ritualTime) <= 0.0f)
+ {
+ ritualTime = 99.0f;
+ timeOver = true;
+ }
+ }
+
+ if (startRitual)
+ {
+ alphaRitual += 0.02f;
+
+ SetMusicVolume(1.0f - alphaRitual);
+
+ if (alphaRitual > 1.0f) finishScreen = 1;
+ }
+}
+
+// Gameplay Screen Draw logic
+void DrawGameplayScreen(void)
+{
+ DrawTexture(background, 0, 0, WHITE);
+
+ // DrawText("STARS ARE ALIGNED! NO TIME TO LOOSE! LIGHT MY RITUAL!",
+
+ // Draw foreground and circles
+ if ((currentLightedLevel == LEVEL_FINISHED) || (currentLightedLevel == LEVEL_III)) DrawTexture(foregroundIII, 0, 0, WHITE);
+ else if (currentLightedLevel == LEVEL_II) DrawTexture(foregroundII, 0, 0, WHITE);
+ else if (currentLightedLevel == LEVEL_I) DrawTexture(foregroundI, 0, 0, WHITE);
+
+ // Draw lighted circles (depends on current lighted level)
+ switch (currentLightedLevel)
+ {
+ case LEVEL_FINISHED:
+ {
+ DrawTexture(circleIIIon, GetScreenWidth()/2 - circleIIIon.width/2, GetScreenHeight()/2 - circleIIIon.height/2, WHITE);
+ DrawTexture(circleIIon, GetScreenWidth()/2 - circleIIon.width/2, GetScreenHeight()/2 - circleIIon.height/2, WHITE);
+ DrawTexture(circleIon, GetScreenWidth()/2 - circleIon.width/2, GetScreenHeight()/2 - circleIon.height/2, WHITE);
+ } break;
+ case LEVEL_III:
+ {
+ DrawTexture(circleIIIoff, GetScreenWidth()/2 - circleIIIoff.width/2, GetScreenHeight()/2 - circleIIIoff.height/2, WHITE);
+ DrawTexture(circleIIon, GetScreenWidth()/2 - circleIIon.width/2, GetScreenHeight()/2 - circleIIon.height/2, WHITE);
+ DrawTexture(circleIon, GetScreenWidth()/2 - circleIon.width/2, GetScreenHeight()/2 - circleIon.height/2, WHITE);
+ } break;
+ case LEVEL_II:
+ {
+ DrawTexture(circleIIoff, GetScreenWidth()/2 - circleIIoff.width/2, GetScreenHeight()/2 - circleIIoff.height/2, WHITE);
+ DrawTexture(circleIon, GetScreenWidth()/2 - circleIon.width/2, GetScreenHeight()/2 - circleIon.height/2, WHITE);
+ } break;
+ case LEVEL_I:
+ {
+ DrawTexture(circleIoff, GetScreenWidth()/2 - circleIoff.width/2, GetScreenHeight()/2 - circleIoff.height/2, WHITE);
+ } break;
+ default: break;
+ }
+
+ // Draw lights (depends on current lighted level)
+ switch (currentLightedLevel)
+ {
+ case LEVEL_FINISHED:
+ case LEVEL_III:
+ {
+ for (int i = 0; i < MAX_LIGHTS_III; i++)
+ {
+ //if (lightsIII[i].active) DrawCircleV(lightsIII[i].position, lightsIII[i].radius, GOLD);
+ //else DrawCircleLines(lightsIII[i].position.x, lightsIII[i].position.y, lightsIII[i].radius, GRAY);
+
+ if (lightsIII[i].active)
+ {
+ DrawTextureRec(texLight, lightsIII[i].frameRec, (Vector2){ lightsIII[i].position.x - 32, lightsIII[i].position.y - 32 }, WHITE);
+ DrawTexture(lightGlow, lightsIII[i].position.x - lightGlow.width/2, lightsIII[i].position.y - lightGlow.height/2, Fade(WHITE, 0.3f));
+ DrawText(FormatText("%02i", lightsIII[i].requiredEnergy), lightsIII[i].position.x - 10, lightsIII[i].position.y + 14, 20, GRAY);
+ }
+ else
+ {
+ DrawTextureRec(texLight, lightsIII[i].frameRec, (Vector2){ lightsIII[i].position.x - 32, lightsIII[i].position.y - 32 }, WHITE);
+ DrawText(FormatText("%02i", lightsIII[i].requiredEnergy), lightsIII[i].position.x - 10, lightsIII[i].position.y + 14, 20, YELLOW);
+ }
+ }
+ }
+ case LEVEL_II:
+ {
+ for (int i = 0; i < MAX_LIGHTS_II; i++)
+ {
+ //if (lightsII[i].active) DrawCircleV(lightsII[i].position, lightsII[i].radius, GOLD);
+ //else DrawCircleLines(lightsI[i].position.x, lightsI[i].position.y, lightsI[i].radius, GRAY);
+
+ if (lightsII[i].active)
+ {
+ DrawTextureRec(texLight, lightsII[i].frameRec, (Vector2){ lightsII[i].position.x - 32, lightsII[i].position.y - 32 }, WHITE);
+ DrawTexture(lightGlow, lightsII[i].position.x - lightGlow.width/2, lightsII[i].position.y - lightGlow.height/2, Fade(WHITE, 0.3f));
+ DrawText(FormatText("%02i", lightsII[i].requiredEnergy), lightsII[i].position.x - 10, lightsII[i].position.y + 14, 20, GRAY);
+ }
+ else
+ {
+ DrawTextureRec(texLight, lightsII[i].frameRec, (Vector2){ lightsII[i].position.x - 32, lightsII[i].position.y - 32 }, WHITE);
+ DrawText(FormatText("%02i", lightsII[i].requiredEnergy), lightsII[i].position.x - 10, lightsII[i].position.y + 14, 20, YELLOW);
+ }
+ }
+ }
+ case LEVEL_I:
+ {
+ for (int i = 0; i < MAX_LIGHTS_I; i++)
+ {
+ //if (lightsI[i].active) DrawCircleV(lightsI[i].position, lightsI[i].radius, GOLD);
+ //else DrawCircleLines(lightsI[i].position.x, lightsI[i].position.y, lightsI[i].radius, GRAY);
+
+ if (lightsI[i].active)
+ {
+ DrawTextureRec(texLight, lightsI[i].frameRec, (Vector2){ lightsI[i].position.x - 32, lightsI[i].position.y - 32 }, WHITE);
+ DrawTexture(lightGlow, lightsI[i].position.x - lightGlow.width/2, lightsI[i].position.y - lightGlow.height/2, Fade(WHITE, 0.3f));
+ DrawText(FormatText("%02i", lightsI[i].requiredEnergy), lightsI[i].position.x - 10, lightsI[i].position.y + 14, 20, GRAY);
+ }
+ else
+ {
+ DrawTextureRec(texLight, lightsI[i].frameRec, (Vector2){ lightsI[i].position.x - 32, lightsI[i].position.y - 32 }, WHITE);
+ DrawText(FormatText("%02i", lightsI[i].requiredEnergy), lightsI[i].position.x - 10, lightsI[i].position.y + 14, 20, YELLOW);
+ }
+ }
+ }
+ default: break;
+ }
+
+ // Draw main lighter
+ DrawTexture(book, GetScreenWidth()/2 - book.width/2, GetScreenHeight()/2, WHITE);
+ DrawTexture(lightRay, GetScreenWidth()/2 - lightRay.width/2, 0, Fade(WHITE, 0.5f));
+
+ // Draw player
+ //DrawCircleV(player.position, player.radius, player.color);
+ DrawTexture(texPlayer, player.position.x - 32, player.position.y - 32, player.color);
+
+ if (currentLightedLevel != LEVEL_FINISHED)
+ {
+ // Draw enemies (depends on current lighted level)
+ for (int i = 0; i < MAX_ENEMIES; i++)
+ {
+ if (enemies[i].active)
+ {
+ //DrawCircleV(enemies[i].position, enemies[i].radius, enemies[i].color);
+ DrawTextureRec(texEnemy, (Rectangle){ 0, 0, 64, 64 }, (Vector2){ enemies[i].position.x - 32, enemies[i].position.y - 32 }, WHITE);
+ }
+ }
+
+ // Draw time left for ritual
+ DrawTextEx(font, FormatText("%02.2f", (99.0f - ritualTime)), (Vector2){ 560, 20 }, font.size, 0, WHITE);
+
+ // Draw light energy bar
+ DrawRectangle(20, 30, 400, 20, GRAY);
+ DrawRectangle(20, 30, (400*player.lightEnergy)/MAX_PLAYER_ENERGY, 20, GOLD);
+ DrawRectangleLines(20, 30, 400, 20, LIGHTGRAY);
+ DrawText(FormatText("%03.0f", player.lightEnergy), 430, 30, 20, WHITE);
+
+ // Draw level lighted bar (for completion)
+ DrawRectangle(GetScreenWidth() - 40, 30, 20, 660, GRAY);
+ DrawRectangle(GetScreenWidth() - 40, 30 + 660 - 660*currentLightEnergy/maxLightEnergy, 20, 660*currentLightEnergy/maxLightEnergy, YELLOW);
+ DrawRectangleLines(GetScreenWidth() - 40, 30, 20, 660, LIGHTGRAY);
+
+ // Show message: "You run out of light!!!" if player.lightEnergy <= 0
+ if (player.lightEnergy < 2)
+ {
+ if ((framesCounter/20)%2) DrawTextEx(font, "YOU'RE RUNNING OUT OF LIGHT!", (Vector2){ 20, 60 }, font.size/2, 0, WHITE);
+ }
+ }
+ else if (!timeOver) // LEVEL_FINISHED
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, 0.4f));
+
+ // Wait some time before jumping to ending: raylib
+ DrawTexture(texRitual, GetScreenWidth()/2 - texRitual.width/2, 100, WHITE);
+ DrawTextEx(font, FormatText("BEST LIGHTING TIME: %02.2f", ritualTime), (Vector2){ 320, 340 }, 50, 0, WHITE);
+ DrawTextEx(font, "PRESS ENTER to START the RITUAL", (Vector2){ 160, 480 }, 60, 0, WHITE);
+
+ if (IsKeyPressed(KEY_ENTER)) startRitual = true;
+ }
+
+ if (timeOver)
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, 0.4f));
+
+ DrawTexture(texTimeOver, GetScreenWidth()/2 - texTimeOver.width/2, 140, WHITE);
+ DrawTextEx(font, FormatText("NEXT STARS ALIGNMENT IN %i YEARS", nextStarsAlignment), (Vector2){ 200, 360 }, 50, 0, WHITE);
+ DrawTextEx(font, "PRESS ENTER to GO HOME...", (Vector2){ 260, 480 }, 60, 0, WHITE);
+
+ if (IsKeyPressed(KEY_ENTER)) finishScreen = 2;
+ }
+
+ if (startRitual) DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, alphaRitual));
+
+ if (pause) DrawTextEx(font, "RITUAL PAUSED", (Vector2){ GetScreenWidth()/2 - MeasureText("RITUAL PAUSED", 40)/2, 110 }, 50, 0, WHITE);
+}
+
+// Gameplay Screen Unload logic
+void UnloadGameplayScreen(void)
+{
+ // Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+ UnloadTexture(foregroundI);
+ UnloadTexture(foregroundII);
+ UnloadTexture(foregroundIII);
+ UnloadTexture(texPlayer);
+ UnloadTexture(texEnemy);
+ UnloadTexture(texLight);
+ UnloadTexture(lightGlow);
+ UnloadTexture(lightRay);
+ UnloadTexture(book);
+ UnloadTexture(texRitual);
+ UnloadTexture(texTimeOver);
+
+ // Unload circles
+ UnloadTexture(circleIoff);
+ UnloadTexture(circleIIoff);
+ UnloadTexture(circleIIIoff);
+ UnloadTexture(circleIon);
+ UnloadTexture(circleIIon);
+ UnloadTexture(circleIIIon);
+
+ // Unload sounds
+ UnloadSound(fxLightOn);
+ UnloadSound(fxLightOff);
+}
+
+// Gameplay Screen should finish?
+int FinishGameplayScreen(void)
+{
+ return finishScreen;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Check two colors if equal
+static bool ColorEqual(Color col1, Color col2)
+{
+ return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a));
+}
+
+// Substract two vectors
+static Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)
+{
+ Vector2 result;
+
+ result.x = v1.x - v2.x;
+ result.y = v1.y - v2.y;
+
+ return result;
+}
+
+// Normalize provided vector
+static void Vector2Normalize(Vector2 *v)
+{
+ float length, ilength;
+
+ length = sqrt(v->x*v->x + v->y*v->y);
+
+ if (length == 0) length = 1.0f;
+
+ ilength = 1.0f/length;
+
+ v->x *= ilength;
+ v->y *= ilength;
+}
+
+// Reset enemy parameters
+// NOTE: Depends on currentLightedLevel
+static void EnemyReset(Enemy *enemy)
+{
+ enemy->active = false;
+ enemy->framesCounter = 0;
+ enemy->color = RED;
+ enemy->radius = 10;
+
+ int side = GetRandomValue(0, 1);
+
+ if (side) enemy->position = (Vector2){ GetRandomValue(50, 150), GetRandomValue(50, GetScreenHeight() - 50) };
+ else enemy->position = (Vector2){ GetRandomValue(GetScreenWidth() - 150, GetScreenWidth() - 50), GetRandomValue(50, GetScreenHeight() - 50) };
+
+ // TODO: Choose only active lights
+ // TODO: if currentLightedLevel has no active lights, choose light from a lower level!
+
+ if (currentLightedLevel == LEVEL_I)
+ {
+ enemy->targetNum = GetRandomValue(0, MAX_LIGHTS_I - 1); // LEVEL_I
+ enemy->targetPos = lightsI[enemy->targetNum].position;
+ enemy->speed = (float)GetRandomValue(15, 20)/10.0f;
+ enemy->awakeFramesDelay = GetRandomValue(90, 400);
+ }
+ else if (currentLightedLevel == LEVEL_II)
+ {
+ enemy->targetNum = GetRandomValue(0, MAX_LIGHTS_II - 1); // LEVEL_II
+ enemy->targetPos = lightsII[enemy->targetNum].position;
+ enemy->speed = (float)GetRandomValue(10, 20)/10.0f;
+ enemy->awakeFramesDelay = GetRandomValue(240, 800);
+ }
+ else if (currentLightedLevel == LEVEL_III)
+ {
+ enemy->targetNum = GetRandomValue(0, MAX_LIGHTS_III - 1); // LEVEL_III
+ enemy->targetPos = lightsIII[enemy->targetNum].position;
+ enemy->speed = (float)GetRandomValue(8, 18)/10.0f;
+ enemy->awakeFramesDelay = GetRandomValue(180, 1200);
+ }
+} \ No newline at end of file
diff --git a/games/light_my_ritual/screens/screen_logo_raylib.c b/games/light_my_ritual/screens/screen_logo_raylib.c
new file mode 100644
index 00000000..40157b10
--- /dev/null
+++ b/games/light_my_ritual/screens/screen_logo_raylib.c
@@ -0,0 +1,214 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Logo Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+#define LOGO_RECS_SIDE 16
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Logo screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static int logoPositionX;
+static int logoPositionY;
+
+static int lettersCount;
+
+static int topSideRecWidth;
+static int leftSideRecHeight;
+
+static int bottomSideRecWidth;
+static int rightSideRecHeight;
+
+static char raylib[8]; // raylib text array, max 8 letters
+static int state; // Tracking animation states (State Machine)
+static float alpha = 1.0f; // Useful for fading
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Logo Screen Initialization logic
+void rlInitLogoScreen(void)
+{
+ // Initialize LOGO screen variables here!
+ finishScreen = 0;
+ framesCounter = 0;
+ lettersCount = 0;
+
+ logoPositionX = GetScreenWidth()/2 - 128;
+ logoPositionY = GetScreenHeight()/2 - 128;
+
+ topSideRecWidth = LOGO_RECS_SIDE;
+ leftSideRecHeight = LOGO_RECS_SIDE;
+ bottomSideRecWidth = LOGO_RECS_SIDE;
+ rightSideRecHeight = LOGO_RECS_SIDE;
+
+ for (int i = 0; i < 8; i++) raylib[i] = '\0';
+
+ state = 0;
+ alpha = 1.0f;
+
+ PlayMusicStream("resources/audio/ambient.ogg");
+ SetMusicVolume(1.0f);
+}
+
+// Logo Screen Update logic
+void rlUpdateLogoScreen(void)
+{
+ // Update LOGO screen variables here!
+ if (state == 0) // State 0: Small box blinking
+ {
+ framesCounter++;
+
+ if (framesCounter == 80)
+ {
+ state = 1;
+ framesCounter = 0; // Reset counter... will be used later...
+ }
+ }
+ else if (state == 1) // State 1: Top and left bars growing
+ {
+ topSideRecWidth += 8;
+ leftSideRecHeight += 8;
+
+ if (topSideRecWidth == 256) state = 2;
+ }
+ else if (state == 2) // State 2: Bottom and right bars growing
+ {
+ bottomSideRecWidth += 8;
+ rightSideRecHeight += 8;
+
+ if (bottomSideRecWidth == 256) state = 3;
+ }
+ else if (state == 3) // State 3: Letters appearing (one by one)
+ {
+ framesCounter++;
+
+ if (framesCounter/10) // Every 12 frames, one more letter!
+ {
+ lettersCount++;
+ framesCounter = 0;
+ }
+
+ switch (lettersCount)
+ {
+ case 1: raylib[0] = 'r'; break;
+ case 2: raylib[1] = 'a'; break;
+ case 3: raylib[2] = 'y'; break;
+ case 4: raylib[3] = 'l'; break;
+ case 5: raylib[4] = 'i'; break;
+ case 6: raylib[5] = 'b'; break;
+ default: break;
+ }
+
+ // When all letters have appeared...
+ if (lettersCount >= 10)
+ {
+ state = 4;
+ framesCounter = 0;
+ }
+ }
+ else if (state == 4)
+ {
+ framesCounter++;
+
+ if (framesCounter > 100)
+ {
+ alpha -= 0.02f;
+
+ if (alpha <= 0.0f)
+ {
+ alpha = 0.0f;
+ finishScreen = 1;
+ }
+ }
+ }
+}
+
+// Logo Screen Draw logic
+void rlDrawLogoScreen(void)
+{
+ if (state == 0)
+ {
+ if ((framesCounter/10)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
+ }
+ else if (state == 1)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+ }
+ else if (state == 2)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+
+ DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
+ }
+ else if (state == 3)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
+ }
+ else if (state == 4)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
+
+ if (framesCounter > 20) DrawText("powered by", logoPositionX, logoPositionY - 27, 20, Fade(DARKGRAY, alpha));
+ }
+}
+
+// Logo Screen Unload logic
+void rlUnloadLogoScreen(void)
+{
+ // TODO: Unload LOGO screen variables here!
+}
+
+// Logo Screen should finish?
+int rlFinishLogoScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/light_my_ritual/screens/screen_title.c b/games/light_my_ritual/screens/screen_title.c
new file mode 100644
index 00000000..c1ecaf12
--- /dev/null
+++ b/games/light_my_ritual/screens/screen_title.c
@@ -0,0 +1,105 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Title Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Title screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+static Texture2D title;
+static float titleAlpha = 0.0f;
+
+static Sound fxStart;
+
+//----------------------------------------------------------------------------------
+// Title Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Title Screen Initialization logic
+void InitTitleScreen(void)
+{
+ // Initialize TITLE screen variables here!
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/back_title.png");
+ title = LoadTexture("resources/textures/title.png");
+
+ fxStart = LoadSound("resources/audio/start.wav");
+}
+
+// Title Screen Update logic
+void UpdateTitleScreen(void)
+{
+ // Update TITLE screen variables here!
+ framesCounter++;
+
+ titleAlpha += 0.005f;
+
+ if (titleAlpha >= 1.0f) titleAlpha = 1.0f;
+
+ // Press enter to change to ATTIC screen
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ PlaySound(fxStart);
+ finishScreen = 1;
+ }
+}
+
+// Title Screen Draw logic
+void DrawTitleScreen(void)
+{
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 26, 26, 26, 255 });
+
+ DrawTexture(background, GetScreenWidth()/2 - background.width/2, 0, WHITE);
+ DrawTexture(title, GetScreenWidth()/2 - title.width/2, 30, Fade(WHITE, titleAlpha));
+
+ DrawText("(c) Developed by Ramon Santamaria (@raysan5)", 20, GetScreenHeight() - 40, 20, LIGHTGRAY);
+
+ if ((framesCounter > 180) && ((framesCounter/40)%2)) DrawTextEx(font, "PRESS ENTER to START LIGHTING", (Vector2){ 230, 450 }, font.size, -2, WHITE);
+}
+
+// Title Screen Unload logic
+void UnloadTitleScreen(void)
+{
+ // Unload TITLE screen variables here!
+ UnloadTexture(background);
+ UnloadTexture(title);
+
+ UnloadSound(fxStart);
+}
+
+// Title Screen should finish?
+int FinishTitleScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/light_my_ritual/screens/screens.h b/games/light_my_ritual/screens/screens.h
new file mode 100644
index 00000000..8fee5274
--- /dev/null
+++ b/games/light_my_ritual/screens/screens.h
@@ -0,0 +1,78 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Screens Functions Declarations (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef SCREENS_H
+#define SCREENS_H
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum GameScreen { LOGO_RL = 0, TITLE, GAMEPLAY } GameScreen;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+GameScreen currentScreen;
+SpriteFont font;
+
+Color *lightsMap;
+int lightsMapWidth, lightsMapHeight;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// raylib Logo Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void rlInitLogoScreen(void);
+void rlUpdateLogoScreen(void);
+void rlDrawLogoScreen(void);
+void rlUnloadLogoScreen(void);
+int rlFinishLogoScreen(void);
+
+//----------------------------------------------------------------------------------
+// Title Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitTitleScreen(void);
+void UpdateTitleScreen(void);
+void DrawTitleScreen(void);
+void UnloadTitleScreen(void);
+int FinishTitleScreen(void);
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitGameplayScreen(void);
+void UpdateGameplayScreen(void);
+void DrawGameplayScreen(void);
+void UnloadGameplayScreen(void);
+int FinishGameplayScreen(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SCREENS_H \ No newline at end of file
diff --git a/games/makefile b/games/makefile
new file mode 100644
index 00000000..2d992896
--- /dev/null
+++ b/games/makefile
@@ -0,0 +1,254 @@
+#**************************************************************************************************
+#
+# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten)
+#
+# Copyright (c) 2015 Ramon Santamaria (@raysan5)
+#
+# This software is provided "as-is", without any express or implied warranty. In no event
+# will the authors be held liable for any damages arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose, including commercial
+# applications, and to alter it and redistribute it freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not claim that you
+# wrote the original software. If you use this software in a product, an acknowledgment
+# in the product documentation would be appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+# as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+#
+#**************************************************************************************************
+
+# define raylib platform to compile for
+# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
+# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
+PLATFORM ?= PLATFORM_DESKTOP
+
+# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ LIBPATH=win32
+ else
+ UNAMEOS:=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ LIBPATH=linux
+ else
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ LIBPATH=osx
+ endif
+ endif
+ endif
+endif
+
+# define compiler: gcc for C program, define as g++ for C++
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # define emscripten compiler
+ CC = emcc
+else
+ifeq ($(PLATFORM_OS),OSX)
+ # define llvm compiler for mac
+ CC = clang
+else
+ # define default gcc compiler
+ CC = gcc
+endif
+endif
+
+# define compiler flags:
+# -O2 defines optimization level
+# -Wall turns on most, but not all, compiler warnings
+# -std=c99 use standard C from 1999 revision
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
+else
+ CFLAGS = -O2 -Wall -std=c99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --shell-file ../../templates/web_shell/shell.html
+ #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it)
+ #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
+ #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+endif
+
+#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
+
+# define any directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ INCLUDES = -I. -I../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+else
+ INCLUDES = -I. -I../src
+# external libraries headers
+# GLFW3
+ INCLUDES += -I../external/glfw3/include
+# GLEW - Not required any more, replaced by GLAD
+ #INCLUDES += -I../external/glew/include
+# OpenAL Soft
+ INCLUDES += -I../external/openal_soft/include
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ LFLAGS = -L. -L../src -L/opt/vc/lib
+else
+ LFLAGS = -L. -L../src
+# external libraries to link with
+ # GLFW3
+ LFLAGS += -L../external/glfw3/lib/$(LIBPATH)
+ ifneq ($(PLATFORM_OS),OSX)
+ # OpenAL Soft
+ LFLAGS += -L../external/openal_soft/lib/$(LIBPATH)
+ # GLEW: Not used, replaced by GLAD
+ #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+ endif
+endif
+
+# define any libraries to link into executable
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ # libraries for Debian GNU/Linux desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
+ # on XWindow could require also below libraries, just uncomment
+ #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+ else
+ ifeq ($(PLATFORM_OS),OSX)
+ # libraries for OS X 10.9 desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
+ else
+ # libraries for Windows desktop compiling
+ # NOTE: GLFW3 and OpenAL Soft libraries should be installed
+ LIBS = -lraylib -lglfw3 -lopengl32 -lopenal32 -lgdi32
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # libraries for Raspberry Pi compiling
+ # NOTE: OpenAL Soft library should be installed (libopenal1 package)
+ LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # NOTE: Set the correct path to libraylib.bc
+ LIBS = ../src/libraylib.bc
+endif
+
+# define additional parameters and flags for windows
+ifeq ($(PLATFORM_OS),WINDOWS)
+ # resources file contains windows exe icon
+ # -Wl,--subsystem,windows hides the console window
+ WINFLAGS = ../src/resources -Wl,--subsystem,windows
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ EXT = .html
+endif
+
+# define all object files required
+SAMPLES = \
+ arkanoid \
+ asteroids \
+ asteroids_survival \
+ floppy \
+ gold_fever \
+ gorilas \
+ missile_commander \
+ pang \
+ snake \
+ space_invaders \
+ tetris \
+ fix_dylib \
+
+
+# typing 'make' will invoke the first target entry in the file,
+# in this case, the 'default' target entry is raylib
+default: samples
+
+# compile all game samples
+samples: $(SAMPLES)
+
+# compile game sample - arkanoid
+arkanoid: arkanoid.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - steroids
+asteroids: asteroids.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - asteroids_survival
+asteroids_survival: asteroids_survival.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - floppy
+floppy: floppy.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - gold_fever
+gold_fever: gold_fever.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - gorilas
+gorilas: gorilas.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - missile_commander
+missile_commander: missile_commander.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - pang
+pang: pang.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - snake
+snake: snake.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - space_invaders
+space_invaders: space_invaders.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile game sample - tetris
+tetris: tetris.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# fix dylib install path name for each executable (MAC)
+fix_dylib:
+ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -print0 | xargs -t -0 -R 1 -I file install_name_tool -change libglfw.3.0.dylib ../external/glfw3/lib/osx/libglfw.3.0.dylib file
+endif
+
+# clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ else
+ ifeq ($(PLATFORM_OS),LINUX)
+ find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
+ else
+ del *.o *.exe
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
+ rm -f *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
+endif
+ @echo Cleaning done
+
+# instead of defining every module one by one, we can define a pattern
+# this pattern below will automatically compile every module defined on $(OBJS)
+#%.exe : %.c
+# $(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM)
diff --git a/games/missile_commander.c b/games/missile_commander.c
new file mode 100644
index 00000000..6317c41a
--- /dev/null
+++ b/games/missile_commander.c
@@ -0,0 +1,539 @@
+/*******************************************************************************************
+*
+* raylib - sample game: missile commander
+*
+* Sample game Marc Palau and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define MAX_MISSILES 100
+#define MAX_INTERCEPTORS 30
+#define MAX_EXPLOSIONS 100
+#define LAUNCHERS_AMOUNT 3 // Not a variable, should not be changed
+#define BUILDINGS_AMOUNT 6 // Not a variable, should not be changed
+
+#define LAUNCHER_SIZE 80
+#define BUILDING_SIZE 60
+#define EXPLOSION_RADIUS 40
+
+#define MISSILE_SPEED 1
+#define MISSILE_LAUNCH_FRAMES 80
+#define INTERCEPTOR_SPEED 10
+#define EXPLOSION_INCREASE_TIME 90 // In frames
+#define EXPLOSION_TOTAL_TIME 210 // In frames
+
+#define EXPLOSION_COLOR (Color){ 125, 125, 125, 125 }
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Missile {
+ Vector2 origin;
+ Vector2 position;
+ Vector2 objective;
+ Vector2 speed;
+
+ bool active;
+} Missile;
+
+typedef struct Interceptor {
+ Vector2 origin;
+ Vector2 position;
+ Vector2 objective;
+ Vector2 speed;
+
+ bool active;
+} Interceptor;
+
+typedef struct Explosion {
+ Vector2 position;
+ float radiusMultiplier;
+ int frame;
+ bool active;
+} Explosion;
+
+typedef struct Launcher {
+ Vector2 position;
+ bool active;
+} Launcher;
+
+typedef struct Building {
+ Vector2 position;
+ bool active;
+} Building;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter = 0;
+static bool gameOver = false;
+static bool pause = false;
+static int score = 0;
+
+static Missile missile[MAX_MISSILES];
+static Interceptor interceptor[MAX_INTERCEPTORS];
+static Explosion explosion[MAX_EXPLOSIONS];
+static Launcher launcher[LAUNCHERS_AMOUNT];
+static Building building[BUILDINGS_AMOUNT];
+static int explosionIndex = 0;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+// Additional module functions
+static void UpdateOutgoingFire();
+static void UpdateIncomingFire();
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: missile commander");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//--------------------------------------------------------------------------------------
+// Game Module Functions Definition
+//--------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ // Initialize missiles
+ for (int i = 0; i < MAX_MISSILES; i++)
+ {
+ missile[i].origin = (Vector2){ 0, 0 };
+ missile[i].speed = (Vector2){ 0, 0 };
+ missile[i].position = (Vector2){ 0, 0 };
+
+ missile[i].active = false;
+ }
+
+ // Initialize interceptors
+ for (int i = 0; i < MAX_INTERCEPTORS; i++)
+ {
+ interceptor[i].origin = (Vector2){ 0, 0 };
+ interceptor[i].speed = (Vector2){ 0, 0 };
+ interceptor[i].position = (Vector2){ 0, 0 };
+
+ interceptor[i].active = false;
+ }
+
+ // Initialize explosions
+ for (int i = 0; i < MAX_EXPLOSIONS; i++)
+ {
+ explosion[i].position = (Vector2){ 0, 0 };
+ explosion[i].frame = 0;
+ explosion[i].active = false;
+ }
+
+ // Initialize buildings and launchers
+ int sparcing = screenWidth/(LAUNCHERS_AMOUNT + BUILDINGS_AMOUNT + 1);
+
+ // Buildings and launchers placing
+ launcher[0].position = (Vector2){ 1*sparcing, screenHeight - LAUNCHER_SIZE/2 };
+ building[0].position = (Vector2){ 2*sparcing, screenHeight - BUILDING_SIZE/2 };
+ building[1].position = (Vector2){ 3*sparcing, screenHeight - BUILDING_SIZE/2 };
+ building[2].position = (Vector2){ 4*sparcing, screenHeight - BUILDING_SIZE/2 };
+ launcher[1].position = (Vector2){ 5*sparcing, screenHeight - LAUNCHER_SIZE/2 };
+ building[3].position = (Vector2){ 6*sparcing, screenHeight - BUILDING_SIZE/2 };
+ building[4].position = (Vector2){ 7*sparcing, screenHeight - BUILDING_SIZE/2 };
+ building[5].position = (Vector2){ 8*sparcing, screenHeight - BUILDING_SIZE/2 };
+ launcher[2].position = (Vector2){ 9*sparcing, screenHeight - LAUNCHER_SIZE/2 };
+
+ // Buildings and launchers activation
+ for (int i = 0; i < LAUNCHERS_AMOUNT; i++) launcher[i].active = true;
+ for (int i = 0; i < BUILDINGS_AMOUNT; i++) building[i].active = true;
+
+ // Initialize game variables
+ score = 0;
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ framesCounter++;
+
+ static
+ float distance;
+
+ // Interceptors update
+ for (int i = 0; i < MAX_INTERCEPTORS; i++)
+ {
+ if (interceptor[i].active)
+ {
+ // Update position
+ interceptor[i].position.x += interceptor[i].speed.x;
+ interceptor[i].position.y += interceptor[i].speed.y;
+
+ // Distance to objective
+ distance = sqrt( pow(interceptor[i].position.x - interceptor[i].objective.x, 2) +
+ pow(interceptor[i].position.y - interceptor[i].objective.y, 2));
+
+ if (distance < INTERCEPTOR_SPEED)
+ {
+ // Interceptor dissapears
+ interceptor[i].active = false;
+
+ // Explosion
+ explosion[explosionIndex].position = interceptor[i].position;
+ explosion[explosionIndex].active = true;
+ explosion[explosionIndex].frame = 0;
+ explosionIndex++;
+ if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0;
+
+ break;
+ }
+ }
+ }
+
+ // Missiles update
+ for (int i = 0; i < MAX_MISSILES; i++)
+ {
+ if (missile[i].active)
+ {
+ // Update position
+ missile[i].position.x += missile[i].speed.x;
+ missile[i].position.y += missile[i].speed.y;
+
+ // Collision and missile out of bounds
+ if (missile[i].position.y > screenHeight) missile[i].active = false;
+ else
+ {
+ // CHeck collision with launchers
+ for (int j = 0; j < LAUNCHERS_AMOUNT; j++)
+ {
+ if (launcher[j].active)
+ {
+ if (CheckCollisionPointRec(missile[i].position, (Rectangle){ launcher[j].position.x - LAUNCHER_SIZE/2, launcher[j].position.y - LAUNCHER_SIZE/2,
+ LAUNCHER_SIZE, LAUNCHER_SIZE }))
+ {
+ // Missile dissapears
+ missile[i].active = false;
+
+ // Explosion and destroy building
+ launcher[j].active = false;
+
+ explosion[explosionIndex].position = missile[i].position;
+ explosion[explosionIndex].active = true;
+ explosion[explosionIndex].frame = 0;
+ explosionIndex++;
+ if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0;
+
+ break;
+ }
+ }
+ }
+
+ // CHeck collision with buildings
+ for (int j = 0; j < BUILDINGS_AMOUNT; j++)
+ {
+ if (building[j].active)
+ {
+ if (CheckCollisionPointRec(missile[i].position, (Rectangle){ building[j].position.x - BUILDING_SIZE/2, building[j].position.y - BUILDING_SIZE/2,
+ BUILDING_SIZE, BUILDING_SIZE }))
+ {
+ // Missile dissapears
+ missile[i].active = false;
+
+ // Explosion and destroy building
+ building[j].active = false;
+
+ explosion[explosionIndex].position = missile[i].position;
+ explosion[explosionIndex].active = true;
+ explosion[explosionIndex].frame = 0;
+ explosionIndex++;
+ if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0;
+
+ break;
+ }
+ }
+ }
+
+ // CHeck collision with explosions
+ for (int j = 0; j < MAX_EXPLOSIONS; j++)
+ {
+ if (explosion[j].active)
+ {
+ if (CheckCollisionPointCircle(missile[i].position, explosion[j].position, EXPLOSION_RADIUS*explosion[j].radiusMultiplier))
+ {
+ // Missile dissapears and we earn 100 points
+ missile[i].active = false;
+ score += 100;
+
+ explosion[explosionIndex].position = missile[i].position;
+ explosion[explosionIndex].active = true;
+ explosion[explosionIndex].frame = 0;
+ explosionIndex++;
+ if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Explosions update
+ for (int i = 0; i < MAX_EXPLOSIONS; i++)
+ {
+ if (explosion[i].active)
+ {
+ explosion[i].frame++;
+
+ if (explosion[i].frame <= EXPLOSION_INCREASE_TIME) explosion[i].radiusMultiplier = explosion[i].frame/(float)EXPLOSION_INCREASE_TIME;
+ else if (explosion[i].frame <= EXPLOSION_TOTAL_TIME) explosion[i].radiusMultiplier = 1 - (explosion[i].frame - (float)EXPLOSION_INCREASE_TIME)/(float)EXPLOSION_TOTAL_TIME;
+ else
+ {
+ explosion[i].frame = 0;
+ explosion[i].active = false;
+ }
+ }
+ }
+
+ // Fire logic
+ UpdateOutgoingFire();
+ UpdateIncomingFire();
+
+ // Game over logic
+ int checker = 0;
+
+ for (int i = 0; i < LAUNCHERS_AMOUNT; i++)
+ {
+ if (!launcher[i].active) checker++;
+ if (checker == LAUNCHERS_AMOUNT) gameOver = true;
+ }
+
+ checker = 0;
+ for (int i = 0; i < BUILDINGS_AMOUNT; i++)
+ {
+ if (!building[i].active) checker++;
+ if (checker == BUILDINGS_AMOUNT) gameOver = true;
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw missiles
+ for (int i = 0; i < MAX_MISSILES; i++)
+ {
+ if (missile[i].active)
+ {
+ DrawLine(missile[i].origin.x, missile[i].origin.y, missile[i].position.x, missile[i].position.y, RED);
+
+ if (framesCounter % 16 < 8) DrawCircle(missile[i].position.x, missile[i].position.y, 3, YELLOW);
+ }
+ }
+
+ // Draw interceptors
+ for (int i = 0; i < MAX_INTERCEPTORS; i++)
+ {
+ if (interceptor[i].active)
+ {
+ DrawLine(interceptor[i].origin.x, interceptor[i].origin.y, interceptor[i].position.x, interceptor[i].position.y, GREEN);
+
+ if (framesCounter % 16 < 8) DrawCircle(interceptor[i].position.x, interceptor[i].position.y, 3, BLUE);
+ }
+ }
+
+ // Draw explosions
+ for (int i = 0; i < MAX_EXPLOSIONS; i++)
+ {
+ if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, EXPLOSION_RADIUS*explosion[i].radiusMultiplier, EXPLOSION_COLOR);
+ }
+
+ // Draw buildings and launchers
+ for (int i = 0; i < LAUNCHERS_AMOUNT; i++)
+ {
+ if (launcher[i].active) DrawRectangle(launcher[i].position.x - LAUNCHER_SIZE/2, launcher[i].position.y - LAUNCHER_SIZE/2, LAUNCHER_SIZE, LAUNCHER_SIZE, GRAY);
+ }
+
+ for (int i = 0; i < BUILDINGS_AMOUNT; i++)
+ {
+ if (building[i].active) DrawRectangle(building[i].position.x - BUILDING_SIZE/2, building[i].position.y - BUILDING_SIZE/2, BUILDING_SIZE, BUILDING_SIZE, LIGHTGRAY);
+ }
+
+ // Draw score
+ DrawText(FormatText("SCORE %4i", score), 20, 20, 40, LIGHTGRAY);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+}
+
+//--------------------------------------------------------------------------------------
+// Additional module functions
+//--------------------------------------------------------------------------------------
+static void UpdateOutgoingFire()
+{
+ static int interceptorNumber = 0;
+ int launcherShooting = 0;
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) launcherShooting = 1;
+ if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) launcherShooting = 2;
+ if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) launcherShooting = 3;
+
+ if (launcherShooting > 0 && launcher[launcherShooting - 1].active)
+ {
+ float module;
+ float sideX;
+ float sideY;
+
+ // Activate the interceptor
+ interceptor[interceptorNumber].active = true;
+
+ // Assign start position
+ interceptor[interceptorNumber].origin = launcher[launcherShooting - 1].position;
+ interceptor[interceptorNumber].position = interceptor[interceptorNumber].origin;
+ interceptor[interceptorNumber].objective = GetMousePosition();
+
+ // Calculate speed
+ module = sqrt( pow(interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x, 2) +
+ pow(interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y, 2));
+
+ sideX = (interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x)*INTERCEPTOR_SPEED/module;
+ sideY = (interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y)*INTERCEPTOR_SPEED/module;
+
+ interceptor[interceptorNumber].speed = (Vector2){ sideX, sideY };
+
+ // Update
+ interceptorNumber++;
+ if (interceptorNumber == MAX_INTERCEPTORS) interceptorNumber = 0;
+ }
+}
+
+static void UpdateIncomingFire()
+{
+ static int missileIndex = 0;
+
+ // Launch missile
+ if (framesCounter % MISSILE_LAUNCH_FRAMES == 0)
+ {
+ float module;
+ float sideX;
+ float sideY;
+
+ // Activate the missile
+ missile[missileIndex].active = true;
+
+ // Assign start position
+ missile[missileIndex].origin = (Vector2){ GetRandomValue(20, screenWidth - 20), -10 };
+ missile[missileIndex].position = missile[missileIndex].origin;
+ missile[missileIndex].objective = (Vector2){ GetRandomValue(20, screenWidth - 20), screenHeight + 10 };
+
+ // Calculate speed
+ module = sqrt( pow(missile[missileIndex].objective.x - missile[missileIndex].origin.x, 2) +
+ pow(missile[missileIndex].objective.y - missile[missileIndex].origin.y, 2));
+
+ sideX = (missile[missileIndex].objective.x - missile[missileIndex].origin.x)*MISSILE_SPEED/module;
+ sideY = (missile[missileIndex].objective.y - missile[missileIndex].origin.y)*MISSILE_SPEED/module;
+
+ missile[missileIndex].speed = (Vector2){ sideX, sideY };
+
+ // Update
+ missileIndex++;
+ if (missileIndex == MAX_MISSILES) missileIndex = 0;
+ }
+} \ No newline at end of file
diff --git a/games/pang.c b/games/pang.c
new file mode 100644
index 00000000..fe1c3005
--- /dev/null
+++ b/games/pang.c
@@ -0,0 +1,630 @@
+/*******************************************************************************************
+*
+* raylib - sample game: pang
+*
+* Sample game developed by Ian Eito and Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define PLAYER_BASE_SIZE 20.0f
+#define PLAYER_SPEED 5.0f
+#define PLAYER_MAX_SHOOTS 1
+
+#define MAX_BIG_BALLS 2
+#define BALLS_SPEED 2.0f
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+typedef struct Player {
+ Vector2 position;
+ Vector2 speed;
+ Vector3 collider;
+ float rotation;
+} Player;
+
+typedef struct Shoot {
+ Vector2 position;
+ Vector2 speed;
+ float radius;
+ float rotation;
+ int lifeSpawn;
+ bool active;
+} Shoot;
+
+typedef struct Ball {
+ Vector2 position;
+ Vector2 speed;
+ float radius;
+ int points;
+ bool active;
+} Ball;
+
+typedef struct Points {
+ Vector2 position;
+ int value;
+ float alpha;
+} Points;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+static int score;
+
+static Player player;
+static Shoot shoot[PLAYER_MAX_SHOOTS];
+static Ball bigBalls[MAX_BIG_BALLS];
+static Ball mediumBalls[MAX_BIG_BALLS*2];
+static Ball smallBalls[MAX_BIG_BALLS*4];
+static Points points[5];
+
+// NOTE: Defined triangle is isosceles with common angles of 70 degrees.
+static float shipHeight;
+static float gravity;
+
+static int countmediumBallss;
+static int countsmallBallss;
+static int meteorsDestroyed;
+static Vector2 linePosition;
+
+static bool victory;
+static bool lose;
+static bool awake;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ InitWindow(screenWidth, screenHeight, "sample game: pang");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+static void InitGame(void)
+{
+ int posx, posy;
+ int velx = 0;
+ int vely = 0;
+
+ framesCounter = 0;
+ gameOver = false;
+ pause = false;
+ score = 0;
+
+ victory = false;
+ lose = false;
+ awake = true;
+ gravity = 0.25f;
+
+ linePosition = (Vector2){ 0.0f , 0.0f };
+ shipHeight = (PLAYER_BASE_SIZE/2)/tanf(20*DEG2RAD);
+
+ // Initialization player
+ player.position = (Vector2){ screenWidth/2, screenHeight };
+ player.speed = (Vector2){ PLAYER_SPEED, PLAYER_SPEED };
+ player.rotation = 0;
+ player.collider = (Vector3){ player.position.x, player.position.y - shipHeight/2.0f, 12.0f };
+
+ meteorsDestroyed = 0;
+
+ // Initialize shoots
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ shoot[i].position = (Vector2){ 0, 0 };
+ shoot[i].speed = (Vector2){ 0, 0 };
+ shoot[i].radius = 2;
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ }
+
+ // Initialize big meteors
+ for (int i = 0; i < MAX_BIG_BALLS; i++)
+ {
+ bigBalls[i].radius = 40.0f;
+ posx = GetRandomValue(0 + bigBalls[i].radius, screenWidth - bigBalls[i].radius);
+ posy = GetRandomValue(0 + bigBalls[i].radius, screenHeight/2);
+
+ bigBalls[i].position = (Vector2){ posx, posy };
+
+ while ((velx == 0) || (vely == 0))
+ {
+ velx = GetRandomValue(-BALLS_SPEED, BALLS_SPEED);
+ vely = GetRandomValue(-BALLS_SPEED, BALLS_SPEED);
+ }
+
+ bigBalls[i].speed = (Vector2){ velx, vely };
+ bigBalls[i].points = 200;
+ bigBalls[i].active = true;
+ }
+
+ // Initialize medium meteors
+ for (int i = 0; i < MAX_BIG_BALLS*2; i++)
+ {
+ mediumBalls[i].position = (Vector2){-100, -100};
+ mediumBalls[i].speed = (Vector2){0,0};
+ mediumBalls[i].radius = 20.0f;
+ mediumBalls[i].points = 100;
+ mediumBalls[i].active = false;
+ }
+
+ // Initialize small meteors
+ for (int i = 0; i < MAX_BIG_BALLS*4; i++)
+ {
+ smallBalls[i].position = (Vector2){ -100, -100 };
+ smallBalls[i].speed = (Vector2){ 0, 0 };
+ smallBalls[i].radius = 10.0f;
+ smallBalls[i].points = 50;
+ smallBalls[i].active = false;
+ }
+
+ // Initialize animated points
+ for (int i = 0; i < 5; i++)
+ {
+ points[i].position = (Vector2){ 0, 0 };
+ points[i].value = 0;
+ points[i].alpha = 0.0f;
+ }
+
+ countmediumBallss = 0;
+ countsmallBallss = 0;
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver && !victory)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ // Player logic
+ if (IsKeyDown(KEY_LEFT)) player.position.x -= player.speed.x;
+ if (IsKeyDown(KEY_RIGHT)) player.position.x += player.speed.x;
+
+ // Player vs wall collision logic
+ if (player.position.x + PLAYER_BASE_SIZE/2 > screenWidth) player.position.x = screenWidth - PLAYER_BASE_SIZE/2;
+ else if (player.position.x - PLAYER_BASE_SIZE/2 < 0) player.position.x = 0 + PLAYER_BASE_SIZE/2;
+
+ // Player shot logic
+ if (IsKeyPressed(KEY_SPACE))
+ {
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (!shoot[i].active)
+ {
+ shoot[i].position = (Vector2){ player.position.x, player.position.y - shipHeight };
+ shoot[i].speed.y = PLAYER_SPEED;
+ shoot[i].active = true;
+
+ linePosition = (Vector2){ player.position.x, player.position.y};
+
+ break;
+ }
+ }
+ }
+
+ // Shoot life timer
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (shoot[i].active) shoot[i].lifeSpawn++;
+ }
+
+ // Shot logic
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (shoot[i].active)
+ {
+ shoot[i].position.y -= shoot[i].speed.y;
+
+ // Shot vs walls collision logic
+ if ((shoot[i].position.x > screenWidth + shoot[i].radius) || (shoot[i].position.x < 0 - shoot[i].radius) ||
+ (shoot[i].position.y > screenHeight + shoot[i].radius) || (shoot[i].position.y < 0 - shoot[i].radius))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ }
+
+ // Player shot life spawn
+ if (shoot[i].lifeSpawn >= 120)
+ {
+ shoot[i].position = (Vector2){ 0.0f, 0.0f };
+ shoot[i].speed = (Vector2){ 0.0f, 0.0f };
+ shoot[i].lifeSpawn = 0;
+ shoot[i].active = false;
+ }
+ }
+ }
+
+ // Player vs meteors collision logic
+ player.collider = (Vector3){player.position.x, player.position.y - shipHeight/2, 12};
+
+ for (int i = 0; i < MAX_BIG_BALLS; i++)
+ {
+ if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, bigBalls[i].position, bigBalls[i].radius) && bigBalls[i].active)
+ {
+ gameOver = true;
+ }
+ }
+
+ for (int i = 0; i < MAX_BIG_BALLS*2; i++)
+ {
+ if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, mediumBalls[i].position, mediumBalls[i].radius) && mediumBalls[i].active)
+ {
+ gameOver = true;
+ }
+ }
+
+ for (int i = 0; i < MAX_BIG_BALLS*4; i++)
+ {
+ if (CheckCollisionCircles((Vector2){ player.collider.x, player.collider.y }, player.collider.z, smallBalls[i].position, smallBalls[i].radius) && smallBalls[i].active)
+ {
+ gameOver = true;
+ }
+ }
+
+ // Meteors logic (big)
+ for (int i = 0; i < MAX_BIG_BALLS; i++)
+ {
+ if (bigBalls[i].active)
+ {
+ // Meteor movement logic
+ bigBalls[i].position.x += bigBalls[i].speed.x;
+ bigBalls[i].position.y += bigBalls[i].speed.y;
+
+ // Meteor vs wall collision logic
+ if (((bigBalls[i].position.x + bigBalls[i].radius) >= screenWidth) || ((bigBalls[i].position.x - bigBalls[i].radius) <= 0)) bigBalls[i].speed.x *= -1;
+ if ((bigBalls[i].position.y - bigBalls[i].radius) <= 0) bigBalls[i].speed.y *= -1.5;
+
+ if ((bigBalls[i].position.y + bigBalls[i].radius) >= screenHeight)
+ {
+ bigBalls[i].speed.y *= -1;
+ bigBalls[i].position.y = screenHeight - bigBalls[i].radius;
+ }
+
+ bigBalls[i].speed.y += gravity;
+ }
+ }
+
+ // Meteors logic (medium)
+ for (int i = 0; i < MAX_BIG_BALLS*2; i++)
+ {
+ if (mediumBalls[i].active)
+ {
+ // Meteor movement logic
+ mediumBalls[i].position.x += mediumBalls[i].speed.x;
+ mediumBalls[i].position.y += mediumBalls[i].speed.y;
+
+ // Meteor vs wall collision logic
+ if (mediumBalls[i].position.x + mediumBalls[i].radius >= screenWidth || mediumBalls[i].position.x - mediumBalls[i].radius <= 0) mediumBalls[i].speed.x *= -1;
+ if (mediumBalls[i].position.y - mediumBalls[i].radius <= 0) mediumBalls[i].speed.y *= -1;
+ if (mediumBalls[i].position.y + mediumBalls[i].radius >= screenHeight)
+ {
+ mediumBalls[i].speed.y *= -1;
+ mediumBalls[i].position.y = screenHeight - mediumBalls[i].radius;
+ }
+
+ mediumBalls[i].speed.y += gravity + 0.12f;
+ }
+ }
+
+ // Meteors logic (small)
+ for (int i = 0; i < MAX_BIG_BALLS*4; i++)
+ {
+ if (smallBalls[i].active)
+ {
+ // Meteor movement logic
+ smallBalls[i].position.x += smallBalls[i].speed.x;
+ smallBalls[i].position.y += smallBalls[i].speed.y;
+
+ // Meteor vs wall collision logic
+ if (smallBalls[i].position.x + smallBalls[i].radius >= screenWidth || smallBalls[i].position.x - smallBalls[i].radius <= 0) smallBalls[i].speed.x *= -1;
+ if (smallBalls[i].position.y - smallBalls[i].radius <= 0) smallBalls[i].speed.y *= -1;
+ if (smallBalls[i].position.y + smallBalls[i].radius >= screenHeight)
+ {
+ smallBalls[i].speed.y *= -1;
+ smallBalls[i].position.y = screenHeight - smallBalls[i].radius;
+ }
+
+ smallBalls[i].speed.y += gravity + 0.25f;
+ }
+ }
+
+ // Player-shot vs meteors logic
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if ((shoot[i].active))
+ {
+ for (int a = 0; a < MAX_BIG_BALLS; a++)
+ {
+ if (bigBalls[a].active && (bigBalls[a].position.x - bigBalls[a].radius <= linePosition.x && bigBalls[a].position.x + bigBalls[a].radius >= linePosition.x)
+ && (bigBalls[a].position.y + bigBalls[a].radius >= shoot[i].position.y))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ bigBalls[a].active = false;
+ meteorsDestroyed++;
+ score += bigBalls[a].points;
+
+ for (int z = 0; z < 5; z++)
+ {
+ if (points[z].alpha == 0.0f)
+ {
+ points[z].position = bigBalls[a].position;
+ points[z].value = bigBalls[a].points;
+ points[z].alpha = 1.0f;
+ z = 5;
+ }
+ }
+
+ for (int j = 0; j < 2; j ++)
+ {
+ if ((countmediumBallss%2) == 0)
+ {
+ mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y};
+ mediumBalls[countmediumBallss].speed = (Vector2){ -1*BALLS_SPEED, BALLS_SPEED };
+ }
+ else
+ {
+ mediumBalls[countmediumBallss].position = (Vector2){bigBalls[a].position.x, bigBalls[a].position.y};
+ mediumBalls[countmediumBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED };
+ }
+
+ mediumBalls[countmediumBallss].active = true;
+ countmediumBallss ++;
+ }
+
+ a = MAX_BIG_BALLS;
+ }
+ }
+ }
+
+ if ((shoot[i].active))
+ {
+ for (int b = 0; b < MAX_BIG_BALLS*2; b++)
+ {
+ if (mediumBalls[b].active && (mediumBalls[b].position.x - mediumBalls[b].radius <= linePosition.x && mediumBalls[b].position.x + mediumBalls[b].radius >= linePosition.x)
+ && (mediumBalls[b].position.y + mediumBalls[b].radius >= shoot[i].position.y))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ mediumBalls[b].active = false;
+ meteorsDestroyed++;
+ score += mediumBalls[b].points;
+
+ for (int z = 0; z < 5; z++)
+ {
+ if (points[z].alpha == 0.0f)
+ {
+ points[z].position = mediumBalls[b].position;
+ points[z].value = mediumBalls[b].points;
+ points[z].alpha = 1.0f;
+ z = 5;
+ }
+ }
+
+ for (int j = 0; j < 2; j ++)
+ {
+ if (countsmallBallss%2 == 0)
+ {
+ smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y};
+ smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED*-1, BALLS_SPEED*-1};
+ }
+ else
+ {
+ smallBalls[countsmallBallss].position = (Vector2){mediumBalls[b].position.x, mediumBalls[b].position.y};
+ smallBalls[countsmallBallss].speed = (Vector2){ BALLS_SPEED, BALLS_SPEED*-1};
+ }
+
+ smallBalls[countsmallBallss].active = true;
+ countsmallBallss ++;
+ }
+
+ b = MAX_BIG_BALLS*2;
+ }
+ }
+ }
+
+ if ((shoot[i].active))
+ {
+ for (int c = 0; c < MAX_BIG_BALLS*4; c++)
+ {
+ if (smallBalls[c].active && (smallBalls[c].position.x - smallBalls[c].radius <= linePosition.x && smallBalls[c].position.x + smallBalls[c].radius >= linePosition.x)
+ && (smallBalls[c].position.y + smallBalls[c].radius >= shoot[i].position.y))
+ {
+ shoot[i].active = false;
+ shoot[i].lifeSpawn = 0;
+ smallBalls[c].active = false;
+ meteorsDestroyed++;
+ score += smallBalls[c].points;
+
+ for (int z = 0; z < 5; z++)
+ {
+ if (points[z].alpha == 0.0f)
+ {
+ points[z].position = smallBalls[c].position;
+ points[z].value = smallBalls[c].points;
+ points[z].alpha = 1.0f;
+ z = 5;
+ }
+ }
+
+ c = MAX_BIG_BALLS*4;
+ }
+ }
+ }
+ }
+
+ if (meteorsDestroyed == (MAX_BIG_BALLS + MAX_BIG_BALLS*2 + MAX_BIG_BALLS*4)) victory = true;
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+
+ // Points move-up and fade logic
+ for (int z = 0; z < 5; z++)
+ {
+ if (points[z].alpha > 0.0f)
+ {
+ points[z].position.y -= 2;
+ points[z].alpha -= 0.02f;
+ }
+
+ if (points[z].alpha < 0.0f) points[z].alpha = 0.0f;
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw player
+ Vector2 v1 = { player.position.x + sinf(player.rotation*DEG2RAD)*(shipHeight), player.position.y - cosf(player.rotation*DEG2RAD)*(shipHeight) };
+ Vector2 v2 = { player.position.x - cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y - sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) };
+ Vector2 v3 = { player.position.x + cosf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2), player.position.y + sinf(player.rotation*DEG2RAD)*(PLAYER_BASE_SIZE/2) };
+ DrawTriangle(v1, v2, v3, MAROON);
+
+ // Draw meteors (big)
+ for (int i = 0;i < MAX_BIG_BALLS; i++)
+ {
+ if (bigBalls[i].active) DrawCircleV(bigBalls[i].position, bigBalls[i].radius, DARKGRAY);
+ else DrawCircleV(bigBalls[i].position, bigBalls[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ // Draw meteors (medium)
+ for (int i = 0;i < MAX_BIG_BALLS*2; i++)
+ {
+ if (mediumBalls[i].active) DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, GRAY);
+ else DrawCircleV(mediumBalls[i].position, mediumBalls[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ // Draw meteors (small)
+ for (int i = 0;i < MAX_BIG_BALLS*4; i++)
+ {
+ if (smallBalls[i].active) DrawCircleV(smallBalls[i].position, smallBalls[i].radius, GRAY);
+ else DrawCircleV(smallBalls[i].position, smallBalls[i].radius, Fade(LIGHTGRAY, 0.3f));
+ }
+
+ // Draw shoot
+ for (int i = 0; i < PLAYER_MAX_SHOOTS; i++)
+ {
+ if (shoot[i].active) DrawLine(linePosition.x, linePosition.y, shoot[i].position.x, shoot[i].position.y, RED);
+ }
+
+ // Draw score points
+ for (int z = 0; z < 5; z++)
+ {
+ if (points[z].alpha > 0.0f)
+ {
+ DrawText(FormatText("+%02i", points[z].value), points[z].position.x, points[z].position.y, 20, Fade(BLUE, points[z].alpha));
+ }
+ }
+
+ // Draw score (UI)
+ DrawText(FormatText("SCORE: %i", score), 10, 10, 20, LIGHTGRAY);
+
+ if (victory)
+ {
+ DrawText("YOU WIN!", screenWidth/2 - MeasureText("YOU WIN!", 60)/2, 100, 60, LIGHTGRAY);
+ DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY);
+ }
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, LIGHTGRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, LIGHTGRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/raylib_demo/makefile b/games/raylib_demo/makefile
index 3e2fe614..a4435bb0 100644
--- a/games/raylib_demo/makefile
+++ b/games/raylib_demo/makefile
@@ -2,7 +2,7 @@
#
# raylib - Basic Game
#
-# makefile to compile basic game
+# makefile to compile advance game for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
#
@@ -23,31 +23,57 @@
#
#**************************************************************************************************
-# define raylib platform (by default, compile for RPI)
-# Other possible platform: PLATFORM_DESKTOP, PLATFORM_WEB, PLATFORM_RPI
-PLATFORM ?= PLATFORM_WEB
+# define raylib platform to compile for
+# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
+# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop()
+PLATFORM ?= PLATFORM_DESKTOP
+
+# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ LIBPATH=win32
+ else
+ UNAMEOS:=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ LIBPATH=linux
+ else
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ LIBPATH=osx
+ endif
+ endif
+ endif
+endif
# define compiler: gcc for C program, define as g++ for C++
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
+ifeq ($(PLATFORM_OS),OSX)
+ # define llvm compiler for mac
+ CC = clang
+else
# define default gcc compiler
CC = gcc
endif
+endif
# define compiler flags:
# -O2 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 use standard C from 1999 revision
ifeq ($(PLATFORM),PLATFORM_RPI)
- CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline
+ CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
else
- CFLAGS = -O1 -Wall -std=c99
+ CFLAGS = -O2 -Wall -std=c99
endif
-
ifeq ($(PLATFORM),PLATFORM_WEB)
- CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 -s ASSERTIONS=1 --preload-file resources
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources --shell-file ../../templates/web_shell/shell.html
+ #-s ASSERTIONS=1 # to check for memory allocation errors (-O1 disables it)
#-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
#-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
endif
@@ -59,33 +85,66 @@ ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I../../src
+# external libraries headers
+# GLFW3
+ INCLUDES += -I../../external/glfw3/include
+# GLEW - Not required any more, replaced by GLAD
+ #INCLUDES += -I../external/glew/include
+# OpenAL Soft
+ INCLUDES += -I../../external/openal_soft/include
endif
# define library paths containing required libs
-ifeq ($(PLATFORM),PLATFORM_WEB)
- LFLAGS = -L.
-else
+ifeq ($(PLATFORM),PLATFORM_RPI)
LFLAGS = -L. -L../../src -L/opt/vc/lib
+else
+ LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+ # external libraries to link with
+ # GLFW3
+ LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+ ifneq ($(PLATFORM_OS),OSX)
+ # OpenAL Soft
+ LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+ # GLEW: Not used, replaced by GLAD
+ #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+ endif
endif
# define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ # libraries for Debian GNU/Linux desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
+ # on XWindow could require also below libraries, just uncomment
+ #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+ else
+ ifeq ($(PLATFORM_OS),OSX)
+ # libraries for OS X 10.9 desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
+ else
+ # libraries for Windows desktop compiling
+ # NOTE: GLFW3 and OpenAL Soft libraries should be installed
+ LIBS = -lraylib -lglfw3 -lopengl32 -lopenal32 -lgdi32
+ endif
+ endif
+endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# libraries for Raspberry Pi compiling
# NOTE: OpenAL Soft library should be installed (libopenal1 package)
LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
-else
- # libraries for Windows desktop compiling
- # NOTE: GLFW3 and OpenAL Soft libraries should be installed
- LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
endif
-
ifeq ($(PLATFORM),PLATFORM_WEB)
+ # NOTE: Set the correct path to libraylib.bc
LIBS = ../../src/libraylib.bc
endif
# define additional parameters and flags for windows
-ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ifeq ($(PLATFORM_OS),WINDOWS)
# resources file contains windows exe icon
# -Wl,--subsystem,windows hides the console window
WINFLAGS = ../../src/resources -Wl,--subsystem,windows
@@ -99,21 +158,30 @@ endif
# in this case, the 'default' target entry is qidv_raylib
default: raylib_demo
-# compile qidv_raylib
+# compile raylib demo
raylib_demo: raylib_demo.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
# clean everything
clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ else
+ ifeq ($(PLATFORM_OS),LINUX)
+ find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
+ else
+ del *.o *.exe
+ endif
+ endif
+endif
ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
rm -f *.o
-# find . -executable -delete
-else
-ifeq ($(PLATFORM),PLATFORM_WEB)
- del *.html *.js
-else
- del *.o *.exe
endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
endif
@echo Cleaning done
diff --git a/games/raylib_demo/raylib_demo.c b/games/raylib_demo/raylib_demo.c
index 5bbccbe8..7f6f291a 100644
--- a/games/raylib_demo/raylib_demo.c
+++ b/games/raylib_demo/raylib_demo.c
@@ -1,10 +1,8 @@
/*******************************************************************************************
*
-* raylib - Talk: QIDV raylib (Learn Videogames Programming)
+* raylib - Features demo 01 (Learn Videogames Programming)
*
-* Aprende a Programar Videojuegos con raylib
-*
-* This talk has been created using raylib v1.2 (www.raylib.com)
+* This show has been created using raylib v1.4 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
@@ -703,11 +701,11 @@ void UpdateDrawOneFrame(void)
{
DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x5c5a5aff));
- DrawTextEx(fontRomulus, "Open-Close Window", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff));
- DrawTextEx(fontRomulus, "Manage Drawing Area", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff));
- DrawTextEx(fontRomulus, "Manage Inputs", (Vector2){ 48, 290 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff));
- DrawTextEx(fontRomulus, "Manage Timming", (Vector2){ 48, 320 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff));
- DrawTextEx(fontRomulus, "Auxiliar Functions", (Vector2){ 48, 350 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x5c5a5aff));
+ DrawTextEx(fontRomulus, "Open-Close Window", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff));
+ DrawTextEx(fontRomulus, "Manage Drawing Area", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff));
+ DrawTextEx(fontRomulus, "Manage Inputs", (Vector2){ 48, 290 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff));
+ DrawTextEx(fontRomulus, "Manage Timming", (Vector2){ 48, 320 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff));
+ DrawTextEx(fontRomulus, "Auxiliar Functions", (Vector2){ 48, 350 }, fontRomulus.size*2, 4, GetColor(0x5c5a5aff));
switch (coreWindow)
{
@@ -733,16 +731,16 @@ void UpdateDrawOneFrame(void)
if (framesCounter > 140)
{
- DrawTextEx(fontMecha, "MOVE ME", (Vector2){ ballPosition.x - 26, ballPosition.y - 20 }, GetFontBaseSize(fontMecha), 2, BLACK);
- DrawTextEx(fontMecha, "[ W A S D ]", (Vector2){ ballPosition.x - 36, ballPosition.y }, GetFontBaseSize(fontMecha), 2, BLACK);
+ DrawTextEx(fontMecha, "MOVE ME", (Vector2){ ballPosition.x - 26, ballPosition.y - 20 }, fontMecha.size, 2, BLACK);
+ DrawTextEx(fontMecha, "[ W A S D ]", (Vector2){ ballPosition.x - 36, ballPosition.y }, fontMecha.size, 2, BLACK);
}
} break;
case SHAPES:
{
DrawText("This module give you functions to:", 48, 200, 10, GetColor(0xcd5757ff));
- DrawTextEx(fontRomulus, "Draw Basic Shapes", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0xcd5757ff));
- DrawTextEx(fontRomulus, "Basic Collision Detection", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0xcd5757ff));
+ DrawTextEx(fontRomulus, "Draw Basic Shapes", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0xcd5757ff));
+ DrawTextEx(fontRomulus, "Basic Collision Detection", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0xcd5757ff));
DrawCircle(screenWidth/4, 120 + 240, 35, DARKBLUE);
DrawCircleGradient(screenWidth/4, 220 + 240, 60, GREEN, SKYBLUE);
@@ -763,8 +761,8 @@ void UpdateDrawOneFrame(void)
{
DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x60815aff));
- DrawTextEx(fontRomulus, "Load Images and Textures", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x60815aff));
- DrawTextEx(fontRomulus, "Draw Textures", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x60815aff));
+ DrawTextEx(fontRomulus, "Load Images and Textures", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x60815aff));
+ DrawTextEx(fontRomulus, "Draw Textures", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x60815aff));
DrawRectangle(138, 348, 260, 260, GRAY);
DrawTexturePro(lena, (Rectangle){ 0, 0, lena.width, lena.height }, (Rectangle){ 140 + 128, 350 + 128, lena.width/2*scaleFactor, lena.height/2*scaleFactor }, (Vector2){ lena.width/4*scaleFactor, lena.height/4*scaleFactor }, 0.0f, WHITE);
@@ -780,21 +778,21 @@ void UpdateDrawOneFrame(void)
{
DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x377764ff));
- DrawTextEx(fontRomulus, "Load SpriteFonts", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x377764ff));
- DrawTextEx(fontRomulus, "Draw Text", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x377764ff));
- DrawTextEx(fontRomulus, "Text Formatting", (Vector2){ 48, 290 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x377764ff));
+ DrawTextEx(fontRomulus, "Load SpriteFonts", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x377764ff));
+ DrawTextEx(fontRomulus, "Draw Text", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x377764ff));
+ DrawTextEx(fontRomulus, "Text Formatting", (Vector2){ 48, 290 }, fontRomulus.size*2, 4, GetColor(0x377764ff));
DrawTexture(texAlagard, 60, 360, WHITE);
- DrawTextEx(fontMechaC, msg1, (Vector2){ 540 + 168, 210 }, GetFontBaseSize(fontMechaC), -3, WHITE);
- DrawTextEx(fontAlagardC, msg2, (Vector2){ 460 + 140, 260 }, GetFontBaseSize(fontAlagardC), -2, WHITE);
- DrawTextEx(fontJupiterC, msg3, (Vector2){ 640 + 70, 300 }, GetFontBaseSize(fontJupiterC), 2, WHITE);
+ DrawTextEx(fontMechaC, msg1, (Vector2){ 540 + 168, 210 }, fontMechaC.size, -3, WHITE);
+ DrawTextEx(fontAlagardC, msg2, (Vector2){ 460 + 140, 260 }, fontAlagardC.size, -2, WHITE);
+ DrawTextEx(fontJupiterC, msg3, (Vector2){ 640 + 70, 300 }, fontJupiterC.size, 2, WHITE);
- DrawTextEx(fontAlagard, "It also includes some...", (Vector2){ 650 + 70, 400 }, GetFontBaseSize(fontAlagard)*2, 2, MAROON);
- DrawTextEx(fontPixelplay, "...free fonts in rBMF format...", (Vector2){ 705 - 26, 450 }, GetFontBaseSize(fontPixelplay)*2, 4, ORANGE);
- DrawTextEx(fontMecha, "...to be used even in...", (Vector2){ 700 + 40, 500 }, GetFontBaseSize(fontMecha)*2, 4, DARKGREEN);
- DrawTextEx(fontSetback, "...comercial projects...", (Vector2){ 710, 550 }, GetFontBaseSize(fontSetback)*2, 4, DARKBLUE);
- DrawTextEx(fontRomulus, "...completely for free!", (Vector2){ 710 + 17, 600 }, GetFontBaseSize(fontRomulus)*2, 3, DARKPURPLE);
+ DrawTextEx(fontAlagard, "It also includes some...", (Vector2){ 650 + 70, 400 }, fontAlagard.size*2, 2, MAROON);
+ DrawTextEx(fontPixelplay, "...free fonts in rBMF format...", (Vector2){ 705 - 26, 450 }, fontPixelplay.size*2, 4, ORANGE);
+ DrawTextEx(fontMecha, "...to be used even in...", (Vector2){ 700 + 40, 500 }, fontMecha.size*2, 4, DARKGREEN);
+ DrawTextEx(fontSetback, "...comercial projects...", (Vector2){ 710, 550 }, fontSetback.size*2, 4, DARKBLUE);
+ DrawTextEx(fontRomulus, "...completely for free!", (Vector2){ 710 + 17, 600 }, fontRomulus.size*2, 3, DARKPURPLE);
DrawText("This is a custom font spritesheet, raylib can load it automatically!", 228, 360 + 295, 10, GRAY);
@@ -803,9 +801,9 @@ void UpdateDrawOneFrame(void)
{
DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x417794ff));
- DrawTextEx(fontRomulus, "Draw Geometric Models", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x417794ff));
- DrawTextEx(fontRomulus, "Load 3D Models", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x417794ff));
- DrawTextEx(fontRomulus, "Draw 3D Models", (Vector2){ 48, 290 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x417794ff));
+ DrawTextEx(fontRomulus, "Draw Geometric Models", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x417794ff));
+ DrawTextEx(fontRomulus, "Load 3D Models", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x417794ff));
+ DrawTextEx(fontRomulus, "Draw 3D Models", (Vector2){ 48, 290 }, fontRomulus.size*2, 4, GetColor(0x417794ff));
Begin3dMode(camera);
@@ -823,7 +821,7 @@ void UpdateDrawOneFrame(void)
DrawCylinder((Vector3){1, 0, -4}, 0, 1.5, 3, 8, GOLD);
DrawCylinderWires((Vector3){1, 0, -4}, 0, 1.5, 3, 8, PINK);
- DrawModelEx(cat, (Vector3){ 8.0f, 0.0f, 2.0f }, (Vector3){ 0.0f, 0.5f*framesCounter, 0.0f }, (Vector3){ 0.1f, 0.1f, 0.1f }, WHITE);
+ DrawModelEx(cat, (Vector3){ 8.0f, 0.0f, 2.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, 0.5f*framesCounter, (Vector3){ 0.1f, 0.1f, 0.1f }, WHITE);
DrawGizmo((Vector3){ 8.0f, 0.0f, 2.0f });
DrawGrid(10.0, 1.0); // Draw a grid
@@ -837,8 +835,8 @@ void UpdateDrawOneFrame(void)
{
DrawText("This module give you functions to:", 48, 200, 10, GetColor(0x8c7539ff));
- DrawTextEx(fontRomulus, "Load and Play Sounds", (Vector2){ 48, 230 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x8c7539ff));
- DrawTextEx(fontRomulus, "Play Music (streaming)", (Vector2){ 48, 260 }, GetFontBaseSize(fontRomulus)*2, 4, GetColor(0x8c7539ff));
+ DrawTextEx(fontRomulus, "Load and Play Sounds", (Vector2){ 48, 230 }, fontRomulus.size*2, 4, GetColor(0x8c7539ff));
+ DrawTextEx(fontRomulus, "Play Music (streaming)", (Vector2){ 48, 260 }, fontRomulus.size*2, 4, GetColor(0x8c7539ff));
DrawText("PRESS SPACE to START PLAYING MUSIC", 135, 350, 20, GRAY);
DrawRectangle(150, 390, 400, 12, LIGHTGRAY);
@@ -891,7 +889,7 @@ void UpdateDrawOneFrame(void)
case ENDING:
{
// Draw ENDING screen
- DrawTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", (Vector2){ screenWidth/2 - MeasureTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", GetFontBaseSize(fontAlagard)*4, 4).x/2, 80 }, GetFontBaseSize(fontAlagard)*4, 4, MAROON);
+ DrawTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", (Vector2){ screenWidth/2 - MeasureTextEx(fontAlagard, "LEARN VIDEOGAMES PROGRAMMING", fontAlagard.size*4, 4).x/2, 80 }, fontAlagard.size*4, 4, MAROON);
DrawTexture(raylibLogoA, logoPositionX, logoPositionY - 40, WHITE);
diff --git a/games/skully_escape/makefile b/games/skully_escape/makefile
new file mode 100644
index 00000000..d47760d3
--- /dev/null
+++ b/games/skully_escape/makefile
@@ -0,0 +1,254 @@
+#**************************************************************************************************
+#
+# raylib - Advance Game
+#
+# makefile to compile advance game
+#
+# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+#
+# This software is provided "as-is", without any express or implied warranty. In no event
+# will the authors be held liable for any damages arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose, including commercial
+# applications, and to alter it and redistribute it freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not claim that you
+# wrote the original software. If you use this software in a product, an acknowledgment
+# in the product documentation would be appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+# as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+#
+#**************************************************************************************************
+
+# define raylib platform if not defined (by default, compile for RPI)
+# Other possible platform: PLATFORM_DESKTOP
+PLATFORM ?= PLATFORM_DESKTOP
+
+# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ LIBPATH=win32
+ else
+ UNAMEOS:=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ LIBPATH=linux
+ else
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ LIBPATH=osx
+ endif
+ endif
+ endif
+endif
+
+# define compiler: gcc for C program, define as g++ for C++
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # define emscripten compiler
+ CC = emcc
+else
+ifeq ($(PLATFORM_OS),OSX)
+ # define llvm compiler for mac
+ CC = clang
+else
+ # define default gcc compiler
+ CC = gcc
+endif
+endif
+
+# define compiler flags:
+# -O2 defines optimization level
+# -Wall turns on most, but not all, compiler warnings
+# -std=c99 use standard C from 1999 revision
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline
+else
+ CFLAGS = -O2 -Wall -std=c99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 --preload-file resources -s ALLOW_MEMORY_GROWTH=1 --shell-file ../../templates/web_shell/shell.html
+ #-s ASSERTIONS=1 --preload-file resources
+ #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
+ #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+endif
+
+# define any directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+else
+ INCLUDES = -I. -I../../src
+# external libraries headers
+# GLFW3
+ INCLUDES += -I../../external/glfw3/include
+# GLEW
+ INCLUDES += -I../../external/glew/include
+# OpenAL Soft
+ INCLUDES += -I../../external/openal_soft/include
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ LFLAGS = -L. -L../../src -L/opt/vc/lib
+else
+ LFLAGS = -L. -L../../src -L../../../src
+ # external libraries to link with
+ # GLFW3
+ LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+ ifneq ($(PLATFORM_OS),OSX)
+ # OpenAL Soft
+ LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+ # GLEW
+ LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+ endif
+endif
+
+# define any libraries to link into executable
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ # libraries for Debian GNU/Linux desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -lGLEW -lGL -lopenal
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ # libraries for OS X 10.9 desktop compiling
+ # requires the following packages:
+ # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
+ LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa
+ else
+ # libraries for Windows desktop compiling
+ # NOTE: GLFW3 and OpenAL Soft libraries should be installed
+ LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # libraries for Raspberry Pi compiling
+ # NOTE: OpenAL Soft library should be installed (libopenal1 package)
+ LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ LIBS = ../../src/libraylib.bc
+endif
+
+# define additional parameters and flags for windows
+ifeq ($(PLATFORM_OS),WINDOWS)
+ # resources file contains windows exe icon
+ # -Wl,--subsystem,windows hides the console window
+ WINFLAGS = ../../src/resources
+ #-Wl,--subsystem,windows
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ EXT = .html
+endif
+
+# define all screen object files required
+SCREENS = \
+ screens/screen_logo.o \
+ screens/screen_logo_raylib.o \
+ screens/screen_title.o \
+ screens/screen_attic.o \
+ screens/screen_aisle01.o \
+ screens/screen_aisle02.o \
+ screens/screen_armory.o \
+ screens/screen_livingroom.o \
+ screens/screen_kitchen.o \
+ screens/screen_bathroom.o \
+ screens/screen_ending.o \
+ player.o \
+ monster.o \
+
+# typing 'make' will invoke the first target entry in the file,
+# in this case, the 'default' target entry is advance_game
+default: skully_escape
+
+# compile template - advance_game
+skully_escape: skully_escape.c $(SCREENS)
+ $(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+# compile screen LOGO
+screens/screen_logo.o: screens/screen_logo.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen LOGO raylib
+screens/screen_logo_raylib.o: screens/screen_logo_raylib.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen TITLE
+screens/screen_title.o: screens/screen_title.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen ATTIC
+screens/screen_attic.o: screens/screen_attic.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen AISLE01
+screens/screen_aisle01.o: screens/screen_aisle01.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen AISLE02
+screens/screen_aisle02.o: screens/screen_aisle02.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen BATHROOM
+screens/screen_bathroom.o: screens/screen_bathroom.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen LIVINGROOM
+screens/screen_livingroom.o: screens/screen_livingroom.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen KITCHEN
+screens/screen_kitchen.o: screens/screen_kitchen.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen ARMORY
+screens/screen_armory.o: screens/screen_armory.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen ENDING
+screens/screen_ending.o: screens/screen_ending.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen LOGO
+player.o: player.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile screen LOGO
+monster.o: monster.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ else
+ ifeq ($(PLATFORM_OS),LINUX)
+ find . -type f -executable -delete
+ rm -f *.o
+ else
+ del *.o *.exe
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
+ rm -f *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
+endif
+ @echo Cleaning done
+
+# instead of defining every module one by one, we can define a pattern
+# this pattern below will automatically compile every module defined on $(OBJS)
+#%.exe : %.c
+# $(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM)
diff --git a/games/skully_escape/monster.c b/games/skully_escape/monster.c
new file mode 100644
index 00000000..643d0a73
--- /dev/null
+++ b/games/skully_escape/monster.c
@@ -0,0 +1,54 @@
+/***********************************************************************************
+*
+* KING GAME JAM - GRAY TEAM
+*
+* <Game title>
+* <Game description>
+*
+* This game has been created using raylib (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+************************************************************************************/
+
+#include "raylib.h"
+#include "monster.h"
+
+void UpdateMonster(Monster *monster)
+{
+ if (!monster->active)
+ {
+ if (CheckCollisionPointRec(GetMousePosition(), monster->bounds)) monster->selected = true;
+ else monster->selected = false;
+ }
+ else if (monster->spooky)
+ {
+ monster->framesCounter++;
+ monster->currentSeq = 0;
+
+ if (monster->framesCounter > 7)
+ {
+ monster->currentFrame++;
+ monster->framesCounter = 0;
+
+ if (monster->currentFrame > monster->numFrames - 1) monster->currentFrame = 1;
+ }
+ }
+
+ monster->frameRec.x = monster->currentFrame*monster->texture.width/monster->numFrames;
+ monster->frameRec.y = monster->currentSeq*monster->texture.height;
+}
+
+void DrawMonster(Monster monster, int scroll)
+{
+ Vector2 scrollPos = { monster.position.x - scroll, monster.position.y };
+
+ if (monster.selected) DrawTextureRec(monster.texture, monster.frameRec, scrollPos, RED);
+ else DrawTextureRec(monster.texture, monster.frameRec, scrollPos, WHITE);
+}
+
+void UnloadMonster(Monster monster)
+{
+ UnloadTexture(monster.texture);
+} \ No newline at end of file
diff --git a/games/skully_escape/monster.h b/games/skully_escape/monster.h
new file mode 100644
index 00000000..e7e01856
--- /dev/null
+++ b/games/skully_escape/monster.h
@@ -0,0 +1,73 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Screens Functions Declarations (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef MONSTER_H
+#define MONSTER_H
+
+#define MONSTER_ANIM_FRAMES 7
+#define MONSTER_ANIM_SEQ 2
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//---------------------------------------------------------------------------------
+typedef struct Monster {
+ Vector2 position;
+ Texture2D texture;
+ Rectangle bounds;
+ Rectangle frameRec;
+ Color color;
+ int framesCounter;
+ int currentFrame;
+ int currentSeq;
+ int numFrames;
+ bool active;
+ bool selected;
+ bool spooky;
+} Monster;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+
+
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Monster Functions Declaration
+//----------------------------------------------------------------------------------
+
+void UpdateMonster(Monster *monster);
+void DrawMonster(Monster monster, int scroll);
+void UnloadMonster(Monster monster);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SCREENS_H \ No newline at end of file
diff --git a/games/skully_escape/player.c b/games/skully_escape/player.c
new file mode 100644
index 00000000..11006f65
--- /dev/null
+++ b/games/skully_escape/player.c
@@ -0,0 +1,281 @@
+/***********************************************************************************
+*
+* KING GAME JAM - GRAY TEAM
+*
+* <Game title>
+* <Game description>
+*
+* This game has been created using raylib (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+************************************************************************************/
+
+#include "raylib.h"
+#include "player.h"
+
+#define PLAYER_ANIM_FRAMES 4
+#define PLAYER_ANIM_SEQ 6
+
+//----------------------------------------------------------------------------------
+// Module Variables Definition
+//----------------------------------------------------------------------------------
+
+// Player mouse moving variables
+static bool movingAnim;
+static int moveDirection;
+static int nextMovePoint;
+
+// Mouse pointer variables
+static Vector2 pointerPosition;
+static bool pointerAnim;
+static float pointerAlpha;
+
+static int framesCounter;
+static bool outControl = false;
+
+static int animTimer = 0;
+
+static Texture2D texLife;
+
+static void DrawLifes(void);
+
+// player initialitaction definition
+void InitPlayer(void)
+{
+ // NOTE: Some player variables are only initialized once
+ player.texture = LoadTexture("resources/textures/skully.png");
+ player.position = (Vector2){ 350, 400 };
+ player.numLifes = 4;
+
+ ResetPlayer();
+
+ framesCounter = 0;
+
+ texLife = LoadTexture("resources/textures/skully_icon.png");
+}
+
+// player update definition
+void UpdatePlayer(void)
+{
+ if (!outControl)
+ {
+ if ((IsKeyDown(KEY_LEFT)) || (IsKeyDown(KEY_RIGHT)))
+ {
+ moveDirection = -1;
+ movingAnim = false;
+ }
+
+ if ((IsKeyDown(KEY_RIGHT)) || (moveDirection == 0))
+ {
+ player.currentSeq = WALK_RIGHT;
+ framesCounter++;
+
+ if (framesCounter > 15)
+ {
+ player.currentFrame++;
+ framesCounter = 0;
+
+ if (player.currentFrame > PLAYER_ANIM_FRAMES - 1) player.currentFrame = 0;
+ }
+
+ player.position.x += 4;
+ }
+ else if ((IsKeyDown(KEY_LEFT)) || (moveDirection == 1))
+ {
+ player.currentSeq = WALK_LEFT;
+ framesCounter++;
+
+ if (framesCounter > 15)
+ {
+ player.currentFrame++;
+ framesCounter = 0;
+
+ if (player.currentFrame > PLAYER_ANIM_FRAMES - 1) player.currentFrame = 0;
+ }
+
+ player.position.x -= 4;
+ }
+ else player.currentFrame = 0;
+ }
+ else
+ {
+ framesCounter++;
+ animTimer++;
+
+ if (framesCounter > 10)
+ {
+ player.currentFrame++;
+ framesCounter = 0;
+
+ if (player.currentFrame > PLAYER_ANIM_FRAMES - 1) player.currentFrame = 0;
+
+ // We can adjust animation playing time depending on sequence
+ switch (player.currentSeq)
+ {
+ case SCARE_RIGHT:
+ {
+ if (animTimer > 180)
+ {
+ animTimer = 0;
+ outControl = false;
+ player.currentSeq = WALK_LEFT;
+ }
+ } break;
+ case SCARE_LEFT:
+ {
+ if (animTimer > 240)
+ {
+ animTimer = 0;
+ outControl = false;
+ player.currentSeq = WALK_RIGHT;
+ }
+ } break;
+ case SEARCH:
+ case FIND_KEY:
+ {
+ if (animTimer > 240)
+ {
+ animTimer = 0;
+ outControl = false;
+ player.currentSeq = WALK_RIGHT;
+ }
+ } break;
+ }
+ }
+ }
+
+ if (player.position.x < 30) player.position.x = 30;
+ else if (player.position.x > (GetScreenWidth() - 200)) player.position.x = GetScreenWidth() - 200;
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ pointerPosition = GetMousePosition();
+ pointerAnim = true;
+ pointerAlpha = 1.0f;
+
+ nextMovePoint = (int)pointerPosition.x;
+ movingAnim = true;
+ }
+
+ if (movingAnim)
+ {
+ if (nextMovePoint > (player.position.x + (player.frameRec.width/2) + 5)) moveDirection = 0; // Move Left
+ else if (nextMovePoint < (player.position.x + (player.frameRec.width/2) - 5)) moveDirection = 1; // Move Right
+ else
+ {
+ moveDirection = -1;
+ movingAnim = 0;
+ }
+ }
+
+ player.frameRec.x = player.currentFrame*player.texture.width/PLAYER_ANIM_FRAMES;
+ player.frameRec.y = (player.currentSeq - 1)*player.texture.height/PLAYER_ANIM_SEQ;
+
+ // Update player bounds
+ player.bounds = (Rectangle){ player.position.x + 50, player.position.y - 60, 100, 300 };
+
+ // Mouse pointer alpha animation
+ if (pointerAnim)
+ {
+ pointerAlpha -= 0.1f;
+
+ if (pointerAlpha <= 0.0f)
+ {
+ pointerAlpha = 0.0f;
+ pointerAnim = false;
+ }
+ }
+}
+//
+void DrawPlayer(void)
+{
+ DrawTextureRec(player.texture, player.frameRec, player.position, WHITE);
+
+ // Draw mouse pointer on click
+ if (pointerAnim) DrawCircleV(pointerPosition, 20, Fade(RED, pointerAlpha));
+
+ DrawLifes();
+}
+
+void UnloadPlayer(void)
+{
+ UnloadTexture(player.texture);
+ UnloadTexture(texLife);
+}
+
+void ResetPlayer(void)
+{
+ // Reset player variables
+ player.frameRec = (Rectangle){ 0, 0, player.texture.width/PLAYER_ANIM_FRAMES, player.texture.height/PLAYER_ANIM_SEQ };
+ player.currentFrame = 0;
+ player.currentSeq = WALK_RIGHT;
+
+ player.key = false;
+ player.dead = false;
+
+ // Reset player position
+ if (player.position.x < 400) player.position.x = GetScreenWidth() - 350;
+ if (player.position.x > (GetScreenWidth() - 400)) player.position.x = 350;
+
+ // Reset moving variables
+ movingAnim = false;
+ moveDirection = -1;
+ nextMovePoint = 0;
+ framesCounter = 0;
+ outControl = false;
+ animTimer = 0;
+
+ // Reset pointer
+ pointerAlpha = 0.0f;
+ pointerAnim = false;
+}
+
+void ScarePlayer(void)
+{
+ player.currentFrame = 0;
+
+ if (moveDirection == 0) player.currentSeq = SCARE_RIGHT;
+ else if (moveDirection == 1) player.currentSeq = SCARE_LEFT;
+ else player.currentSeq = SCARE_RIGHT;
+
+ player.numLifes--;
+
+ if (player.numLifes <= 0) player.dead = true;
+
+ outControl = true;
+}
+
+void SearchKeyPlayer(void)
+{
+ moveDirection = -1;
+ movingAnim = 0;
+
+ player.currentFrame = 0;
+ player.currentSeq = SEARCH;
+
+ outControl = true;
+}
+
+void FindKeyPlayer(void)
+{
+ player.currentFrame = 0;
+ player.currentSeq = FIND_KEY;
+ player.key = true;
+
+ outControl = true;
+}
+
+static void DrawLifes(void)
+{
+ if (player.numLifes != 0)
+ {
+ Vector2 position = { 20, GetScreenHeight() - texLife.height - 20 };
+
+ for(int i = 0; i < player.numLifes; i++)
+ {
+ DrawTexture(texLife, position.x + i*texLife.width, position.y, Fade(RAYWHITE, 0.7f));
+ }
+ }
+} \ No newline at end of file
diff --git a/games/skully_escape/player.h b/games/skully_escape/player.h
new file mode 100644
index 00000000..7d59bdde
--- /dev/null
+++ b/games/skully_escape/player.h
@@ -0,0 +1,51 @@
+#ifndef PLAYER_H
+#define PLAYER_H
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum { NONE, WALK_RIGHT, WALK_LEFT, SCARE_RIGHT, SCARE_LEFT, SEARCH, FIND_KEY } PlayerSequence;
+
+typedef struct Player {
+ Vector2 position;
+ Rectangle bounds;
+ Texture2D texture;
+ Color color;
+
+ // Animation variables
+ Rectangle frameRec;
+ int currentFrame;
+ int currentSeq;
+
+ bool key;
+ int numLifes;
+ bool dead;
+} Player;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+Player player;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitPlayer(void);
+void UpdatePlayer(void);
+void DrawPlayer(void);
+void UnloadPlayer(void);
+void ResetPlayer(void);
+
+void ScarePlayer(void);
+void SearchKeyPlayer(void);
+void FindKeyPlayer(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SCREENS_H \ No newline at end of file
diff --git a/games/skully_escape/resources/audio/come_play_with_me.ogg b/games/skully_escape/resources/audio/come_play_with_me.ogg
new file mode 100644
index 00000000..425498b8
--- /dev/null
+++ b/games/skully_escape/resources/audio/come_play_with_me.ogg
Binary files differ
diff --git a/games/skully_escape/resources/audio/door.ogg b/games/skully_escape/resources/audio/door.ogg
new file mode 100644
index 00000000..a1d1cd1b
--- /dev/null
+++ b/games/skully_escape/resources/audio/door.ogg
Binary files differ
diff --git a/games/skully_escape/resources/audio/scream.ogg b/games/skully_escape/resources/audio/scream.ogg
new file mode 100644
index 00000000..41524027
--- /dev/null
+++ b/games/skully_escape/resources/audio/scream.ogg
Binary files differ
diff --git a/games/skully_escape/resources/textures/alagard.png b/games/skully_escape/resources/textures/alagard.png
new file mode 100644
index 00000000..c5cc54dc
--- /dev/null
+++ b/games/skully_escape/resources/textures/alagard.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_aisle01.png b/games/skully_escape/resources/textures/background_aisle01.png
new file mode 100644
index 00000000..482056f8
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_aisle01.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_aisle02.png b/games/skully_escape/resources/textures/background_aisle02.png
new file mode 100644
index 00000000..fced627f
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_aisle02.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_armory.png b/games/skully_escape/resources/textures/background_armory.png
new file mode 100644
index 00000000..1a93807f
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_armory.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_attic.png b/games/skully_escape/resources/textures/background_attic.png
new file mode 100644
index 00000000..446e09a7
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_attic.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_bathroom.png b/games/skully_escape/resources/textures/background_bathroom.png
new file mode 100644
index 00000000..55061d1f
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_bathroom.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_kitchen.png b/games/skully_escape/resources/textures/background_kitchen.png
new file mode 100644
index 00000000..5c74c74e
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_kitchen.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/background_livingroom.png b/games/skully_escape/resources/textures/background_livingroom.png
new file mode 100644
index 00000000..f91a11f9
--- /dev/null
+++ b/games/skully_escape/resources/textures/background_livingroom.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/doors.png b/games/skully_escape/resources/textures/doors.png
new file mode 100644
index 00000000..f5a75d05
--- /dev/null
+++ b/games/skully_escape/resources/textures/doors.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_arc.png b/games/skully_escape/resources/textures/monster_arc.png
new file mode 100644
index 00000000..ae3e346d
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_arc.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_blazon01.png b/games/skully_escape/resources/textures/monster_blazon01.png
new file mode 100644
index 00000000..2d2a409c
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_blazon01.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_blazon02.png b/games/skully_escape/resources/textures/monster_blazon02.png
new file mode 100644
index 00000000..8cea9361
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_blazon02.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_blazon03.png b/games/skully_escape/resources/textures/monster_blazon03.png
new file mode 100644
index 00000000..cc4665a1
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_blazon03.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_candle.png b/games/skully_escape/resources/textures/monster_candle.png
new file mode 100644
index 00000000..9feef00d
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_candle.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_chair_left.png b/games/skully_escape/resources/textures/monster_chair_left.png
new file mode 100644
index 00000000..b3ac070f
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_chair_left.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_chair_right.png b/games/skully_escape/resources/textures/monster_chair_right.png
new file mode 100644
index 00000000..d29cc021
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_chair_right.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_closet.png b/games/skully_escape/resources/textures/monster_closet.png
new file mode 100644
index 00000000..7c0c8f27
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_closet.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_lamp_left.png b/games/skully_escape/resources/textures/monster_lamp_left.png
new file mode 100644
index 00000000..3b31b77f
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_lamp_left.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_lamp_right.png b/games/skully_escape/resources/textures/monster_lamp_right.png
new file mode 100644
index 00000000..26491866
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_lamp_right.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_mirror.png b/games/skully_escape/resources/textures/monster_mirror.png
new file mode 100644
index 00000000..2e994309
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_mirror.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_phone.png b/games/skully_escape/resources/textures/monster_phone.png
new file mode 100644
index 00000000..a4862ef7
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_phone.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_picture.png b/games/skully_escape/resources/textures/monster_picture.png
new file mode 100644
index 00000000..29549895
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_picture.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/monster_window.png b/games/skully_escape/resources/textures/monster_window.png
new file mode 100644
index 00000000..47d70a79
--- /dev/null
+++ b/games/skully_escape/resources/textures/monster_window.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/skully.png b/games/skully_escape/resources/textures/skully.png
new file mode 100644
index 00000000..9ce6cd58
--- /dev/null
+++ b/games/skully_escape/resources/textures/skully.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/skully_icon.png b/games/skully_escape/resources/textures/skully_icon.png
new file mode 100644
index 00000000..91a0bc2a
--- /dev/null
+++ b/games/skully_escape/resources/textures/skully_icon.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/skully_logo.png b/games/skully_escape/resources/textures/skully_logo.png
new file mode 100644
index 00000000..93e8bfe2
--- /dev/null
+++ b/games/skully_escape/resources/textures/skully_logo.png
Binary files differ
diff --git a/games/skully_escape/resources/textures/title.png b/games/skully_escape/resources/textures/title.png
new file mode 100644
index 00000000..20e08c88
--- /dev/null
+++ b/games/skully_escape/resources/textures/title.png
Binary files differ
diff --git a/games/skully_escape/screens/screen_aisle01.c b/games/skully_escape/screens/screen_aisle01.c
new file mode 100644
index 00000000..17d25058
--- /dev/null
+++ b/games/skully_escape/screens/screen_aisle01.c
@@ -0,0 +1,409 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorRight;
+static Door doorCenter;
+static Door doorLeft;
+
+// Decalre monsters
+static Monster lamp;
+static Monster picture;
+
+static bool monsterHover = false;
+static int monsterCheck = -1; // Identify checking monster
+
+static const char message[256] = "WHO IS THERE???\nANYBODY IN THE ROOM???";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+static int scroll = 0;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitAisle01Screen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_aisle01.png");
+
+ scroll = player.position.x - 200;
+
+ // Initialize doors
+ doorLeft.position = (Vector2) { -30, 135 };
+ doorLeft.facing = 0;
+ doorLeft.locked = true;
+ doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2};
+ doorLeft.selected = false;
+
+ doorCenter.position = (Vector2) { 1115, 104 };
+ doorCenter.facing = 1;
+ doorCenter.locked = true;
+ doorCenter.frameRec =(Rectangle) {((doors.width/3)*doorCenter.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorCenter.bound = (Rectangle) { doorCenter.position.x, doorCenter.position.y, doors.width/3, doors.height/2};
+ doorCenter.selected = false;
+
+ doorRight.position = (Vector2) { 1710, 140 };
+ doorRight.facing = 2;
+ doorRight.locked = true;
+ doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2};
+
+ // Monster init: lamp
+ lamp.position = (Vector2){ 187, 256 };
+ lamp.texture = LoadTexture("resources/textures/monster_lamp_left.png");
+ lamp.currentFrame = 0;
+ lamp.framesCounter = 0;
+ lamp.numFrames = 4;
+ lamp.bounds = (Rectangle){ lamp.position.x + 20, lamp.position.y, 90, 380 };
+ lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height };
+ lamp.selected = false;
+ lamp.active = false;
+ lamp.spooky = true;
+
+ // Monster init: arc
+ picture.position = (Vector2){ 637, 178 };
+ picture.texture = LoadTexture("resources/textures/monster_picture.png");
+ picture.currentFrame = 0;
+ picture.framesCounter = 0;
+ picture.numFrames = 4;
+ picture.bounds = (Rectangle){ picture.position.x + 44, picture.position.y, 174, 256 };
+ picture.frameRec = (Rectangle) { 0, 0, picture.texture.width/picture.numFrames, picture.texture.height };
+ picture.selected = false;
+ picture.active = false;
+ picture.spooky = false;
+}
+
+// Gameplay Screen Update logic
+void UpdateAisle01Screen(void)
+{
+ // Update doors bounds
+ doorLeft.bound.x = doorLeft.position.x - scroll;
+ doorCenter.bound.x = doorCenter.position.x - scroll;
+ doorRight.bound.x = doorRight.position.x - scroll;
+
+ if (player.key)
+ {
+ // Door: left
+ if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true;
+ else doorLeft.selected = false;
+
+ if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorLeft.locked)
+ {
+ doorLeft.frameRec.y = 0;
+ doorLeft.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+
+ // Door: center
+ if ((CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorCenter.bound))) doorCenter.selected = true;
+ else doorCenter.selected = false;
+
+ if ((doorCenter.selected) && (CheckCollisionRecs(player.bounds, doorCenter.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorCenter.locked)
+ {
+ doorCenter.frameRec.y = 0;
+ doorCenter.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 2;
+ }
+ }
+
+ // Door: right
+ if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true;
+ else doorRight.selected = false;
+
+ if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorRight.locked)
+ {
+ doorRight.frameRec.y = 0;
+ doorRight.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 3;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&lamp);
+ UpdateMonster(&picture);
+ }
+
+ // Update monster bounds
+ lamp.bounds.x = lamp.position.x + 20 - scroll;
+ picture.bounds.x = picture.position.x + 44 - scroll;
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) ||
+ ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active)) monsterHover = true;
+ else monsterHover = false;
+
+ // Monters logic: lamp
+ if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active)
+ {
+ lamp.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else lamp.selected = false;
+
+ // Monters logic: picture
+ if ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active)
+ {
+ picture.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), picture.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else picture.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (lamp.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ lamp.active = true;
+ lamp.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (picture.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ picture.active = true;
+ picture.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+
+ if (player.position.x > 200)
+ {
+ scroll = player.position.x - 200;
+
+ if (scroll > 620) scroll = 620;
+ }
+}
+
+// Gameplay Screen Draw logic
+void DrawAisle01Screen(void)
+{
+ DrawTexture(background, -scroll, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(lamp, scroll);
+ DrawMonster(picture, scroll);
+
+ // Draw door
+ Vector2 doorScrollPos = { doorCenter.position.x - scroll, doorCenter.position.y };
+ if (doorCenter.selected) DrawTextureRec(doors, doorCenter.frameRec, doorScrollPos, GREEN);
+ else DrawTextureRec(doors, doorCenter.frameRec, doorScrollPos, WHITE);
+
+ doorScrollPos = (Vector2){ doorLeft.position.x - scroll, doorLeft.position.y };
+ if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, GREEN);
+ else DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, WHITE);
+
+ doorScrollPos = (Vector2){ doorRight.position.x - scroll, doorRight.position.y };
+ if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorScrollPos, GREEN);
+ else DrawTextureRec(doors, doorRight.frameRec, doorScrollPos, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(picture.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadAisle01Screen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(lamp);
+ UnloadMonster(picture);
+}
+
+// Gameplay Screen should finish?
+int FinishAisle01Screen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_aisle02.c b/games/skully_escape/screens/screen_aisle02.c
new file mode 100644
index 00000000..6186a1fc
--- /dev/null
+++ b/games/skully_escape/screens/screen_aisle02.c
@@ -0,0 +1,444 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorLeft;
+
+// Decalre monsters
+static Monster lamp;
+static Monster chair;
+static Monster picture;
+static Monster arc;
+
+static bool monsterHover = false;
+static int monsterCheck = -1; // Identify checking monster
+
+static const char message[256] = "HAS LEGS BUT CAN NOT WALK...\nSEARCH FOR IT TO OPEN THE DOOR!";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+static int scroll = 0;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitAisle02Screen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_aisle02.png");
+
+ scroll = player.position.x - 200;
+
+ // Initialize doors
+ doorLeft.position = (Vector2) { -10, 136 };
+ doorLeft.facing = 0;
+ doorLeft.locked = true;
+ doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2};
+ doorLeft.selected = false;
+
+ // Monster init: lamp
+ lamp.position = (Vector2){ 1520, 300 };
+ lamp.texture = LoadTexture("resources/textures/monster_lamp_right.png");
+ lamp.currentFrame = 0;
+ lamp.framesCounter = 0;
+ lamp.numFrames = 4;
+ lamp.bounds = (Rectangle){ lamp.position.x + 200, lamp.position.y, 90, 380 };
+ lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height };
+ lamp.selected = false;
+ lamp.active = false;
+ lamp.spooky = true;
+
+ // Monster init: chair
+ chair.position = (Vector2){ 1400, 404 };
+ chair.texture = LoadTexture("resources/textures/monster_chair_right.png");
+ chair.currentFrame = 0;
+ chair.framesCounter = 0;
+ chair.numFrames = 4;
+ chair.bounds = (Rectangle){ chair.position.x + 50, chair.position.y + 30, 120, 190 };
+ chair.frameRec = (Rectangle) { 0, 0, chair.texture.width/chair.numFrames, chair.texture.height };
+ chair.selected = false;
+ chair.active = false;
+ chair.spooky = false;
+
+ // Monster init: picture
+ picture.position = (Vector2){ 837, 162 };
+ picture.texture = LoadTexture("resources/textures/monster_picture.png");
+ picture.currentFrame = 0;
+ picture.framesCounter = 0;
+ picture.numFrames = 4;
+ picture.bounds = (Rectangle){ picture.position.x + 44, picture.position.y, 174, 264 };
+ picture.frameRec = (Rectangle) { 0, 0, picture.texture.width/picture.numFrames, picture.texture.height };
+ picture.selected = false;
+ picture.active = false;
+ picture.spooky = true;
+
+ // Monster init: arc
+ arc.position = (Vector2){ 388, 423 };
+ arc.texture = LoadTexture("resources/textures/monster_arc.png");
+ arc.currentFrame = 0;
+ arc.framesCounter = 0;
+ arc.numFrames = 4;
+ arc.bounds = (Rectangle){ arc.position.x + 44, arc.position.y + 70, 220, 120 };
+ arc.frameRec = (Rectangle) { 0, 0, arc.texture.width/arc.numFrames, arc.texture.height };
+ arc.selected = false;
+ arc.active = false;
+ arc.spooky = true;
+}
+
+// Gameplay Screen Update logic
+void UpdateAisle02Screen(void)
+{
+ // Update doors bounds
+ doorLeft.bound.x = doorLeft.position.x - scroll;
+
+ if (player.key)
+ {
+ // Door: left
+ if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true;
+ else doorLeft.selected = false;
+
+ if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorLeft.locked)
+ {
+ doorLeft.frameRec.y = 0;
+ doorLeft.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&lamp);
+ UpdateMonster(&chair);
+ UpdateMonster(&picture);
+ UpdateMonster(&arc);
+ }
+
+ // Update monster bounds
+ lamp.bounds.x = lamp.position.x + 200 - scroll;
+ chair.bounds.x = chair.position.x + 50 - scroll;
+ picture.bounds.x = picture.position.x + 44 - scroll;
+ arc.bounds.x = arc.position.x + 44 - scroll;
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) ||
+ ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active) ||
+ ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) ||
+ ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active)) monsterHover = true;
+ else monsterHover = false;
+
+
+ // Monters logic: lamp
+ if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active)
+ {
+ lamp.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else lamp.selected = false;
+
+ // Monters logic: chair
+ if ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active)
+ {
+ chair.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), chair.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else chair.selected = false;
+
+ // Monters logic: picture
+ if ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active)
+ {
+ picture.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), picture.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 3;
+ }
+ }
+ else picture.selected = false;
+
+ // Monters logic: arc
+ if ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active)
+ {
+ arc.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), arc.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 4;
+ }
+ }
+ else arc.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (lamp.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ lamp.active = true;
+ lamp.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (chair.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ chair.active = true;
+ chair.selected = false;
+ }
+ else if (monsterCheck == 3)
+ {
+ if (picture.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ picture.active = true;
+ picture.selected = false;
+ }
+ else if (monsterCheck == 4)
+ {
+ if (arc.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ arc.active = true;
+ arc.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+
+ if (player.position.x > 200)
+ {
+ scroll = player.position.x - 200;
+
+ if (scroll > 620) scroll = 620;
+ }
+}
+
+// Gameplay Screen Draw logic
+void DrawAisle02Screen(void)
+{
+ DrawTexture(background, -scroll, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(lamp, scroll);
+ DrawMonster(arc, scroll);
+ DrawMonster(picture, scroll);
+ DrawMonster(chair, scroll);
+
+ // Draw door
+ Vector2 doorScrollPos = { doorLeft.position.x - scroll, doorLeft.position.y };
+
+ if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, GREEN);
+ else DrawTextureRec(doors, doorLeft.frameRec, doorScrollPos, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(arc.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(chair.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(picture.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadAisle02Screen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(lamp);
+ UnloadMonster(chair);
+ UnloadMonster(picture);
+ UnloadMonster(arc);
+}
+
+// Gameplay Screen should finish?
+int FinishAisle02Screen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_armory.c b/games/skully_escape/screens/screen_armory.c
new file mode 100644
index 00000000..622299f0
--- /dev/null
+++ b/games/skully_escape/screens/screen_armory.c
@@ -0,0 +1,404 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorLeft;
+static Door doorRight;
+
+// Decalre monsters
+static Monster blazon01;
+static Monster blazon02;
+static Monster blazon03;
+
+static bool monsterHover = false;
+static int monsterCheck = -1; // Identify checking monster
+
+static const char message[256] = "NO MORE TIPS...\nFOLLOW YOUR INSTINCT!";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitArmoryScreen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_armory.png");
+
+ // Initialize doors
+ doorLeft.position = (Vector2) { -50, 145 };
+ doorLeft.facing = 0;
+ doorLeft.locked = true;
+ doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2};
+ doorLeft.selected = false;
+
+ doorRight.position = (Vector2) { 1074, 140 };
+ doorRight.facing = 2;
+ doorRight.locked = true;
+ doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2};
+ doorRight.selected = false;
+
+ // Monster init: blazon01
+ blazon01.position = (Vector2){ 300, 260 };
+ blazon01.texture = LoadTexture("resources/textures/monster_blazon01.png");
+ blazon01.currentFrame = 0;
+ blazon01.framesCounter = 0;
+ blazon01.numFrames = 4;
+ blazon01.bounds = (Rectangle){ blazon01.position.x, blazon01.position.y + 20, 160, 230 };
+ blazon01.frameRec = (Rectangle) { 0, 0, blazon01.texture.width/blazon01.numFrames, blazon01.texture.height };
+ blazon01.selected = false;
+ blazon01.active = false;
+ blazon01.spooky = true;
+
+ // Monster init: blazon02
+ blazon02.position = (Vector2){ 550, 260 };
+ blazon02.texture = LoadTexture("resources/textures/monster_blazon02.png");
+ blazon02.currentFrame = 0;
+ blazon02.framesCounter = 0;
+ blazon02.numFrames = 4;
+ blazon02.bounds = (Rectangle){ blazon02.position.x, blazon02.position.y + 20, 160, 230 };
+ blazon02.frameRec = (Rectangle) { 0, 0, blazon02.texture.width/blazon02.numFrames, blazon02.texture.height };
+ blazon02.selected = false;
+ blazon02.active = false;
+ blazon02.spooky = true;
+
+ // Monster init: blazon03
+ blazon03.position = (Vector2){ 800, 260 };
+ blazon03.texture = LoadTexture("resources/textures/monster_blazon03.png");
+ blazon03.currentFrame = 0;
+ blazon03.framesCounter = 0;
+ blazon03.numFrames = 4;
+ blazon03.bounds = (Rectangle){ blazon03.position.x, blazon03.position.y + 20, 160, 230 };
+ blazon03.frameRec = (Rectangle) { 0, 0, blazon03.texture.width/blazon03.numFrames, blazon03.texture.height };
+ blazon03.selected = false;
+ blazon03.active = false;
+ blazon03.spooky = false;
+}
+
+// Gameplay Screen Update logic
+void UpdateArmoryScreen(void)
+{
+ if (player.key)
+ {
+ // Door: left
+ if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true;
+ else doorLeft.selected = false;
+
+ if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorLeft.locked)
+ {
+ doorLeft.frameRec.y = 0;
+ doorLeft.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+
+ // Door: right
+ if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true;
+ else doorRight.selected = false;
+
+ if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorRight.locked)
+ {
+ doorRight.frameRec.y = 0;
+ doorRight.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 2;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&blazon01);
+ UpdateMonster(&blazon02);
+ UpdateMonster(&blazon03);
+ }
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, blazon01.bounds)) && !blazon01.active) ||
+ ((CheckCollisionRecs(player.bounds, blazon02.bounds)) && !blazon02.active) ||
+ ((CheckCollisionRecs(player.bounds, blazon03.bounds)) && !blazon03.active)) monsterHover = true;
+ else monsterHover = false;
+
+ // Monters logic: blazon01
+ if ((CheckCollisionRecs(player.bounds, blazon01.bounds)) && !blazon01.active)
+ {
+ blazon01.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), blazon01.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else blazon01.selected = false;
+
+ // Monters logic: blazon02
+ if ((CheckCollisionRecs(player.bounds, blazon02.bounds)) && !blazon02.active)
+ {
+ blazon02.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), blazon02.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else blazon02.selected = false;
+
+ // Monters logic: blazon03
+ if ((CheckCollisionRecs(player.bounds, blazon03.bounds)) && !blazon03.active)
+ {
+ blazon03.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), blazon03.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 3;
+ }
+ }
+ else blazon03.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (blazon01.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ blazon01.active = true;
+ blazon01.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (blazon02.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ blazon02.active = true;
+ blazon02.selected = false;
+ }
+ else if (monsterCheck == 3)
+ {
+ if (blazon03.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ blazon03.active = true;
+ blazon03.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+}
+
+// Gameplay Screen Draw logic
+void DrawArmoryScreen(void)
+{
+ DrawTexture(background, 0, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(blazon01, 0);
+ DrawMonster(blazon02, 0);
+ DrawMonster(blazon03, 0);
+
+ // Draw door
+ if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, GREEN);
+ else DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, WHITE);
+
+ if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN);
+ else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(blazon01.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(blazon02.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(blazon03.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadArmoryScreen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(blazon01);
+ UnloadMonster(blazon02);
+ UnloadMonster(blazon03);
+}
+
+// Gameplay Screen should finish?
+int FinishArmoryScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_attic.c b/games/skully_escape/screens/screen_attic.c
new file mode 100644
index 00000000..a8bc0a6b
--- /dev/null
+++ b/games/skully_escape/screens/screen_attic.c
@@ -0,0 +1,332 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorRight;
+
+// Decalre monsters
+static Monster lamp;
+static Monster arc;
+
+static bool monsterHover;
+static int monsterCheck; // Identify checking monster
+
+static const char message[256] = "YOUR PARENTS ARE GONE! TIME TO ESCAPE!\nTHE DOOR IS LOCKED... TURN ON THE LIGHTS! ;)";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitAtticScreen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_attic.png");
+
+ // Initialize doors
+ doorRight.position = (Vector2) { 1074, 140 };
+ doorRight.facing = 2;
+ doorRight.locked = true;
+ doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2};
+ doorRight.selected = false;
+
+ // Monster init: lamp
+ lamp.position = (Vector2){ 50, 316 };
+ lamp.texture = LoadTexture("resources/textures/monster_lamp_left.png");
+ lamp.currentFrame = 0;
+ lamp.framesCounter = 0;
+ lamp.numFrames = 4;
+ lamp.bounds = (Rectangle){ lamp.position.x + 20, lamp.position.y, 90, 380 };
+ lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height };
+ lamp.selected = false;
+ lamp.active = false;
+ lamp.spooky = false;
+
+ // Monster init: arc
+ arc.position = (Vector2){ 760, 430 };
+ arc.texture = LoadTexture("resources/textures/monster_arc.png");
+ arc.currentFrame = 0;
+ arc.framesCounter = 0;
+ arc.numFrames = 4;
+ arc.bounds = (Rectangle){ arc.position.x + 44, arc.position.y + 70, 220, 120 };
+ arc.frameRec = (Rectangle) { 0, 0, arc.texture.width/arc.numFrames, arc.texture.height };
+ arc.selected = false;
+ arc.active = false;
+ arc.spooky = true;
+}
+
+// Gameplay Screen Update logic
+void UpdateAtticScreen(void)
+{
+ if (player.key)
+ {
+ // Door: right
+ if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true;
+ else doorRight.selected = false;
+
+ if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorRight.locked)
+ {
+ doorRight.frameRec.y = 0;
+ doorRight.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&lamp);
+ UpdateMonster(&arc);
+ }
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) ||
+ ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active)) monsterHover = true;
+ else monsterHover = false;
+
+ // Monters logic: lamp
+ if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active)
+ {
+ lamp.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else lamp.selected = false;
+
+ // Monters logic: arc
+ if ((CheckCollisionRecs(player.bounds, arc.bounds)) && !arc.active)
+ {
+ arc.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), arc.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else arc.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (lamp.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ lamp.active = true;
+ lamp.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (arc.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ arc.active = true;
+ arc.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+
+ if (IsKeyPressed('M'))
+ {
+ finishScreen = 1;
+ }
+}
+
+// Gameplay Screen Draw logic
+void DrawAtticScreen(void)
+{
+ DrawTexture(background, 0, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(lamp, 0);
+ DrawMonster(arc, 0);
+
+ // Draw door
+ if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN);
+ else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(arc.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadAtticScreen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(lamp);
+ UnloadMonster(arc);
+}
+
+// Gameplay Screen should finish?
+int FinishAtticScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_bathroom.c b/games/skully_escape/screens/screen_bathroom.c
new file mode 100644
index 00000000..176967a7
--- /dev/null
+++ b/games/skully_escape/screens/screen_bathroom.c
@@ -0,0 +1,383 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorRight;
+
+// Decalre monst
+static Monster lamp;
+static Monster chair;
+static Monster mirror;
+
+static bool monsterHover = false;
+static int monsterCheck = -1; // Identify checking monster
+
+static const char message[256] = "TRICK OR TREAT! WHO IS THE MOST BEAUTIFUL\nSKELETON IN THE WORLD?";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitBathroomScreen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_bathroom.png");
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ // Initialize doors
+ doorRight.position = (Vector2) { 1070, 135 };
+ doorRight.facing = 2;
+ doorRight.locked = true;
+ doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2};
+ doorRight.selected = false;
+
+ // Monster init: lamp
+ lamp.position = (Vector2){ 35, 334 };
+ lamp.texture = LoadTexture("resources/textures/monster_lamp_left.png");
+ lamp.currentFrame = 0;
+ lamp.framesCounter = 0;
+ lamp.numFrames = 4;
+ lamp.bounds = (Rectangle){ lamp.position.x + 20, lamp.position.y + 0, 90, 380};
+ lamp.frameRec = (Rectangle) { 0, 0, lamp.texture.width/lamp.numFrames, lamp.texture.height };
+ lamp.selected = false;
+ lamp.active = false;
+ lamp.spooky = true;
+
+ // Monster init: mirror
+ mirror.position = (Vector2){ 300, 200 };
+ mirror.texture = LoadTexture("resources/textures/monster_mirror.png");
+ mirror.currentFrame = 0;
+ mirror.framesCounter = 0;
+ mirror.numFrames = 4;
+ mirror.bounds = (Rectangle){ mirror.position.x + 40, mirror.position.y + 20, 190, 200 };
+ mirror.frameRec = (Rectangle) { 0, 0, mirror.texture.width/mirror.numFrames, mirror.texture.height };
+ mirror.selected = false;
+ mirror.active = false;
+ mirror.spooky = false;
+
+ // Monster init: chair
+ chair.position = (Vector2){ 760, 430 };
+ chair.texture = LoadTexture("resources/textures/monster_chair_right.png");
+ chair.currentFrame = 0;
+ chair.framesCounter = 0;
+ chair.numFrames = 4;
+ chair.bounds = (Rectangle){ chair.position.x + 30, chair.position.y + 30, 120, 190 };
+ chair.frameRec = (Rectangle) { 0, 0, chair.texture.width/chair.numFrames, chair.texture.height };
+ chair.selected = false;
+ chair.active = false;
+ chair.spooky = true;
+}
+
+// Gameplay Screen Update logic
+void UpdateBathroomScreen(void)
+{
+ if (player.key)
+ {
+ // Door: right
+ if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true;
+ else doorRight.selected = false;
+
+ if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorRight.locked)
+ {
+ doorRight.frameRec.y = 0;
+ doorRight.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&lamp);
+ UpdateMonster(&mirror);
+ UpdateMonster(&chair);
+ }
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active) ||
+ ((CheckCollisionRecs(player.bounds, mirror.bounds)) && !mirror.active) ||
+ ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active)) monsterHover = true;
+ else monsterHover = false;
+
+
+ // Monters logic: lamp
+ if ((CheckCollisionRecs(player.bounds, lamp.bounds)) && !lamp.active)
+ {
+ lamp.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), lamp.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else lamp.selected = false;
+
+ // Monters logic: mirror
+ if ((CheckCollisionRecs(player.bounds, mirror.bounds)) && !mirror.active)
+ {
+ mirror.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), mirror.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else mirror.selected = false;
+
+ // Monters logic: chair
+ if ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active)
+ {
+ chair.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), chair.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 3;
+ }
+ }
+ else chair.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (lamp.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ lamp.active = true;
+ lamp.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (mirror.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ mirror.active = true;
+ mirror.selected = false;
+ }
+ else if (monsterCheck == 3)
+ {
+ if (chair.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ chair.active = true;
+ chair.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+}
+
+// Gameplay Screen Draw logic
+void DrawBathroomScreen(void)
+{
+ DrawTexture(background, 0, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(lamp, 0);
+ DrawMonster(mirror, 0);
+ DrawMonster(chair, 0);
+
+ // Draw door
+ if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN);
+ else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(lamp.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(mirror.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(chair.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadBathroomScreen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(lamp);
+ UnloadMonster(chair);
+ UnloadMonster(mirror);
+}
+
+// Gameplay Screen should finish?
+int FinishBathroomScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_ending.c b/games/skully_escape/screens/screen_ending.c
new file mode 100644
index 00000000..120d9071
--- /dev/null
+++ b/games/skully_escape/screens/screen_ending.c
@@ -0,0 +1,90 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Ending Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Ending screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static float alpha = 0.0f;
+
+//----------------------------------------------------------------------------------
+// Ending Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Ending Screen Initialization logic
+void InitEndingScreen(void)
+{
+ // TODO: Initialize ENDING screen variables here!
+ framesCounter = 0;
+ finishScreen = 0;
+ alpha = 0.0f;
+}
+
+// Ending Screen Update logic
+void UpdateEndingScreen(void)
+{
+ // TODO: Update ENDING screen variables here!
+ framesCounter++;
+
+ alpha += 0.005f;
+
+ if (alpha >= 1.0f) alpha = 1.0f;
+
+ // Press enter to change to ATTIC screen
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ finishScreen = 1;
+ }
+}
+
+// Ending Screen Draw logic
+void DrawEndingScreen(void)
+{
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), DARKGRAY);
+
+ DrawTextEx(font, "CONGRATULATIONS!", (Vector2){ 50, 160 }, font.size*3, 2, Fade(WHITE, alpha));
+ DrawTextEx(font, "SKULLY ESCAPED!", (Vector2){ 100, 300 }, font.size*3, 2, Fade(WHITE, alpha));
+
+ if ((framesCounter > 180) && ((framesCounter/40)%2)) DrawText("PRESS ENTER or CLICK", 380, 545, 40, BLACK);
+}
+
+// Ending Screen Unload logic
+void UnloadEndingScreen(void)
+{
+ // TODO: Unload ENDING screen variables here!
+}
+
+// Ending Screen should finish?
+int FinishEndingScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_kitchen.c b/games/skully_escape/screens/screen_kitchen.c
new file mode 100644
index 00000000..a6b8924d
--- /dev/null
+++ b/games/skully_escape/screens/screen_kitchen.c
@@ -0,0 +1,403 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorLeft;
+static Door doorRight;
+
+// Decalre monsters
+static Monster closet;
+static Monster chair;
+static Monster window;
+
+static bool monsterHover = false;
+static int monsterCheck = -1; // Identify checking monster
+
+static const char message[256] = "QUITE BORING AROUND...\nANY BETTER ENTERTAINING?";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitKitchenScreen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_kitchen.png");
+
+ // Initialize doors
+ doorLeft.position = (Vector2) { -45, 136 };
+ doorLeft.facing = 0;
+ doorLeft.locked = true;
+ doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2};
+ doorLeft.selected = false;
+
+ doorRight.position = (Vector2) { 1090, 148 };
+ doorRight.facing = 2;
+ doorRight.locked = true;
+ doorRight.frameRec =(Rectangle) {((doors.width/3)*doorRight.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorRight.bound = (Rectangle) { doorRight.position.x, doorRight.position.y, doors.width/3, doors.height/2};
+ doorRight.selected = false;
+
+ // Monster init: lamp
+ closet.position = (Vector2){ 280, 260 };
+ closet.texture = LoadTexture("resources/textures/monster_closet.png");
+ closet.currentFrame = 0;
+ closet.framesCounter = 0;
+ closet.numFrames = 4;
+ closet.bounds = (Rectangle){ closet.position.x + 100, closet.position.y+25, 272,348 };
+ closet.frameRec = (Rectangle) { 0, 0, closet.texture.width/closet.numFrames, closet.texture.height };
+ closet.selected = false;
+ closet.active = false;
+ closet.spooky = true;
+
+ // Monster init: chair
+ chair.position = (Vector2){ 230, 410 };
+ chair.texture = LoadTexture("resources/textures/monster_chair_left.png");
+ chair.currentFrame = 0;
+ chair.framesCounter = 0;
+ chair.numFrames = 4;
+ chair.bounds = (Rectangle){ chair.position.x + 30, chair.position.y + 60, 100, 160 };
+ chair.frameRec = (Rectangle) { 0, 0, chair.texture.width/chair.numFrames, chair.texture.height };
+ chair.selected = false;
+ chair.active = false;
+ chair.spooky = true;
+
+ // Monster init: window
+ window.position = (Vector2){ 715, 88 };
+ window.texture = LoadTexture("resources/textures/monster_window.png");
+ window.currentFrame = 0;
+ window.framesCounter = 0;
+ window.numFrames = 4;
+ window.bounds = (Rectangle){ window.position.x + 100, window.position.y + 10, 200, 370 };
+ window.frameRec = (Rectangle) { 0, 0, window.texture.width/window.numFrames, window.texture.height };
+ window.selected = false;
+ window.active = false;
+ window.spooky = false;
+}
+
+// Gameplay Screen Update logic
+void UpdateKitchenScreen(void)
+{
+ if (player.key)
+ {
+ // Door: left
+ if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true;
+ else doorLeft.selected = false;
+
+ if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorLeft.locked)
+ {
+ doorLeft.frameRec.y = 0;
+ doorLeft.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+
+ // Door: right
+ if ((CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorRight.bound))) doorRight.selected = true;
+ else doorRight.selected = false;
+
+ if ((doorRight.selected) && (CheckCollisionRecs(player.bounds, doorRight.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorRight.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorRight.locked)
+ {
+ doorRight.frameRec.y = 0;
+ doorRight.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 2;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&closet);
+ UpdateMonster(&chair);
+ UpdateMonster(&window);
+ }
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, closet.bounds)) && !closet.active) ||
+ ((CheckCollisionRecs(player.bounds, window.bounds)) && !window.active)) monsterHover = true;
+ else monsterHover = false;
+
+ // Monters logic: closet
+ if ((CheckCollisionRecs(player.bounds, closet.bounds)) && !closet.active)
+ {
+ closet.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), closet.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else closet.selected = false;
+
+ // Monters logic: chair
+ if ((CheckCollisionRecs(player.bounds, chair.bounds)) && !chair.active)
+ {
+ chair.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), chair.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else chair.selected = false;
+
+ // Monters logic: window
+ if ((CheckCollisionRecs(player.bounds, window.bounds)) && !window.active)
+ {
+ window.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), window.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 3;
+ }
+ }
+ else window.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (closet.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ closet.active = true;
+ closet.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (chair.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ chair.active = true;
+ chair.selected = false;
+ }
+ else if (monsterCheck == 3)
+ {
+ if (window.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ window.active = true;
+ window.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+}
+
+// Gameplay Screen Draw logic
+void DrawKitchenScreen(void)
+{
+ DrawTexture(background, 0, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(closet, 0);
+ DrawMonster(chair, 0);
+ DrawMonster(window, 0);
+
+ // Draw door
+ if (doorRight.selected) DrawTextureRec(doors, doorRight.frameRec, doorRight.position, GREEN);
+ else DrawTextureRec(doors, doorRight.frameRec, doorRight.position, WHITE);
+
+ if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, GREEN);
+ else DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(closet.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(window.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(chair.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadKitchenScreen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(closet);
+ UnloadMonster(chair);
+ UnloadMonster(window);
+}
+
+// Gameplay Screen should finish?
+int FinishKitchenScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_livingroom.c b/games/skully_escape/screens/screen_livingroom.c
new file mode 100644
index 00000000..b2b09d9a
--- /dev/null
+++ b/games/skully_escape/screens/screen_livingroom.c
@@ -0,0 +1,403 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+#include "../player.h"
+#include "../monster.h"
+
+#include <string.h>
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Gameplay screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D background;
+
+// Declare doors
+static Door doorCenter;
+static Door doorLeft;
+
+// Decalre monsters
+static Monster candle;
+static Monster picture;
+static Monster phone;
+
+static bool monsterHover = false;
+static int monsterCheck = -1; // Identify checking monster
+
+static const char message[256] = "WHEN WIND BLOWS, IT KNOWS THE DIRECTION\nLET IT GUIDE YOU!";
+static int msgPosX = 100;
+
+static int msgState = 0; // 0-writting, 1-wait, 2-choose
+static int lettersCounter = 0;
+static char msgBuffer[256] = { '\0' };
+static int msgCounter = 0;
+
+static bool searching = false;
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitLivingroomScreen(void)
+{
+ ResetPlayer();
+
+ // Reset Screen variables
+ monsterHover = false;
+ monsterCheck = -1;
+ msgState = 0;
+ msgCounter = 0;
+ lettersCounter = 0;
+ for (int i = 0; i < 256; i++) msgBuffer[i] = '\0';
+
+ framesCounter = 0;
+ finishScreen = 0;
+
+ background = LoadTexture("resources/textures/background_livingroom.png");
+
+ // Initialize doors
+ doorLeft.position = (Vector2) { -45, 140};
+ doorLeft.facing = 0;
+ doorLeft.locked = true;
+ doorLeft.frameRec =(Rectangle) {((doors.width/3)*doorLeft.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorLeft.bound = (Rectangle) { doorLeft.position.x, doorLeft.position.y, doors.width/3, doors.height/2};
+ doorLeft.selected = false;
+
+ doorCenter.position = (Vector2) { 830, 108 };
+ doorCenter.facing = 1;
+ doorCenter.locked = true;
+ doorCenter.frameRec =(Rectangle) {((doors.width/3)*doorCenter.facing), doors.height/2, doors.width/3, doors.height/2};
+ doorCenter.bound = (Rectangle) { doorCenter.position.x, doorCenter.position.y, doors.width/3, doors.height/2};
+ doorCenter.selected = false;
+
+ // Monster init: lamp
+ candle.position = (Vector2){ 154, 256 };
+ candle.texture = LoadTexture("resources/textures/monster_candle.png");
+ candle.currentFrame = 0;
+ candle.framesCounter = 0;
+ candle.numFrames = 4;
+ candle.bounds = (Rectangle){ candle.position.x + 90, candle.position.y + 30, 185, 340 };
+ candle.frameRec = (Rectangle) { 0, 0, candle.texture.width/candle.numFrames, candle.texture.height };
+ candle.selected = false;
+ candle.active = false;
+ candle.spooky = false;
+
+ // Monster init: arc
+ picture.position = (Vector2){ 504, 164 };
+ picture.texture = LoadTexture("resources/textures/monster_picture.png");
+ picture.currentFrame = 0;
+ picture.framesCounter = 0;
+ picture.numFrames = 4;
+ picture.bounds = (Rectangle){ picture.position.x + 44, picture.position.y, 174, 264 };
+ picture.frameRec = (Rectangle) { 0, 0, picture.texture.width/picture.numFrames, picture.texture.height };
+ picture.selected = false;
+ picture.active = false;
+ picture.spooky = true;
+
+ // Monster init: phone
+ phone.position = (Vector2){ 1054, 404 };
+ phone.texture = LoadTexture("resources/textures/monster_phone.png");
+ phone.currentFrame = 0;
+ phone.framesCounter = 0;
+ phone.numFrames = 4;
+ phone.bounds = (Rectangle){ phone.position.x + 64, phone.position.y +120, 100, 160 };
+ phone.frameRec = (Rectangle) { 0, 0, phone.texture.width/phone.numFrames, phone.texture.height };
+ phone.selected = false;
+ phone.active = false;
+ phone.spooky = true;
+}
+
+// Gameplay Screen Update logic
+void UpdateLivingroomScreen(void)
+{
+ if (player.key)
+ {
+ // Door: left
+ if ((CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorLeft.bound))) doorLeft.selected = true;
+ else doorLeft.selected = false;
+
+ if ((doorLeft.selected) && (CheckCollisionRecs(player.bounds, doorLeft.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorLeft.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorLeft.locked)
+ {
+ doorLeft.frameRec.y = 0;
+ doorLeft.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 1;
+ }
+ }
+
+ // Door: center
+ if ((CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) ||
+ (CheckCollisionRecs(player.bounds, doorCenter.bound))) doorCenter.selected = true;
+ else doorCenter.selected = false;
+
+ if ((doorCenter.selected) && (CheckCollisionRecs(player.bounds, doorCenter.bound)))
+ {
+ if (((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && CheckCollisionPointRec(GetMousePosition(), doorCenter.bound)) || (IsKeyPressed(KEY_SPACE)))
+ {
+ if (doorCenter.locked)
+ {
+ doorCenter.frameRec.y = 0;
+ doorCenter.locked = false;
+ PlaySound(sndDoor);
+ }
+ else finishScreen = 2;
+ }
+ }
+ }
+
+ if (msgState > 2)
+ {
+ UpdatePlayer();
+
+ // Monsters logic
+ UpdateMonster(&candle);
+ UpdateMonster(&picture);
+ UpdateMonster(&phone);
+ }
+
+ // Check player hover monsters to interact
+ if (((CheckCollisionRecs(player.bounds, candle.bounds)) && !candle.active) ||
+ ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active) ||
+ ((CheckCollisionRecs(player.bounds, phone.bounds)) && !phone.active)) monsterHover = true;
+ else monsterHover = false;
+
+ // Monters logic: candle
+ if ((CheckCollisionRecs(player.bounds, candle.bounds)) && !candle.active)
+ {
+ candle.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), candle.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 1;
+ }
+ }
+ else candle.selected = false;
+
+ // Monters logic: picture
+ if ((CheckCollisionRecs(player.bounds, picture.bounds)) && !picture.active)
+ {
+ picture.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), picture.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 2;
+ }
+ }
+ else picture.selected = false;
+
+ // Monters logic: phone
+ if ((CheckCollisionRecs(player.bounds, phone.bounds)) && !phone.active)
+ {
+ phone.selected = true;
+
+ if ((IsKeyPressed(KEY_SPACE)) ||
+ ((IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) && (CheckCollisionPointRec(GetMousePosition(), phone.bounds))))
+ {
+ SearchKeyPlayer();
+ searching = true;
+ framesCounter = 0;
+
+ monsterCheck = 3;
+ }
+ }
+ else phone.selected = false;
+
+ if (searching)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180)
+ {
+ if (monsterCheck == 1)
+ {
+ if (candle.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ candle.active = true;
+ candle.selected = false;
+ }
+ else if (monsterCheck == 2)
+ {
+ if (picture.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ picture.active = true;
+ picture.selected = false;
+ }
+ else if (monsterCheck == 3)
+ {
+ if (phone.spooky)
+ {
+ ScarePlayer();
+ PlaySound(sndScream);
+ }
+ else FindKeyPlayer();
+
+ phone.active = true;
+ phone.selected = false;
+ }
+
+ searching = false;
+ framesCounter = 0;
+ }
+ }
+
+ // Text animation
+ framesCounter++;
+
+ if ((framesCounter%2) == 0) lettersCounter++;
+
+ if (msgState == 0)
+ {
+ if (lettersCounter <= (int)strlen(message)) strncpy(msgBuffer, message, lettersCounter);
+ else
+ {
+ for (int i = 0; i < (int)strlen(msgBuffer); i++) msgBuffer[i] = '\0';
+
+ lettersCounter = 0;
+ msgState = 1;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) msgState = 1;
+ }
+ else if (msgState == 1)
+ {
+ msgCounter++;
+
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ msgState = 2;
+ msgCounter = 0;
+ }
+ }
+ else if (msgState == 2)
+ {
+ msgCounter++;
+
+ if (msgCounter > 180) msgState = 3;
+ }
+ else msgCounter++;
+}
+
+// Gameplay Screen Draw logic
+void DrawLivingroomScreen(void)
+{
+ DrawTexture(background, 0, 0, WHITE);
+
+ // Draw monsters
+ DrawMonster(picture, 0);
+ DrawMonster(candle, 0);
+ DrawMonster(phone, 0);
+
+ // Draw door
+ if (doorCenter.selected) DrawTextureRec(doors, doorCenter.frameRec, doorCenter.position, GREEN);
+ else DrawTextureRec(doors, doorCenter.frameRec, doorCenter.position, WHITE);
+ if (doorLeft.selected) DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, GREEN);
+ else DrawTextureRec(doors, doorLeft.frameRec, doorLeft.position, WHITE);
+
+ // Draw messsages
+ if (msgState < 2) DrawRectangle(0, 40, GetScreenWidth(), 200, Fade(LIGHTGRAY, 0.5f));
+ else if (msgState == 2) DrawRectangle(0, 80, GetScreenWidth(), 100, Fade(LIGHTGRAY, 0.5f));
+
+ if (msgState == 0)
+ {
+ DrawTextEx(font, msgBuffer, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+ }
+ else if (msgState == 1)
+ {
+ DrawTextEx(font, message, (Vector2){ msgPosX, 80 }, font.size, 2, WHITE);
+
+ if ((msgCounter/30)%2) DrawText("PRESS ENTER or CLICK", GetScreenWidth() - 280, 200, 20, BLACK);
+ }
+ else if (msgState == 2)
+ {
+ if ((msgCounter/30)%2)
+ {
+ DrawTextEx(font, "CHOOSE WISELY!", (Vector2){ 300, 95 }, font.size*2, 2, WHITE);
+
+ DrawRectangleRec(candle.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(phone.bounds, Fade(RED, 0.6f));
+ DrawRectangleRec(picture.bounds, Fade(RED, 0.6f));
+ }
+ }
+ else
+ {
+ if ((monsterHover) && ((msgCounter/30)%2))
+ {
+ DrawRectangle(0, 0, GetScreenWidth(), 50, Fade(LIGHTGRAY, 0.5f));
+ DrawText("PRESS SPACE or CLICK to INTERACT", 420, 15, 20, BLACK);
+ }
+ }
+
+ DrawPlayer(); // NOTE: Also draws mouse pointer!
+}
+
+// Gameplay Screen Unload logic
+void UnloadLivingroomScreen(void)
+{
+ // TODO: Unload GAMEPLAY screen variables here!
+ UnloadTexture(background);
+
+ UnloadMonster(candle);
+ UnloadMonster(picture);
+ UnloadMonster(phone);
+}
+
+// Gameplay Screen should finish?
+int FinishLivingroomScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_logo.c b/games/skully_escape/screens/screen_logo.c
new file mode 100644
index 00000000..f07f5f54
--- /dev/null
+++ b/games/skully_escape/screens/screen_logo.c
@@ -0,0 +1,108 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Logo Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Logo screen global variables
+static int framesCounter = 0;
+static int finishScreen;
+
+static Texture2D logo;
+static float logoAlpha = 0;
+
+static int state = 0;
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Logo Screen Initialization logic
+void InitLogoScreen(void)
+{
+ // Initialize LOGO screen variables here!
+ finishScreen = 0;
+
+ logo = LoadTexture("resources/textures/skully_logo.png");
+}
+
+// Logo Screen Update logic
+void UpdateLogoScreen(void)
+{
+ // Update LOGO screen variables here!
+ if (state == 0)
+ {
+ logoAlpha += 0.04f;
+
+ if (logoAlpha >= 1.0f) state = 1;
+ }
+ else if (state == 1)
+ {
+ framesCounter++;
+
+ if (framesCounter > 180) state = 2;
+ }
+ else if (state == 2)
+ {
+ logoAlpha -= 0.04f;
+
+ if (logoAlpha <= 0.0f)
+ {
+ framesCounter = 0;
+ state = 3;
+ }
+ }
+ else if (state == 3)
+ {
+ finishScreen = 1;
+ }
+}
+
+// Logo Screen Draw logic
+void DrawLogoScreen(void)
+{
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), RAYWHITE);
+
+ DrawTexture(logo, GetScreenWidth()/2 - logo.width/2, 130, Fade(WHITE, logoAlpha));
+
+ DrawText("GRAY TEAM", 340, 450, 100, Fade(DARKGRAY, logoAlpha));
+}
+
+// Logo Screen Unload logic
+void UnloadLogoScreen(void)
+{
+ // Unload LOGO screen variables here!
+ UnloadTexture(logo);
+}
+
+// Logo Screen should finish?
+int FinishLogoScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_logo_raylib.c b/games/skully_escape/screens/screen_logo_raylib.c
new file mode 100644
index 00000000..e5efe843
--- /dev/null
+++ b/games/skully_escape/screens/screen_logo_raylib.c
@@ -0,0 +1,201 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Logo Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+#define LOGO_RECS_SIDE 16
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Logo screen global variables
+static int framesCounter = 0;
+static int finishScreen;
+
+static int logoPositionX;
+static int logoPositionY;
+
+static int lettersCount = 0;
+
+static int topSideRecWidth = LOGO_RECS_SIDE;
+static int leftSideRecHeight = LOGO_RECS_SIDE;
+
+static int bottomSideRecWidth = LOGO_RECS_SIDE;
+static int rightSideRecHeight = LOGO_RECS_SIDE;
+
+static char raylib[8]; // raylib text array, max 8 letters
+static int state = 0; // Tracking animation states (State Machine)
+static float alpha = 1.0f; // Useful for fading
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Logo Screen Initialization logic
+void rlInitLogoScreen(void)
+{
+ // TODO: Initialize LOGO screen variables here!
+ finishScreen = 0;
+
+ logoPositionX = GetScreenWidth()/2 - 128;
+ logoPositionY = GetScreenHeight()/2 - 128;
+
+ for (int i = 0; i < 8; i++) raylib[i] = '\0';
+}
+
+// Logo Screen Update logic
+void rlUpdateLogoScreen(void)
+{
+ // Update LOGO screen variables here!
+ if (state == 0) // State 0: Small box blinking
+ {
+ framesCounter++;
+
+ if (framesCounter == 80)
+ {
+ state = 1;
+ framesCounter = 0; // Reset counter... will be used later...
+ }
+ }
+ else if (state == 1) // State 1: Top and left bars growing
+ {
+ topSideRecWidth += 8;
+ leftSideRecHeight += 8;
+
+ if (topSideRecWidth == 256) state = 2;
+ }
+ else if (state == 2) // State 2: Bottom and right bars growing
+ {
+ bottomSideRecWidth += 8;
+ rightSideRecHeight += 8;
+
+ if (bottomSideRecWidth == 256) state = 3;
+ }
+ else if (state == 3) // State 3: Letters appearing (one by one)
+ {
+ framesCounter++;
+
+ if (framesCounter/10) // Every 12 frames, one more letter!
+ {
+ lettersCount++;
+ framesCounter = 0;
+ }
+
+ switch (lettersCount)
+ {
+ case 1: raylib[0] = 'r'; break;
+ case 2: raylib[1] = 'a'; break;
+ case 3: raylib[2] = 'y'; break;
+ case 4: raylib[3] = 'l'; break;
+ case 5: raylib[4] = 'i'; break;
+ case 6: raylib[5] = 'b'; break;
+ default: break;
+ }
+
+ // When all letters have appeared...
+ if (lettersCount >= 10)
+ {
+ state = 4;
+ framesCounter = 0;
+ }
+ }
+ else if (state == 4)
+ {
+ framesCounter++;
+
+ if (framesCounter > 100)
+ {
+ alpha -= 0.02f;
+
+ if (alpha <= 0.0f)
+ {
+ alpha = 0.0f;
+ finishScreen = 1;
+ }
+ }
+ }
+}
+
+// Logo Screen Draw logic
+void rlDrawLogoScreen(void)
+{
+ if (state == 0)
+ {
+ if ((framesCounter/10)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
+ }
+ else if (state == 1)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+ }
+ else if (state == 2)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+
+ DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
+ }
+ else if (state == 3)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
+ }
+ else if (state == 4)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
+
+ if (framesCounter > 20) DrawText("powered by", logoPositionX, logoPositionY - 27, 20, Fade(DARKGRAY, alpha));
+ }
+}
+
+// Logo Screen Unload logic
+void rlUnloadLogoScreen(void)
+{
+ // TODO: Unload LOGO screen variables here!
+}
+
+// Logo Screen should finish?
+int rlFinishLogoScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screen_title.c b/games/skully_escape/screens/screen_title.c
new file mode 100644
index 00000000..837b5112
--- /dev/null
+++ b/games/skully_escape/screens/screen_title.c
@@ -0,0 +1,92 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Title Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Title screen global variables
+static int framesCounter;
+static int finishScreen;
+
+static Texture2D title;
+static float titleAlpha = 0.0f;
+
+//----------------------------------------------------------------------------------
+// Title Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Title Screen Initialization logic
+void InitTitleScreen(void)
+{
+ // Initialize TITLE screen variables here!
+ framesCounter = 0;
+ finishScreen = 0;
+
+ title = LoadTexture("resources/textures/title.png");
+}
+
+// Title Screen Update logic
+void UpdateTitleScreen(void)
+{
+ // Update TITLE screen variables here!
+ framesCounter++;
+
+ titleAlpha += 0.005f;
+
+ if (titleAlpha >= 1.0f) titleAlpha = 1.0f;
+
+ // Press enter to change to ATTIC screen
+ if ((IsKeyPressed(KEY_ENTER)) || (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ finishScreen = 1;
+ }
+}
+
+// Title Screen Draw logic
+void DrawTitleScreen(void)
+{
+ //DrawText("TITLE SCREEN", 100, 100, 140, Fade(BLACK, titleAlpha));
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), DARKGRAY);
+ DrawTexture(title, GetScreenWidth()/2 - title.width/2, 20, Fade(WHITE, titleAlpha));
+
+ if ((framesCounter > 180) && ((framesCounter/40)%2)) DrawText("PRESS ENTER to START", 380, 545, 40, BLACK);
+}
+
+// Title Screen Unload logic
+void UnloadTitleScreen(void)
+{
+ // Unload TITLE screen variables here!
+ UnloadTexture(title);
+}
+
+// Title Screen should finish?
+int FinishTitleScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/skully_escape/screens/screens.h b/games/skully_escape/screens/screens.h
new file mode 100644
index 00000000..790df9ff
--- /dev/null
+++ b/games/skully_escape/screens/screens.h
@@ -0,0 +1,164 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Screens Functions Declarations (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef SCREENS_H
+#define SCREENS_H
+
+#define PLAYER_ANIM_FRAMES 7
+#define PLAYER_ANIM_SEQ 2
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum GameScreen { LOGO = 0, LOGO_RL, TITLE, ATTIC, AISLE01, AISLE02, BATHROOM, LIVINGROOM, KITCHEN, ARMORY, ENDING } GameScreen;
+
+typedef struct Door {
+ Vector2 position;
+ int facing;
+ bool locked;
+ bool selected;
+ Rectangle frameRec;
+ Rectangle bound;
+} Door;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+GameScreen currentScreen;
+SpriteFont font;
+
+Texture2D doors;
+Sound sndDoor;
+Sound sndScream;
+
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitLogoScreen(void);
+void UpdateLogoScreen(void);
+void DrawLogoScreen(void);
+void UnloadLogoScreen(void);
+int FinishLogoScreen(void);
+
+//----------------------------------------------------------------------------------
+// raylib Logo Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void rlInitLogoScreen(void);
+void rlUpdateLogoScreen(void);
+void rlDrawLogoScreen(void);
+void rlUnloadLogoScreen(void);
+int rlFinishLogoScreen(void);
+
+//----------------------------------------------------------------------------------
+// Title Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitTitleScreen(void);
+void UpdateTitleScreen(void);
+void DrawTitleScreen(void);
+void UnloadTitleScreen(void);
+int FinishTitleScreen(void);
+
+//----------------------------------------------------------------------------------
+// Attic Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitAtticScreen(void);
+void UpdateAtticScreen(void);
+void DrawAtticScreen(void);
+void UnloadAtticScreen(void);
+int FinishAtticScreen(void);
+
+//----------------------------------------------------------------------------------
+// Aisle01 Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitAisle01Screen(void);
+void UpdateAisle01Screen(void);
+void DrawAisle01Screen(void);
+void UnloadAisle01Screen(void);
+int FinishAisle01Screen(void);
+
+//----------------------------------------------------------------------------------
+// Aisle02 Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitAisle02Screen(void);
+void UpdateAisle02Screen(void);
+void DrawAisle02Screen(void);
+void UnloadAisle02Screen(void);
+int FinishAisle02Screen(void);
+
+//----------------------------------------------------------------------------------
+// Bathroom Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitBathroomScreen(void);
+void UpdateBathroomScreen(void);
+void DrawBathroomScreen(void);
+void UnloadBathroomScreen(void);
+int FinishBathroomScreen(void);
+
+//----------------------------------------------------------------------------------
+// Livingroom Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitLivingroomScreen(void);
+void UpdateLivingroomScreen(void);
+void DrawLivingroomScreen(void);
+void UnloadLivingroomScreen(void);
+int FinishLivingroomScreen(void);
+
+//----------------------------------------------------------------------------------
+// Kitchen Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitKitchenScreen(void);
+void UpdateKitchenScreen(void);
+void DrawKitchenScreen(void);
+void UnloadKitchenScreen(void);
+int FinishKitchenScreen(void);
+
+//----------------------------------------------------------------------------------
+// Armory Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitArmoryScreen(void);
+void UpdateArmoryScreen(void);
+void DrawArmoryScreen(void);
+void UnloadArmoryScreen(void);
+int FinishArmoryScreen(void);
+
+//----------------------------------------------------------------------------------
+// Ending Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitEndingScreen(void);
+void UpdateEndingScreen(void);
+void DrawEndingScreen(void);
+void UnloadEndingScreen(void);
+int FinishEndingScreen(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SCREENS_H \ No newline at end of file
diff --git a/games/skully_escape/skully_escape.c b/games/skully_escape/skully_escape.c
new file mode 100644
index 00000000..22cc04e4
--- /dev/null
+++ b/games/skully_escape/skully_escape.c
@@ -0,0 +1,403 @@
+/*******************************************************************************************
+*
+* SKULLY ESCAPE [KING GAME JAM 2015]
+*
+* This game has been created using raylib (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "screens/screens.h" // NOTE: Defines global variable: currentScreen
+
+#include "player.h"
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+const int screenWidth = 1280;
+const int screenHeight = 720;
+
+// Required variables to manage screen transitions (fade-in, fade-out)
+float transAlpha = 0;
+bool onTransition = false;
+bool transFadeOut = false;
+int transFromScreen = -1;
+int transToScreen = -1;
+
+static int framesCounter = 0;
+
+//----------------------------------------------------------------------------------
+// Local Functions Declaration
+//----------------------------------------------------------------------------------
+void TransitionToScreen(int screen);
+void ChangeToScreen(int screen); // No transition effect
+void UpdateTransition(void);
+void DrawTransition(void);
+
+void UpdateDrawFrame(void); // Update and Draw one frame
+
+//----------------------------------------------------------------------------------
+// Main entry point
+//----------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //---------------------------------------------------------
+ const char windowTitle[30] = "SKULLY ESCAPE [KING GAMEJAM]";
+
+ InitWindow(screenWidth, screenHeight, windowTitle);
+
+ // Global data loading (assets that must be available in all screens, i.e. fonts)
+ InitAudioDevice();
+
+ PlayMusicStream("resources/audio/come_play_with_me.ogg");
+
+ font = LoadSpriteFont("resources/textures/alagard.png");
+ doors = LoadTexture("resources/textures/doors.png");
+ sndDoor = LoadSound("resources/audio/door.ogg");
+ sndScream = LoadSound("resources/audio/scream.ogg");
+
+ InitPlayer();
+
+ // Setup and Init first screen
+ currentScreen = LOGO;
+ InitLogoScreen();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ UpdateDrawFrame();
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+
+ // Unload all global loaded data (i.e. fonts) here!
+ UnloadPlayer();
+ UnloadSpriteFont(font);
+ UnloadTexture(doors);
+ UnloadSound(sndDoor);
+ UnloadSound(sndScream);
+
+ CloseAudioDevice();
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+void TransitionToScreen(int screen)
+{
+ onTransition = true;
+ transFromScreen = currentScreen;
+ transToScreen = screen;
+}
+
+void ChangeToScreen(int screen)
+{
+ switch (currentScreen)
+ {
+ case LOGO: UnloadLogoScreen(); break;
+ case LOGO_RL: rlUnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case ATTIC: UnloadAtticScreen(); break;
+ case AISLE01: UnloadAisle01Screen();break;
+ case AISLE02: UnloadAisle02Screen();break;
+ case ARMORY: UnloadArmoryScreen();break;
+ case LIVINGROOM: UnloadLivingroomScreen();break;
+ case KITCHEN: UnloadKitchenScreen(); break;
+ case BATHROOM: UnloadBathroomScreen(); break;
+ case ENDING: UnloadEndingScreen(); break;
+ default: break;
+ }
+
+ switch (screen)
+ {
+ case LOGO: InitLogoScreen(); break;
+ case LOGO_RL: rlInitLogoScreen(); break;
+ case TITLE: InitTitleScreen(); break;
+ case ATTIC: InitAtticScreen(); break;
+ case AISLE01: InitAisle01Screen();break;
+ case AISLE02: InitAisle02Screen();break;
+ case ARMORY: InitArmoryScreen();break;
+ case LIVINGROOM: InitLivingroomScreen();break;
+ case KITCHEN: InitKitchenScreen(); break;
+ case BATHROOM: InitBathroomScreen(); break;
+ case ENDING: InitEndingScreen(); break;
+ default: break;
+ }
+
+ currentScreen = screen;
+}
+
+void UpdateTransition(void)
+{
+ if (!transFadeOut)
+ {
+ transAlpha += 0.05f;
+
+ if (transAlpha >= 1.0)
+ {
+ transAlpha = 1.0;
+
+ switch (transFromScreen)
+ {
+ case LOGO: UnloadLogoScreen(); break;
+ case LOGO_RL: rlUnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case ATTIC: UnloadAtticScreen(); break;
+ case AISLE01: UnloadAisle01Screen();break;
+ case AISLE02: UnloadAisle02Screen();break;
+ case ARMORY: UnloadArmoryScreen();break;
+ case LIVINGROOM: UnloadLivingroomScreen();break;
+ case KITCHEN: UnloadKitchenScreen(); break;
+ case BATHROOM: UnloadBathroomScreen(); break;
+ case ENDING: UnloadEndingScreen(); break;
+ default: break;
+ }
+
+ switch (transToScreen)
+ {
+ case LOGO:
+ {
+ InitLogoScreen();
+ currentScreen = LOGO;
+ } break;
+ case LOGO_RL:
+ {
+ rlInitLogoScreen();
+ currentScreen = LOGO_RL;
+ } break;
+ case TITLE:
+ {
+ InitTitleScreen();
+ currentScreen = TITLE;
+ } break;
+ case ATTIC:
+ {
+ InitAtticScreen();
+ currentScreen = ATTIC;
+ } break;
+ case AISLE01:
+ {
+ InitAisle01Screen();
+ currentScreen = AISLE01;
+ } break;
+ case AISLE02:
+ {
+ InitAisle02Screen();
+ currentScreen = AISLE02;
+ } break;
+ case BATHROOM:
+ {
+ InitBathroomScreen();
+ currentScreen = BATHROOM;
+ } break;
+ case LIVINGROOM:
+ {
+ InitLivingroomScreen();
+ currentScreen = LIVINGROOM;
+ } break;
+ case KITCHEN:
+ {
+ InitKitchenScreen();
+ currentScreen = KITCHEN;
+ } break;
+ case ARMORY:
+ {
+ InitArmoryScreen();
+ currentScreen = ARMORY;
+ } break;
+ case ENDING:
+ {
+ InitEndingScreen();
+ currentScreen = ENDING;
+ } break;
+ default: break;
+ }
+
+ transFadeOut = true;
+ }
+ }
+ else // Transition fade out logic
+ {
+ transAlpha -= 0.05f;
+
+ if (transAlpha <= 0)
+ {
+ transAlpha = 0;
+ transFadeOut = false;
+ onTransition = false;
+ transFromScreen = -1;
+ transToScreen = -1;
+ }
+ }
+}
+
+void DrawTransition(void)
+{
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha));
+}
+
+// Update and draw game frame
+void UpdateDrawFrame(void)
+{
+ // Update
+ //----------------------------------------------------------------------------------
+ if (!onTransition)
+ {
+ if (player.dead)
+ {
+ framesCounter++;
+
+ if (framesCounter > 80)
+ {
+ framesCounter = 0;
+ player.dead = false;
+ player.numLifes = 4;
+
+ TransitionToScreen(TITLE);
+ }
+ }
+
+ switch(currentScreen)
+ {
+ case LOGO:
+ {
+ UpdateLogoScreen();
+
+ if (FinishLogoScreen()) ChangeToScreen(LOGO_RL);
+
+ } break;
+ case LOGO_RL:
+ {
+ rlUpdateLogoScreen();
+
+ if (rlFinishLogoScreen()) TransitionToScreen(TITLE);
+
+ } break;
+ case TITLE:
+ {
+ UpdateTitleScreen();
+
+ if (FinishTitleScreen() == 1) TransitionToScreen(ATTIC);
+
+ } break;
+ case ATTIC:
+ {
+ UpdateAtticScreen();
+
+ if (FinishAtticScreen() == 1) TransitionToScreen(AISLE01);
+
+ } break;
+ case AISLE01:
+ {
+ UpdateAisle01Screen();
+
+ if (FinishAisle01Screen() == 1) TransitionToScreen(BATHROOM);
+ else if(FinishAisle01Screen() == 2) TransitionToScreen(KITCHEN);
+ else if(FinishAisle01Screen() == 3) TransitionToScreen(LIVINGROOM);
+
+ } break;
+ case BATHROOM:
+ {
+ UpdateBathroomScreen();
+
+ if (FinishBathroomScreen() == 1) TransitionToScreen(AISLE01);
+
+ } break;
+ case LIVINGROOM:
+ {
+ UpdateLivingroomScreen();
+
+ if (FinishLivingroomScreen() == 1) TransitionToScreen(AISLE01);
+ else if(FinishLivingroomScreen() == 2)TransitionToScreen(AISLE02);
+
+ } break;
+ case AISLE02:
+ {
+ UpdateAisle02Screen();
+
+ if (FinishAisle02Screen() == 1) TransitionToScreen(KITCHEN);
+
+ } break;
+ case KITCHEN:
+ {
+ UpdateKitchenScreen();
+
+ if (FinishKitchenScreen() == 1) TransitionToScreen(ARMORY);
+ else if(FinishKitchenScreen() == 2)TransitionToScreen(AISLE02);
+
+ } break;
+ case ARMORY:
+ {
+ UpdateArmoryScreen();
+
+ if(FinishArmoryScreen() == 1) TransitionToScreen(ENDING);
+ else if(FinishArmoryScreen() == 2) TransitionToScreen(KITCHEN);
+
+ } break;
+ case ENDING:
+ {
+ UpdateEndingScreen();
+
+ if (FinishEndingScreen()) TransitionToScreen(TITLE);
+
+ } break;
+ default: break;
+ }
+ }
+ else
+ {
+ // Update transition (fade-in, fade-out)
+ UpdateTransition();
+ }
+
+ UpdateMusicStream();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ switch(currentScreen)
+ {
+ case LOGO: DrawLogoScreen(); break;
+ case LOGO_RL: rlDrawLogoScreen(); break;
+ case TITLE: DrawTitleScreen(); break;
+ case ATTIC: DrawAtticScreen(); break;
+ case AISLE01: DrawAisle01Screen();break;
+ case AISLE02: DrawAisle02Screen();break;
+ case BATHROOM: DrawBathroomScreen();break;
+ case LIVINGROOM: DrawLivingroomScreen();break;
+ case KITCHEN: DrawKitchenScreen();break;
+ case ARMORY: DrawArmoryScreen();break;
+ case ENDING: DrawEndingScreen(); break;
+ default: break;
+ }
+
+ if (onTransition) DrawTransition();
+
+ //DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+}
+
diff --git a/games/snake.c b/games/snake.c
new file mode 100644
index 00000000..ac2f6132
--- /dev/null
+++ b/games/snake.c
@@ -0,0 +1,293 @@
+/*******************************************************************************************
+*
+* raylib - sample game: snake
+*
+* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define SNAKE_LENGTH 256
+#define SQUARE_SIZE 31
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Snake {
+ Vector2 position;
+ Vector2 size;
+ Vector2 speed;
+ Color color;
+} Snake;
+
+typedef struct Food {
+ Vector2 position;
+ Vector2 size;
+ bool active;
+ Color color;
+} Food;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+
+static Food fruit;
+static Snake snake[SNAKE_LENGTH];
+static Vector2 snakePosition[SNAKE_LENGTH];
+static bool allowMove;
+static Vector2 offset;
+static int counterTail;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: snake");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ framesCounter = 0;
+ gameOver = false;
+ pause = false;
+
+ counterTail = 1;
+ allowMove = false;
+
+ offset.x = screenWidth%SQUARE_SIZE;
+ offset.y = screenHeight%SQUARE_SIZE;
+
+ for (int i = 0; i < SNAKE_LENGTH; i++)
+ {
+ snake[i].position = (Vector2){ offset.x/2, offset.y/2 };
+ snake[i].size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE };
+ snake[i].speed = (Vector2){ SQUARE_SIZE, 0 };
+
+ if (i == 0) snake[i].color = DARKBLUE;
+ else snake[i].color = BLUE;
+ }
+
+ for (int i = 0; i < SNAKE_LENGTH; i++)
+ {
+ snakePosition[i] = (Vector2){ 0.0f, 0.0f };
+ }
+
+ fruit.size = (Vector2){ SQUARE_SIZE, SQUARE_SIZE };
+ fruit.color = SKYBLUE;
+ fruit.active = false;
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ // control
+ if (IsKeyPressed(KEY_RIGHT) && (snake[0].speed.x == 0) && allowMove)
+ {
+ snake[0].speed = (Vector2){ SQUARE_SIZE, 0 };
+ allowMove = false;
+ }
+ if (IsKeyPressed(KEY_LEFT) && (snake[0].speed.x == 0) && allowMove)
+ {
+ snake[0].speed = (Vector2){ -SQUARE_SIZE, 0 };
+ allowMove = false;
+ }
+ if (IsKeyPressed(KEY_UP) && (snake[0].speed.y == 0) && allowMove)
+ {
+ snake[0].speed = (Vector2){ 0, -SQUARE_SIZE };
+ allowMove = false;
+ }
+ if (IsKeyPressed(KEY_DOWN) && (snake[0].speed.y == 0) && allowMove)
+ {
+ snake[0].speed = (Vector2){ 0, SQUARE_SIZE };
+ allowMove = false;
+ }
+
+ // movement
+ for (int i = 0; i < counterTail; i++) snakePosition[i] = snake[i].position;
+
+ if ((framesCounter%5) == 0)
+ {
+ for (int i = 0; i < counterTail; i++)
+ {
+ if (i == 0)
+ {
+ snake[0].position.x += snake[0].speed.x;
+ snake[0].position.y += snake[0].speed.y;
+ allowMove = true;
+ }
+ else snake[i].position = snakePosition[i-1];
+ }
+ }
+
+ // wall behaviour
+ if (((snake[0].position.x) > (screenWidth - offset.x)) ||
+ ((snake[0].position.y) > (screenHeight - offset.y)) ||
+ (snake[0].position.x < 0) || (snake[0].position.y < 0))
+ {
+ gameOver = true;
+ }
+
+ // collision with yourself
+ for (int i = 1; i < counterTail; i++)
+ {
+ if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) gameOver = true;
+ }
+
+ // TODO: review logic: fruit.position calculation
+ if (!fruit.active)
+ {
+ fruit.active = true;
+ fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.x/2, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2 };
+
+ for (int i = 0; i < counterTail; i++)
+ {
+ while ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y))
+ {
+ fruit.position = (Vector2){ GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE };
+ i = 0;
+ }
+ }
+ }
+
+ // collision
+ if (CheckCollisionRecs((Rectangle){(int)snake[0].position.x, (int)snake[0].position.y, (int)snake[0].size.x, (int)snake[0].size.y},
+ (Rectangle){(int)fruit.position.x, (int)fruit.position.y, (int)fruit.size.x, (int)fruit.size.y}))
+ {
+ snake[counterTail].position = snakePosition[counterTail - 1];
+ counterTail += 1;
+ fruit.active = false;
+ }
+
+ framesCounter++;
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw grid lines
+ for (int i = 0; i < screenWidth/SQUARE_SIZE + 1; i++)
+ {
+ DrawLineV((Vector2){SQUARE_SIZE*i + offset.x/2, offset.y/2}, (Vector2){SQUARE_SIZE*i + offset.x/2, screenHeight - offset.y/2}, LIGHTGRAY);
+ }
+
+ for (int i = 0; i < screenHeight/SQUARE_SIZE + 1; i++)
+ {
+ DrawLineV((Vector2){offset.x/2, SQUARE_SIZE*i + offset.y/2}, (Vector2){screenWidth - offset.x/2, SQUARE_SIZE*i + offset.y/2}, LIGHTGRAY);
+ }
+
+ // Draw snake
+ for (int i = 0; i < counterTail; i++) DrawRectangleV(snake[i].position, snake[i].size, snake[i].color);
+
+ // Draw fruit to pick
+ DrawRectangleV(fruit.position, fruit.size, fruit.color);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/space_invaders.c b/games/space_invaders.c
new file mode 100644
index 00000000..c2dd0c61
--- /dev/null
+++ b/games/space_invaders.c
@@ -0,0 +1,406 @@
+/*******************************************************************************************
+*
+* raylib - sample game: space invaders
+*
+* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define NUM_SHOOTS 50
+#define NUM_MAX_ENEMIES 50
+#define FIRST_WAVE 10
+#define SECOND_WAVE 20
+#define THIRD_WAVE 50
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum { FIRST = 0, SECOND, THIRD } EnemyWave;
+
+typedef struct Player{
+ Rectangle rec;
+ Vector2 speed;
+ Color color;
+} Player;
+
+typedef struct Enemy{
+ Rectangle rec;
+ Vector2 speed;
+ bool active;
+ Color color;
+} Enemy;
+
+typedef struct Shoot{
+ Rectangle rec;
+ Vector2 speed;
+ bool active;
+ Color color;
+} Shoot;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static int framesCounter;
+static bool gameOver;
+static bool pause;
+static int score;
+static bool victory;
+
+static Player player;
+static Enemy enemy[NUM_MAX_ENEMIES];
+static Shoot shoot[NUM_SHOOTS];
+static EnemyWave wave;
+
+static int shootRate;
+static float alpha;
+
+static int activeEnemies;
+static int enemiesKill;
+static bool smooth;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: space invaders");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------
+// Module Functions Definitions (local)
+//------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ // Initialize game variables
+ shootRate = 0;
+ pause = false;
+ gameOver = false;
+ victory = false;
+ smooth = false;
+ wave = FIRST;
+ activeEnemies = FIRST_WAVE;
+ enemiesKill = 0;
+ score = 0;
+ alpha = 0;
+
+ // Initialize player
+ player.rec.x = 20;
+ player.rec.y = 50;
+ player.rec.width = 20;
+ player.rec.height = 20;
+ player.speed.x = 5;
+ player.speed.y = 5;
+ player.color = BLACK;
+
+ // Initialize enemies
+ for (int i = 0; i < NUM_MAX_ENEMIES; i++)
+ {
+ enemy[i].rec.width = 10;
+ enemy[i].rec.height = 10;
+ enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000);
+ enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height);
+ enemy[i].speed.x = 5;
+ enemy[i].speed.y = 5;
+ enemy[i].active = true;
+ enemy[i].color = GRAY;
+ }
+
+ // Initialize shoots
+ for (int i = 0; i < NUM_SHOOTS; i++)
+ {
+ shoot[i].rec.x = player.rec.x;
+ shoot[i].rec.y = player.rec.y + player.rec.height/4;
+ shoot[i].rec.width = 10;
+ shoot[i].rec.height = 5;
+ shoot[i].speed.x = 7;
+ shoot[i].speed.y = 0;
+ shoot[i].active = false;
+ shoot[i].color = MAROON;
+ }
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ switch (wave)
+ {
+ case FIRST:
+ {
+ if (!smooth)
+ {
+ alpha += 0.02f;
+
+ if (alpha >= 1.0f) smooth = true;
+ }
+
+ if (smooth) alpha -= 0.02f;
+
+ if (enemiesKill == activeEnemies)
+ {
+ enemiesKill = 0;
+
+ for (int i = 0; i < activeEnemies; i++)
+ {
+ if (!enemy[i].active) enemy[i].active = true;
+ }
+
+ activeEnemies = SECOND_WAVE;
+ wave = SECOND;
+ smooth = false;
+ alpha = 0.0f;
+ }
+ } break;
+ case SECOND:
+ {
+ if (!smooth)
+ {
+ alpha += 0.02f;
+
+ if (alpha >= 1.0f) smooth = true;
+ }
+
+ if (smooth) alpha -= 0.02f;
+
+ if (enemiesKill == activeEnemies)
+ {
+ enemiesKill = 0;
+
+ for (int i = 0; i < activeEnemies; i++)
+ {
+ if (!enemy[i].active) enemy[i].active = true;
+ }
+
+ activeEnemies = THIRD_WAVE;
+ wave = THIRD;
+ smooth = false;
+ alpha = 0.0f;
+ }
+ } break;
+ case THIRD:
+ {
+ if (!smooth)
+ {
+ alpha += 0.02f;
+
+ if (alpha >= 1.0f) smooth = true;
+ }
+
+ if (smooth) alpha -= 0.02f;
+
+ if (enemiesKill == activeEnemies) victory = true;
+
+ } break;
+ default: break;
+ }
+
+ // Player movement
+ if (IsKeyDown(KEY_RIGHT)) player.rec.x += player.speed.x;
+ if (IsKeyDown(KEY_LEFT)) player.rec.x -= player.speed.x;
+ if (IsKeyDown(KEY_UP)) player.rec.y -= player.speed.y;
+ if (IsKeyDown(KEY_DOWN)) player.rec.y += player.speed.y;
+
+ // Player collision with enemy
+ for (int i = 0; i < activeEnemies; i++)
+ {
+ if (CheckCollisionRecs(player.rec, enemy[i].rec)) gameOver = true;
+ }
+
+ // Enemy behaviour
+ for (int i = 0; i < activeEnemies; i++)
+ {
+ if (enemy[i].active)
+ {
+ enemy[i].rec.x -= enemy[i].speed.x;
+
+ if (enemy[i].rec.x < 0)
+ {
+ enemy[i].rec.x = GetRandomValue(screenWidth, screenWidth + 1000);
+ enemy[i].rec.y = GetRandomValue(0, screenHeight - enemy[i].rec.height);
+ }
+ }
+ }
+
+ // Wall behaviour
+ if (player.rec.x <= 0) player.rec.x = 0;
+ if (player.rec.x + player.rec.width >= screenWidth) player.rec.x = screenWidth - player.rec.width;
+ if (player.rec.y <= 0) player.rec.y = 0;
+ if (player.rec.y + player.rec.height >= screenHeight) player.rec.y = screenHeight - player.rec.height;
+
+ //Shoot initialization
+ if (IsKeyDown(KEY_SPACE))
+ {
+ shootRate += 5;
+
+ for (int i = 0; i < NUM_SHOOTS; i++)
+ {
+ if (!shoot[i].active && shootRate%20 == 0)
+ {
+ shoot[i].rec.x = player.rec.x;
+ shoot[i].rec.y = player.rec.y + player.rec.height/4;
+ shoot[i].active = true;
+ break;
+ }
+ }
+ }
+
+ // Shoot logic
+ for (int i = 0; i < NUM_SHOOTS; i++)
+ {
+ if (shoot[i].active)
+ {
+ // Movement
+ shoot[i].rec.x += shoot[i].speed.x;
+
+ // Collision with enemy
+ for (int j = 0; j < activeEnemies; j++)
+ {
+ if (enemy[j].active)
+ {
+ if (CheckCollisionRecs(shoot[i].rec, enemy[j].rec))
+ {
+ shoot[i].active = false;
+ enemy[j].rec.x = GetRandomValue(screenWidth, screenWidth + 1000);
+ enemy[j].rec.y = GetRandomValue(0, screenHeight - enemy[j].rec.height);
+ shootRate = 0;
+ enemiesKill++;
+ score += 100;
+ }
+
+ if (shoot[i].rec.x + shoot[i].rec.width >= screenWidth)
+ {
+ shoot[i].active = false;
+ shootRate = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ DrawRectangleRec(player.rec, player.color);
+
+ if (wave == FIRST) DrawText("FIRST WAVE", screenWidth/2 - MeasureText("FIRST WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha));
+ else if (wave == SECOND) DrawText("SECOND WAVE", screenWidth/2 - MeasureText("SECOND WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha));
+ else if (wave == THIRD) DrawText("THIRD WAVE", screenWidth/2 - MeasureText("THIRD WAVE", 40)/2, screenHeight/2 - 40, 40, Fade(BLACK, alpha));
+
+ for (int i = 0; i < activeEnemies; i++)
+ {
+ if (enemy[i].active) DrawRectangleRec(enemy[i].rec, enemy[i].color);
+ }
+
+ for (int i = 0; i < NUM_SHOOTS; i++)
+ {
+ if (shoot[i].active) DrawRectangleRec(shoot[i].rec, shoot[i].color);
+ }
+
+ DrawText(FormatText("%04i", score), 20, 20, 40, GRAY);
+
+ if (victory) DrawText("YOU WIN", screenWidth/2 - MeasureText("YOU WIN", 40)/2, screenHeight/2 - 40, 40, BLACK);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+} \ No newline at end of file
diff --git a/games/tetris.c b/games/tetris.c
new file mode 100644
index 00000000..62400201
--- /dev/null
+++ b/games/tetris.c
@@ -0,0 +1,836 @@
+/*******************************************************************************************
+*
+* raylib - sample game: tetris
+*
+* Sample game Marc Palau and Ramon Santamaria
+*
+* This game has been created using raylib v1.3 (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+//----------------------------------------------------------------------------------
+// Some Defines
+//----------------------------------------------------------------------------------
+#define SQUARE_SIZE 20
+
+#define GRID_HORIZONTAL_SIZE 12
+#define GRID_VERTICAL_SIZE 20
+
+#define LATERAL_SPEED 10
+#define TURNING_SPEED 12
+#define FAST_FALL_AWAIT_COUNTER 30
+
+#define FADING_TIME 33
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING } GridSquare;
+
+//------------------------------------------------------------------------------------
+// Global Variables Declaration
+//------------------------------------------------------------------------------------
+static int screenWidth = 800;
+static int screenHeight = 450;
+
+static bool gameOver = false;
+static bool pause = false;
+
+// Matrices
+static GridSquare grid [GRID_HORIZONTAL_SIZE][GRID_VERTICAL_SIZE];
+static GridSquare piece [4][4];
+static GridSquare incomingPiece [4][4];
+
+// Theese variables keep track of the active piece position
+static int piecePositionX = 0;
+static int piecePositionY = 0;
+
+// Game parameters
+static Color fadingColor;
+//static int fallingSpeed; // In frames
+
+static bool beginPlay = true; // This var is only true at the begining of the game, used for the first matrix creations
+static bool pieceActive = false;
+static bool detection = false;
+static bool lineToDelete = false;
+
+// Statistics
+static int level = 1;
+static int lines = 0;
+
+// Counters
+static int gravityMovementCounter = 0;
+static int lateralMovementCounter = 0;
+static int turnMovementCounter = 0;
+static int fastFallMovementCounter = 0;
+
+static int fadeLineCounter = 0;
+
+// Based on level
+static int gravitySpeed = 30;
+
+//------------------------------------------------------------------------------------
+// Module Functions Declaration (local)
+//------------------------------------------------------------------------------------
+static void InitGame(void); // Initialize game
+static void UpdateGame(void); // Update game (one frame)
+static void DrawGame(void); // Draw game (one frame)
+static void UnloadGame(void); // Unload game
+static void UpdateDrawFrame(void); // Update and Draw (one frame)
+
+// Additional module functions
+static bool Createpiece();
+static void GetRandompiece();
+static void ResolveFallingMovement();
+static bool ResolveLateralMovement();
+static bool ResolveTurnMovement();
+static void CheckDetection();
+static void CheckCompletition();
+static void DeleteCompleteLines();
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main()
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "sample game: tetris");
+
+ InitGame();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateGame();
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ DrawGame();
+ //----------------------------------------------------------------------------------
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadGame(); // Unload loaded data (textures, sounds, models...)
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//--------------------------------------------------------------------------------------
+// Game Module Functions Definition
+//--------------------------------------------------------------------------------------
+
+// Initialize game variables
+void InitGame(void)
+{
+ // Initialize game statistics
+ level = 1;
+ lines = 0;
+
+ fadingColor = GRAY;
+
+ piecePositionX = 0;
+ piecePositionY = 0;
+
+ pause = false;
+
+ beginPlay = true;
+ pieceActive = false;
+ detection = false;
+ lineToDelete = false;
+
+ // Counters
+ gravityMovementCounter = 0;
+ lateralMovementCounter = 0;
+ turnMovementCounter = 0;
+ fastFallMovementCounter = 0;
+
+ fadeLineCounter = 0;
+ gravitySpeed = 30;
+
+ // Initialize grid matrices
+ for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
+ {
+ for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
+ {
+ if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK;
+ else grid[i][j] = EMPTY;
+ }
+ }
+
+ // Initialize incoming piece matrices
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j< 4; j++)
+ {
+ incomingPiece[i][j] = EMPTY;
+ }
+ }
+}
+
+// Update game (one frame)
+void UpdateGame(void)
+{
+ if (!gameOver)
+ {
+ if (IsKeyPressed('P')) pause = !pause;
+
+ if (!pause)
+ {
+ if (!lineToDelete)
+ {
+ if (!pieceActive)
+ {
+ // Get another piece
+ pieceActive = Createpiece();
+
+ // We leave a little time before starting the fast falling down
+ fastFallMovementCounter = 0;
+ }
+ else // Piece falling
+ {
+ // Counters update
+ fastFallMovementCounter++;
+ gravityMovementCounter++;
+ lateralMovementCounter++;
+ turnMovementCounter++;
+
+ // We make sure to move if we've pressed the key this frame
+ if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT)) lateralMovementCounter = LATERAL_SPEED;
+ if (IsKeyPressed(KEY_UP)) turnMovementCounter = TURNING_SPEED;
+
+ // Fall down
+ if (IsKeyDown(KEY_DOWN) && (fastFallMovementCounter >= FAST_FALL_AWAIT_COUNTER))
+ {
+ // We make sure the piece is going to fall this frame
+ gravityMovementCounter += gravitySpeed;
+ }
+
+ if (gravityMovementCounter >= gravitySpeed)
+ {
+ // Basic falling movement
+ CheckDetection(&detection);
+
+ // Check if the piece has collided with another piece or with the boundings
+ ResolveFallingMovement(&detection, &pieceActive);
+
+ // Check if we fullfilled a line and if so, erase the line and pull down the the lines above
+ CheckCompletition(&lineToDelete);
+
+ gravityMovementCounter = 0;
+ }
+
+ // Move laterally at player's will
+ if (lateralMovementCounter >= LATERAL_SPEED)
+ {
+ // Update the lateral movement and if success, reset the lateral counter
+ if (!ResolveLateralMovement()) lateralMovementCounter = 0;
+ }
+
+ // Turn the piece at player's will
+ if (turnMovementCounter >= TURNING_SPEED)
+ {
+ // Update the turning movement and reset the turning counter
+ if (ResolveTurnMovement()) turnMovementCounter = 0;
+ }
+ }
+
+ // Game over logic
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if (grid[i][j] == FULL)
+ {
+ gameOver = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Animation when deleting lines
+ fadeLineCounter++;
+
+ if (fadeLineCounter%8 < 4) fadingColor = MAROON;
+ else fadingColor = GRAY;
+
+ if (fadeLineCounter >= FADING_TIME)
+ {
+ DeleteCompleteLines();
+ fadeLineCounter = 0;
+ lineToDelete = false;
+
+ lines++;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (IsKeyPressed(KEY_ENTER))
+ {
+ InitGame();
+ gameOver = false;
+ }
+ }
+}
+
+// Draw game (one frame)
+void DrawGame(void)
+{
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ if (!gameOver)
+ {
+ // Draw gameplay area
+ Vector2 offset;
+ offset.x = screenWidth/2 - (GRID_HORIZONTAL_SIZE*SQUARE_SIZE/2) - 50;
+ offset.y = screenHeight/2 - ((GRID_VERTICAL_SIZE - 1)*SQUARE_SIZE/2) + SQUARE_SIZE*2;
+
+ offset.y -= 50; // NOTE: Harcoded position!
+
+ int controller = offset.x;
+
+ for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
+ {
+ for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
+ {
+ // Draw each square of the grid
+ if (grid[i][j] == EMPTY)
+ {
+ DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
+ DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
+ DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
+ DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
+ offset.x += SQUARE_SIZE;
+ }
+ else if (grid[i][j] == FULL)
+ {
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
+ offset.x += SQUARE_SIZE;
+ }
+ else if (grid[i][j] == MOVING)
+ {
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, DARKGRAY);
+ offset.x += SQUARE_SIZE;
+ }
+ else if (grid[i][j] == BLOCK)
+ {
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, LIGHTGRAY);
+ offset.x += SQUARE_SIZE;
+ }
+ else if (grid[i][j] == FADING)
+ {
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fadingColor);
+ offset.x += SQUARE_SIZE;
+ }
+ }
+
+ offset.x = controller;
+ offset.y += SQUARE_SIZE;
+ }
+
+ // Draw incoming piece (hardcoded)
+ offset.x = 500;
+ offset.y = 45;
+
+ int controler = offset.x;
+
+ for (int j = 0; j < 4; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ if (incomingPiece[i][j] == EMPTY)
+ {
+ DrawLine(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, LIGHTGRAY );
+ DrawLine(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, LIGHTGRAY );
+ DrawLine(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
+ DrawLine(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, LIGHTGRAY );
+ offset.x += SQUARE_SIZE;
+ }
+ else if (incomingPiece[i][j] == MOVING)
+ {
+ DrawRectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, GRAY);
+ offset.x += SQUARE_SIZE;
+ }
+ }
+
+ offset.x = controler;
+ offset.y += SQUARE_SIZE;
+ }
+
+ DrawText("INCOMING:", offset.x, offset.y - 100, 10, GRAY);
+ DrawText(FormatText("LINES: %04i", lines), offset.x, offset.y + 20, 10, GRAY);
+
+ if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY);
+ }
+ else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY);
+
+ EndDrawing();
+}
+
+// Unload game variables
+void UnloadGame(void)
+{
+ // TODO: Unload all dynamic loaded data (textures, sounds, models...)
+}
+
+// Update and Draw (one frame)
+void UpdateDrawFrame(void)
+{
+ UpdateGame();
+ DrawGame();
+}
+
+//--------------------------------------------------------------------------------------
+// Additional module functions
+//--------------------------------------------------------------------------------------
+static bool Createpiece()
+{
+ piecePositionX = (int)((GRID_HORIZONTAL_SIZE - 4)/2);
+ piecePositionY = 0;
+
+ // If the game is starting and you are going to create the first piece, we create an extra one
+ if (beginPlay)
+ {
+ GetRandompiece();
+ beginPlay = false;
+ }
+
+ // We assign the incoming piece to the actual piece
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j< 4; j++)
+ {
+ piece[i][j] = incomingPiece[i][j];
+ }
+ }
+
+ // We assign a random piece to the incoming one
+ GetRandompiece();
+
+ // Assign the piece to the grid
+ for (int i = piecePositionX; i < piecePositionX + 4; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
+ }
+ }
+
+ return true;
+}
+
+static void GetRandompiece()
+{
+ srand(time(NULL));
+ int random = rand() % 7;
+
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ incomingPiece[i][j] = EMPTY;
+ }
+ }
+
+ switch(random)
+ {
+ case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube
+ case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L
+ case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa
+ case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta
+ case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada
+ case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S
+ case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa
+ }
+}
+
+static void ResolveFallingMovement(bool *detection, bool *pieceActive)
+{
+ // If we finished moving this piece, we stop it
+ if (*detection)
+ {
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if (grid[i][j] == MOVING)
+ {
+ grid[i][j] = FULL;
+ *detection = false;
+ *pieceActive = false;
+ }
+ }
+ }
+ }
+ // We move down the piece
+ else
+ {
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if (grid[i][j] == MOVING)
+ {
+ grid[i][j+1] = MOVING;
+ grid[i][j] = EMPTY;
+ }
+ }
+ }
+ piecePositionY++;
+ }
+}
+
+static bool ResolveLateralMovement()
+{
+ bool collision = false;
+
+ // Move left
+ if (IsKeyDown(KEY_LEFT))
+ {
+ // Check if is possible to move to left
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if (grid[i][j] == MOVING)
+ {
+ // Check if we are touching the left wall or we have a full square at the left
+ if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
+ }
+ }
+ }
+ // If able, move left
+ if (!collision)
+ {
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right
+ {
+ // Move everything to the left
+ if (grid[i][j] == MOVING)
+ {
+ grid[i-1][j] = MOVING;
+ grid[i][j] = EMPTY;
+ }
+ }
+ }
+
+ piecePositionX--;
+ }
+ }
+
+ // Move right
+ else if (IsKeyDown(KEY_RIGHT))
+ {
+ // Check if is possible to move to right
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if (grid[i][j] == MOVING)
+ {
+ // Check if we are touching the right wall or we have a full square at the right
+ if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
+ {
+ collision = true;
+
+ }
+ }
+ }
+ }
+ // If able move right
+ if (!collision)
+ {
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left
+ {
+ // Move everything to the right
+ if (grid[i][j] == MOVING)
+ {
+ grid[i+1][j] = MOVING;
+ grid[i][j] = EMPTY;
+ }
+ }
+ }
+
+ piecePositionX++;
+ }
+ }
+
+ return collision;
+}
+
+static bool ResolveTurnMovement()
+{
+ // Input for turning the piece
+ if (IsKeyDown(KEY_UP))
+ {
+ int aux;
+ bool checker = false;
+
+ // Check all turning possibilities
+ if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
+ (grid[piecePositionX][piecePositionY] != EMPTY) &&
+ (grid[piecePositionX][piecePositionY] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
+ (grid[piecePositionX + 3][piecePositionY] != EMPTY) &&
+ (grid[piecePositionX + 3][piecePositionY] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
+ (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) &&
+ (grid[piecePositionX + 3][piecePositionY + 3] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX][piecePositionY] == MOVING) &&
+ (grid[piecePositionX][piecePositionY + 3] != EMPTY) &&
+ (grid[piecePositionX][piecePositionY + 3] != MOVING))
+ {
+ checker = true;
+ }
+
+
+ if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
+ (grid[piecePositionX][piecePositionY + 2] != EMPTY) &&
+ (grid[piecePositionX][piecePositionY + 2] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
+ (grid[piecePositionX + 1][piecePositionY] != EMPTY) &&
+ (grid[piecePositionX + 1][piecePositionY] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
+ (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) &&
+ (grid[piecePositionX + 3][piecePositionY + 1] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
+ (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) &&
+ (grid[piecePositionX + 2][piecePositionY + 3] != MOVING))
+ {
+ checker = true;
+ }
+
+
+ if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
+ (grid[piecePositionX][piecePositionY + 1] != EMPTY) &&
+ (grid[piecePositionX][piecePositionY + 1] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
+ (grid[piecePositionX + 2][piecePositionY] != EMPTY) &&
+ (grid[piecePositionX + 2][piecePositionY] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
+ (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) &&
+ (grid[piecePositionX + 3][piecePositionY + 2] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
+ (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) &&
+ (grid[piecePositionX + 1][piecePositionY + 3] != MOVING))
+ {
+ checker = true;
+ }
+
+ if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
+ (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) &&
+ (grid[piecePositionX + 1][piecePositionY + 2] != MOVING))
+ {
+ checker = true;
+ }
+
+ if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
+ (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) &&
+ (grid[piecePositionX + 1][piecePositionY + 1] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
+ (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) &&
+ (grid[piecePositionX + 2][piecePositionY + 1] != MOVING))
+ {
+ checker = true;
+ }
+ if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
+ (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) &&
+ (grid[piecePositionX + 2][piecePositionY + 2] != MOVING))
+ {
+ checker = true;
+ }
+
+ if (!checker)
+ {
+ aux = piece[0][0];
+ piece[0][0] = piece[3][0];
+ piece[3][0] = piece[3][3];
+ piece[3][3] = piece[0][3];
+ piece[0][3] = aux;
+
+ aux = piece[1][0];
+ piece[1][0] = piece[3][1];
+ piece[3][1] = piece[2][3];
+ piece[2][3] = piece[0][2];
+ piece[0][2] = aux;
+
+ aux = piece[2][0];
+ piece[2][0] = piece[3][2];
+ piece[3][2] = piece[1][3];
+ piece[1][3] = piece[0][1];
+ piece[0][1] = aux;
+
+ aux = piece[1][1];
+ piece[1][1] = piece[2][1];
+ piece[2][1] = piece[2][2];
+ piece[2][2] = piece[1][2];
+ piece[1][2] = aux;
+ }
+
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if (grid[i][j] == MOVING)
+ {
+ grid[i][j] = EMPTY;
+ }
+ }
+ }
+
+ for (int i = piecePositionX; i < piecePositionX + 4; i++)
+ {
+ for (int j = piecePositionY; j < piecePositionY + 4; j++)
+ {
+ if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
+ {
+ grid[i][j] = MOVING;
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+static void CheckDetection(bool *detection)
+{
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
+ }
+ }
+}
+
+static void CheckCompletition(bool *lineToDelete)
+{
+ int calculator;
+
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ calculator = 0;
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ // Count each square of the line
+ if (grid[i][j] == FULL)
+ {
+ calculator++;
+ }
+
+ // Check if we completed the whole line
+ if (calculator == GRID_HORIZONTAL_SIZE - 2)
+ {
+ *lineToDelete = true;
+ calculator = 0;
+ // points++;
+
+ // Mark the completed line
+ for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
+ {
+ grid[z][j] = FADING;
+ }
+ }
+ }
+ }
+}
+
+static void DeleteCompleteLines()
+{
+ // erase the completed line
+ for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+ {
+ while (grid[1][j] == FADING)
+ {
+ for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+ {
+ grid[i][j] = EMPTY;
+ }
+ for (int j2 = j-1; j2 >= 0; j2--)
+ {
+ for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++)
+ {
+ if (grid[i2][j2] == FULL)
+ {
+ grid[i2][j2+1] = FULL;
+ grid[i2][j2] = EMPTY;
+ }
+ else if (grid[i2][j2] == FADING)
+ {
+ grid[i2][j2+1] = FADING;
+ grid[i2][j2] = EMPTY;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file