Mój pierwszy efekt
W tym poradniku nauczysz się tworzyć efekty cząsteczkowe (Particle Effects, PFX) — od prostego dymu, przez ogień, po deszcz i śnieg.
Jak działają efekty cząsteczkowe?
System PFX w Gothic emituje cząsteczki (małe sprite'y z teksturą) z emitera o określonym kształcie. Każda cząsteczka ma swój kierunek, prędkość, czas życia i wygląd.
Efekty definiowane są jako instancje klasy C_ParticleFX w plikach w katalogu System/PFX/:
| Plik | Opis |
|---|---|
PfxInst.d | Efekty ogólne (ogień, dym, iskry, woda, pogoda) |
PfxInstEngine.d | Efekty wymagane przez silnik (krew, kurz, plusk wody) |
PfxInstMagic.d | Efekty magiczne (zaklęcia, runy, aury) |
Klasa C_ParticleFX — przegląd
Klasa ma 49 pól podzielonych na 7 kategorii. Nie musisz ustawiać wszystkich — pola, których nie ustawisz, przyjmą wartości domyślne (zazwyczaj 0 lub pusty string).
1. Emisja — ile cząsteczek i kiedy
| Pole | Typ | Opis |
|---|---|---|
ppsValue | float | Bazowa liczba cząsteczek na sekundę |
ppsScaleKeys_S | string | Mnożniki rozłożone w czasie, np. "1 2 3" |
ppsIsLooping | int | 1 = zapętlone, 0 = jednorazowe |
ppsIsSmooth | int | 1 = płynna interpolacja między kluczami |
ppsFPS | float | Prędkość odtwarzania kluczy (klatki/s) |
ppsCreateEm_S | string | Nazwa efektu potomnego (spawny per cząsteczka) |
ppsCreateEmDelay | float | Opóźnienie efektu potomnego |
2. Kształt emitera — skąd lecą cząsteczki
| Pole | Typ | Opis |
|---|---|---|
shpType_S | string | Kształt: "POINT", "LINE", "BOX", "CIRCLE", "SPHERE", "MESH" |
shpFOR_S | string | Układ odniesienia: "OBJECT" lub "WORLD" |
shpOffsetVec_S | string | Przesunięcie: "X Y Z" |
shpDistribType_S | string | Rozkład: "RAND", "UNIFORM", "WALK", "DIR" |
shpIsVolume | int | 1 = emisja z objętości, 0 = z powierzchni |
shpDim_S | string | Wymiary (zależne od kształtu) |
shpMesh_S | string | Mesh emitera (gdy shpType_S = "MESH") |
shpMeshRender_B | int | 1 = renderuj mesh emitera |
3. Kierunek i prędkość
| Pole | Typ | Opis |
|---|---|---|
dirMode_S | string | Tryb: "DIR", "TARGET", "MESH_POLY", "RAND", "NONE" |
dirFOR_S | string | Układ odniesienia kierunku |
dirAngleHead | float | Kąt obrotu poziomego (°) |
dirAngleHeadVar | float | Wariancja kąta (±°) |
dirAngleElev | float | Kąt elewacji (°); 90 = w górę, -90 = w dół |
dirAngleElevVar | float | Wariancja elewacji (±°) |
velAvg | float | Średnia prędkość początkowa |
velVar | float | Wariancja prędkości (±) |
4. Czas życia cząsteczek
| Pole | Typ | Opis |
|---|---|---|
lspPartAvg | float | Średni czas życia (ms) |
lspPartVar | float | Wariancja czasu życia (±ms) |
5. Zachowanie w locie
| Pole | Typ | Opis |
|---|---|---|
flyGravity_S | string | Wektor grawitacji: "X Y Z" |
flyCollDet_B | int | 0 = brak kolizji, 1 = kolizje, 3 = kolizje + ślady |
6. Wizualizacja
| Pole | Typ | Opis |
|---|---|---|
visName_S | string | Tekstura (.TGA) lub model (.3DS) |
visOrientation_S | string | Billboard: "NONE", "VELO", "VELO3D", "VOB" |
visTexIsQuadPoly | int | 0 = trójkąt, 1 = kwadrat |
visTexAniFPS | float | FPS animacji tekstury |
visTexAniIsLooping | int | 0 = raz, 1 = pętla, 2 = ping-pong |
visTexColorStart_S | string | Kolor początkowy: "R G B" (0–255) |
visTexColorEnd_S | string | Kolor końcowy (interpolacja w czasie życia) |
visSizeStart_S | string | Rozmiar początkowy: "W H" |
visSizeEndScale | float | Mnożnik rozmiaru końcowego |
visAlphaFunc_S | string | Blending: "BLEND", "ADD", "MUL" |
visAlphaStart | float | Przezroczystość początkowa (0–255) |
visAlphaEnd | float | Przezroczystość końcowa (0–255) |
7. Efekty dodatkowe
| Pole | Typ | Opis |
|---|---|---|
trlFadeSpeed | float | Prędkość zanikania śladu (trail) |
trlTexture_S | string | Tekstura śladu |
trlWidth | float | Szerokość śladu |
mrkFadeSpeed | float | Prędkość zanikania odcisku (mark) |
mrkTexture_S | string | Tekstura odcisku |
mrkSize | float | Rozmiar odcisku |
flockMode | string | Tryb stadny: "WIND" |
flockStrength | float | Siła efektu stadnego |
useEmittersFOR | int | 1 = cząsteczki podążają za emiterem |
timeStartEnd_S | string | Okno czasowe renderowania: "8 22" (8:00–22:00) |
m_bIsAmbientPFX | int | 1 = efekt ambientowy (można wyłączyć w gothic.ini) |
Przykład 1: Prosty dym
Zacznijmy od czegoś prostego — słup dymu unoszący się w górę:
instance PFX_MojDym (C_ParticleFX)
{
// --- Emisja: 30 cząsteczek/s, ciągłe ---
ppsValue = 30;
ppsScaleKeys_S = "1";
ppsIsLooping = 1;
// --- Kształt: punkt ---
shpType_S = "POINT";
shpFOR_S = "OBJECT";
// --- Kierunek: w górę z losowym odchyleniem ---
dirMode_S = "DIR";
dirFOR_S = "OBJECT";
dirAngleElev = 90; // w górę
dirAngleElevVar = 15; // ±15° odchylenia
dirAngleHeadVar = 180; // rozrzut na boki
velAvg = 0.02; // powolny
velVar = 0.01;
// --- Czas życia: 2–3 sekundy ---
lspPartAvg = 2500;
lspPartVar = 500;
// --- Brak grawitacji (dym unosi się) ---
flyGravity_S = "0 0.0001 0"; // lekko w górę
// --- Wygląd ---
visName_S = "SMOKE1.TGA";
visOrientation_S = "NONE"; // billboard skierowany do kamery
visTexColorStart_S = "150 150 150"; // szary
visTexColorEnd_S = "80 80 80"; // ciemniejszy z czasem
visSizeStart_S = "10 10";
visSizeEndScale = 5; // rośnie 5x
visAlphaFunc_S = "BLEND"; // zwykłe przenikanie
visAlphaStart = 180;
visAlphaEnd = 0; // zanika
};
visAlphaFunc_S — tryby blendingu:
"BLEND"— klasyczne przenikanie (dym, mgła, kurz)"ADD"— addytywne (ogień, iskry, magia — jasne, świecące)"MUL"— multiplikatywne (cienie, przyciemnianie)
Przykład 2: Ognisko
Ogień to połączenie szybkiej emisji, addytywnego blendingu i animowanej tekstury:
instance PFX_MojOgien (C_ParticleFX)
{
// --- Emisja: dużo cząsteczek, ciągłe ---
ppsValue = 80;
ppsScaleKeys_S = "1";
ppsIsLooping = 1;
// --- Kształt: koło (baza ogniska) ---
shpType_S = "CIRCLE";
shpFOR_S = "OBJECT";
shpIsVolume = 1;
shpDim_S = "15"; // promień 15 jednostek
// --- Kierunek: w górę ---
dirMode_S = "DIR";
dirFOR_S = "OBJECT";
dirAngleElev = 90;
dirAngleElevVar = 20;
dirAngleHeadVar = 180;
velAvg = 0.05;
velVar = 0.02;
// --- Czas życia: krótki (szybki ogień) ---
lspPartAvg = 800;
lspPartVar = 200;
// --- Lekka grawitacja w górę (gorące powietrze) ---
flyGravity_S = "0 0.0003 0";
// --- Wygląd ---
visName_S = "FIREFLARE.TGA";
visOrientation_S = "NONE";
visTexAniFPS = 8; // animacja tekstury
visTexAniIsLooping = 1; // zapętlona
visTexColorStart_S = "255 255 255"; // biały (prześwietlony środek)
visTexColorEnd_S = "255 100 30"; // pomarańczowy (krawędzie)
visSizeStart_S = "5 5";
visSizeEndScale = 4; // rośnie
visAlphaFunc_S = "ADD"; // addytywne = świecące
visAlphaStart = 255;
visAlphaEnd = 0;
};
Przykład 3: Iskry
Iskry to małe, szybkie cząsteczki z grawitacją i kolizjami:
instance PFX_MojeIskry (C_ParticleFX)
{
// --- Emisja: jednorazowy wybuch ---
ppsValue = 50;
ppsScaleKeys_S = "1 0"; // natychmiast, potem nic
ppsIsLooping = 0; // jednorazowe
ppsFPS = 2;
// --- Kształt: punkt ---
shpType_S = "POINT";
shpFOR_S = "OBJECT";
// --- Kierunek: rozbiegają się we wszystkie strony ---
dirMode_S = "DIR";
dirFOR_S = "OBJECT";
dirAngleHeadVar = 180; // pełne 360°
dirAngleElev = 45; // lekko w górę
dirAngleElevVar = 45; // ale z dużym rozrzutem
velAvg = 0.15; // szybkie
velVar = 0.08;
// --- Czas życia: krótki ---
lspPartAvg = 600;
lspPartVar = 300;
// --- Grawitacja ciągnie w dół ---
flyGravity_S = "0 -0.0005 0";
flyCollDet_B = 1; // kolizje ze światem
// --- Wygląd: małe, jaskrawe punkty ---
visName_S = "ZFLARE1.TGA";
visOrientation_S = "NONE";
visTexColorStart_S = "255 220 100"; // żółty
visTexColorEnd_S = "255 80 20"; // ciemny pomarańcz
visSizeStart_S = "2 2";
visSizeEndScale = 0.5; // zmniejszają się
visAlphaFunc_S = "ADD";
visAlphaStart = 255;
visAlphaEnd = 0;
};
Przykład 4: Śnieg
Śnieg to duży emiter na dużej wysokości, wolno opadające cząsteczki:
instance PFX_MojSnieg (C_ParticleFX)
{
// --- Emisja: ciągła ---
ppsValue = 50;
ppsScaleKeys_S = "1";
ppsIsLooping = 1;
// --- Kształt: duży okrąg wysoko nad graczem ---
shpType_S = "CIRCLE";
shpFOR_S = "OBJECT";
shpOffsetVec_S = "0 500 0"; // 500 jednostek nad emiterem
shpIsVolume = 1;
shpDim_S = "300"; // promień 300
// --- Kierunek: w dół ---
dirMode_S = "DIR";
dirFOR_S = "OBJECT";
dirAngleHead = 20; // lekki wiatr
dirAngleHeadVar = 10;
dirAngleElev = -89; // prawie prosto w dół
velAvg = 0.05;
velVar = 0.02;
// --- Czas życia: długi ---
lspPartAvg = 5000;
// --- Brak grawitacji (stała prędkość opadania) ---
flyGravity_S = "0 0 0";
// --- Wygląd: białe płatki ---
visName_S = "MFX_SLEEP_STAR.TGA";
visOrientation_S = "NONE";
visTexColorStart_S = "255 255 255";
visTexColorEnd_S = "255 255 255";
visSizeStart_S = "5 5";
visSizeEndScale = 1;
visAlphaFunc_S = "ADD";
visAlphaStart = 255;
visAlphaEnd = 255;
// --- Efekt ambientowy (gracz może wyłączyć w opcjach) ---
m_bIsAmbientPFX = 1;
};
Przykład 5: Krew (efekt potomny)
System potomnych emiterów pozwala tworzyć złożone efekty. Krew w Gothic składa się z dwóch instancji — głównej (bryzy krwi) i potomnej (plamy na podłożu):
// Główny efekt: bryzy krwi rozlatujące się
instance PFX_MojaKrew (C_ParticleFX)
{
ppsValue = 64;
ppsCreateEm_S = "PFX_MojaKrew_Plama"; // potomny efekt!
dirMode_S = "DIR";
dirFOR_S = "OBJECT";
dirAngleHeadVar = 30;
dirAngleElevVar = 30;
velAvg = 0.1;
velVar = 0.05;
lspPartAvg = 750;
lspPartVar = 550;
flyGravity_S = "0 -0.0001 0"; // spada
flyCollDet_B = 1;
visName_S = "BLOOD1.TGA";
visTexColorStart_S = "255 255 255";
visTexColorEnd_S = "255 255 255";
visSizeStart_S = "6 6";
visSizeEndScale = 1;
visAlphaFunc_S = "BLEND";
visAlphaStart = 255;
};
// Efekt potomny: plama na podłożu
instance PFX_MojaKrew_Plama (C_ParticleFX)
{
ppsValue = 1;
ppsIsLooping = 0; // jedna plama
shpType_S = "POINT";
dirMode_S = "NONE"; // bez ruchu
velAvg = 0;
lspPartAvg = 3000; // 3 sekundy
visName_S = "YOURBLOODSPLAT.TGA";
visSizeStart_S = "10 10";
visSizeEndScale = 1;
visAlphaFunc_S = "BLEND";
visAlphaStart = 200;
visAlphaEnd = 0; // zanika
};
ppsCreateEm_S — każda cząsteczka z głównego emitera staje się źródłem nowego efektu potomnego. To potężne narzędzie, ale kosztowne — używaj ostrożnie, by nie obciążyć silnika.
Kształty emiterów
| Kształt | shpType_S | shpDim_S | Opis |
|---|---|---|---|
| Punkt | "POINT" | — | Emisja z jednego punktu |
| Linia | "LINE" | "100" (długość) | Emisja wzdłuż linii |
| Prostopadłościan | "BOX" | "W H D" | Emisja z prostokątnego obszaru |
| Okrąg | "CIRCLE" | "50" (promień) | Emisja z koła (lub dysku gdy shpIsVolume = 1) |
| Sfera | "SPHERE" | "50" (promień) | Emisja z kuli |
| Mesh | "MESH" | "250" (skala) | Emisja z powierzchni mesha 3D |
shpIsVolume
shpIsVolume = 0— cząsteczki pojawiają się na krawędzi kształtu (np. na obwodzie koła)shpIsVolume = 1— cząsteczki pojawiają się wewnątrz kształtu (np. w całym kole)
Orientacja cząsteczek
| Tryb | visOrientation_S | Opis |
|---|---|---|
| Billboard | "NONE" | Cząsteczki zawsze zwrócone do kamery (domyślne) |
| Wzdłuż prędkości | "VELO" | Cząsteczki rozciągnięte w kierunku ruchu (deszcz, iskry) |
| 3D wzdłuż prędkości | "VELO3D" | Jak VELO, ale z pełną rotacją 3D |
| Obiekt | "VOB" | Orientacja zgodna z obiektem nadrzędnym |
Rejestracja w ParticleFX.src
Efekty cząsteczkowe mają oddzielną kompilację od skryptów gry. Dodaj swój plik do System/ParticleFX.src:
_intern\ParticleFx.d
Pfx\PfxInstEngine.d
Pfx\PfxInst.d
Pfx\PfxInstMagic.d
Pfx\MojePfx.d
Efekty PFX nie są kompilowane przez Gothic.src — używają własnego pliku ParticleFX.src w katalogu System/.
Porady praktyczne
Wydajność
- Im wyższe
ppsValue, tym więcej cząsteczek = więcej obliczeń flyCollDet_Bz dużą ilością cząsteczek mocno obciąża CPUuseEmittersFOR = 1wraz zflyCollDet_Bto najkosztowniejsza kombinacjappsCreateEm_Smnoży liczbę efektów — każda cząsteczka tworzy nowy emiter
Debugowanie
- Jeśli efekt nie jest widoczny, sprawdź czy
visAlphaStart> 0 ivisSizeStart_Snie jest za małe - Sprawdź, czy tekstura (
.TGA) istnieje w kataloguTextures/ - Efekty z
m_bIsAmbientPFX = 1mogą być wyłączone w opcjach gry
Częste wzorce
| Efekt | Kluczowe ustawienia |
|---|---|
| Dym | BLEND, duży visSizeEndScale, visAlphaEnd = 0 |
| Ogień | ADD, animowana tekstura, krótki lspPartAvg |
| Iskry | ADD, jednorazowy burst, grawitacja w dół, kolizje |
| Deszcz/śnieg | Duży emiter CIRCLE, offset w Y, dirAngleElev = -89 |
| Krew | BLEND, grawitacja, efekt potomny (plamy) |
| Magia/aura | ADD, CIRCLE emiter, useEmittersFOR = 1 |
Podsumowanie
Tworzenie efektów cząsteczkowych wymaga:
- Instancji klasy
C_ParticleFXz odpowiednimi parametrami - Kształtu emitera (
shpType_S) — skąd lecą cząsteczki - Kierunku i prędkości — jak się poruszają
- Wizualizacji — tekstura, kolor, rozmiar, przenikanie
- Rejestracji w
ParticleFX.src(nie wGothic.src!)