Skip to content

Kapitola 6.4: Systém kamer ​


Úvod ​

DayZ používá vícevrstvý systém kamer. Kamera hráče je spravována enginem prostřednictvím podtříd DayZPlayerCamera. Pro moddování a ladění umožňuje FreeDebugCamera volný let. Engine také poskytuje globální přístupové metody pro aktuální stav kamery. Tato kapitola pokrývá typy kamer, jak přistupovat k datům kamery a jak používat skriptované kamerové nástroje.


Aktuální stav kamery (globální přístupové metody) ​

Tyto metody jsou dostupné odkudkoli a vracejí stav aktivní kamery bez ohledu na její typ:

c
// Aktuální světová pozice kamery
proto native vector GetGame().GetCurrentCameraPosition();

// Aktuální směr kamery (jednotkový vektor)
proto native vector GetGame().GetCurrentCameraDirection();

// Převod světové pozice na souřadnice obrazovky
proto native vector GetGame().GetScreenPos(vector world_pos);
// Vrací: x = obrazovka X (pixely), y = obrazovka Y (pixely), z = hloubka (vzdálenost od kamery)

Příklad --- kontrola, zda je pozice na obrazovce:

c
bool IsPositionOnScreen(vector worldPos)
{
    vector screenPos = GetGame().GetScreenPos(worldPos);

    // z < 0 znamená za kamerou
    if (screenPos[2] < 0)
        return false;

    int screenW, screenH;
    GetScreenSize(screenW, screenH);

    return (screenPos[0] >= 0 && screenPos[0] <= screenW &&
            screenPos[1] >= 0 && screenPos[1] <= screenH);
}

Příklad --- získání vzdálenosti od kamery k bodu:

c
float DistanceFromCamera(vector worldPos)
{
    return vector.Distance(GetGame().GetCurrentCameraPosition(), worldPos);
}

Systém DayZPlayerCamera ​

Kamery hráčů DayZ jsou nativní třídy spravované řídicím systémem hráče enginu. Nejsou přímo vytvářeny ze skriptu --- místo toho engine vybere vhodnou kameru na základě stavu hráče (stojící, ležící, plavání, vozidlo, v bezvědomí atd.).

Typy kamer (konstanty DayZPlayerCameras) ​

ID typů kamer jsou definovány jako konstanty:

KonstantaPopis
DayZPlayerCameras.DAYZCAMERA_1STKamera z pohledu první osoby
DayZPlayerCameras.DAYZCAMERA_3RD_ERCTřetí osoba vzpřímeně (stojící)
DayZPlayerCameras.DAYZCAMERA_3RD_CROTřetí osoba v podřepu
DayZPlayerCameras.DAYZCAMERA_3RD_PROTřetí osoba vleže
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_SPRTřetí osoba sprint
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_RAISEDTřetí osoba se zdviženou zbraní
DayZPlayerCameras.DAYZCAMERA_3RD_CRO_RAISEDTřetí osoba v podřepu se zbraní
DayZPlayerCameras.DAYZCAMERA_IRONSIGHTSMíření přes mířidla
DayZPlayerCameras.DAYZCAMERA_OPTICSMíření přes optiku/puškohled
DayZPlayerCameras.DAYZCAMERA_3RD_VEHICLETřetí osoba ve vozidle
DayZPlayerCameras.DAYZCAMERA_1ST_VEHICLEPrvní osoba ve vozidle
DayZPlayerCameras.DAYZCAMERA_1ST_UNCONSCIOUSPrvní osoba v bezvědomí
DayZPlayerCameras.DAYZCAMERA_3RD_CLIMBTřetí osoba lezení
DayZPlayerCameras.DAYZCAMERA_3RD_JUMPTřetí osoba skok

Získání aktuálního typu kamery ​

c
DayZPlayer player = GetGame().GetPlayer();
if (player)
{
    DayZPlayerCamera cam = player.GetCurrentCamera();
    if (cam && cam.GetCameraName() == "DayZPlayerCamera1stPerson")
    {
        Print("Player is in first person");
    }
}

FreeDebugCamera ​

Soubor: 3_Game/entities/camera.c

Kamera volného letu používaná pro ladění a filmovou práci. Dostupná v diagnostických buildech nebo při povolení mody.

Přístup k instanci ​

c
static proto native FreeDebugCamera GetInstance();

Tato statická metoda vrací singleton instanci volné kamery (nebo null, pokud neexistuje). Volejte ji jako FreeDebugCamera.GetInstance().

Klíčové metody ​

c
// Povolit/zakázat volnou kameru (zděděno z Camera)
proto native void SetActive(bool active);
proto native bool IsActive();

// Pozice a orientace
vector GetPosition();
void   SetPosition(vector pos);
vector GetOrientation();
void   SetOrientation(vector ori);   // otočení, náklon, naklonění

// Směr kamery
vector GetDirection();

Příklad --- aktivace volné kamery a teleportace:

c
void ActivateDebugCamera(vector pos)
{
    FreeDebugCamera cam = FreeDebugCamera.GetInstance();
    if (cam)
    {
        cam.SetActive(true);
        cam.SetPosition(pos);
        cam.SetOrientation(Vector(0, -30, 0));  // Mírně pohled dolů
    }
}

Zorné pole (FOV) ​

Engine řídí FOV nativně. Můžete jej číst a upravovat prostřednictvím systému kamery hráče:

Čtení FOV ​

c
// Získat aktuální FOV kamery (v radiánech)
float fov = Camera.GetCurrentFOV();

Přepsání FOV v DayZPlayerCamera ​

Ve vlastních třídách kamery, které rozšiřují DayZPlayerCamera, můžete přepsat FOV:

c
class MyCustomCamera extends DayZPlayerCamera1stPerson
{
    override void OnUpdate(float pDt, out DayZPlayerCameraResult pOutResult)
    {
        super.OnUpdate(pDt, pOutResult);
        pOutResult.m_fFovAbsolute = 0.7854;  // ~45 stupňů (radiány)
    }
}

Hloubka ostrosti (DOF) ​

Hloubka ostrosti je řízena prostřednictvím systému post-processingových efektů (viz Kapitola 6.5). Systém kamer však pracuje s DOF prostřednictvím těchto mechanismů:

Nastavení DOF přes CGame ​

c
// OverrideDOF(enable, focusDistance, focusLength, focusLengthNear, blur, focusDepthOffset)
GetGame().OverrideDOF(true, 5.0, 100.0, 0.5, 0.3, 0.0);

Vypnutí DOF ​

c
GetGame().OverrideDOF(false, 0, 0, 0, 0, 1);  // První argument false vypne DOF

ScriptCamera (GameLib) ​

Soubor: 2_GameLib/entities/scriptcamera.c

Nízkoúrovňová skriptovaná entita kamery z vrstvy GameLib. Toto je základ pro vlastní implementace kamer.

Vytvoření kamery ​

c
ScriptCamera camera = ScriptCamera.Cast(
    GetGame().CreateObject("ScriptCamera", pos, true)  // pouze lokální
);

Klíčové metody ​

Poznámka: ScriptCamera se kompiluje pouze pod #ifdef GAME_TEMPLATE a není přítomna v herním buildu DayZ. Konfiguruje se prostřednictvím kamerových metod třídy GenericEntity (SetCameraVerticalFOV, SetCameraNearPlane, SetCameraFarPlane, SetCameraType). Níže uvedené metody patří k enginové třídě Camera (3_Game/entities/camera.c), kterou FreeDebugCamera rozšiřuje:

c
proto native void SetFOV(float fov);                 // FOV v radiánech
proto native void SetNearPlane(float nearPlane);     // interně omezeno na 0.01m
proto native float GetNearPlane();
proto native void SetFocus(float distance, float blur);  // hloubka ostrosti

Aktivace kamery ​

c
// Nastavit tuto kameru jako aktivní renderovací kameru
GetGame().SelectPlayer(null, null);   // Odpojit od hráče
GetGame().ObjectRelease(camera);      // Uvolnit pro engine

Poznámka: Přepnutí z kamery hráče vyžaduje pečlivé zacházení se vstupy a HUD. Většina modů používá volnou debug kameru nebo PPE překryvné efekty místo vytváření vlastních kamer.


Raycast z kamery ​

Běžný vzor je provádění raycastu z pozice kamery ve směru kamery pro nalezení toho, na co se hráč dívá:

c
Object GetObjectInCrosshair(float maxDistance)
{
    vector from = GetGame().GetCurrentCameraPosition();
    vector to = from + (GetGame().GetCurrentCameraDirection() * maxDistance);

    vector contactPos;
    vector contactDir;
    int contactComponent;
    set<Object> hitObjects = new set<Object>;

    if (DayZPhysics.RaycastRV(from, to, contactPos, contactDir,
                               contactComponent, hitObjects, null, null,
                               false, false, ObjIntersectView, 0.0))
    {
        if (hitObjects.Count() > 0)
            return hitObjects[0];
    }

    return null;
}

Shrnutí ​

KonceptKlíčový bod
Globální přístupové metodyGetCurrentCameraPosition(), GetCurrentCameraDirection(), GetScreenPos()
Typy kamerKonstanty DayZPlayerCameras (1ST, 3RD_ERC, IRONSIGHTS, OPTICS, VEHICLE atd.)
Aktuální typplayer.GetCurrentCamera().GetCameraName()
Volná kameraFreeDebugCamera.GetInstance(), pak cam.SetActive(true)
FOVCamera.GetCurrentFOV() pro čtení, nastavit pOutResult.m_fFovAbsolute v OnUpdate
DOFGetGame().OverrideDOF(enable, focusDist, focusLen, focusLenNear, blur, offset)
Převod na obrazovkuGetScreenPos(worldPos) vrací pixel XY + hloubku Z

Osvědčené postupy ​

  • Cachujte pozici kamery při opakovaném dotazování v rámci jednoho snímku. GetGame().GetCurrentCameraPosition() a GetCurrentCameraDirection() jsou volání enginu -- uložte výsledek do lokální proměnné, pokud ho potřebujete ve více výpočtech v rámci jednoho snímku.
  • Používejte kontrolu hloubky GetScreenPos() před umístěním UI. Vždy ověřte screenPos[2] > 0 (před kamerou) před vykreslováním HUD značek na světových pozicích, jinak se značky objeví zrcadlově za hráčem.
  • Vyhněte se vytváření vlastních instancí ScriptCamera pro jednoduché efekty. FreeDebugCamera a systém PPE pokrývají většinu filmových a vizuálních potřeb. Vlastní kamery vyžadují pečlivou správu vstupů/HUD, která se snadno rozbije.
  • Respektujte přechody typů kamer enginu. Nevynucujte změny typu kamery ze skriptu, pokud plně nezvládáte stav řídicího systému hráče. Neočekávané přepnutí kamery může zablokovat pohyb hráče nebo způsobit desynchronizaci.
  • Zabezpečte použití volné kamery za kontrolou admin/debug oprávnění. FreeDebugCamera poskytuje neomezený pohled na svět. Povolte ji pouze pro ověřené administrátory nebo diagnostické buildy, aby se předešlo zneužití.

Kompatibilita a dopad ​

  • Multi-Mod: Přístupové metody kamery jsou globální jen pro čtení, takže více modů může bezpečně číst stav kamery současně. Konflikty vznikají pouze pokud dva mody oba aktivují FreeDebugCamera nebo vlastní instance ScriptCamera.
  • Výkon: GetScreenPos() a GetCurrentCameraPosition() jsou lehká volání enginu. Raycast z kamery (DayZPhysics.RaycastRV) je náročnější -- omezte na jednou za snímek, ne za entitu.
  • Server/Klient: Stav kamery existuje pouze na klientovi. Všechny metody kamery vracejí bezvýznamná data na dedikovaném serveru. Nikdy nepoužívejte dotazy na kameru v serverové logice.

<< Předchozí: Počasí | Kamery | Další: Post-processingové efekty >>

Released under CC BY-SA 4.0 | Code examples under MIT License