/**********************************************************************************************
							 | 
						|
								*
							 | 
						|
								*   raylib - Advance Game template
							 | 
						|
								*
							 | 
						|
								*   Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
							 | 
						|
								*
							 | 
						|
								*   Copyright (c) 2014-2018 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.
							 | 
						|
								*
							 | 
						|
								**********************************************************************************************/
							 | 
						|
								
							 | 
						|
								#include "raylib.h"
							 | 
						|
								#include "screens.h"
							 | 
						|
								
							 | 
						|
								#include <string.h>
							 | 
						|
								#include <stdlib.h>
							 | 
						|
								#include <stdio.h>
							 | 
						|
								
							 | 
						|
								//#define MAX_CODING_WORDS    12
							 | 
						|
								//#define MAX_MISSION_WORDS    8
							 | 
						|
								#define MAX_LINE_CHAR  30
							 | 
						|
								
							 | 
						|
								/*
							 | 
						|
								// NOTE: Coding words are generic and the same words 
							 | 
						|
								// are used for all missions, 
							 | 
						|
								typedef enum CodingWords { 
							 | 
						|
								    POLLO = 0,
							 | 
						|
								    CONEJO,
							 | 
						|
								    HUEVO,
							 | 
						|
								    NIDO,
							 | 
						|
								    AIRE,
							 | 
						|
								    ARMARIO,
							 | 
						|
								    AGUJERO,
							 | 
						|
								    COSA,
							 | 
						|
								    WORD,
							 | 
						|
								} CodingWords;
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								static char *codingWords[MAX_CODING_WORDS] = { 
							 | 
						|
								    "pollo\0", 
							 | 
						|
								    "conejo\0", 
							 | 
						|
								    "huevo\0",
							 | 
						|
								    "nido\0", 
							 | 
						|
								    "aire\0", 
							 | 
						|
								    "armario\0", 
							 | 
						|
								    "agujero\0",
							 | 
						|
								    "platano\0",
							 | 
						|
								    "pastel\0",
							 | 
						|
								    "mercado\0",
							 | 
						|
								    "raton\0",
							 | 
						|
								    "melon\0"
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// Words to be coded or coding words
							 | 
						|
								/*typedef struct Word {
							 | 
						|
								    int id;
							 | 
						|
								    Rectangle rec;
							 | 
						|
								    Rectangle iniRec;
							 | 
						|
								    bool hover;
							 | 
						|
								    bool picked;
							 | 
						|
								    char text[32];          // text
							 | 
						|
								} Word;*/
							 | 
						|
								
							 | 
						|
								/*
							 | 
						|
								// Mission information
							 | 
						|
								typedef struct Mission {
							 | 
						|
								    int id;
							 | 
						|
								    char brief[512];        // Mission briefing
							 | 
						|
								    char key[32];           // Mission keyword
							 | 
						|
								    char msg[256];          // Message to be coded
							 | 
						|
								    int wordsCount;         // Number of words to coded
							 | 
						|
								    int sols[8];            // Solution code, depends on wordsCount
							 | 
						|
								} Mission;
							 | 
						|
								*/
							 | 
						|
								//----------------------------------------------------------------------------------
							 | 
						|
								// Global Variables Definition (local to this module)
							 | 
						|
								//----------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								// Gameplay screen global variables
							 | 
						|
								static int framesCounter;
							 | 
						|
								static int finishScreen;
							 | 
						|
								
							 | 
						|
								static Texture2D texBackground;
							 | 
						|
								static Font fontMessage;
							 | 
						|
								static Texture2D texWordsAtlas;
							 | 
						|
								static Texture2D texVignette;
							 | 
						|
								
							 | 
						|
								static Sound fxGrab;
							 | 
						|
								static Sound fxPlace;
							 | 
						|
								static Sound fxLeave;
							 | 
						|
								
							 | 
						|
								static Music musSpy;
							 | 
						|
								
							 | 
						|
								static Word words[MAX_CODING_WORDS] = { 0 };
							 | 
						|
								
							 | 
						|
								// Hay que hacerlo global, para poder consultar el resultado desde la endingscreen
							 | 
						|
								//static Word messageWords[MAX_MISSION_WORDS] = { 0 };
							 | 
						|
								
							 | 
						|
								static Mission *missions = NULL;
							 | 
						|
								
							 | 
						|
								static bool canSend = false;
							 | 
						|
								
							 | 
						|
								Vector2 msgOffset = { 430, 300 };
							 | 
						|
								
							 | 
						|
								//----------------------------------------------------------------------------------
							 | 
						|
								// Gameplay Screen Functions Definition
							 | 
						|
								//----------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								// Gameplay Screen Initialization logic
							 | 
						|
								void InitGameplayScreen(void)
							 | 
						|
								{
							 | 
						|
								    framesCounter = 0;
							 | 
						|
								    finishScreen = 0;
							 | 
						|
								    
							 | 
						|
								    fontMessage = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 30, 250, 0);
							 | 
						|
								    
							 | 
						|
								    texBackground = LoadTexture("resources/textures/message_background.png");
							 | 
						|
								    texVignette = LoadTexture("resources/textures/message_vignette.png");
							 | 
						|
								    
							 | 
						|
								    fxGrab = LoadSound("resources/audio/fx_grab.ogg");
							 | 
						|
								    fxPlace = LoadSound("resources/audio/fx_place.ogg");
							 | 
						|
								    fxLeave = LoadSound("resources/audio/fx_leave.ogg");
							 | 
						|
								    
							 | 
						|
								    musSpy = LoadMusicStream("resources/audio/s_p_y.xm");
							 | 
						|
								    PlayMusicStream(musSpy);
							 | 
						|
								    
							 | 
						|
								#if defined(PLATFORM_WEB)
							 | 
						|
								    #define WORD_ATLAS_FROM_FILE
							 | 
						|
								#endif
							 | 
						|
								#if defined(WORD_ATLAS_FROM_FILE)
							 | 
						|
								    texWordsAtlas = LoadTexture("resources/textures/mission_words.png");
							 | 
						|
								#else
							 | 
						|
								    // Generate coding words atlas directly from text
							 | 
						|
								    Image imWordsBase = LoadImage("resources/textures/words_base.png");
							 | 
						|
								    Image imWords = GenImageColor(imWordsBase.width, imWordsBase.height*MAX_CODING_WORDS, WHITE);
							 | 
						|
								    
							 | 
						|
								    for (int i = 0; i < MAX_CODING_WORDS; i++)
							 | 
						|
								    {
							 | 
						|
								        ImageDraw(&imWords, imWordsBase, 
							 | 
						|
								                  (Rectangle){ 0, 0, imWordsBase.width, imWordsBase.height },
							 | 
						|
								                  (Rectangle){ 0, imWordsBase.height*i, imWordsBase.width, imWordsBase.height });
							 | 
						|
								                  
							 | 
						|
								        ImageDrawTextEx(&imWords,(Vector2){ imWordsBase.width/2 - MeasureTextEx(fontMessage, codingWords[i], 
							 | 
						|
								                        fontMessage.baseSize, 0).x/2, imWordsBase.height*i }, fontMessage, codingWords[i], 
							 | 
						|
								                        fontMessage.baseSize, 0, BLACK); 
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    texWordsAtlas = LoadTextureFromImage(imWords);
							 | 
						|
								    
							 | 
						|
								    UnloadImage(imWordsBase);
							 | 
						|
								    UnloadImage(imWords);
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								    // Initialize missions
							 | 
						|
								    // WARNING: Some problem with imWords image generation (memory leak?) could cause
							 | 
						|
								    // that loading missions before/after generation breaks game, on web is the other way round... :(
							 | 
						|
								    missions = LoadMissions("resources/missions.txt");
							 | 
						|
								    TraceLog(LOG_WARNING, "Words count %i", missions[currentMission].wordsCount);
							 | 
						|
								
							 | 
						|
								    // Initialize coding words
							 | 
						|
								    for (int i = 0; i < MAX_CODING_WORDS; i++)
							 | 
						|
								    {
							 | 
						|
								        words[i].id = -1;          // Not placed anywhere
							 | 
						|
								
							 | 
						|
								        words[i].rec.x = 110 + 940*(i/(MAX_CODING_WORDS/2));
							 | 
						|
								        words[i].rec.y = 200 + 60*(i%(MAX_CODING_WORDS/2));
							 | 
						|
								        words[i].rec.width = 140;  // texWordsAtlas.width/MAX_MISSIONS
							 | 
						|
								        words[i].rec.height = 35;  // texWordsAtlas.height/MAX_MISSION_WORDS
							 | 
						|
								        words[i].iniRec = words[i].rec;
							 | 
						|
								        words[i].hover = false;    // Mouse hover detected
							 | 
						|
								        words[i].picked = false;   // Mouse picked
							 | 
						|
								        
							 | 
						|
								        //words[i].text = ''; //codingWords[i];     // Fill text if required...
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    // Analize missions[currentMission].msg string for words!
							 | 
						|
								    int msgLen = strlen(missions[currentMission].msg);
							 | 
						|
								    
							 | 
						|
								    // Add '/' each MAX_LINE_CHAR chars
							 | 
						|
								    int currentLine = 1;
							 | 
						|
								    int i = currentLine * MAX_LINE_CHAR;
							 | 
						|
								
							 | 
						|
								    while (i < msgLen - 1)
							 | 
						|
								    {
							 | 
						|
								        if (missions[currentMission].msg[i] == ' ')
							 | 
						|
								        {
							 | 
						|
								            missions[currentMission].msg[i] = '/';
							 | 
						|
								            currentLine++;
							 | 
						|
								            i = currentLine*MAX_LINE_CHAR;
							 | 
						|
								        }
							 | 
						|
								        else i++;
							 | 
						|
								    }      
							 | 
						|
								    
							 | 
						|
								    int currentWord = 0;
							 | 
						|
								    int offsetX = 0;
							 | 
						|
								    int offsetY = 0;
							 | 
						|
								    bool foundWord = false;
							 | 
						|
								    int wordInitPosX = 0;
							 | 
						|
								    int wordInitPosY = 0;
							 | 
						|
								    
							 | 
						|
								    // TODO: messageWords should be reseted every mission
							 | 
						|
								    //memcpy(messageWords, 0, sizeof(Word)*MAX_MISSION_WORDS);
							 | 
						|
								
							 | 
						|
								    for (int i = 0; i < msgLen; i++)
							 | 
						|
								    {        
							 | 
						|
								        char c = missions[currentMission].msg[i];
							 | 
						|
								        if (foundWord && (c == ' ' || c == '.'))
							 | 
						|
								        {
							 | 
						|
								            foundWord = false;
							 | 
						|
								            
							 | 
						|
								            messageWords[currentWord - 1].rec.width = (int)MeasureTextEx(fontMessage, SubText(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), 30, 0).x;
							 | 
						|
								            messageWords[currentWord - 1].rec.height = fontMessage.baseSize;
							 | 
						|
								            
							 | 
						|
								            //TODO: Guardar en message
							 | 
						|
								            strncpy(messageWords[currentWord - 1].text, SubText(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), i - wordInitPosX);
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        if (c == '@') // One word to change
							 | 
						|
								        {
							 | 
						|
								            foundWord = true;
							 | 
						|
								            missions[currentMission].msg[i] = ' ';
							 | 
						|
								
							 | 
						|
								            offsetX = (int)MeasureTextEx(fontMessage, SubText(missions[currentMission].msg, wordInitPosY, (i + 1) - wordInitPosY), 30, 0).x;
							 | 
						|
								            
							 | 
						|
								            messageWords[currentWord].rec.x = offsetX;
							 | 
						|
								            messageWords[currentWord].rec.y = offsetY;
							 | 
						|
								
							 | 
						|
								            wordInitPosX = i + 1;
							 | 
						|
								
							 | 
						|
								            currentWord++;
							 | 
						|
								        }
							 | 
						|
								        else if (c == '/')
							 | 
						|
								        {
							 | 
						|
								            missions[currentMission].msg[i] = '\n';
							 | 
						|
								            wordInitPosY = i;
							 | 
						|
								            offsetY += (fontMessage.baseSize + fontMessage.baseSize/2);     // raylib internal increment on line break...
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    for (int i = 0; i < missions[currentMission].wordsCount; i++)
							 | 
						|
								    {
							 | 
						|
								        messageWords[i].id = -1;          // Not required for message words, id is the array position
							 | 
						|
								        
							 | 
						|
								        // Recalculate words rectangles considering text offset on screen
							 | 
						|
								        messageWords[i].rec.x += msgOffset.x;
							 | 
						|
								        messageWords[i].rec.y += msgOffset.y;
							 | 
						|
								        
							 | 
						|
								        // Recalculate words rectangle considering new width height
							 | 
						|
								        messageWords[i].rec.x -= (texWordsAtlas.width - messageWords[i].rec.width)/2;
							 | 
						|
								        messageWords[i].rec.y -= ((texWordsAtlas.height / MAX_CODING_WORDS) - messageWords[i].rec.height)/2;
							 | 
						|
								        
							 | 
						|
								        //Recalculate width height 
							 | 
						|
								        messageWords[i].rec.width =  texWordsAtlas.width;
							 | 
						|
								        messageWords[i].rec.height = texWordsAtlas.height / MAX_CODING_WORDS;
							 | 
						|
								
							 | 
						|
								        messageWords[i].hover = false;    // Mouse hover detected
							 | 
						|
								        messageWords[i].picked = false;   // Mouse picked
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Gameplay Screen Update logic
							 | 
						|
								void UpdateGameplayScreen(void)
							 | 
						|
								{
							 | 
						|
								    UpdateMusicStream(musSpy);
							 | 
						|
								    
							 | 
						|
								    for (int i = 0; i < MAX_CODING_WORDS; i++)
							 | 
						|
								    {
							 | 
						|
								        if (CheckCollisionPointRec(GetMousePosition(), words[i].rec))
							 | 
						|
								        {
							 | 
						|
								            words[i].hover = true;
							 | 
						|
								            
							 | 
						|
								            if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
							 | 
						|
								            {
							 | 
						|
								                words[i].picked = true;
							 | 
						|
								                PlaySound(fxGrab);
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								        else words[i].hover = false;
							 | 
						|
								        
							 | 
						|
								        
							 | 
						|
								        if (words[i].picked)
							 | 
						|
								        {  
							 | 
						|
								            for (int j = 0; j < missions[currentMission].wordsCount; j++)
							 | 
						|
								            {               
							 | 
						|
								                if (CheckCollisionPointRec(GetMousePosition(), messageWords[j].rec)) messageWords[j].hover = true;
							 | 
						|
								                else messageWords[j].hover = false;
							 | 
						|
								            }
							 | 
						|
								            
							 | 
						|
								            if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
							 | 
						|
								            {              
							 | 
						|
								                words[i].picked = false;
							 | 
						|
								                
							 | 
						|
								                for (int j = 0; j < missions[currentMission].wordsCount; j++)
							 | 
						|
								                {     
							 | 
						|
								                    messageWords[j].hover = false;
							 | 
						|
								                    
							 | 
						|
								                    if (CheckCollisionPointRec(GetMousePosition(), messageWords[j].rec))
							 | 
						|
								                    {
							 | 
						|
								                        PlaySound(fxPlace);
							 | 
						|
								                        
							 | 
						|
								                        words[i].rec.x = messageWords[j].rec.x;
							 | 
						|
								                        words[i].rec.y = messageWords[j].rec.y;
							 | 
						|
								                        
							 | 
						|
								                        if (messageWords[j].id != -1)
							 | 
						|
								                        {
							 | 
						|
								                            int id = messageWords[j].id;
							 | 
						|
								                            words[id].rec = words[id].iniRec;
							 | 
						|
								                        }
							 | 
						|
								                        
							 | 
						|
								                        messageWords[j].id = i;
							 | 
						|
								                        for (int k = 0; k < missions[currentMission].wordsCount; k++)
							 | 
						|
								                        {
							 | 
						|
								                            if (j != k && messageWords[j].id == messageWords[k].id) 
							 | 
						|
								                            {
							 | 
						|
								                                messageWords[k].id = -1;
							 | 
						|
								                                break;
							 | 
						|
								                            }
							 | 
						|
								                        }
							 | 
						|
								                        break;
							 | 
						|
								                    }
							 | 
						|
								                    else 
							 | 
						|
								                    {
							 | 
						|
								                        PlaySound(fxLeave);
							 | 
						|
								                        
							 | 
						|
								                        words[i].rec = words[i].iniRec;
							 | 
						|
								                        if (i == messageWords[j].id) messageWords[j].id = -1;
							 | 
						|
								                    }
							 | 
						|
								                } 
							 | 
						|
								            }            
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        // TODO: Move word picked with mouse
							 | 
						|
								        if (words[i].picked)
							 | 
						|
								        {
							 | 
						|
								            words[i].rec.x = GetMouseX() - words[i].rec.width/2;
							 | 
						|
								            words[i].rec.y = GetMouseY() - words[i].rec.height/2;
							 | 
						|
								            
							 | 
						|
								            // TODO: Check if label is placed in some mission word position
							 | 
						|
								            //if (CheckCollisionRecs(words[i].rec))
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            //if (words[i].id != -1)
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    canSend = true;
							 | 
						|
								    for(int j = 0; j < missions[currentMission].wordsCount; j++)
							 | 
						|
								    {               
							 | 
						|
								        if(messageWords[j].id == -1)
							 | 
						|
								        {
							 | 
						|
								            canSend = false;
							 | 
						|
								            break;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    if (canSend && (IsKeyPressed(KEY_ENTER) || IsButtonPressed())) 
							 | 
						|
								    {       
							 | 
						|
								        finishScreen = true;
							 | 
						|
								    } 
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Gameplay Screen Draw logic
							 | 
						|
								void DrawGameplayScreen(void)
							 | 
						|
								{
							 | 
						|
								    DrawTexture(texBackground, 0, 0, WHITE);
							 | 
						|
								    
							 | 
						|
								    DrawTextEx(fontMessage, missions[currentMission].msg, msgOffset, fontMessage.baseSize, 0, BLACK);
							 | 
						|
								    
							 | 
						|
								    for (int i = 0; i < missions[currentMission].wordsCount; i++)
							 | 
						|
								    {
							 | 
						|
								        Rectangle recLines = messageWords[i].rec;
							 | 
						|
								        DrawRectangleLines(recLines.x, recLines.y, recLines.width, recLines.height, Fade(RED, 0.35f));
							 | 
						|
								        if(messageWords[i].hover) DrawRectangleRec(messageWords[i].rec, Fade(RED, 0.30f));
							 | 
						|
								        DrawText(FormatText("%i", messageWords[i].id), i*25, 0, 30, RED);
							 | 
						|
								    }
							 | 
						|
								    for (int i = 0; i < MAX_CODING_WORDS; i++)
							 | 
						|
								    {
							 | 
						|
								        if (words[i].picked) DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, MAROON);
							 | 
						|
								        else if (words[i].hover) DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, RED);
							 | 
						|
								        else DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, WHITE);
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    DrawTexturePro(texVignette, (Rectangle){0,0,texVignette.width, texVignette.height}, (Rectangle){0,0,GetScreenWidth(), GetScreenHeight()}, (Vector2){0,0}, 0, WHITE);
							 | 
						|
								    
							 | 
						|
								    if (canSend) DrawButton("enviar");
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Gameplay Screen Unload logic
							 | 
						|
								void UnloadGameplayScreen(void)
							 | 
						|
								{
							 | 
						|
								    UnloadTexture(texBackground);
							 | 
						|
								    UnloadTexture(texVignette);
							 | 
						|
								    UnloadTexture(texWordsAtlas);
							 | 
						|
								    
							 | 
						|
								    UnloadSound(fxGrab);
							 | 
						|
								    UnloadSound(fxLeave);
							 | 
						|
								    UnloadSound(fxPlace);
							 | 
						|
								    
							 | 
						|
								    UnloadMusicStream(musSpy);
							 | 
						|
								    
							 | 
						|
								    free(missions);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// Gameplay Screen should finish?
							 | 
						|
								int FinishGameplayScreen(void)
							 | 
						|
								{
							 | 
						|
								    return finishScreen;
							 | 
						|
								}
							 |