Megosztás a következőn keresztül:


Érintésvezérlés játékokhoz

Ismerje meg, hogyan adhat hozzá alapszintű érintésvezérléseket az Univerzális Windows Platform (UWP) C++ játékhoz a DirectX használatával. Bemutatjuk, hogyan adhat hozzá érintésalapú vezérlőket a rögzített síkú fényképezőgépek Direct3D környezetben való mozgatásához, ahol az ujjal vagy tollal történő húzással eltolhatja a kamera perspektíváját.

Ezeket a vezérlőket olyan játékokba is beépítheti, amelyekben azt szeretné, hogy a játékos húzással görgetjen vagy pásztázzon egy 3D-s környezetben, például térképen vagy játéktéren. Például egy stratégiában vagy puzzle-játékban ezekkel a vezérlőkkel engedélyezheti a játékosnak a képernyőnél nagyobb játékkörnyezet megtekintését balra vagy jobbra pásztázva.

Jegyzet A kód egéralapú pásztázó vezérlőkkel is működik. A mutatóval kapcsolatos eseményeket a Windows Futtatókörnyezet API-k absztrakcióval kezelik, így érintéses vagy egéralapú mutatóeseményeket is kezelhetnek.

 

Célkitűzések

  • Hozzon létre egy egyszerű érintéses húzási vezérlőt, amellyel rögzített síkú kamerát pásztázhat egy DirectX-játékban.

Az alapszintű érintéses eseményinfrastruktúra beállítása

Először meghatározzuk az alapvezérlő típusát, a CameraPanControllert ebben az esetben. Itt egy vezérlőt absztrakciós ötletként határozunk meg, a felhasználó által végrehajtható viselkedések halmazát.

A CameraPanController osztály rendszeresen frissített információgyűjtemény a kameravezérlő állapotáról, és lehetővé teszi az alkalmazás számára, hogy ezeket az információkat a frissítési ciklusból szerezze be.

using namespace Windows::UI::Core;
using namespace Windows::System;
using namespace Windows::Foundation;
using namespace Windows::Devices::Input;
#include <directxmath.h>

// Methods to get input from the UI pointers
ref class CameraPanController
{
}

Most hozzunk létre egy fejlécet, amely meghatározza a kameravezérlő állapotát, valamint a kameravezérlő interakcióit megvalósító alapvető metódusokat és eseménykezelőket.

ref class CameraPanController
{
private:
    // Properties of the controller object
    DirectX::XMFLOAT3 m_position;               // the position of the camera

    // Properties of the camera pan control
    bool m_panInUse;                
    uint32 m_panPointerID;          
    DirectX::XMFLOAT2 m_panFirstDown;           
    DirectX::XMFLOAT2 m_panPointerPosition;   
    DirectX::XMFLOAT3 m_panCommand;         
    
internal:
    // Accessor to set the position of the controller
    void SetPosition( _In_ DirectX::XMFLOAT3 pos );

       // Accessor to set the fixed "look point" of the controller
       DirectX::XMFLOAT3 get_FixedLookPoint();

    // Returns the position of the controller object
    DirectX::XMFLOAT3 get_Position();

public:

    // Methods to get input from the UI pointers
    void OnPointerPressed(
        _In_ Windows::UI::Core::CoreWindow^ sender,
        _In_ Windows::UI::Core::PointerEventArgs^ args
        );

    void OnPointerMoved(
        _In_ Windows::UI::Core::CoreWindow^ sender,
        _In_ Windows::UI::Core::PointerEventArgs^ args
        );

    void OnPointerReleased(
        _In_ Windows::UI::Core::CoreWindow^ sender,
        _In_ Windows::UI::Core::PointerEventArgs^ args
        );

    // Set up the Controls supported by this controller
    void Initialize( _In_ Windows::UI::Core::CoreWindow^ window );

    void Update( Windows::UI::Core::CoreWindow ^window );

};  // Class CameraPanController

A privát mezők a kameravezérlő aktuális állapotát tartalmazzák. Tekintsük át őket.

  • m_position a kamera helye a jelenettérben. Ebben a példában a z koordináta értéke 0. Használhatunk egy DirectX::XMFLOAT2-t ennek az értéknek az ábrázolásához, de a minta és a jövőbeli bővíthetőség érdekében DirectX::XMFLOAT3-at használunk. Ezt az értéket az get_Position tulajdonságon keresztül továbbítja magának az alkalmazásnak, hogy ennek megfelelően frissíthesse a nézetportot.
  • m_panInUse logikai érték, amely azt jelzi, hogy egy panoráma művelet aktív-e; pontosabban azt, hogy a játékos megérinti a képernyőt, és mozgatja a kamerát.
  • m_panPointerID a mutató egyedi azonosítója. Ezt nem fogjuk használni a mintában, de ajánlott a vezérlőállapot-osztályt egy adott mutatóhoz társítani.
  • m_panFirstDown az a pont a képernyőn, ahol a játékos először megérintette a képernyőt, vagy kattintott az egérrel a kamera elhúzásának művelete során. Ezt az értéket később arra használjuk, hogy holt zónát állítsunk be a képernyő megérintésekor, vagy ha az egér egy kicsit rázkód.
  • m_panPointerPosition az a pont a képernyőn, ahol a játékos éppen áthelyezte az egérmutatót. Arra használjuk, hogy megállapítsuk, milyen irányban szeretne a játékos mozogni, a m_panFirstDown-hez viszonyítva megvizsgálva azt.
  • m_panCommand a kameravezérlő utolsó számított parancsa: fel, le, balra vagy jobbra. Mivel az x-y síkhoz van rögzítve a kameránk, ez lehet akár egy DirectX::XMFLOAT2 érték is.

Ezt a 3 eseménykezelőt használjuk a kameravezérlő állapotinformációinak frissítéséhez.

  • Az OnPointerPressed egy eseménykezelő, amelyet az alkalmazás akkor hív meg, amikor a játékosok az ujját lenyomják az érintési felületre, és a mutató a lenyomás koordinátáira kerül.
  • Az OnPointerMoved egy eseménykezelő, amelyet az alkalmazás meghív, amikor a játékos ujjal pöccint az érintési felületen. Frissül a húzási útvonal új koordinátáival.
  • Az OnPointerReleased egy eseménykezelő, amelyet az alkalmazás akkor hív meg, amikor a lejátszó eltávolítja az ujját az érintési felületről.

Végül ezeket a módszereket és tulajdonságokat használjuk a kameravezérlő állapotadatainak inicializálására, elérésére és frissítésére.

  • inicializálása egy eseménykezelő, amelyet az alkalmazásunk hív meg a vezérlők inicializálására és azok csatolására ahhoz a CoreWindow objektumhoz, amely leírja a megjelenítési ablakot.
  • SetPosition egy metódus, amelyet az alkalmazás a vezérlőid (x, y és z) koordinátáinak beállítására használ a jelenettérben. Vegye figyelembe, hogy a z-koordináta a teljes oktatóanyag során 0.
  • get_Position egy olyan tulajdonság, amelyhez az alkalmazás hozzáfér a kamera aktuális pozíciójának lekéréséhez a jelenettérben. Ezzel a tulajdonságkal kommunikálhat az aktuális kamerapozícióval az alkalmazással.
  • get_FixedLookPoint egy olyan tulajdonság, amelyhez az alkalmazás hozzáfér, hogy megkapja azt az aktuális pontot, amerre a vezérlő kamerája néz. Ebben a példában az x-y síkhoz normál módon van zárolva.
  • frissítési olyan módszer, amely beolvassa a vezérlő állapotát, és frissíti a kamera helyzetét. Ezt a <az alkalmazás fő hurokjából>, hogy frissítse a kameravezérlő adatait és a kamera pozícióját a jelenettérben.

Most itt találja az érintésvezérlés implementálásához szükséges összes összetevőt. Észlelheti, hogy mikor és hol történtek az érintéses vagy egérmutatós események, és hogy mi a művelet. Beállíthatja a kamera helyzetét és tájolását a jelenettérhez viszonyítva, és nyomon követheti a változásokat. Végül közölheti az új kamerapozíciót a hívó alkalmazással.

Most kapcsoljuk össze ezeket a darabokat.

Az alapszintű érintéses események létrehozása

A Windows Futtatókörnyezet esemény-diszpécser 3 eseményt biztosít, amelyeket az alkalmazásnak kezelnie kell:

Ezek az események a CoreWindow típusán vannak implementálva. Feltételezzük, hogy rendelkezik egy CoreWindow objektummal, amellyel dolgozni szeretne. További információ : UWP C++ alkalmazás beállítása DirectX-nézet megjelenítéséhez.

Mivel ezek az események az alkalmazás futtatása közben aktiválódik, a kezelők frissítik a privát mezőkben definiált kameravezérlő állapotinformációit.

Először töltse ki az érintésmutató eseménykezelőjét. Az első eseménykezelőben, OnPointerPressed, akkor szerezzük meg a mutató x-y koordinátáit a CoreWindow-ből, amely kezeli a megjelenítést, amikor a felhasználó megérinti a képernyőt vagy rákattint az egérre.

OnPointerPressed

void CameraPanController::OnPointerPressed(
                                           _In_ CoreWindow^ sender,
                                           _In_ PointerEventArgs^ args)
{
    // Get the current pointer position.
    uint32 pointerID = args->CurrentPoint->PointerId;
    DirectX::XMFLOAT2 position = DirectX::XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    auto device = args->CurrentPoint->PointerDevice;
    auto deviceType = device->PointerDeviceType;
    

       if ( !m_panInUse )   // If no pointer is in this control yet.
    {
       m_panFirstDown = position;                   // Save the location of the initial contact.
       m_panPointerPosition = position;
       m_panPointerID = pointerID;              // Store the id of the pointer using this control.
       m_panInUse = TRUE;
    }
    
}

Ezzel a kezelővel tudatjuk az aktuális CameraPanController-példánysal , hogy a kameravezérlőt aktívként kell kezelni a m_panInUse IGAZ értékre állításával. Így, amikor az alkalmazás meghívja az Update-et , az aktuális pozícióadatokat fogja használni a nézetport frissítéséhez.

Most, hogy meghatároztuk a kamera mozgásának alapértékeit, amikor a felhasználó megérinti a képernyőt, vagy kattintással vagy lenyomással megnyomja a képernyőt, meg kell határoznunk, hogy mit kell tennünk, ha a felhasználó a képernyő érintésének húzása vagy az egérgomb lenyomva tartásával mozgatja az egeret.

A OnPointerMoved eseménykezelő minden alkalommal aktiválódik, amikor a mutató mozog, minden olyan osztásnál, amelyet a játékos húz a képernyőn. Az alkalmazásnak tisztában kell maradnia az egérmutató aktuális helyével, és ezt kell megtennie.

OnPointerMoved

void CameraPanController::OnPointerMoved(
                                        _In_ CoreWindow ^sender,
                                        _In_ PointerEventArgs ^args)
{
    uint32 pointerID = args->CurrentPoint->PointerId;
    DirectX::XMFLOAT2 position = DirectX::XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    m_panPointerPosition = position;
}

Végül inaktiválnunk kell a kamera pásztázó viselkedését, amikor a játékos abbahagyja a képernyő érintését. A OnPointerReleased(amely akkor van meghívva, amikor a PointerReleased aktiválódik) az m_panInUse FALSE értékre állításához, a kamera mozgatásának leállításához, és a mutatóazonosító nullára állításához.

OnPointerReleased

void CameraPanController::OnPointerReleased(
                                             _In_ CoreWindow ^sender,
                                             _In_ PointerEventArgs ^args)
{
    uint32 pointerID = args->CurrentPoint->PointerId;
    DirectX::XMFLOAT2 position = DirectX::XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    m_panInUse = FALSE;
    m_panPointerID = 0;
}

Az érintésvezérlés és a vezérlő állapotának inicializálása

Kapcsoljuk össze az eseményeket, és inicializáljuk a kameravezérlő összes alapállapot-mezőjét.

inicializál

void CameraPanController::Initialize( _In_ CoreWindow^ window )
{

    // Start receiving touch/mouse events.
    window->PointerPressed += 
    ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &CameraPanController::OnPointerPressed);

    window->PointerMoved += 
    ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &CameraPanController::OnPointerMoved);

    window->PointerReleased += 
    ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &CameraPanController::OnPointerReleased);


    // Initialize the state of the controller.
    m_panInUse = FALSE;             
    m_panPointerID = 0;

    //  Initialize this as it is reset on every frame.
    m_panCommand = DirectX::XMFLOAT3( 0.0f, 0.0f, 0.0f );

}

A inicializálása egy paraméterként kapja az alkalmazás CoreWindow példányára tett hivatkozást, és regisztrálja az általunk fejlesztett eseménykezelőket a megfelelő eseményekre azon a CoreWindow-n.

A kameravezérlő helyének lekérése és beállítása

Határozzunk meg néhány módszert a kameravezérlő helyének lekérésére és beállítására a jelenettérben.

void CameraPanController::SetPosition( _In_ DirectX::XMFLOAT3 pos )
{
    m_position = pos;
}

// Returns the position of the controller object
DirectX::XMFLOAT3 CameraPanController::get_Position()
{
    return m_position;
}

DirectX::XMFLOAT3 CameraPanController::get_FixedLookPoint()
{
    // For this sample, we don't need to use the trig functions because our
    // look point is fixed. 
    DirectX::XMFLOAT3 result= m_position;
    result.z += 1.0f;
    return result;    

}

A SetPosition egy nyilvános módszer, amelyet az alkalmazásból hívhatunk meg, ha a kameravezérlő pozícióját egy adott pontra kell állítani.

get_Position a legfontosabb nyilvános tulajdonságunk: az alkalmazás így kapja meg a kameravezérlő aktuális pozícióját a jelenettérben, hogy ennek megfelelően frissíthesse a nézetportot.

get_FixedLookPoint egy olyan nyilvános tulajdonság, amely ebben a példában egy az x-y síkra merőleges nézési pontot határoz meg. Ezt a módszert módosíthatja a trigonometriai függvények, a sin és a cos függvények használatára az x, y és z koordináta értékek kiszámításakor, ha ferdeebb szögeket szeretne létrehozni a rögzített kamera számára.

A kameravezérlő állapotadatainak frissítése

Most elvégezzük a számításokat, amelyek a m_panPointerPosition által nyomon követett mutatókoordináta-információkat átalakítják 3D jelenettérünk új koordináta-információivá. Az alkalmazás minden alkalommal meghívja ezt a metódust, amikor frissítjük a fő alkalmazáshurkot. Ebben kiszámítjuk azokat az új pozícióadatokat, amelyeket át szeretnénk adni az alkalmazásnak, amely a nézetmátrix frissítésére szolgál a nézetportba való kivetítés előtt.


void CameraPanController::Update( CoreWindow ^window )
{
    if ( m_panInUse )
    {
        pointerDelta.x = m_panPointerPosition.x - m_panFirstDown.x;
        pointerDelta.y = m_panPointerPosition.y - m_panFirstDown.y;

        if ( pointerDelta.x > 16.0f )        // Leave 32 pixel-wide dead spot for being still.
            m_panCommand.x += 1.0f;
        else
            if ( pointerDelta.x < -16.0f )
                m_panCommand.x += -1.0f;

        if ( pointerDelta.y > 16.0f )        
            m_panCommand.y += 1.0f;
        else
            if (pointerDelta.y < -16.0f )
                m_panCommand.y += -1.0f;
    }

       DirectX::XMFLOAT3 command = m_panCommand;
   
    // Our velocity is based on the command.
    DirectX::XMFLOAT3 Velocity;
    Velocity.x =  command.x;
    Velocity.y =  command.y;
    Velocity.z =  0.0f;

    // Integrate
    m_position.x = m_position.x + Velocity.x;
    m_position.y = m_position.y + Velocity.y;
    m_position.z = m_position.z + Velocity.z;

    // Clear the movement input accumulator for use during the next frame.
    m_panCommand = DirectX::XMFLOAT3( 0.0f, 0.0f, 0.0f );

}

Mivel nem szeretnénk, hogy az érintőképernyős vagy egérműveletek akadozóvá tegyék a kamerapásztázást, egy 32 képpont átmérőjű holtteret állítunk be a mutató körül. Van egy megadott sebességérték is, amely ebben az esetben 1:1 a mutató holtzónán túli pixelmozgásával. Ezt a viselkedést úgy módosíthatja, hogy lelassítsa vagy felgyorsítsa a mozgás sebességét.

A nézetmátrix frissítése az új kamerapozícióval

Most már beszerezhetünk egy jelenettérkoordinátát, amelyre a kameránk összpontosít, és amely minden alkalommal frissül, amikor erre utasítja az alkalmazását (például minden 60. másodpercben a főalkalmazás-ciklusban). Ez a pszeudokód a megvalósítható hívási viselkedésre utal:

 myCameraPanController->Update( m_window ); 

 // Update the view matrix based on the camera position.
 myCamera->MyMethodToComputeViewMatrix(
        myController->get_Position(),        // The position in the 3D scene space.
        myController->get_FixedLookPoint(),      // The point in the space we are looking at.
        DirectX::XMFLOAT3( 0, 1, 0 )                    // The axis that is "up" in our space.
        );  

Gratulálok! A játékban egy egyszerű kamera pásztázó érintésvezérlést valósított meg.