Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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
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.