Przejdź do głównej zawartości

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/:

PlikOpis
PfxInst.dEfekty ogólne (ogień, dym, iskry, woda, pogoda)
PfxInstEngine.dEfekty wymagane przez silnik (krew, kurz, plusk wody)
PfxInstMagic.dEfekty 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

PoleTypOpis
ppsValuefloatBazowa liczba cząsteczek na sekundę
ppsScaleKeys_SstringMnożniki rozłożone w czasie, np. "1 2 3"
ppsIsLoopingint1 = zapętlone, 0 = jednorazowe
ppsIsSmoothint1 = płynna interpolacja między kluczami
ppsFPSfloatPrędkość odtwarzania kluczy (klatki/s)
ppsCreateEm_SstringNazwa efektu potomnego (spawny per cząsteczka)
ppsCreateEmDelayfloatOpóźnienie efektu potomnego

2. Kształt emitera - skąd lecą cząsteczki

PoleTypOpis
shpType_SstringKształt: "POINT", "LINE", "BOX", "CIRCLE", "SPHERE", "MESH"
shpFOR_SstringUkład odniesienia: "OBJECT" lub "WORLD"
shpOffsetVec_SstringPrzesunięcie: "X Y Z"
shpDistribType_SstringRozkład: "RAND", "UNIFORM", "WALK", "DIR"
shpIsVolumeint1 = emisja z objętości, 0 = z powierzchni
shpDim_SstringWymiary (zależne od kształtu)
shpMesh_SstringMesh emitera (gdy shpType_S = "MESH")
shpMeshRender_Bint1 = renderuj mesh emitera

3. Kierunek i prędkość

PoleTypOpis
dirMode_SstringTryb: "DIR", "TARGET", "MESH_POLY", "RAND", "NONE"
dirFOR_SstringUkład odniesienia kierunku
dirAngleHeadfloatKąt obrotu poziomego (°)
dirAngleHeadVarfloatWariancja kąta (±°)
dirAngleElevfloatKąt elewacji (°); 90 = w górę, -90 = w dół
dirAngleElevVarfloatWariancja elewacji (±°)
velAvgfloatŚrednia prędkość początkowa
velVarfloatWariancja prędkości (±)

4. Czas życia cząsteczek

PoleTypOpis
lspPartAvgfloatŚredni czas życia (ms)
lspPartVarfloatWariancja czasu życia (±ms)

5. Zachowanie w locie

PoleTypOpis
flyGravity_SstringWektor grawitacji: "X Y Z"
flyCollDet_Bint0 = brak kolizji, 1 = kolizje, 3 = kolizje + ślady

6. Wizualizacja

PoleTypOpis
visName_SstringTekstura (.TGA) lub model (.3DS)
visOrientation_SstringBillboard: "NONE", "VELO", "VELO3D", "VOB"
visTexIsQuadPolyint0 = trójkąt, 1 = kwadrat
visTexAniFPSfloatFPS animacji tekstury
visTexAniIsLoopingint0 = raz, 1 = pętla, 2 = ping-pong
visTexColorStart_SstringKolor początkowy: "R G B" (0–255)
visTexColorEnd_SstringKolor końcowy (interpolacja w czasie życia)
visSizeStart_SstringRozmiar początkowy: "W H"
visSizeEndScalefloatMnożnik rozmiaru końcowego
visAlphaFunc_SstringBlending: "BLEND", "ADD", "MUL"
visAlphaStartfloatPrzezroczystość początkowa (0–255)
visAlphaEndfloatPrzezroczystość końcowa (0–255)

7. Efekty dodatkowe

PoleTypOpis
trlFadeSpeedfloatPrędkość zanikania śladu (trail)
trlTexture_SstringTekstura śladu
trlWidthfloatSzerokość śladu
mrkFadeSpeedfloatPrędkość zanikania odcisku (mark)
mrkTexture_SstringTekstura odcisku
mrkSizefloatRozmiar odcisku
flockModestringTryb stadny: "WIND"
flockStrengthfloatSiła efektu stadnego
useEmittersFORint1 = cząsteczki podążają za emiterem
timeStartEnd_SstringOkno czasowe renderowania: "8 22" (8:00–22:00)
m_bIsAmbientPFXint1 = 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;
dirAngleElevVar = 15;
dirAngleHeadVar = 180;
velAvg = 0.02;
velVar = 0.01;

// --- Czas życia: 2–3 sekundy ---
lspPartAvg = 2500;
lspPartVar = 500;

// --- Brak grawitacji (dym unosi się) ---
flyGravity_S = "0 0.0001 0";

// --- Wygląd ---
visName_S = "SMOKE1.TGA";
visOrientation_S = "NONE";
visTexColorStart_S = "150 150 150";
visTexColorEnd_S = "80 80 80";
visSizeStart_S = "10 10";
visSizeEndScale = 5;
visAlphaFunc_S = "BLEND";
visAlphaStart = 180;
visAlphaEnd = 0;
};
PoleWartośćOpis
ppsValue3030 cząsteczek na sekundę
ppsScaleKeys_S"1"Stała emisja (bez skalowania)
ppsIsLooping1Ciągła emisja
shpType_S"POINT"Emisja z pojedynczego punktu
shpFOR_S"OBJECT"Względem obiektu emitera
dirMode_S"DIR"Emisja kierunkowa
dirFOR_S"OBJECT"Kierunek względem obiektu
dirAngleElev90Kierunek w górę
dirAngleElevVar15±15° losowe odchylenie
dirAngleHeadVar180Pełny rozrzut 360° na boki
velAvg0.02Powolna prędkość
velVar0.01Lekka wariancja prędkości
lspPartAvg2500Średni czas życia 2,5 sekundy
lspPartVar500±0,5s wariancja czasu życia
flyGravity_S"0 0.0001 0"Lekko w górę (dym unosi się)
visName_S"SMOKE1.TGA"Tekstura dymu
visOrientation_S"NONE"Billboard skierowany do kamery
visTexColorStart_S"150 150 150"Szary przy powstaniu
visTexColorEnd_S"80 80 80"Ciemniejszy z czasem
visSizeStart_S"10 10"Rozmiar początkowy 10×10
visSizeEndScale5Rośnie 5×
visAlphaFunc_S"BLEND"Zwykłe przenikanie
visAlphaStart180Półprzezroczyste przy powstaniu
visAlphaEnd0Zanika całkowicie
wskazówka

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";

// --- 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;
visTexAniIsLooping = 1;
visTexColorStart_S = "255 255 255";
visTexColorEnd_S = "255 100 30";
visSizeStart_S = "5 5";
visSizeEndScale = 4;
visAlphaFunc_S = "ADD";
visAlphaStart = 255;
visAlphaEnd = 0;
};
PoleWartośćOpis
ppsValue8080 cząsteczek na sekundę
ppsScaleKeys_S"1"Stała emisja
ppsIsLooping1Ciągła emisja
shpType_S"CIRCLE"Kołowy kształt emitera
shpFOR_S"OBJECT"Względem obiektu emitera
shpIsVolume1Emisja z całego dysku
shpDim_S"15"Promień koła: 15 jednostek
dirMode_S"DIR"Emisja kierunkowa
dirFOR_S"OBJECT"Kierunek względem obiektu
dirAngleElev90Kierunek w górę
dirAngleElevVar20±20° losowe odchylenie
dirAngleHeadVar180Pełny rozrzut 360° na boki
velAvg0.05Umiarkowana prędkość
velVar0.02Wariancja prędkości
lspPartAvg800Krótki czas życia (0,8s)
lspPartVar200±0,2s wariancja
flyGravity_S"0 0.0003 0"Lekkie ciągnięcie w górę
visName_S"FIREFLARE.TGA"Tekstura ognia
visOrientation_S"NONE"Billboard skierowany do kamery
visTexAniFPS8Prędkość animacji tekstury
visTexAniIsLooping1Animacja 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"Rozmiar początkowy 5×5
visSizeEndScale4Rośnie 4×
visAlphaFunc_S"ADD"Addytywne blending (świecące)
visAlphaStart255W pełni widoczne przy powstaniu
visAlphaEnd0Zanika całkowicie

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";
ppsIsLooping = 0;
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;
dirAngleElev = 45;
dirAngleElevVar = 45;
velAvg = 0.15;
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;

// --- Wygląd: małe, jaskrawe punkty ---
visName_S = "ZFLARE1.TGA";
visOrientation_S = "NONE";
visTexColorStart_S = "255 220 100";
visTexColorEnd_S = "255 80 20";
visSizeStart_S = "2 2";
visSizeEndScale = 0.5;
visAlphaFunc_S = "ADD";
visAlphaStart = 255;
visAlphaEnd = 0;
};
PoleWartośćOpis
ppsValue5050 cząsteczek w wybuchu
ppsScaleKeys_S"1 0"Natychmiastowy wybuch, potem nic
ppsIsLooping0Jednorazowe (bez pętli)
ppsFPS2Prędkość odtwarzania kluczy
shpType_S"POINT"Emisja z pojedynczego punktu
shpFOR_S"OBJECT"Względem obiektu emitera
dirMode_S"DIR"Emisja kierunkowa
dirFOR_S"OBJECT"Kierunek względem obiektu
dirAngleHeadVar180Pełny rozrzut 360°
dirAngleElev45Lekko w górę
dirAngleElevVar45Duży rozrzut pionowy
velAvg0.15Szybkie
velVar0.08Duża wariancja prędkości
lspPartAvg600Krótki czas życia (0,6s)
lspPartVar300±0,3s wariancja
flyGravity_S"0 -0.0005 0"Grawitacja ciągnie w dół
flyCollDet_B1Kolizje z geometrią świata
visName_S"ZFLARE1.TGA"Tekstura małego błysku
visOrientation_S"NONE"Billboard skierowany do kamery
visTexColorStart_S"255 220 100"Żółty
visTexColorEnd_S"255 80 20"Ciemny pomarańcz
visSizeStart_S"2 2"Mały rozmiar 2×2
visSizeEndScale0.5Zmniejszają się do połowy
visAlphaFunc_S"ADD"Addytywne blending (świecące)
visAlphaStart255W pełni widoczne przy powstaniu
visAlphaEnd0Zanikają całkowicie

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";
shpIsVolume = 1;
shpDim_S = "300";

// --- Kierunek: w dół ---
dirMode_S = "DIR";
dirFOR_S = "OBJECT";
dirAngleHead = 20;
dirAngleHeadVar = 10;
dirAngleElev = -89;
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;
};
PoleWartośćOpis
ppsValue5050 cząsteczek na sekundę
ppsScaleKeys_S"1"Stała emisja
ppsIsLooping1Ciągła emisja
shpType_S"CIRCLE"Kołowy kształt emitera
shpFOR_S"OBJECT"Względem obiektu emitera
shpOffsetVec_S"0 500 0"500 jednostek nad emiterem
shpIsVolume1Emisja z całego dysku
shpDim_S"300"Promień okręgu: 300 jednostek
dirMode_S"DIR"Emisja kierunkowa
dirFOR_S"OBJECT"Kierunek względem obiektu
dirAngleHead20Lekki wiatr boczny
dirAngleHeadVar10±10° wariancja wiatru
dirAngleElev-89Prawie prosto w dół
velAvg0.05Powolna prędkość opadania
velVar0.02Lekka wariancja prędkości
lspPartAvg5000Długi czas życia (5 sekund)
flyGravity_S"0 0 0"Brak grawitacji (stała prędkość opadania)
visName_S"MFX_SLEEP_STAR.TGA"Tekstura płatka śniegu
visOrientation_S"NONE"Billboard skierowany do kamery
visTexColorStart_S"255 255 255"Biały
visTexColorEnd_S"255 255 255"Pozostaje biały
visSizeStart_S"5 5"Rozmiar płatka 5×5
visSizeEndScale1Bez zmiany rozmiaru
visAlphaFunc_S"ADD"Addytywne blending (jasne płatki)
visAlphaStart255W pełni widoczne
visAlphaEnd255Nie zanikają
m_bIsAmbientPFX1Efekt ambientowy (można wyłączyć w opcjach)

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";

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";
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;

shpType_S = "POINT";

dirMode_S = "NONE";
velAvg = 0;

lspPartAvg = 3000;

visName_S = "YOURBLOODSPLAT.TGA";
visSizeStart_S = "10 10";
visSizeEndScale = 1;
visAlphaFunc_S = "BLEND";
visAlphaStart = 200;
visAlphaEnd = 0;
};

PFX_MojaKrew:

PoleWartośćOpis
ppsValue6464 cząsteczki w wybuchu
ppsCreateEm_S"PFX_MojaKrew_Plama"Tworzy efekt potomny na cząsteczkę
dirMode_S"DIR"Emisja kierunkowa
dirFOR_S"OBJECT"Kierunek względem obiektu
dirAngleHeadVar30±30° rozrzut poziomy
dirAngleElevVar30±30° rozrzut pionowy
velAvg0.1Umiarkowana prędkość
velVar0.05Wariancja prędkości
lspPartAvg750Czas życia 0,75s
lspPartVar550Duża wariancja czasu życia
flyGravity_S"0 -0.0001 0"Spada w dół
flyCollDet_B1Kolizje z geometrią świata
visName_S"BLOOD1.TGA"Tekstura krwi
visTexColorStart_S"255 255 255"Biały (zachowuje kolor tekstury)
visTexColorEnd_S"255 255 255"Bez zmiany koloru
visSizeStart_S"6 6"Rozmiar początkowy 6×6
visSizeEndScale1Bez zmiany rozmiaru
visAlphaFunc_S"BLEND"Zwykłe przenikanie
visAlphaStart255W pełni widoczne

PFX_MojaKrew_Plama:

PoleWartośćOpis
ppsValue1Jedna cząsteczka (jedna plama)
ppsIsLooping0Jednorazowe
shpType_S"POINT"Emiter punktowy
dirMode_S"NONE"Bez kierunku ruchu
velAvg0Nieruchome
lspPartAvg3000Trwa 3 sekundy
visName_S"YOURBLOODSPLAT.TGA"Tekstura plamy
visSizeStart_S"10 10"Rozmiar plamy 10×10
visSizeEndScale1Bez zmiany rozmiaru
visAlphaFunc_S"BLEND"Zwykłe przenikanie
visAlphaStart200Lekko przezroczysta
visAlphaEnd0Zanika całkowicie
informacja

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łtshpType_SshpDim_SOpis
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

TrybvisOrientation_SOpis
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
ostrzeżenie

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_B z dużą ilością cząsteczek mocno obciąża CPU
  • useEmittersFOR = 1 wraz z flyCollDet_B to najkosztowniejsza kombinacja
  • ppsCreateEm_S mnoży liczbę efektów - każda cząsteczka tworzy nowy emiter

Debugowanie

  • Jeśli efekt nie jest widoczny, sprawdź czy visAlphaStart > 0 i visSizeStart_S nie jest za małe
  • Sprawdź, czy tekstura (.TGA) istnieje w katalogu Textures/
  • Efekty z m_bIsAmbientPFX = 1 mogą być wyłączone w opcjach gry

Częste wzorce

EfektKluczowe ustawienia
DymBLEND, duży visSizeEndScale, visAlphaEnd = 0
OgieńADD, animowana tekstura, krótki lspPartAvg
IskryADD, jednorazowy burst, grawitacja w dół, kolizje
Deszcz/śniegDuży emiter CIRCLE, offset w Y, dirAngleElev = -89
KrewBLEND, grawitacja, efekt potomny (plamy)
Magia/auraADD, CIRCLE emiter, useEmittersFOR = 1

Podsumowanie

Tworzenie efektów cząsteczkowych wymaga:

  1. Instancji klasy C_ParticleFX z odpowiednimi parametrami
  2. Kształtu emitera (shpType_S) - skąd lecą cząsteczki
  3. Kierunku i prędkości - jak się poruszają
  4. Wizualizacji - tekstura, kolor, rozmiar, przenikanie
  5. Rejestracji w ParticleFX.src (nie w Gothic.src!)