diff --git a/DayNightCycle.hpp b/DayNightCycle.hpp new file mode 100644 index 0000000..ef6c6c8 --- /dev/null +++ b/DayNightCycle.hpp @@ -0,0 +1,96 @@ +#ifndef DAYNIGHTCYCLE_HPP +#define DAYNIGHTCYCLE_HPP + +#include "GL/glew.h" +#include + +class DayNightCycle { +private: + bool isNight; + +public: + // Konstruktor - domyślnie startujemy w dzień + DayNightCycle() : isNight(false) {} + + // Funkcja przełączająca stan + void toggle() { + isNight = !isNight; + if (isNight) { + std::cout << "Tryb: NOC" << std::endl; + } + else { + std::cout << "Tryb: DZIEN" << std::endl; + } + } + + // Zwraca informację czy jest noc (przydatne np. do włączania świateł łazika) + bool isNightMode() const { + return isNight; + } + + // Główna funkcja ustawiająca światła i tło + void apply() { + if (isNight) { + // === USTAWIENIA NOCNE === + + // Kolor nieba (Tło) - Ciemny granat/czarny + glClearColor(0.05f, 0.05f, 0.1f, 1.0f); + + // GL_LIGHT0 (Księżyc) - Zimne, słabe światło + GLfloat nightAmbient[] = { 0.1f, 0.1f, 0.2f, 1.0f }; + GLfloat nightDiffuse[] = { 0.2f, 0.2f, 0.35f, 1.0f }; // Niebieskawy odcień + GLfloat nightSpecular[] = { 0.1f, 0.1f, 0.1f, 1.0f }; // Bardzo słaby połysk + + glLightfv(GL_LIGHT0, GL_AMBIENT, nightAmbient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, nightDiffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, nightSpecular); + + // GL_LIGHT1 (Doświetlenie cieni) - Prawie wyłączone w nocy + GLfloat fillAmbient[] = { 0.02f, 0.02f, 0.05f, 1.0f }; + GLfloat fillDiffuse[] = { 0.05f, 0.05f, 0.1f, 1.0f }; + + glLightfv(GL_LIGHT1, GL_AMBIENT, fillAmbient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, fillDiffuse); + + // Opcjonalnie: Włączamy gęstą czarną mgłę dla klimatu + glEnable(GL_FOG); + GLfloat fogColor[] = { 0.05f, 0.05f, 0.1f, 1.0f }; + glFogfv(GL_FOG_COLOR, fogColor); + glFogi(GL_FOG_MODE, GL_EXP2); + glFogf(GL_FOG_DENSITY, 0.002f); // Gęstość mgły + + } + else { + // === USTAWIENIA DZIENNE === + + // Kolor nieba (Tło) - Jasny błękit + glClearColor(0.53f, 0.81f, 0.92f, 1.0f); + + // GL_LIGHT0 (Słońce) - Ciepłe, jasne światło + GLfloat dayAmbient[] = { 0.4f, 0.4f, 0.4f, 1.0f }; + GLfloat dayDiffuse[] = { 0.9f, 0.9f, 0.8f, 1.0f }; // Lekko żółtawe + GLfloat daySpecular[] = { 0.5f, 0.5f, 0.5f, 1.0f }; + + glLightfv(GL_LIGHT0, GL_AMBIENT, dayAmbient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dayDiffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, daySpecular); + + // GL_LIGHT1 (Doświetlenie cieni) + GLfloat fillAmbient[] = { 0.4f, 0.4f, 0.4f, 1.0f }; + GLfloat fillDiffuse[] = { 0.3f, 0.3f, 0.4f, 1.0f }; // Niebieskawe cienie + + glLightfv(GL_LIGHT1, GL_AMBIENT, fillAmbient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, fillDiffuse); + + // Wyłączamy mgłę w dzień (lub ustawiamy bardzo rzadką) + glDisable(GL_FOG); + } + + // Pozycję światła ustawiamy taką samą dla obu (wysoko w górze) + // W przyszłości możesz tu zrobić animację przesuwania się słońca + GLfloat lightPos[] = { 100.0f, 150.0f, 100.0f, 0.0f }; // 0.0f na końcu = światło kierunkowe + glLightfv(GL_LIGHT0, GL_POSITION, lightPos); + } +}; + +#endif \ No newline at end of file diff --git a/grafikaKBT.vcxproj b/grafikaKBT.vcxproj index 86452c6..b2fc3d5 100644 --- a/grafikaKBT.vcxproj +++ b/grafikaKBT.vcxproj @@ -135,11 +135,13 @@ + + diff --git a/grafikaKBT.vcxproj.filters b/grafikaKBT.vcxproj.filters index 13cb0f2..962d18c 100644 --- a/grafikaKBT.vcxproj.filters +++ b/grafikaKBT.vcxproj.filters @@ -83,6 +83,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/main.cpp b/main.cpp index be3ed50..c22932d 100644 --- a/main.cpp +++ b/main.cpp @@ -39,7 +39,8 @@ #include "fabula.hpp" #include "GL/wglew.h" #include "Logger.hpp" - +#include "rain.hpp" +#include "DayNightCycle.hpp" using namespace glm; @@ -470,6 +471,10 @@ void SetDCPixelFormat(HDC hDC) { lazik user(10.0f, 0.0f, 0.0f, "res/models/lazik4.obj"); // obiekty eksportujemy z Forward Axis Z, Up Axis Y. plane mapa( 0.0f, 0.0f, 0.0f, "res/models/mapka3_nofence_noplatform.obj"); + +RainSystem rainSystem(2000, 250.0f, 200.0f); +DayNightCycle dayNight; + static void SetupRC() { // 1. Podstawowe ustawienia OpenGL glEnable(GL_DEPTH_TEST); // Usuwanie niewidocznych powierzchni @@ -581,6 +586,8 @@ void static RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + dayNight.apply(); + // ========================================== // 1. OBSŁUGA KAMERY // ========================================== @@ -697,6 +704,14 @@ void static RenderScene(void) { plot(450.0f, 3.0f, 10 * 90.0f, 900.0f, 4.0f, 1); plot(10 * 90.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0); + // --- DESZCZ: Logika i Rysowanie --- + // Aktualizujemy pozycję deszczu przekazując deltaTime oraz pozycję gracza (Foward, Sides) + // Dzięki temu deszcz "chodzi" za nami. + rainSystem.update(deltaTime, Foward, Sides); + + // Rysujemy deszcz + rainSystem.draw(); + glFlush(); } @@ -1062,6 +1077,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case 112: // F1 - Widok z pierwszej osoby (FPV) fpv_view = !fpv_view; if (fpv_view) panoramic_view = false; // Wyłącz panoramę, jeśli włączasz FPV + case 'N': // Klawisz N przełącza dzień/noc + dayNight.toggle(); break; // Obsługa innych klawiszy diff --git a/rain.hpp b/rain.hpp new file mode 100644 index 0000000..9d39496 --- /dev/null +++ b/rain.hpp @@ -0,0 +1,137 @@ +#ifndef RAIN_HPP +#define RAIN_HPP + +#include +#include +#include +#include +#include "GL/glew.h" + +// Struktura pojedynczej kropli +struct RainDrop { + float x, y, z; // Pozycja + float speed; // Prędkość spadania + bool isSplash; // Czy to jest moment rozbicia? + float splashTime; // Czas trwania animacji rozbicia + float life; // Do losowania długości życia kropli +}; + +class RainSystem { +private: + std::vector drops; + int maxDrops; + float range; // Promień wokół gracza, gdzie pada deszcz + float skyHeight; // Wysokość, z której spada deszcz + + // Funkcja pomocnicza do losowania liczb float + float randomFloat(float min, float max) { + return min + static_cast(rand()) / (static_cast(RAND_MAX / (max - min))); + } + +public: + RainSystem(int count = 2000, float rangeRadius = 300.0f, float height = 200.0f) { + maxDrops = count; + range = rangeRadius; + skyHeight = height; + + // Inicjalizacja kropel + for (int i = 0; i < maxDrops; i++) { + RainDrop drop; + drop.isSplash = false; + drop.splashTime = 0.0f; + drop.speed = randomFloat(200.0f, 300.0f); // Szybkość deszczu + + // Losowa pozycja początkowa + drop.x = randomFloat(-range, range); + drop.y = randomFloat(0.0f, skyHeight * 2.0f); // Rozrzucamy je w pionie na start + drop.z = randomFloat(-range, range); + + drops.push_back(drop); + } + } + + // Aktualizacja fizyki deszczu + void update(float deltaTime, float playerX, float playerZ) { + for (auto& drop : drops) { + if (drop.isSplash) { + // Obsługa animacji rozbicia + drop.splashTime -= deltaTime; + if (drop.splashTime <= 0.0f) { + // Koniec rozbicia, reset kropli do nieba + drop.isSplash = false; + drop.y = skyHeight + randomFloat(0.0f, 50.0f); + + // Reset pozycji względem gracza (deszcz podąża za łazikiem) + drop.x = playerX + randomFloat(-range, range); + drop.z = playerZ + randomFloat(-range, range); + drop.speed = randomFloat(200.0f, 300.0f); + } + } + else { + // Spadanie + drop.y -= drop.speed * deltaTime; + + // Sprawdzenie kolizji z podłogą (y <= 0) + if (drop.y <= 0.0f) { + drop.y = 0.1f; // Lekko nad ziemią + drop.isSplash = true; + drop.splashTime = 0.2f; // Czas trwania "plusku" (0.2 sekundy) + } + + // Jeśli gracz uciekł zbyt daleko od kropli, przenieś ją bliżej gracza + // (Optymalizacja: nie liczymy deszczu tam, gdzie nas nie ma) + if (std::abs(drop.x - playerX) > range) drop.x = playerX + randomFloat(-range, range); + if (std::abs(drop.z - playerZ) > range) drop.z = playerZ + randomFloat(-range, range); + } + } + } + + // Rysowanie deszczu + void draw() { + // Zapisujemy aktualny stan OpenGL + glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_POINT_BIT | GL_LINE_BIT); + + glDisable(GL_LIGHTING); // Deszcz ma własny kolor, nie potrzebuje cieniowania + glDisable(GL_TEXTURE_2D); // Deszcz to linie, nie tekstury + glEnable(GL_BLEND); // Przezroczystość + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); // Deszcz nie powinien zasłaniać obiektów w buforze głębokości (opcjonalne) + + glLineWidth(1.0f); + + glBegin(GL_LINES); + glColor4f(0.7f, 0.8f, 1.0f, 0.6f); // Jasnoniebieski, lekko przezroczysty + + for (const auto& drop : drops) { + if (!drop.isSplash) { + // Rysuj spadającą linię (długość zależna od prędkości dla efektu rozmycia) + glVertex3f(drop.x, drop.y, drop.z); + glVertex3f(drop.x, drop.y + 4.0f, drop.z); + } + } + glEnd(); + + // Rysowanie rozbryzgów (jako punkty) + glPointSize(3.0f); // Grubsze kropki dla rozbryzgów + glBegin(GL_POINTS); + glColor4f(0.9f, 0.9f, 1.0f, 0.8f); // Bardziej białe przy uderzeniu + + for (const auto& drop : drops) { + if (drop.isSplash) { + // Mały losowy rozrzut dla efektu rozbicia + float splashOffset = (0.2f - drop.splashTime) * 10.0f; // Rozszerza się z czasem + + // Rysujemy 3 małe kropelki odbijające się od ziemi + glVertex3f(drop.x + splashOffset, drop.y + splashOffset * 0.5f, drop.z); + glVertex3f(drop.x - splashOffset, drop.y + splashOffset * 0.5f, drop.z); + glVertex3f(drop.x, drop.y + splashOffset, drop.z + splashOffset); + } + } + glEnd(); + + glDepthMask(GL_TRUE); // Przywracamy zapis do bufora głębokości + glPopAttrib(); // Przywracamy stare ustawienia + } +}; + +#endif \ No newline at end of file