diff options
Diffstat (limited to 'games/transmission/screens/screen_gameplay.c')
| -rw-r--r-- | games/transmission/screens/screen_gameplay.c | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/games/transmission/screens/screen_gameplay.c b/games/transmission/screens/screen_gameplay.c new file mode 100644 index 00000000..00c451fc --- /dev/null +++ b/games/transmission/screens/screen_gameplay.c @@ -0,0 +1,423 @@ +/********************************************************************************************** +* +* 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 SpriteFont 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 = LoadSpriteFontEx("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; +} |
