Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Meer informatie over het toevoegen van eenvoudige aanraakbesturingselementen aan uw Universal Windows Platform (UWP) C++-game met DirectX. We laten zien hoe u besturingselementen op basis van aanraakbediening kunt toevoegen om een camera met een vast vlak te verplaatsen in een Direct3D-omgeving, waarbij slepen met een vinger of stylus het cameraperspectief verschuift.
U kunt deze controles opnemen in games waarin u de speler wilt laten scrollen of bewegen over een 3D-omgeving, zoals een kaart of speelveld. In een strategie- of puzzelspel kunt u deze besturingselementen bijvoorbeeld gebruiken om de speler een spelomgeving te laten bekijken die groter is dan het scherm door naar links of rechts te pannen.
Opmerking Onze code werkt ook met muisbesturing voor het schuiven. De aanwijzer gerelateerde gebeurtenissen worden geabstraheerd door de Windows Runtime-API's, zodat ze aanraak- of muisaanwijzergebeurtenissen kunnen verwerken.
Doelstellingen
- Maak een eenvoudig aanraakbediening voor het pannen van een camera met een vast vlak in een DirectX-game.
De basisinfrastructuur voor touch-gebeurtenissen instellen
Eerst definiëren we ons basiscontrollertype, de CameraPanController, in dit geval. Hier definiëren we een controller als een abstract idee, de set gedragingen die de gebruiker kan uitvoeren.
De klasse CameraPanController is een regelmatig vernieuwde verzameling informatie over de status van de cameracontroller en biedt een manier voor onze app om die informatie op te halen uit de updatelus.
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
{
}
Nu gaan we een koptekst maken die de status van de cameracontroller definieert en de basismethoden en gebeurtenis-handlers die de interacties van de cameracontroller implementeren.
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
De privévelden bevatten de huidige status van de cameracontroller. Laten we ze eens bekijken.
- m_position is de positie van de camera in de scèneruimte. In dit voorbeeld wordt de waarde van de z-coördinaat vastgesteld op 0. We kunnen een DirectX::XMFLOAT2 gebruiken om deze waarde weer te geven, maar voor de doeleinden van dit voorbeeld en toekomstige uitbreidbaarheid gebruiken we een DirectX::XMFLOAT3. Deze waarde wordt doorgegeven aan de eigenschap get_Position aan de app zelf, zodat deze de viewport dienovereenkomstig kan bijwerken.
- m_panInUse is een Booleaanse waarde die aangeeft of een panbewerking actief is; of, meer specifiek, of de speler het scherm aanraakt en de camera verplaatst.
- m_panPointerID is een unieke id voor de aanwijzer. We gebruiken dit niet in het voorbeeld, maar het is een goede gewoonte om uw controllerstatusklasse te koppelen aan een specifieke aanwijzer.
- m_panFirstDown is het punt op het scherm waar de speler het scherm voor het eerst heeft aangeraakt of op de muis heeft geklikt tijdens de actie camerapan. We gebruiken deze waarde later om een dode zone in te stellen om jitter te voorkomen wanneer het scherm wordt aangeraakt of als de muis een beetje schudt.
- m_panPointerPosition is het punt op het scherm waar de speler de aanwijzer momenteel heeft verplaatst. We gebruiken het om te bepalen in welke richting de speler wilde bewegen door het te analyseren in relatie tot m_panFirstDown.
- m_panCommand is de uiteindelijke berekende opdracht voor de cameracontroller: omhoog, omlaag, links of rechts. Omdat we met een camera werken die is vastgezet aan het x-y-vlak, kan dit in plaats daarvan een DirectX::XMFLOAT2 waarde zijn.
We gebruiken deze drie gebeurtenis-handlers om de statusgegevens van de cameracontroller bij te werken.
- OnPointerPressed is een event-handler die door onze app wordt aangeroepen wanneer de speler met een vinger op het aanraakoppervlak drukt en de aanwijzer zich al op de coördinaten van de pers bevindt.
- OnPointerMoved is een gebeurtenishandler die door onze app wordt aanroepen wanneer de speler met een vinger over het aanraakoppervlak swipet. Het wordt bijgewerkt met de nieuwe coördinaten van het sleeppad.
- OnPointerReleased is een gebeurtenishandler die door onze app wordt aanroepen wanneer de speler de drukvinger van het aanraakoppervlak verwijdert.
Ten slotte gebruiken we deze methoden en eigenschappen om de statusgegevens van de cameracontroller te initialiseren, te openen en bij te werken.
- Initialiseer is een gebeurtenishandler die onze app aanroept om de bedieningselementen te initialiseren en aan het CoreWindow--object te koppelen dat uw weergavevenster beschrijft.
- SetPosition is een methode die door onze app wordt aangeroepen om de coördinaten (x, y en z) van uw besturingselementen in de scèneruimte in te stellen. Houd er rekening mee dat onze z-coördinaat gedurende deze zelfstudie 0 is.
- get_Position is een eigenschap waartoe onze app toegang heeft om de huidige positie van de camera in de scèneruimte op te halen. U gebruikt deze eigenschap als manier om de huidige camerapositie aan de app te communiceren.
- get_FixedLookPoint is een eigenschap die door onze app wordt benaderd om het huidige punt te verkrijgen waar de controllercamera op gericht is. In dit voorbeeld is het normaal ten opzichte van het x-y-vlak vergrendeld.
- Update is een methode die de status van de controller leest en de camerapositie bijwerkt. U roept deze <voortdurend iets> vanuit de hoofdlus van de app om de gegevens van de cameracontroller en de camerapositie in de scèneruimte te vernieuwen.
Nu hebt u hier alle onderdelen die u nodig hebt om aanraakbesturingselementen te implementeren. U kunt detecteren wanneer en waar de aanraak- of muisaanwijzergebeurtenissen zijn opgetreden en wat de actie is. U kunt de positie en stand van de camera instellen ten opzichte van de scèneruimte en de wijzigingen bijhouden. Ten slotte kunt u de nieuwe camerapositie doorgeven aan de aanroepende app.
Nu gaan we deze onderdelen met elkaar verbinden.
De eenvoudige aanraakevenementen maken
De Windows Runtime-gebeurtenis-dispatcher biedt drie gebeurtenissen die we in onze app willen verwerken:
Deze gebeurtenissen worden geïmplementeerd op het CoreWindow type. We gaan ervan uit dat u een CoreWindow--object hebt om mee te werken. Zie Uw UWP C++-app instellen om een DirectX-weergave weer te geven voor meer informatie.
Terwijl deze gebeurtenissen worden geactiveerd terwijl onze app wordt uitgevoerd, werken de handlers de statusgegevens van de cameracontroller bij die zijn gedefinieerd in onze privévelden.
Laten we eerst de handlers voor aanraakaanwijzers vullen. In de eerste gebeurtenishandler, OnPointerPressed, krijgen we de x-y-coördinaten van de aanwijzer van de CoreWindow die ons scherm beheert wanneer de gebruiker het scherm aanraakt of op de muis klikt.
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;
}
}
We gebruiken deze handler om het huidige CameraPanController-exemplaar te laten weten dat de cameracontroller moet worden behandeld als actief door m_panInUse in te stellen op TRUE. Op die manier worden, wanneer de app Update aanroept, de huidige positiegegevens gebruikt om de viewport bij te werken.
Nu we de basiswaarden voor de camerabeweging hebben vastgesteld wanneer de gebruiker het scherm aanraakt of op klikken in het schermvenster drukt, moeten we bepalen wat er moet worden gedaan wanneer de gebruiker het scherm sleept of de muis beweegt met de knop ingedrukt.
De OnPointerMoved gebeurtenishandler wordt geactiveerd wanneer de aanwijzer beweegt, bij elke beweging dat de speler deze over het scherm sleept. We moeten de app op de hoogte houden van de huidige locatie van de aanwijzer. Dit is hoe we dit doen.
OnPointer Verplaatst
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;
}
Ten slotte moeten we het gedrag van de camerapan deactiveren wanneer de speler stopt met het aanraken van het scherm. We gebruiken OnPointerReleased, die wordt aangeroepen wanneer PointerReleased wordt geactiveerd, om m_panInUse in te stellen op FALSE en de beweging van de camerapan uit te schakelen en de aanwijzer-id in te stellen op 0.
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;
}
De aanraakbesturingselementen en de controllerstatus initialiseren
Laten we de gebeurtenissen koppelen en alle basisstatusvelden van de cameracontroller initialiseren.
initialiseren
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 );
}
Initialize verwijst naar de CoreWindow-instantie van de app als parameter en registreert de gebeurtenishandlers die we hebben ontwikkeld voor de juiste gebeurtenissen op die CoreWindow.
De positie van de cameracontroller verkrijgen en instellen
Laten we een aantal methoden definiëren om de positie van de cameracontroller in de scèneruimte op te halen en in te stellen.
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;
}
SetPosition is een openbare methode die we vanuit onze app kunnen aanroepen als we de positie van de cameracontroller moeten instellen op een specifiek punt.
get_Position is onze belangrijkste openbare eigenschap: het is de manier waarop onze app de huidige positie van de cameracontroller in de scèneruimte krijgt, zodat deze de viewport dienovereenkomstig kan bijwerken.
get_FixedLookPoint is een openbare eigenschap die in dit voorbeeld een kijkpunt krijgt dat normaal is voor het x-y-vlak. U kunt deze methode wijzigen om de trigonometrische functies, sin en cos te gebruiken bij het berekenen van de x-, y- en z-coördinaatwaarden als u meer schuine hoeken wilt maken voor de vaste camera.
De statusinformatie van de cameracontroller bijwerken
Nu voeren we onze berekeningen uit waarmee de coördinatengegevens van de aanwijzer die in m_panPointerPosition worden bijgehouden, worden geconverteerd naar nieuwe coördinaatgegevens van onze 3D-scèneruimte. Onze app roept deze methode aan telkens wanneer we de hoofd-app-lus vernieuwen. Hierin berekenen we de nieuwe positiegegevens die we willen doorgeven aan de app die wordt gebruikt om de weergavematrix bij te werken voordat de projectie in de viewport wordt weergegeven.
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 );
}
Omdat we niet willen dat schommelingen van de touch of muis onze camera een schokkerige beweging geven, stellen we een dode zone in rond de aanwijzer met een diameter van 32 pixels. We hebben ook een snelheidsmeting, die in dit geval 1:1 is met de pixelverplaatsing van de aanwijzer voorbij de dode zone. U kunt dit gedrag aanpassen om de snelheid van beweging te vertragen of te versnellen.
De weergavematrix bijwerken met de nieuwe camerapositie
We kunnen nu een scèneruimtecoördinaat verkrijgen waarop onze camera is gericht en die wordt bijgewerkt wanneer u uw app dit vertelt (bijvoorbeeld elke 60 seconden in de hoofd-app-lus). Met deze pseudocode wordt het aanroepende gedrag voorgesteld dat u kunt implementeren:
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.
);
Gefeliciteerd! Je hebt een eenvoudige set bedieningen voor het pannen van camera's in je game geïmplementeerd.