소스 검색

Uploaded gamejam game sources

Ray 9 년 전
부모
커밋
e484d58d9c
33개의 변경된 파일1713개의 추가작업 그리고 0개의 파일을 삭제
  1. 271 0
      games/light_my_ritual/light_my_ritual.c
  2. 203 0
      games/light_my_ritual/makefile
  3. BIN
      games/light_my_ritual/resources/audio/ambient.ogg
  4. BIN
      games/light_my_ritual/resources/audio/light_off.wav
  5. BIN
      games/light_my_ritual/resources/audio/light_on.wav
  6. BIN
      games/light_my_ritual/resources/audio/ritual.ogg
  7. BIN
      games/light_my_ritual/resources/audio/start.wav
  8. BIN
      games/light_my_ritual/resources/font_arcadian.png
  9. BIN
      games/light_my_ritual/resources/lights_map.png
  10. BIN
      games/light_my_ritual/resources/textures/back_title.png
  11. BIN
      games/light_my_ritual/resources/textures/background.png
  12. BIN
      games/light_my_ritual/resources/textures/book.png
  13. BIN
      games/light_my_ritual/resources/textures/circle_level_i_off.png
  14. BIN
      games/light_my_ritual/resources/textures/circle_level_i_on.png
  15. BIN
      games/light_my_ritual/resources/textures/circle_level_ii_off.png
  16. BIN
      games/light_my_ritual/resources/textures/circle_level_ii_on.png
  17. BIN
      games/light_my_ritual/resources/textures/circle_level_iii_off.png
  18. BIN
      games/light_my_ritual/resources/textures/circle_level_iii_on.png
  19. BIN
      games/light_my_ritual/resources/textures/enemy.png
  20. BIN
      games/light_my_ritual/resources/textures/foreground_level_i.png
  21. BIN
      games/light_my_ritual/resources/textures/foreground_level_ii.png
  22. BIN
      games/light_my_ritual/resources/textures/foreground_level_iii.png
  23. BIN
      games/light_my_ritual/resources/textures/light.png
  24. BIN
      games/light_my_ritual/resources/textures/light_glow.png
  25. BIN
      games/light_my_ritual/resources/textures/light_ray.png
  26. BIN
      games/light_my_ritual/resources/textures/msg_ritual.png
  27. BIN
      games/light_my_ritual/resources/textures/player.png
  28. BIN
      games/light_my_ritual/resources/textures/time_over.png
  29. BIN
      games/light_my_ritual/resources/textures/title.png
  30. 842 0
      games/light_my_ritual/screens/screen_gameplay.c
  31. 214 0
      games/light_my_ritual/screens/screen_logo_raylib.c
  32. 105 0
      games/light_my_ritual/screens/screen_title.c
  33. 78 0
      games/light_my_ritual/screens/screens.h

+ 271 - 0
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 - [email protected])
+*
+********************************************************************************************/
+
+#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();
+    //----------------------------------------------------------------------------------
+}
+

+ 203 - 0
games/light_my_ritual/makefile

@@ -0,0 +1,203 @@
+#**************************************************************************************************
+#
+#   raylib - Advance Game
+#
+#   makefile to compile advance game
+#
+#   Copyright (c) 2014 Ramon Santamaria (Ray San - [email protected])
+#    
+#   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
+    #-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. -IC:/raylib/raylib/src -IC:/raylib/raylib/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. -LC:/raylib/raylib/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 = C:/raylib/raylib/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 = C:/raylib/raylib/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)

BIN
games/light_my_ritual/resources/audio/ambient.ogg


BIN
games/light_my_ritual/resources/audio/light_off.wav


BIN
games/light_my_ritual/resources/audio/light_on.wav


BIN
games/light_my_ritual/resources/audio/ritual.ogg


BIN
games/light_my_ritual/resources/audio/start.wav


BIN
games/light_my_ritual/resources/font_arcadian.png


BIN
games/light_my_ritual/resources/lights_map.png


BIN
games/light_my_ritual/resources/textures/back_title.png


BIN
games/light_my_ritual/resources/textures/background.png


BIN
games/light_my_ritual/resources/textures/book.png


BIN
games/light_my_ritual/resources/textures/circle_level_i_off.png


BIN
games/light_my_ritual/resources/textures/circle_level_i_on.png


BIN
games/light_my_ritual/resources/textures/circle_level_ii_off.png


BIN
games/light_my_ritual/resources/textures/circle_level_ii_on.png


BIN
games/light_my_ritual/resources/textures/circle_level_iii_off.png


BIN
games/light_my_ritual/resources/textures/circle_level_iii_on.png


BIN
games/light_my_ritual/resources/textures/enemy.png


BIN
games/light_my_ritual/resources/textures/foreground_level_i.png


BIN
games/light_my_ritual/resources/textures/foreground_level_ii.png


BIN
games/light_my_ritual/resources/textures/foreground_level_iii.png


BIN
games/light_my_ritual/resources/textures/light.png


BIN
games/light_my_ritual/resources/textures/light_glow.png


BIN
games/light_my_ritual/resources/textures/light_ray.png


BIN
games/light_my_ritual/resources/textures/msg_ritual.png


BIN
games/light_my_ritual/resources/textures/player.png


BIN
games/light_my_ritual/resources/textures/time_over.png


BIN
games/light_my_ritual/resources/textures/title.png


+ 842 - 0
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 - [email protected])
+*
+*   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);
+    }
+}

+ 214 - 0
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 - [email protected])
+*
+*   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;
+}

+ 105 - 0
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 - [email protected])
+*
+*   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;
+}

+ 78 - 0
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 - [email protected])
+*
+*   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