137 lines
5.1 KiB
C++
137 lines
5.1 KiB
C++
#ifndef RAIN_HPP
|
|
#define RAIN_HPP
|
|
|
|
#include <vector>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
#include <cmath>
|
|
#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<RainDrop> 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<float>(rand()) / (static_cast<float>(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 |