diff --git a/SQCSim2021/define.h b/SQCSim2021/define.h index e8b9e47..c9b3322 100644 --- a/SQCSim2021/define.h +++ b/SQCSim2021/define.h @@ -39,6 +39,7 @@ enum GameState { MAIN_MENU, SPLASH, + LOBBY, OPTIONS, QUIT, PLAY, diff --git a/SQCSim2021/engine.cpp b/SQCSim2021/engine.cpp index d7b675a..1fdb750 100644 --- a/SQCSim2021/engine.cpp +++ b/SQCSim2021/engine.cpp @@ -70,61 +70,12 @@ void Engine::Init() { m_whoosh[x] = nullptr; } - char* ch = new char[2]; - - std::cout << "Jouer en ligne? [o/N] "; - std::cin.getline(ch, 2); - std::cout << std::endl; - - if (*ch == 'o' || *ch == 'O') { - char* input = new char[32]; - std::string playname, srvname; - - while (playname.size() < 1) { - std::cout << "Veuillez entrer un nom de joueur: "; - std::cin.getline(input, 32); - std::cout << std::endl; - playname = input; - if (playname.size() < 1 || playname.size() > 32) - std::puts("Nom invalide."); - } - while (srvname.size() < 1) { - std::cout << "Veuillez entrer une adresse de serveur: "; - std::cin.getline(input, 32); - std::cout << std::endl; - srvname = input; - if (srvname.size() < 1 || srvname.size() > 32) - std::puts("Adresse serveur invalide."); - } - delete[] input; - - if (!m_conn.Init()) { - if (!m_conn.Connect(srvname.c_str(), playname)) { - // setup jeu en reseau. - std::cout << "ID recu du serveur: " << std::to_string(m_conn.getId()) << "!" << std::endl; - std::cout << "Seed recu du serveur: " << std::to_string(m_conn.getSeed()) << "!" << std::endl; - m_player = Player(m_conn.getOrigin().position); - - for (auto& [key, player] : m_conn.m_players) - m_players[key] = new RemotePlayer(player); - - seed = m_conn.getSeed(); - m_networkgame = true; - } - else std::cout << "Erreur de connexion." << std::endl; - } - else std::cout << "Erreur de creation de socket." << std::endl; - } - delete[] ch; - m_world.SetSeed(seed); // Init Chunks m_world.GetChunks().Reset(nullptr); m_startTime = std::chrono::high_resolution_clock::now(); - - m_remotePlayer.SetPosition(Vector3f(.5, CHUNK_SIZE_Y + 10., .5)); } void Engine::DeInit() {} @@ -136,8 +87,9 @@ void Engine::LoadResource() { LoadTexture(m_textureGun, TEXTURE_PATH "gun01.png", false); LoadTexture(m_texturePovGun, TEXTURE_PATH "GUN.png", false); + LoadTexture(m_textureLobbyMenu, TEXTURE_PATH "menus/backgrounds/bgLobby.png", false); LoadTexture(m_textureMainMenu, TEXTURE_PATH "menus/backgrounds/bgMainMenu.png", false); - LoadTexture(m_texturePauseMenu, TEXTURE_PATH "menus/backgrounds/bgPause.png", false); + //LoadTexture(m_texturePauseMenu, TEXTURE_PATH "menus/backgrounds/bgPause.png", false); LoadTexture(m_textureOptionsMenu, TEXTURE_PATH "menus/backgrounds/bgOptions.png", false); LoadTexture(m_textureSplashScreen, TEXTURE_PATH "menus/backgrounds/bgSplash.png", false); @@ -550,14 +502,10 @@ void Engine::DisplayPovGun() { glLoadIdentity(); glTranslated(xTranslation, 0, 0); glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2i(0, 0); - glTexCoord2f(1, 0); - glVertex2i(quadWidth, 0); - glTexCoord2f(1, 1); - glVertex2i(quadWidth, quadHeight); - glTexCoord2f(0, 1); - glVertex2i(0, quadHeight); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(quadWidth, 0); + glTexCoord2f(1, 1); glVertex2i(quadWidth, quadHeight); + glTexCoord2f(0, 1); glVertex2i(0, quadHeight); glEnd(); // Reset du blend function @@ -624,6 +572,60 @@ int Engine::GetOptionsChoice() { return m_selectedOption; } +void Engine::StartMultiplayerGame() { + char* ch = new char[2]; + + //std::cout << "Jouer en ligne? [o/N] "; + //std::cin.getline(ch, 2); + //std::cout << std::endl; + + char* input = new char[32]; + std::string playname, srvname; + + /*if (*ch == 'o' || *ch == 'O') { + char* input = new char[32]; + std::string playname, srvname; + + while (playname.size() < 1) { + std::cout << "Veuillez entrer un nom de joueur: "; + std::cin.getline(input, 32); + std::cout << std::endl; + playname = input; + if (playname.size() < 1 || playname.size() > 32) + std::puts("Nom invalide."); + } + while (srvname.size() < 1) { + std::cout << "Veuillez entrer une adresse de serveur: "; + std::cin.getline(input, 32); + std::cout << std::endl; + srvname = input; + if (srvname.size() < 1 || srvname.size() > 32) + std::puts("Adresse serveur invalide."); + } + delete[] input; + + + } + delete[] ch;*/ + + if (!m_conn.Init()) { + if (!m_conn.Connect(srvname.c_str(), playname)) { + // setup jeu en reseau. + std::cout << "ID recu du serveur: " << std::to_string(m_conn.getId()) << "!" << std::endl; + std::cout << "Seed recu du serveur: " << std::to_string(m_conn.getSeed()) << "!" << std::endl; + m_player = Player(m_conn.getOrigin().position); + + for (auto& [key, player] : m_conn.m_players) + m_players[key] = new RemotePlayer(player); + + //seed = m_conn.getSeed(); + m_networkgame = true; + } + else std::cout << "Erreur de connexion." << std::endl; + } + else std::cout << "Erreur de creation de socket." << std::endl; +} + void Engine::DisplayInfo(float elapsedTime, BlockType bloc) { m_textureFont.Bind(); std::ostringstream ss; @@ -709,15 +711,60 @@ void Engine::DisplaySplashScreen() { glPopMatrix(); } -void Engine::DisplayPauseMenu() { +void Engine::DisplayLobbyMenu() { + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); - m_texturePauseMenu.Bind(); + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + m_textureLobbyMenu.Bind(); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2i(0, 0); glTexCoord2f(1, 0); glVertex2i(Width(), 0); glTexCoord2f(1, 1); glVertex2i(Width(), Height()); glTexCoord2f(0, 1); glVertex2i(0, Height()); glEnd(); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + m_textureFont.Bind(); + std::ostringstream ss; + + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glBindTexture(GL_TEXTURE_2D, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(Width() * 0.6, Height() * 0.425); + glTexCoord2f(1, 0); glVertex2i(Width() * 0.95, Height() * 0.425); + glTexCoord2f(1, 1); glVertex2i(Width() * 0.95, Height() * 0.475); + glTexCoord2f(0, 1); glVertex2i(Width() * 0.6, Height() * 0.475); + glEnd(); + + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } void Engine::DisplayMainMenu() { @@ -1155,8 +1202,8 @@ void Engine::Render(float elapsedTime) { return; } - if (m_gamestate == GameState::PAUSE) { - DisplayPauseMenu(); + if (m_gamestate == GameState::LOBBY) { + DisplayLobbyMenu(); return; } @@ -1697,7 +1744,8 @@ void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y) { } else if (x > leftButton && x < rightButton && y > bottomSecond && y < topSecond) { if (m_selectedPlayOptions) { - m_gamestate = GameState::PLAY; + m_gamestate = GameState::LOBBY; + StartMultiplayerGame(); } else { m_gamestate = GameState::OPTIONS; diff --git a/SQCSim2021/engine.h b/SQCSim2021/engine.h index aff6ebd..8161620 100644 --- a/SQCSim2021/engine.h +++ b/SQCSim2021/engine.h @@ -45,6 +45,7 @@ private: int GetFps(float elapsedTime) const; int GetCountdown(float elapsedTime); int GetOptionsChoice(); + void StartMultiplayerGame(); bool LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps = true, bool stopOnError = true); @@ -61,7 +62,7 @@ private: void DisplayInfo(float elapsedTime, BlockType bloc); void DisplaySplashScreen(); - void DisplayPauseMenu(); + void DisplayLobbyMenu(); void DisplayMainMenu(); void DrawButtonBackgrounds(float centerX, float centerY, int iterations); @@ -122,6 +123,7 @@ private: Texture m_texturePovGun; Texture m_textureSkybox; + Texture m_textureLobbyMenu; Texture m_textureMainMenu; Texture m_textureOptionsMenu; Texture m_texturePauseMenu; diff --git a/SQCSim2021/media/textures/menus/backgrounds/bgLobby.png b/SQCSim2021/media/textures/menus/backgrounds/bgLobby.png new file mode 100644 index 0000000..fab6550 Binary files /dev/null and b/SQCSim2021/media/textures/menus/backgrounds/bgLobby.png differ diff --git a/enc_temp_folder/b3c3cb753ef72fdaf31cb22525389b8/engine.cpp b/enc_temp_folder/b3c3cb753ef72fdaf31cb22525389b8/engine.cpp new file mode 100644 index 0000000..508c0e3 --- /dev/null +++ b/enc_temp_folder/b3c3cb753ef72fdaf31cb22525389b8/engine.cpp @@ -0,0 +1,1893 @@ +#include "engine.h" +#include +#include +#include +#include +#include +#include +#include + +// Define a structure to represent notifications +struct Notification { + std::string message; + float displayStartTime = 0.0f; +}; + +// Use a queue to manage notifications +//std::queue notificationQueue; +// Use a vector to manage notifications +std::vector notifications; + +Engine::Engine() : m_remotePlayer(&m_pinfo), m_pinfo() {} + +Engine::~Engine() { + m_world.CleanUpWorld(m_renderCount, true); + for (int x = 0; x < WORLD_SIZE_X; ++x) + for (int y = 0; y < WORLD_SIZE_Y; ++y) + if (m_world.GetChunks().Get(x, y)) + m_world.GetChunks().Get(x, y)->~Chunk(); +} + +void Engine::Init() { + GLenum glewErr = glewInit(); + if (glewErr != GLEW_OK) { + std::cerr << " ERREUR GLEW : " << glewGetErrorString(glewErr) << std::endl; + abort(); + } + + uint64_t seed = SEED; + + glDisable(GL_FRAMEBUFFER_SRGB); + glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); + glEnable(GL_POINT_SMOOTH); + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f, (float)Width() / (float)Height(), 0.1f, VIEW_DISTANCE); + glShadeModel(GL_SMOOTH); + + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_SUBTRACT); + + if (m_istarted) + return; + else m_istarted = true; + + // Objet de skybox avec sa propre texture et son propre shader! + m_skybox.Init(0.2f); + // Objet de musique! + //m_audio.ToggleMusicState(); + + // Array pour les balles. + for (int x = 0; x < MAX_BULLETS; ++x) { + m_bullets[x] = nullptr; + m_whoosh[x] = nullptr; + } + + m_world.SetSeed(seed); + + // Init Chunks + m_world.GetChunks().Reset(nullptr); + + m_startTime = std::chrono::high_resolution_clock::now(); +} + +void Engine::DeInit() {} + +void Engine::LoadResource() { + LoadTexture(m_skybox.GetTexture(), TEXTURE_PATH "skybox.png", true); + LoadTexture(m_textureCrosshair, TEXTURE_PATH "cross.bmp", true); + LoadTexture(m_textureFont, TEXTURE_PATH "font.bmp", true); + LoadTexture(m_textureGun, TEXTURE_PATH "gun01.png", false); + LoadTexture(m_texturePovGun, TEXTURE_PATH "GUN.png", false); + + LoadTexture(m_textureLobbyMenu, TEXTURE_PATH "menus/backgrounds/bgLobby.png", false); + LoadTexture(m_textureMainMenu, TEXTURE_PATH "menus/backgrounds/bgMainMenu.png", false); + //LoadTexture(m_texturePauseMenu, TEXTURE_PATH "menus/backgrounds/bgPause.png", false); + LoadTexture(m_textureOptionsMenu, TEXTURE_PATH "menus/backgrounds/bgOptions.png", false); + LoadTexture(m_textureSplashScreen, TEXTURE_PATH "menus/backgrounds/bgSplash.png", false); + + LoadTexture(m_textureCheck, TEXTURE_PATH "menus/others/check.png", false); + LoadTexture(m_textureChecked, TEXTURE_PATH "menus/others/checked.png", false); + + LoadTexture(m_textureOptAudio, TEXTURE_PATH "menus/buttons/options/optAudio.png", false); + LoadTexture(m_textureOptBack, TEXTURE_PATH "menus/buttons/options/optBack.png", false); + LoadTexture(m_textureOptGameplay, TEXTURE_PATH "menus/buttons/options/optGameplay.png", false); + LoadTexture(m_textureOptGraphics, TEXTURE_PATH "menus/buttons/options/optGraphics.png", false); + LoadTexture(m_textureOptMain, TEXTURE_PATH "menus/buttons/options/optMain.png", false); + LoadTexture(m_textureOptMusic, TEXTURE_PATH "menus/buttons/options/optMusic.png", false); + LoadTexture(m_textureOptOptions, TEXTURE_PATH "menus/buttons/options/optOptions.png", false); + LoadTexture(m_textureOptResolution, TEXTURE_PATH "menus/buttons/options/optResolution.png", false); + LoadTexture(m_textureOptSensitivity, TEXTURE_PATH "menus/buttons/options/optSensitivity.png", false); + LoadTexture(m_textureOptSfx, TEXTURE_PATH "menus/buttons/options/optSfx.png", false); + + LoadTexture(m_textureHd, TEXTURE_PATH "menus/labels/labelHd.png", false); + LoadTexture(m_textureFhd, TEXTURE_PATH "menus/labels/labelFhd.png", false); + LoadTexture(m_textureQhd, TEXTURE_PATH "menus/labels/labelQhd.png", false); + LoadTexture(m_textureUhd, TEXTURE_PATH "menus/labels/labelUhd.png", false); + LoadTexture(m_textureMenuTitle, TEXTURE_PATH "menus/labels/labelTitle.png", false); + + LoadTexture(m_textureMenuBack, TEXTURE_PATH "menus/buttons/main/mainBack.png", false); + LoadTexture(m_textureMenuMulti, TEXTURE_PATH "menus/buttons/main/mainMulti.png", false); + LoadTexture(m_textureMenuOptions, TEXTURE_PATH "menus/buttons/main/mainOptions.png", false); + LoadTexture(m_textureMenuPlay, TEXTURE_PATH "menus/buttons/main/mainPlay.png", false); + LoadTexture(m_textureMenuQuit, TEXTURE_PATH "menus/buttons/main/mainQuit.png", false); + LoadTexture(m_textureMenuSingle, TEXTURE_PATH "menus/buttons/main/mainSingle.png", false); + + TextureAtlas::TextureIndex texDirtIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal3.png"); + TextureAtlas::TextureIndex texIceIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal2.png"); + TextureAtlas::TextureIndex texGrassIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "grass.png"); + TextureAtlas::TextureIndex texMetalIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "dirt.png"); + TextureAtlas::TextureIndex texGreenGrassIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "greengrass.png"); + TextureAtlas::TextureIndex texBoostHeal = m_textureAtlas.AddTexture(BOOSTER_TEXTURE_PATH "BoosterVert.png"); + TextureAtlas::TextureIndex texBoostDmg = m_textureAtlas.AddTexture(BOOSTER_TEXTURE_PATH "BoosterRouge.png"); + TextureAtlas::TextureIndex texBoostSpd = m_textureAtlas.AddTexture(BOOSTER_TEXTURE_PATH "BoosterBleu.png"); + TextureAtlas::TextureIndex texBoostInv = m_textureAtlas.AddTexture(BOOSTER_TEXTURE_PATH "BoosterJaune.png"); + + //AJOUTER LES TEXTURES DANS L'ORDRE DE L'ÉNUM + + //JUMP + //TextureAtlas::TextureIndex JumpBack = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueBackJumpRight.png"); + //TextureAtlas::TextureIndex JumpFront = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueFrontJumpRight.png"); + //TextureAtlas::TextureIndex JumpQuarterBackLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftBackJumpLeft.png"); + //TextureAtlas::TextureIndex JumpQuarterBackRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightBackJumpRight.png"); + //TextureAtlas::TextureIndex JumpProfiltLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilJumpLeft.png"); + //TextureAtlas::TextureIndex JumpProfiltRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilJumpRight.png"); + //TextureAtlas::TextureIndex JumpQuarterFrontLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftFrontJumpLeft.png"); + //TextureAtlas::TextureIndex JumpQuarterFrontRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightFrontJumpRight.png"); + + //STILL + //TextureAtlas::TextureIndex StillBack = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueBackRight.png"); + TextureAtlas::TextureIndex StillFront = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueFrontRight.png"); + //TextureAtlas::TextureIndex StillQuarterBackLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftBack.png"); + //TextureAtlas::TextureIndex StillQuarterBackRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightBack.png"); + //TextureAtlas::TextureIndex StillProfiltLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilLeft.png"); + //TextureAtlas::TextureIndex StillProfiltRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilRight.png"); + //TextureAtlas::TextureIndex StillQuarterFrontLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeft.png"); + //TextureAtlas::TextureIndex StillQuarterFrontRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRight.png"); + + //SHOOTINGSTILL + //SHOOTINGJUMP + + if (!m_animeAtlas.Generate(TEXTURE_SIZE, false)) { + std::cout << " Unable to generate texture atlas ..." << std::endl; + abort(); + } + + if (!m_textureAtlas.Generate(TEXTURE_SIZE, false)) { + std::cout << " Unable to generate texture atlas ..." << std::endl; + abort(); + } + + float u, v, s; + m_textureAtlas.TextureIndexToCoord(texDirtIndex, u, v, s, s); + m_blockinfo[BTYPE_DIRT] = new BlockInfo(BTYPE_DIRT, "Dirt", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texGrassIndex, u, v, s, s); + m_blockinfo[BTYPE_GRASS] = new BlockInfo(BTYPE_GRASS, "Grass", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texMetalIndex, u, v, s, s); + m_blockinfo[BTYPE_METAL] = new BlockInfo(BTYPE_METAL, "Metal", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texIceIndex, u, v, s, s); + m_blockinfo[BTYPE_ICE] = new BlockInfo(BTYPE_ICE, "Ice", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texGreenGrassIndex, u, v, s, s); + m_blockinfo[BTYPE_GREENGRASS] = new BlockInfo(BTYPE_GREENGRASS, "GreenGrass", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texBoostHeal, u, v, s, s); + m_boostinfo[BTYPE_HEAL] = new BoostInfo(BTYPE_HEAL, "Heal", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texBoostDmg, u, v, s, s); + m_boostinfo[BTYPE_DAMAGE] = new BoostInfo(BTYPE_DAMAGE, "Dmg", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texBoostSpd, u, v, s, s); + m_boostinfo[BTYPE_SPEED] = new BoostInfo(BTYPE_SPEED, "Spd", u, v, s, 1); + m_textureAtlas.TextureIndexToCoord(texIceIndex, u, v, s, s); + m_boostinfo[BTYPE_INVINCIBLE] = new BoostInfo(BTYPE_INVINCIBLE, "Inv", u, v, s, 1); + + m_animeAtlas.TextureIndexToCoord(0, u, v, s, s); + + std::cout << " Loading and compiling shaders ..." << std::endl; + if (!m_shader01.Load(SHADER_PATH "shader01.vert", SHADER_PATH "shader01.frag", true)) { + std::cout << " Failed to load shader " << std::endl; + exit(1); + } + + if (!m_skybox.GetShader().Load(SHADER_PATH "skybox.vert", SHADER_PATH "skybox.frag", true)) { + std::cout << " Failed to load shader " << std::endl; + exit(1); + } +} + +void Engine::UnloadResource() {} + + + +void Engine::InstantDamage() { + m_player.InflictDamage(0.10f); + m_damage = false; +} + +void Engine::SystemNotification(std::string systemLog) { + std::string message = ""; + + message = systemLog; + + DisplayNotification(message); +} + +void Engine::KillNotification(Player killer, Player killed) { + std::string message = ""; + + message = killed.GetUsername() + " killed by -> " + killer.GetUsername(); + + DisplayNotification(message); +} + +void Engine::DisplayNotification(std::string message) { + + if (message.length() > 45) { + message = message.substr(0, 45); + } + // Create a new notification and add it to the queue + Notification newNotification; + newNotification.message = message; + newNotification.displayStartTime = m_time; + + notifications.push_back(newNotification); +} + +// Add a method to process the notification queue +void Engine::ProcessNotificationQueue() { + //PrintText(fPosX, fUsernamePosY, ss.str(), 1.5f); + //float fPosX = (Width() / 100.0f) * scaleX; + //float fPosY = Height() - (Height() * 0.05) * scaleY; + + m_textureFont.Bind(); + float xOffset = Width() * 0.66f; + float yOffset = Height() * 0.83f; + + for (auto it = notifications.begin(); it != notifications.end(); ) { + float timeSinceDisplay = m_time - it->displayStartTime; + + float y = yOffset - (20.0f * (it - notifications.begin())); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + PrintText(xOffset, y, it->message); + + glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR); + glBlendEquation(GL_FUNC_SUBTRACT); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + if (timeSinceDisplay >= 4.0f) { + it = notifications.erase(it); + } + else { + ++it; + } + } +} + +void Engine::DisplayCrosshair() { + m_textureCrosshair.Bind(); + static const int crossSize = 32; + glLoadIdentity(); + glTranslated(Width() / 2 - crossSize / 2, Height() / 2 - crossSize / 2, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2i(0, 0); + glTexCoord2f(1, 0); + glVertex2i(crossSize, 0); + glTexCoord2f(1, 1); + glVertex2i(crossSize, crossSize); + glTexCoord2f(0, 1); + glVertex2i(0, crossSize); + glEnd(); +} + +void Engine::DisplayCurrentItem() {} + +void Engine::DisplayHud(int timer) { + glBindTexture(GL_TEXTURE_2D, 0); + glLoadIdentity(); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + float itemBackgroundWidthProportion = 0.25f; + float itemBackgroundHeightProportion = 0.175f; + float itemBackgroundWidth = Width() * itemBackgroundWidthProportion; + float itemBackgroundHeight = Height() * itemBackgroundHeightProportion; + float itemBackgroundXOffset = Width() * 0.05f; + float itemBackgroundYOffset = Height() * 0.6f; + float itemBackgroundXPos = itemBackgroundXOffset; + float itemBackgroundYPos = Height() - itemBackgroundHeight - itemBackgroundYOffset; + + // Selected item background + glColor4f(1.0f, 1.0f, 1.0f, 0.2f); + glBegin(GL_QUADS); + glVertex2f(itemBackgroundXPos, itemBackgroundYPos); + glVertex2f(itemBackgroundXPos + itemBackgroundWidth, itemBackgroundYPos); + glVertex2f(itemBackgroundXPos + itemBackgroundWidth, itemBackgroundYPos + itemBackgroundHeight); + glVertex2f(itemBackgroundXPos, itemBackgroundYPos + itemBackgroundHeight); + glEnd(); + + // HP Bar + float playerHp = m_player.GetHP(); + float facteurOmbrage = m_displayInfo ? 0.5f : 1.0f; + + float hpBarWidthProportion = 0.25f; + float hpBarHeightProportion = 0.045f; + float hpBarWidth = Width() * hpBarWidthProportion; + float hpBarHeight = Height() * hpBarHeightProportion; + float hpBarXOffset = Width() * 0.05f; + float hpBarYOffset = Height() * 0.7f; + float hpBarYPos = Height() - hpBarHeight - hpBarYOffset; + + // HP Bar Background + glColor3f(1.0f * facteurOmbrage, 1.0f * facteurOmbrage, 1.0f * facteurOmbrage); + glBegin(GL_QUADS); + glVertex2f(itemBackgroundXPos, hpBarYPos - hpBarHeight); + glVertex2f(itemBackgroundXPos + itemBackgroundWidth, hpBarYPos - hpBarHeight); + glVertex2f(itemBackgroundXPos + itemBackgroundWidth, hpBarYPos); + glVertex2f(itemBackgroundXPos, hpBarYPos); + glEnd(); + + //TODO: Associer avec mechanique de vie du joueur + + // Barre HP + glColor3f(0.0f * facteurOmbrage, 1.0f * facteurOmbrage, 0.0f * facteurOmbrage); + glBegin(GL_QUADS); + glVertex2f(itemBackgroundXPos, hpBarYPos - hpBarHeight); + glVertex2f(itemBackgroundXPos + itemBackgroundWidth * playerHp, hpBarYPos - hpBarHeight); + glVertex2f(itemBackgroundXPos + itemBackgroundWidth * playerHp, hpBarYPos); + glVertex2f(itemBackgroundXPos, hpBarYPos); + glEnd(); + + // Equip Bar + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor3f(1.0f * facteurOmbrage, 1.0f * facteurOmbrage, 1.0f * facteurOmbrage); + + float equipWidthProportion = 0.8f; + float equipHeightProportion = 0.7f; + float equipWidth = itemBackgroundWidth * equipWidthProportion; + float equipHeight = itemBackgroundHeight * equipHeightProportion; + float equipXOffset = itemBackgroundXPos + (itemBackgroundWidth - equipWidth) * 0.1f; + float equipYOffset = itemBackgroundYPos + (itemBackgroundHeight - equipHeight) * 0.75f; + + glTranslatef(equipXOffset, equipYOffset, 0); + + m_textureGun.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(0, 0); + glTexCoord2f(1, 0); glVertex2f(equipWidth, 0); + glTexCoord2f(1, 1); glVertex2f(equipWidth, equipHeight); + glTexCoord2f(0, 1); glVertex2f(0, equipHeight); + glEnd(); + + // Username + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor3f(1.0f, 1.0f, 1.0f); + + m_textureFont.Bind(); + std::ostringstream ss; + float fUsernamePosY = hpBarYPos - (hpBarHeight * 2); + + ss.str(""); + ss << m_player.GetUsername(); + PrintText(itemBackgroundXPos, fUsernamePosY, ss.str(), 1.5f); + + ss.str(""); + ss << m_player.GetHP() * 100 << "%"; + PrintText(itemBackgroundXPos * 5.25f, fUsernamePosY, ss.str(), 1.5f); + + float countdownXOffset = Width() * 0.2f; + float countdownYOffset = Height() * 0.1f; + float countdownXPos = Width() - countdownXOffset; + float countdownYPos = Height() - countdownYOffset; + + // Countdown + ss.str(""); + ss << "Time: " << (int)(timer / 60) << ":" << std::setw(2) << std::setfill('0') << timer % 60; + PrintText(countdownXPos, countdownYPos, ss.str(), 2.0f); +} + +void Engine::DrawHud(float elapsedTime, BlockType bloc) { + // Setter le blend function, tout ce qui sera noir sera transparent + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + glEnable(GL_BLEND); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + int timer = GetCountdown(elapsedTime); + for (int i = 1; i < WORLD_SIZE_X; i++) { + if (timer <= COUNTDOWN - m_timerReductionChunk * i) { + m_world.RemoveChunk(m_nbReductionChunk * i); + m_renderer.RemoveChunk(m_nbReductionChunk * i); + } + } + if (m_keyK) { + SystemNotification(m_messageNotification); + m_keyK = false; + } + if (m_keyL) { + + KillNotification(m_player, m_player); + m_keyL = false; + } + + if (m_displayInfo) { + DisplayInfo(elapsedTime, bloc); + } + + if (m_displayHud) { + DisplayHud(timer); + } + + if (m_displayCrosshair) { + DisplayCrosshair(); + } + + glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR); + glBlendEquation(GL_FUNC_SUBTRACT); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Engine::DisplayPovGun() { + // Setter le blend function, tout ce qui sera noir sera transparent + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + float baseXOffsetPercentage = 0.4958; + float baseWidthPercentage = 0.4688; + float baseHeightPercentage = 0.5787; + + float xTranslation = baseXOffsetPercentage * Width(); + float quadWidth = baseWidthPercentage * Width(); + float quadHeight = baseHeightPercentage * Height(); + + m_texturePovGun.Bind(); + glLoadIdentity(); + glTranslated(xTranslation, 0, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(quadWidth, 0); + glTexCoord2f(1, 1); glVertex2i(quadWidth, quadHeight); + glTexCoord2f(0, 1); glVertex2i(0, quadHeight); + glEnd(); + + // Reset du blend function + glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR); + glBlendEquation(GL_FUNC_SUBTRACT); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Engine::PrintText(float x, float y, const std::string& t, float charSizeMultiplier) { + float windowWidth = static_cast(Width()); + float windowHeight = static_cast(Height()); + + float posX = x * windowWidth; + float posY = y * windowHeight; + + float baseCharSize = 20 + (24 - 20) * (windowWidth - 1600) / (1920 - 1600); + float charSize = baseCharSize * charSizeMultiplier; + + glPushMatrix(); + glLoadIdentity(); + glTranslated(x, y, 0); + + for (unsigned int i = 0; i < t.length(); ++i) { + float left = (float)((t[i] - 32) % 16) / 16.f; + float top = (float)((t[i] - 32) / 16) / 16.f; + top += 0.5f; + + glBegin(GL_QUADS); + glTexCoord2f(left, 1.f - top - .0625f); glVertex2f(0, 0); + glTexCoord2f(left + .0625f, 1.f - top - .0625f); glVertex2f(charSize, 0); + glTexCoord2f(left + .0625f, 1.f - top); glVertex2f(charSize, charSize); + glTexCoord2f(left, 1.f - top); glVertex2f(0, charSize); + glEnd(); + + glTranslated(0.5555f * charSize, 0, 0); + } + glPopMatrix(); +} + +int Engine::GetFps(float elapsedTime) const { return 1 / elapsedTime; } + +int Engine::GetCountdown(float elapsedTime) { + if (m_resetcountdown) { + m_nbReductionChunk = 4; + m_timerReductionChunk = 30; + m_countdown = m_time + COUNTDOWN; + m_resetcountdown = false; + } + if (m_countdown < m_time) + Stop(); + if (!m_stopcountdown) + m_time += elapsedTime; + return m_countdown - (int)m_time; +} + +int Engine::GetOptionsChoice() { + return m_selectedOption; +} + +void Engine::StartMultiplayerGame() { + char* ch = new char[2]; + + //std::cout << "Jouer en ligne? [o/N] "; + //std::cin.getline(ch, 2); + //std::cout << std::endl; + + char* input = new char[32]; + std::string playname, srvname; + + /*if (*ch == 'o' || *ch == 'O') { + char* input = new char[32]; + std::string playname, srvname; + + while (playname.size() < 1) { + std::cout << "Veuillez entrer un nom de joueur: "; + std::cin.getline(input, 32); + std::cout << std::endl; + playname = input; + if (playname.size() < 1 || playname.size() > 32) + std::puts("Nom invalide."); + } + while (srvname.size() < 1) { + std::cout << "Veuillez entrer une adresse de serveur: "; + std::cin.getline(input, 32); + std::cout << std::endl; + srvname = input; + if (srvname.size() < 1 || srvname.size() > 32) + std::puts("Adresse serveur invalide."); + } + delete[] input; + + + } + delete[] ch;*/ + + if (!m_conn.Init()) { + if (!m_conn.Connect(srvname.c_str(), playname)) { + // setup jeu en reseau. + std::cout << "ID recu du serveur: " << std::to_string(m_conn.getId()) << "!" << std::endl; + std::cout << "Seed recu du serveur: " << std::to_string(m_conn.getSeed()) << "!" << std::endl; + m_player = Player(m_conn.getOrigin().position); + + for (auto& [key, player] : m_conn.m_players) + m_players[key] = new RemotePlayer(player); + + //seed = m_conn.getSeed(); + m_networkgame = true; + } + else std::cout << "Erreur de connexion." << std::endl; + } + else std::cout << "Erreur de creation de socket." << std::endl; +} + +void Engine::DisplayInfo(float elapsedTime, BlockType bloc) { + m_textureFont.Bind(); + std::ostringstream ss; + + float marginX = Width() * 0.01; + float marginY = Height() * 0.05; + + float fPosX = marginX; + float fPosY = Height() - marginY; + + float charSize = 20 + (24 - 20) * (Width() - 1600) / (1920 - 1600); + + ss << " Fps : " << GetFps(elapsedTime); + PrintText(fPosX, fPosY, ss.str()); + ss.str(""); + fPosY -= charSize; + + ss << " Rendered Chunks : " << m_renderCount; + PrintText(fPosX, fPosY, ss.str()); + ss.str(""); + fPosY -= charSize; + + ss << " To-Be-Deleted Chunks : " << m_world.GettbDeleted(); + PrintText(fPosX, fPosY, ss.str()); + ss.str(""); + fPosY -= charSize; + + float fPosYJump = Height() * 0.09; + fPosY = fPosYJump; + fPosY -= charSize; + + ss << " Velocity : " << m_remotePlayer.GetVelocity(); + PrintText(fPosX, fPosY, ss.str()); + ss.str(""); + fPosY -= charSize; + + ss << " Player Position : " << m_player.GetPosition(); + PrintText(fPosX, fPosY, ss.str()); + ss.str(""); + fPosY -= charSize; + + ss << " Remote Position : " << m_remotePlayer.GetPosition();//m_player.GetPosition(); + PrintText(fPosX, fPosY, ss.str()); + ss.str(""); + fPosY -= charSize; + + ss << " Block : "; + if (bloc == BTYPE_LAST) + ss << "Weapon"; + else + ss << (int)bloc; + PrintText(fPosX, fPosYJump, ss.str()); +} + +void Engine::DisplaySplashScreen() { + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-Width() / 2, Width() / 2, -Height() / 2, Height() / 2, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + int imageWidth = Width(); + int imageHeight = Height(); + + m_textureSplashScreen.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(-imageWidth / 2, -imageHeight / 2); + glTexCoord2f(1, 0); glVertex2i(imageWidth / 2, -imageHeight / 2); + glTexCoord2f(1, 1); glVertex2i(imageWidth / 2, imageHeight / 2); + glTexCoord2f(0, 1); glVertex2i(-imageWidth / 2, imageHeight / 2); + glEnd(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Engine::DisplayLobbyMenu() { + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + m_textureLobbyMenu.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(Width(), 0); + glTexCoord2f(1, 1); glVertex2i(Width(), Height()); + glTexCoord2f(0, 1); glVertex2i(0, Height()); + glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glBindTexture(GL_TEXTURE_2D, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(Width() * 0.6, Height() * 0.425); + glTexCoord2f(1, 0); glVertex2i(Width() * 0.95, Height() * 0.425); + glTexCoord2f(1, 1); glVertex2i(Width() * 0.95, Height() * 0.475); + glTexCoord2f(0, 1); glVertex2i(Width() * 0.6, Height() * 0.475); + glEnd(); + + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Engine::DisplayMainMenu() { + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + // Background + m_textureMainMenu.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); + glTexCoord2f(1.0f, 0.0f); glVertex2f(Width(), 0.0f); + glTexCoord2f(1.0f, 1.0f); glVertex2f(Width(), Height()); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, Height()); + glEnd(); + + // Title + float centerX = Width() * 0.5f; + float centerY = Height() * 0.5f; + + glColor4f(1.0f, 0.5f, 0.0f, 1.0f); + m_textureMenuTitle.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.05, centerY + Height() * 0.05); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.45, centerY + Height() * 0.05); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.45, centerY + Height() * 0.45); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.05, centerY + Height() * 0.45); + glEnd(); + + DrawButtonBackgrounds(centerX, centerY, 3); + + if (m_gamestate == GameState::MAIN_MENU) { + if (m_selectedPlayOptions) { + DrawSingleMultiButtons(centerX, centerY); + } + else { + DrawMainMenuButtons(centerX, centerY); + } + } + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + ShowCursor(); +} + +void Engine::DrawMainMenuButtons(float centerX, float centerY) { + m_textureMenuPlay.Bind(); + glColor4f(0.75f, 0.05f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.16, centerY - Height() * 0.065); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.34, centerY - Height() * 0.065); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.34, centerY - Height() * 0.01); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.16, centerY - Height() * 0.01); + glEnd(); + + m_textureMenuOptions.Bind(); + glColor4f(0.75f, 0.05f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.08, centerY - Height() * 0.165); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.42, centerY - Height() * 0.165); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.42, centerY - Height() * 0.11); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.08, centerY - Height() * 0.11); + glEnd(); + + m_textureMenuQuit.Bind(); + glColor4f(0.75f, 0.05f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.16, centerY - Height() * 0.265); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.34, centerY - Height() * 0.265); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.34, centerY - Height() * 0.21); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.16, centerY - Height() * 0.21); + glEnd(); +} + +void Engine::DrawSingleMultiButtons(float centerX, float centerY) { + m_textureMenuSingle.Bind(); + glColor4f(0.75f, 0.05f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.06, centerY - Height() * 0.065); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.44, centerY - Height() * 0.065); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.44, centerY - Height() * 0.01); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.06, centerY - Height() * 0.01); + glEnd(); + + m_textureMenuMulti.Bind(); + glColor4f(0.75f, 0.05f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.08, centerY - Height() * 0.165); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.42, centerY - Height() * 0.165); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.42, centerY - Height() * 0.11); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.08, centerY - Height() * 0.11); + glEnd(); + + m_textureMenuBack.Bind(); + glColor4f(0.75f, 0.05f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.16, centerY - Height() * 0.265); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.34, centerY - Height() * 0.265); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.34, centerY - Height() * 0.21); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.16, centerY - Height() * 0.21); + glEnd(); +} + +void Engine::DrawButtonBackgrounds(float centerX, float centerY, int iterations) { + glColor4f(1.0f, 1.0f, 1.0f, 0.5f); + glBindTexture(GL_TEXTURE_2D, 0); + + float bottomOffset = 0.075f; + float topOffset = 0.0f; + float distanceBetween = 0.1f; + + for (int i = 0; i < iterations; i++) { + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(centerX + Width() * 0.05, centerY - Height() * bottomOffset); + glTexCoord2f(1.0f, 0.0f); glVertex2f(centerX + Width() * 0.45, centerY - Height() * bottomOffset); + glTexCoord2f(1.0f, 1.0f); glVertex2f(centerX + Width() * 0.45, centerY - Height() * topOffset); + glTexCoord2f(0.0f, 1.0f); glVertex2f(centerX + Width() * 0.05, centerY - Height() * topOffset); + glEnd(); + + bottomOffset += distanceBetween; + topOffset += distanceBetween; + } +} + +void Engine::DisplayOptionsMenu() { + static const int sTitle = 400; + static const int sButton = 225; + + float centerX = Width() * 0.5f; + float centerY = Height() * 0.5f; + + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + m_textureOptionsMenu.Bind(); + glLoadIdentity(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(Width(), 0); + glTexCoord2f(1, 1); glVertex2i(Width(), Height()); + glTexCoord2f(0, 1); glVertex2i(0, Height()); + glEnd(); + + glColor4f(1.0f, 0.0f, 1.0f, 1.0f); + m_textureOptOptions.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.175, centerY + Height() * 0.35); + glTexCoord2f(1, 0); glVertex2i(centerX + Width() * 0.175, centerY + Height() * 0.35); + glTexCoord2f(1, 1); glVertex2i(centerX + Width() * 0.175, centerY + Height() * 0.45); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.175, centerY + Height() * 0.45); + glEnd(); + + if (m_selectedOption == 0) { + glColor4f(0.5f, 1.0f, 0.0f, 1.0f); + } + m_textureOptAudio.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.35, centerY + Height() * 0.2); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.2, centerY + Height() * 0.2); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.2, centerY + Height() * 0.25); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.35, centerY + Height() * 0.25); + glEnd(); + + glColor4f(1.0f, 0.0f, 1.0f, 1.0f); + if (m_selectedOption == 1) { + glColor4f(0.5f, 1.0f, 0.0f, 1.0f); + } + m_textureOptGraphics.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.4, centerY + Height() * 0.05); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.2, centerY + Height() * 0.05); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.2, centerY + Height() * 0.1); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.4, centerY + Height() * 0.1); + glEnd(); + + glColor4f(1.0f, 0.0f, 1.0f, 1.0f); + if (m_selectedOption == 2) { + glColor4f(0.5f, 1.0f, 0.0f, 1.0f); + } + m_textureOptGameplay.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.375, centerY - Height() * 0.1); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.2, centerY - Height() * 0.1); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.2, centerY - Height() * 0.05); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.375, centerY - Height() * 0.05); + glEnd(); + + // Séparateur + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glBindTexture(GL_TEXTURE_2D, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.175, centerY - Height() * 0.1); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.18, centerY - Height() * 0.1); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.18, centerY + Height() * 0.25); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.175, centerY + Height() * 0.25); + glEnd(); + + glColor4f(1.0f, 0.0f, 1.0f, 1.0f); + m_textureOptBack.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.075, centerY - Height() * 0.25); + glTexCoord2f(1, 0); glVertex2i(centerX + Width() * 0.075, centerY - Height() * 0.25); + glTexCoord2f(1, 1); glVertex2i(centerX + Width() * 0.075, centerY - Height() * 0.2); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.075, centerY - Height() * 0.2); + glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + if (m_selectedOption == 0) { + DisplayAudioMenu(centerX, centerY); + } + else if (m_selectedOption == 1) { + DisplayGraphicsMenu(centerX, centerY); + } + else if (m_selectedOption == 2) { + DisplayGameplayMenu(centerX, centerY); + } + + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Engine::DisplayAudioMenu(float centerX, float centerY) { + float minBar = centerX - Width() * 0.15; + float maxBar = centerX + Width() * 0.3; + float percentPosX = centerX + Width() * 0.31f; + + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + m_textureOptMain.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.215); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.075, centerY + Height() * 0.215); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.075, centerY + Height() * 0.25); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.25); + glEnd(); + + float principalBottom = centerY + Height() * 0.165f; + float principalTop = centerY + Height() * 0.2f; + + DrawSliderBackground(centerX, centerY, minBar, maxBar, principalBottom, principalTop); + DrawSlider(centerX, centerY, m_volPrincipal, minBar, maxBar, principalBottom, principalTop); + DisplayBarPercentValue(centerX, centerY, percentPosX, principalBottom, minBar, maxBar, m_volPrincipal); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + m_textureOptMusic.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.09); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.05, centerY + Height() * 0.09); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.05, centerY + Height() * 0.125); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.125); + glEnd(); + + float musiqueBottom = centerY + Height() * 0.04f; + float musiqueTop = centerY + Height() * 0.075f; + + DrawSliderBackground(centerX, centerY, minBar, maxBar, musiqueBottom, musiqueTop); + DrawSlider(centerX, centerY, m_volMusique, minBar, maxBar, musiqueBottom, musiqueTop); + DisplayBarPercentValue(centerX, centerY, percentPosX, musiqueBottom, minBar, maxBar, m_volMusique); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + m_textureOptSfx.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY - Height() * 0.035); + glTexCoord2f(1, 0); glVertex2i(centerX - Width() * 0.075, centerY - Height() * 0.035); + glTexCoord2f(1, 1); glVertex2i(centerX - Width() * 0.075, centerY - Height() * 0.00001); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY - Height() * 0.00001); + glEnd(); + + float effectsBottom = centerY - Height() * 0.085f; + float effectsTop = centerY - Height() * 0.05f; + + DrawSliderBackground(centerX, centerY, minBar, maxBar, effectsBottom, effectsTop); + DrawSlider(centerX, centerY, m_volEffets, minBar, maxBar, effectsBottom, effectsTop); + DisplayBarPercentValue(centerX, centerY, percentPosX, effectsBottom, minBar, maxBar, m_volEffets); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +void Engine::DisplayGraphicsMenu(float centerX, float centerY) { + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + m_textureOptResolution.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.215); + glTexCoord2f(1, 0); glVertex2i(centerX, centerY + Height() * 0.215); + glTexCoord2f(1, 1); glVertex2i(centerX, centerY + Height() * 0.25); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.25); + glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 0.5f); + glBindTexture(GL_TEXTURE_2D, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.16, centerY + Height() * 0.165); + glTexCoord2f(1, 0); glVertex2i(centerX + Width() * 0.1, centerY + Height() * 0.165); + glTexCoord2f(1, 1); glVertex2i(centerX + Width() * 0.1, centerY - Height() * 0.04); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.16, centerY - Height() * 0.04); + glEnd(); + + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + m_textureHd.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.125); + glTexCoord2f(1, 0); glVertex2i(centerX + Width() * 0.05, centerY + Height() * 0.125); + glTexCoord2f(1, 1); glVertex2i(centerX + Width() * 0.05, centerY + Height() * 0.15); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.15); + glEnd(); + + m_textureFhd.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.075); + glTexCoord2f(1, 0); glVertex2i(centerX, centerY + Height() * 0.075); + glTexCoord2f(1, 1); glVertex2i(centerX, centerY + Height() * 0.1); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.1); + glEnd(); + + m_textureQhd.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.025); + glTexCoord2f(1, 0); glVertex2i(centerX, centerY + Height() * 0.025); + glTexCoord2f(1, 1); glVertex2i(centerX, centerY + Height() * 0.05); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.05); + glEnd(); + + m_textureUhd.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY - Height() * 0.025); + glTexCoord2f(1, 0); glVertex2i(centerX + Width() * 0.015, centerY - Height() * 0.025); + glTexCoord2f(1, 1); glVertex2i(centerX + Width() * 0.015, centerY); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY); + glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + float heightRatioBottom = 0.125f; + float heightRatioTop = 0.15; + + // Checkboxes + for (int i = 0; i < 4; i++) { + if (static_cast(m_resolution) == i) { + m_textureChecked.Bind(); + } + else { + m_textureCheck.Bind(); + } + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX + Width() * 0.075, centerY + Height() * heightRatioBottom); + glTexCoord2f(1, 0); glVertex2i(centerX + Width() * 0.09, centerY + Height() * heightRatioBottom); + glTexCoord2f(1, 1); glVertex2i(centerX + Width() * 0.09, centerY + Height() * heightRatioTop); + glTexCoord2f(0, 1); glVertex2i(centerX + Width() * 0.075, centerY + Height() * heightRatioTop); + glEnd(); + + heightRatioBottom -= 0.05f; + heightRatioTop -= 0.05f; + } + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +void Engine::Render(float elapsedTime) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + if (m_gamestate == GameState::SPLASH) { + if (m_splashTime > 0.0f) { + DisplaySplashScreen(); + } + else { + m_gamestate = GameState::MAIN_MENU; + } + + m_splashTime -= elapsedTime; + return; + } + + if (m_gamestate == GameState::MAIN_MENU) { + DisplayMainMenu(); + return; + } + + if (m_gamestate == GameState::OPTIONS) { + DisplayOptionsMenu(); + return; + } + + if (m_gamestate == GameState::LOBBY) { + DisplayLobbyMenu(); + return; + } + + if (m_gamestate == GameState::PLAY) { + HideCursor(); + CenterMouse(); //D�placement de centermouse dans l'action de jouer + + //static float gameTime = elapsedTime; + static irrklang::ISound* step; // Pour les sons de pas. + static float pollTime = 0; + static float bulletTime = 0; + static float gameTime = 0; + static BlockType bloc = 1; + + if (elapsedTime > 0.1f) return; + + //gameTime += elapsedTime; + pollTime += elapsedTime; + + Transformation all; + Transformation skybox; + Transformation remotePlayer; + + Vector3f vstep; + + // Transformations initiales + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (bulletTime > 0.f) bulletTime -= elapsedTime; + if (bulletTime < 0.f) bulletTime = 0.f; + + static bool leftright = false; + if (pollTime >= .005f) { + Player::Sound snd = m_player.ApplyPhysics(m_player.GetInput(m_keyW, m_keyS, m_keyA, m_keyD, m_keySpace, (bloc == BTYPE_LAST && bulletTime <= 0.f && m_mouseL), elapsedTime), &m_world, elapsedTime); + switch (snd) { + case Player::Sound::STEP: + if (leftright) + vstep = Vector3f(m_player.GetPosition().x + m_player.GetDirection().z, m_player.GetPosition().y - 1.7f, m_player.GetPosition().z + m_player.GetDirection().x); + else vstep = Vector3f(m_player.GetPosition().x - m_player.GetDirection().z, m_player.GetPosition().y - 1.7f, m_player.GetPosition().z - m_player.GetDirection().x); + m_audio.Create3DAudioObj(step, AUDIO_PATH "step.wav", vstep, m_player.GetVelocity(), false, .8f); + leftright = !leftright; + break; + case Player::Sound::FALL: + m_audio.Create3DAudioObj(step, AUDIO_PATH "hit.wav", m_player.GetPosition(), m_player.GetVelocity(), false, 1.f); + break; + default: break; + } + m_audio.Update3DAudio(m_player.GetPOV(), m_player.GetDirection(), m_player.GetVelocity()); // Ajustement du positionnement 3D avec les coordonnees du joueur et + // son vecteur de velocite (pour l'effet Doppler) + pollTime = 0; + } + + m_player.ApplyTransformation(all); + + m_player.ApplyTransformation(skybox, false); // Version d'ApplyTransformation qui ne tient compte que de la rotation + // (donc l'objet ne bouge pas relativement au joueur, ce qui est pratique pour une skybox!). + + m_player.ApplyTransformation(remotePlayer, true, false); + + if (m_key1) bloc++; + else if (m_key2) bloc--; + + if (m_mouseWU) bloc++; + else if (m_mouseWD) bloc--; + if (bloc == BTYPE_LAST + 1) bloc = BTYPE_AIR + 1; + else if (bloc == BTYPE_AIR) bloc = BTYPE_LAST; // La selection de BTYPE_LAST �quipe l'arme. + m_mouseWU = m_mouseWD = m_key1 = m_key2 = false; + + if (m_mouseL) { + if (bloc != BTYPE_LAST) + m_world.ChangeBlockAtCursor(bloc, m_player.GetPosition(), m_player.GetDirection(), m_block); + else if (bulletTime <= 0.f) { + for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow"). + if (!m_bullets[x]) { + m_bullets[x] = new Bullet(m_player.GetPOV() + m_player.GetDirection(), m_player.GetDirection()); + break; + } + else if (x == MAX_BULLETS - 1) { // S'il y a pas d'espace dans l'array, prendre la place de la première balle de l'array. + m_bullets[0]->~Bullet(); + m_bullets[0] = new Bullet(m_player.GetPOV() + m_player.GetDirection(), m_player.GetDirection()); + } + bulletTime = BULLET_TIME; + m_audio.Create3DAudioObj(m_powpow, AUDIO_PATH "pow.wav", m_player.GetPOV(), m_player.GetDirection() * 10, false, .5f); + if (m_flash) { // Coupe le rendering et affiche un frame blanc, pour simuler un flash. + glClearColor(.8f, .8f, .8f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClearColor(0.f, 0.f, 0.f, 1.f); + return; + } + } + } + else if (m_mouseR) + m_world.ChangeBlockAtCursor(BTYPE_AIR, m_player.GetPosition(), m_player.GetDirection(), m_block); + + for (int x = 0; x < MAX_BULLETS; ++x) { // Array de bullets en jeu. + if (m_bullets[x]) { + for (int b = 0; b < BULLET_UPDATES_PER_FRAME; ++b) { + if (m_bullets[x]->Update(&m_world, elapsedTime, BULLET_UPDATES_PER_FRAME, m_players)) { + m_bullets[x]->~Bullet(); + if (m_whoosh[x]) + m_whoosh[x]->drop(); + m_bullets[x] = nullptr; + m_whoosh[x] = nullptr; + break; + } + else if (!m_whoosh[x]) { + m_whoosh[x] = m_audio.Create3DAudioObj(m_whoosh[x], AUDIO_PATH "noise.wav", m_bullets[x]->getPos(), m_bullets[x]->getVel(), true, (m_bullets[x]->getPos() - m_player.GetPosition()).Length()); + } + else { + Vector3f pos = m_bullets[x]->getPos(), vel = m_bullets[x]->getVel(); + m_audio.Render3DAudioObj(m_whoosh[x], pos, vel, 5 - (m_bullets[x]->getPos() - m_player.GetPosition()).Length()); + } + } + } + } + + gameTime += elapsedTime * 10; + + Vector3f dance = Vector3f(sin(gameTime), 0, cos(-gameTime)); + dance.Normalize(); + m_remotePlayer.ApplyPhysics(dance, &m_world, elapsedTime); + m_world.Update(m_bullets, m_player.GetPosition(), m_blockinfo); + m_renderer.UpdateMesh(&m_world, m_player.GetPosition(), m_blockinfo); + m_remotePlayer.Render(m_animeAtlas, m_shader01, all, elapsedTime); + m_booster.RenderBillboard({ 195,16,195 }, m_textureAtlas, m_shader01, all); + + if (m_isSkybox) m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas); + + //glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + //m_remotePlayer.Render(m_textureAtlas, m_shader01, all, elapsedTime); + + m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas); + + if (m_isSkybox) m_skybox.Render(skybox); + + DrawHud(elapsedTime, bloc); + DisplayPovGun(); + ProcessNotificationQueue(); + if (m_damage) { + InstantDamage(); + } + static bool fell = false; + if (m_player.GetPosition().y < 1.7f && !fell) { + m_audio.Create3DAudioObj(m_scream, AUDIO_PATH "scream.wav", m_player.GetPOV(), m_player.GetVelocity(), false, 1.f); + fell = true; + } + else if (m_player.GetPosition().y < -20.f) { + m_player = Player(Vector3f(.5f, CHUNK_SIZE_Y + 1.8f, .5f)); // Respawn si le bonho- joueur tombe en bas du monde. + fell = false; + } + + if (m_networkgame) { // Pour se gerer le paquet. + using namespace std::chrono; + using namespace netprot; + Timestamp tstamp = duration_cast(high_resolution_clock::now() - m_startTime).count(); + Input input; + Sync sync; + uint64_t id = m_conn.getId(); + static std::vector lsPck; + + if (false) { // TODO: Faire un checkup pour chaque ~1000ms. + sync.sid = id; + sync.timestamp = tstamp; + sync.position = m_player.GetPosition(); + sync.hp = m_player.GetHP(); + // TODO: Garrocher ca quelque-part. + } + + input.sid = id; + input.direction = m_player.GetDirection(); + input.timestamp = tstamp; + input.keys.forward = m_keyW; + input.keys.backward = m_keyS; + input.keys.left = m_keyA; + input.keys.right = m_keyD; + input.keys.jump = m_keySpace; + input.keys.block = m_mouseR; + input.keys.shoot = m_mouseL; + + sendPackTo(m_conn.m_sock_udp, &input, &m_bufout, &m_conn.m_srvsockaddr); + + lsPck = recvPacks(m_conn.m_sock_udp, &m_buf); + char* prevptr = nullptr; + for (auto& pck : lsPck) { // We could make a few threads out of this. + Sync sync; + Output out; + if (!prevptr) + prevptr = m_buf.ptr; + uint32_t bsize = m_buf.len - (pck - prevptr); + prevptr = pck; + switch (getType(pck, 1)) { + using enum PACKET_TYPE; + case SYNC: + if (Deserialize(&sync, pck, &bsize)) { + if (sync.sid != m_conn.getId()) + break; + // TODO: Vérifier si les positions concordent au sync local. + } + break; + case OUTPUT: + if (Deserialize(&out, pck, &bsize)) { + RemotePlayer* r = (RemotePlayer*)m_players[out.id]; + r->Feed(out); + } + break; + default: + break; + } + } + lsPck.clear(); + } + } +} + +void Engine::DisplayGameplayMenu(float centerX, float centerY) { + float minBar = centerX - Width() * 0.15; + float maxBar = centerX + Width() * 0.3; + float percentPosX = centerX + Width() * 0.31f; + + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + m_textureOptSensitivity.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.215); + glTexCoord2f(1, 0); glVertex2i(centerX, centerY + Height() * 0.215); + glTexCoord2f(1, 1); glVertex2i(centerX, centerY + Height() * 0.25); + glTexCoord2f(0, 1); glVertex2i(centerX - Width() * 0.15, centerY + Height() * 0.25); + glEnd(); + + float sensibleBottom = centerY + Height() * 0.165f; + float sensibleTop = centerY + Height() * 0.2f; + + DrawSliderBackground(centerX, centerY, minBar, maxBar, sensibleBottom, sensibleTop); + DrawSlider(centerX, centerY, m_volSensible, minBar, maxBar, sensibleBottom, sensibleTop); + DisplayBarPercentValue(centerX, centerY, percentPosX, sensibleBottom, minBar, maxBar, m_volSensible); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +void Engine::DrawSliderBackground(float centerX, float centerY, float minVal, float maxVal, float bottomSideValue, float topSideValue) { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glBindTexture(GL_TEXTURE_2D, 0); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(minVal, bottomSideValue); + glTexCoord2f(1, 0); glVertex2i(maxVal, bottomSideValue); + glTexCoord2f(1, 1); glVertex2i(maxVal, topSideValue); + glTexCoord2f(0, 1); glVertex2i(minVal, topSideValue); + glEnd(); +} + +void Engine::DisplayBarPercentValue(float centerX, float centerY, float posX, float posY, float minVal, float maxVal, float value) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + float percentage = (value / (maxVal - minVal)) * 100; + + if (percentage < 0.0f) { + percentage = 0.0f; + } + else if (percentage > 100.0f) { + percentage = 100.0f; + } + + m_textureFont.Bind(); + std::ostringstream ss; + ss.str(""); + ss << std::fixed << std::setprecision(2); + ss << percentage << "%"; + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + PrintText(posX, posY, ss.str(), 2.0f); + + glDisable(GL_BLEND); +} + +void Engine::DrawSlider(float centerX, float centerY, float value, float minVal, float maxVal, float bottomSideValue, float topSideValue) { + if (value < 0.0f) { + value = 0.0f; + } + else if (value > (maxVal - minVal)) { + value = (maxVal - minVal); + } + + if (value >= 0.0f && value <= (maxVal - minVal)) { + glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(minVal, bottomSideValue); + glTexCoord2f(1, 0); glVertex2i(minVal + value, bottomSideValue); + glTexCoord2f(1, 1); glVertex2i(minVal + value, topSideValue); + glTexCoord2f(0, 1); glVertex2i(minVal, topSideValue); + glEnd(); + } +} + + + +void Engine::KeyPressEvent(unsigned char key) { + switch (key) { + case 0: // A - Gauche + if (!m_keyA) { + m_keyA = true; + } + break; + case 3: // D - Droite + if (!m_keyD) { + m_keyD = true; + } + break; + case 18: // S - Reculer + if (!m_keyS) { + m_keyS = true; + } + break; + case 22: // W - Avancer + if (!m_keyW) { + m_keyW = true; + } + break; + case 36: // ESC - Quitter + if (m_gamestate == GameState::PLAY) { + m_gamestate = GameState::PAUSE; + } + else if (m_gamestate == GameState::PAUSE) { + m_gamestate = GameState::PLAY; + } + //Stop(); + break; + case 57: // Space - Sauter + if (!m_keySpace) { + m_keySpace = true; + } + break; + case 94: // F10 - Plein �cran + IsFullscreen() ? SetFullscreen(false) : SetFullscreen(true); + //SetFullscreen(!IsFullscreen()); + break; + case 2: // C - Ignorer + break; + case 5: // F - Ignorer + break; + case 10: // K - Debugging DisplayNotification() + m_keyK = true; + m_messageNotification = "notifications systeme peuvent etre affichees"; + break; + case 11: // L - Debugging DisplayNotification() + m_keyL = true; + break; + case 6: // G - Ignorer + break; + case 12: // M - Ignorer + break; + case 7: // H - Ignorer + break; + case 8: // I - Ignorer + break; + case 9: // J - InstantDamage + m_damage = true; + case 15: // P - Ignorer + break; + case 17: // R - Ignorer + break; + case 19: // T - Ignorer + break; + case 24: // Y - Ignorer + break; + case 27: // 1 + break; + case 28: // 2 + break; + case 255: // Fn - Ignorer + break; + default: + std::cout << "Unhandled key: " << (int)key << std::endl; + } +} + +void Engine::KeyReleaseEvent(unsigned char key) { + switch (key) { + case 0: // A - Stop gauche + m_keyA = false; + break; + case 2: // C - Toggle crosshair + m_displayCrosshair = !m_displayCrosshair; + break; + case 3: // D - Stop droite + m_keyD = false; + break; + case 5: // F - Toggle flash + m_flash = !m_flash; + break; + case 6: // G - Toggle Stop Countdown + m_stopcountdown = !m_stopcountdown; + std::cout << "STOP COUNTDOWN " << (m_stopcountdown ? "enabled" : "disabled") << std::endl; + break; + case 7: // H - Toggle HUD + m_displayHud = !m_displayHud; + std::cout << "DISPLAY HUD " << (m_displayHud ? "enabled" : "disabled") << std::endl; + break; + case 8: // I - Toggle render data + m_displayInfo = !m_displayInfo; + std::cout << "DISPLAY INFO " << (m_displayInfo ? "enabled" : "disabled") << std::endl; + break; + case 10: // K + m_keyK = false; + break; + case 11: // L - Debugging DisplayNotification() + m_keyL = false; + break; + case 12: // M - Toggle music + m_audio.ToggleMusicState(); + break; + case 15: + for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow"). + if (!m_bullets[x]) { + m_bullets[x] = new Bullet(m_player.GetPOV() - Vector3f(1.f, 0.f, 1.f), Vector3f(1.f, 0.f, 1.f)); + break; + } + else if (x == MAX_BULLETS - 1) { // S'il y a pas d'espace dans l'array, prendre la place de la premi�re balle de l'array. + m_bullets[0]->~Bullet(); + m_bullets[0] = new Bullet(m_player.GetPOV() - Vector3f(1.f, 0.f, 1.f), Vector3f(1.f, 0.f, 1.f)); + } + break; + case 17: // R - Toggle skybox + m_isSkybox = !m_isSkybox; + break; + case 18: // S - Stop reculer + m_keyS = false; + break; + case 19: // T -Reset countdown + m_resetcountdown = true; + std::cout << "RESET COUNTDOWN" << std::endl; + break; + case 22: // W - Stop avancer + m_keyW = false; + break; + case 24: // Y - Wireframe + m_wireframe = !m_wireframe; + if (m_wireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + else + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + break; + case 27: // 1 + m_key1 = true; + break; + case 28: // 2 + m_key2 = true; + break; + case 57: // Espace - Stop sauter + m_keySpace = false; + break; + } +} + +void Engine::MouseMoveEvent(int x, int y) { + if (m_gamestate == GameState::PLAY) { + m_player.TurnLeftRight(x - (Width() / 2)); + m_player.TurnTopBottom(y - (Height() / 2)); + + // Centrer la souris seulement si elle n'est pas d�j� centr�e + // Il est n�cessaire de faire la v�rification pour �viter de tomber + // dans une boucle infinie o� l'appel � CenterMouse g�n�re un + // MouseMoveEvent, qui rapelle CenterMouse qui rapelle un autre + // MouseMoveEvent, etc + if (x == (Width() / 2) && y == (Height() / 2)) + return; + } + else if (m_gamestate == GameState::MAIN_MENU) { + DisplayMainMenu(); + } + else if (m_gamestate == GameState::OPTIONS) { + float centerX = Width() * 0.5f; + float centerY = Height() * 0.5f; + float leftBar = centerX - Width() * 0.15f; + float rightBar = centerX + Width() * 0.3f; + + if (m_selectedOption == 0 && m_selectedOptAudioMainBar) { + m_volPrincipal = x - leftBar; + } + else if (m_selectedOption == 0 && m_selectedOptAudioMusicBar) { + m_volMusique = x - leftBar; + } + else if (m_selectedOption == 0 && m_selectedOptAudioSfxBar) { + m_volEffets = x - leftBar; + } + else if (m_selectedOption == 2 && m_selectedGameplaySensitivityBar) { + m_volSensible = x - leftBar; + } + } +} + +void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y) { + m_mousemx = x; + m_mousemy = y; + float centerX = Width() * 0.5f; + float centerY = Height() * 0.5f; + + if (m_gamestate == GameState::PLAY) { + switch (button) { + case MOUSE_BUTTON_LEFT: + m_mouseL = true; + break; + case MOUSE_BUTTON_RIGHT: + m_mouseR = true; + break; + case MOUSE_BUTTON_MIDDLE: + m_mouseC = true; + break; + case MOUSE_BUTTON_WHEEL_UP: + m_mouseWU = true; + break; + case MOUSE_BUTTON_WHEEL_DOWN: + m_mouseWD = true; + break; + case MOUSE_BUTTON_NONE: break; + } + } + else if (m_gamestate == GameState::MAIN_MENU) { + + float leftButton = centerX + Width() * 0.045f; + float rightButton = centerX + Width() * 0.4455f; + + float topFirst = centerY + Height() * 0.073f; + float bottomFirst = centerY; + + float topSecond = centerY + Height() * 0.177f; + float bottomSecond = centerY + Height() * 0.105f; + + float topThird = centerY + Height() * 0.275f; + float bottomThird = centerY + Height() * 0.198f; + + if (x > leftButton && x < rightButton && y > bottomFirst && y < topFirst) { + if (m_selectedPlayOptions) { + m_gamestate = GameState::PLAY; + } + else { + m_selectedPlayOptions = true; + } + } + else if (x > leftButton && x < rightButton && y > bottomSecond && y < topSecond) { + if (m_selectedPlayOptions) { + m_gamestate = GameState::LOBBY; + StartMultiplayerGame(); + } + else { + m_gamestate = GameState::OPTIONS; + } + } + else if (x > leftButton && x < rightButton && y > bottomThird && y < topThird) { + if (m_selectedPlayOptions) { + m_selectedPlayOptions = false; + } + else { + m_gamestate = GameState::QUIT; + } + } + } + else if (m_gamestate == GameState::OPTIONS) { + float leftAudio = centerX - Width() * 0.35f; + float rightAudio = centerX - Width() * 0.2f; + float topAudio = (Height() * 0.25f) + ((Height() * 0.25f) - (Height() * 0.2f)); + float bottomAudio = (Height() * 0.2f) + ((Height() * 0.25f) - (Height() * 0.2f)); + + float leftGraph = centerX - Width() * 0.4f; + float rightGraph = centerX - Width() * 0.2f; + float topGraph = centerY - Height() * 0.05f; + float bottomGraph = centerY - Height() * 0.1f; + + float leftGameplay = centerX - Width() * 0.375f; + float rightGameplay = centerX - Width() * 0.2f; + float topGameplay = centerY + Height() * 0.1f; + float bottomGameplay = centerY + Height() * 0.05f; + + float leftBack = centerX - Width() * 0.075f; + float rightBack = centerX + Width() * 0.075f; + float topBack = centerY + Height() * 0.25f; + float bottomBack = centerY + Height() * 0.2f; + + if (x > leftAudio && x < rightAudio && y > bottomAudio && y < topAudio) { + m_selectedOption = 0; // Volume + } + else if (x > leftGraph && x < rightGraph && y > bottomGraph && y < topGraph) { + m_selectedOption = 1; // Graphics + } + else if (x > leftGameplay && x < rightGameplay && y > bottomGameplay && y < topGameplay) { + m_selectedOption = 2; // Gameplay + } + else if (x > leftBack && x < rightBack && y > bottomBack && y < topBack) { + m_gamestate = GameState::MAIN_MENU; + } + + // Audio + float leftBar = centerX - Width() * 0.15f; + float rightBar = centerX + Width() * 0.3f; + + float topBarPrincipal = centerY - Height() * 0.165f; + float bottomBarPrincipal = centerY - Height() * 0.2f; + + float topBarMusique = centerY - Height() * 0.0415f; + float bottomBarMusique = centerY - Height() * 0.075f; + + float topBarEffets = centerY + Height() * 0.085f; + float bottomBarEffets = centerY + Height() * 0.05f; + + if (m_selectedOption == 0 && x > leftBar && x < rightBar && y > bottomBarPrincipal && y < topBarPrincipal) { + m_volPrincipal = x - leftBar; + m_selectedOptAudioMainBar = true; + } + else if (m_selectedOption == 0 && x > leftBar && x < rightBar && y > bottomBarMusique && y < topBarMusique) { + m_volMusique = x - leftBar; + m_selectedOptAudioMusicBar = true; + } + else if (m_selectedOption == 0 && x > leftBar && x < rightBar && y > bottomBarEffets && y < topBarEffets) { + m_volEffets = x - leftBar; + m_selectedOptAudioSfxBar = true; + } + + // Resolution + float leftChk = centerX + Width() * 0.075f; + float rightChk = centerX + Width() * 0.09f; + + float topChkHD = centerY - Height() * 0.125f; + float bottomChkHD = centerY - Height() * 0.155f; + + float topChkFHD = centerY - Height() * 0.0725f; + float bottomChkFHD = centerY - Height() * 0.1f; + + float topChkQHD = centerY - Height() * 0.025f; + float bottomChkQHD = centerY - Height() * 0.05f; + + float topChkUHD = centerY + Height() * 0.025f; + float bottomChkUHD = centerY; + + if (m_selectedOption == 1 && leftChk && x < rightChk && y > bottomChkHD && y < topChkHD) { + m_resolution = HD; + } + else if (m_selectedOption == 1 && x > leftChk && x < rightChk && y > bottomChkFHD && y < topChkFHD) { + m_resolution = FHD; + } + else if (m_selectedOption == 1 && x > leftChk && x < rightChk && y > bottomChkQHD && y < topChkQHD) { + m_resolution = QHD; + } + else if (m_selectedOption == 1 && x > leftChk && x < rightChk && y > bottomChkUHD && y < topChkUHD) { + m_resolution = UHD; + } + + // Gameplay + if (m_selectedOption == 2 && x > leftBar && x < rightBar && y > bottomBarPrincipal && y < topBarPrincipal) { + m_volSensible = x - leftBar; + m_selectedGameplaySensitivityBar = true; + } + } +} + +void Engine::MouseReleaseEvent(const MOUSE_BUTTON& button, int x, int y) { + switch (button) { + case MOUSE_BUTTON_LEFT: + m_mouseL = false; + m_block = false; + m_selectedOptAudioMainBar = false; + m_selectedOptAudioMusicBar = false; + m_selectedOptAudioSfxBar = false; + m_selectedGameplaySensitivityBar = false; + break; + case MOUSE_BUTTON_RIGHT: + m_mouseR = false; + m_block = false; + break; + case MOUSE_BUTTON_MIDDLE: + m_mouseC = false; + break; + case MOUSE_BUTTON_WHEEL_UP: + m_mouseWU = false; + break; + case MOUSE_BUTTON_WHEEL_DOWN: + m_mouseWD = false; + break; + case MOUSE_BUTTON_NONE: break; + } +} + +bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps, bool stopOnError) { + texture.Load(filename, useMipmaps); + if (!texture.IsValid()) { + std::cerr << "Unable to load texture (" << filename << ")" << std::endl; + if (stopOnError) + Stop(); + + return false; + } + + return true; +} + +