Didacticiel : ajouter des contrôles tactiles à votre jeu DirectX

Applies to Windows and Windows Phone

Découvrez comment ajouter des contrôles tactiles de base à votre jeu du Windows Store en C++ avec DirectX. Nous allons vous montrer comment ajouter des contrôles tactiles pour déplacer une caméra de plan fixe dans un environnement Direct3D, où le glissement avec un doigt ou un stylet décale la perspective de la caméra.

Vous pouvez incorporer ces contrôles à des jeux où le joueur doit faire glisser pour effectuer un défilement ou un panoramique dans un environnement 3D, par exemple une carte ou un terrain de jeux. Par exemple, dans un jeu de stratégie ou de casse-tête, vous pouvez utiliser ces contrôles pour permettre au joueur de voir un environnement de jeu plus grand que l’écran par un mouvement panoramique gauche ou droit.

Remarque  Notre code fonctionne également pour les contrôles panoramiques avec la souris. Les événements associés au pointeur étant abstraits par les API Windows Runtime, ils peuvent gérer les événements de pointeur tactiles ou avec la souris.

Objectifs

  • Créer un simple contrôle de glisser tactile pour le panoramique d’une caméra de plan fixe dans un jeu DirectX.

Configurer l’infrastructure des événements tactiles de base

Définissons d’abord notre type de contrôleur de base, CameraPanController, dans ce cas. Nous définissons ici un contrôleur comme une idée abstraite, l’ensemble de comportements que l’utilisateur peut adopter.

La classe CameraPanController est une collection régulièrement mise à jour d’informations sur l’état du contrôleur de la caméra, et permet à notre application d’obtenir ces informations à partir de sa boucle de mise à jour.


using namespace Windows::UI::Core;
using namespace Windows::System;
using namespace Windows::Foundation;
using namespace Windows::Devices::Input;

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

Créons maintenant un en-tête qui définit l’état du contrôleur de la caméra, plus les méthodes de base et gestionnaires d’événements qui implémentent les interactions du contrôleur de la caméra.


ref class CameraPanController
{
private:
    // properties of the controller object
    float3 m_position;			    // the position of the camera

    // properties of the camera pan control
    bool m_panInUse;			    
    uint32 m_panPointerID;		    
    float2 m_panFirstDown;		    
    float2 m_panPointerPosition;   
    float3 m_panCommand;		    

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

    // accessor to set the position of the ontroller
    void SetPosition( _In_ float3 pos );

	   // accessor to set fixed "look point" of the controller
	   float3 get_FixedLookPoint();

    // returns the position of the controller object
    float3 get_Position();


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

};  // class CameraPanController

Les champs privés contiennent l’état actuel du contrôleur de la caméra. Passons-les en revue.

  • m_position représente la position de la caméra dans l’espace de scène. Dans cet exemple, la valeur de coordonnée z est fixée à 0. Nous pourrions utiliser float2 pour représenter cette valeur, mais dans le cadre de cet exemple et à des fins d’extensibilité future, nous utilisons float3. Nous passons cette valeur via la propriété get_Position à l’application elle-même afin qu’elle puisse mettre à jour la fenêtre d’affichage en conséquence.
  • m_panInUse est une valeur booléenne qui indique si une opération panoramique est active ou, plus spécifiquement, si le joueur touche l’écran et déplace la caméra.
  • m_panPointerID représente un ID unique pour le pointeur. Nous ne l’utiliserons pas dans cet exemple, mais il est conseillé d’associer la classe de l’état du contrôleur à un pointeur spécifique.
  • m_panFirstDown est le point de l’écran où le joueur a touché pour la première fois l’écran ou a cliqué sur la souris pendant l’action panoramique de la caméra. Nous utiliserons cette valeur plus tard pour définir une zone morte afin d’empêcher tout sautillement lorsque l’écran est touché ou si la souris bouge un petit peu.
  • m_panPointerPosition est le point de l’écran où le joueur a actuellement placé le pointeur. Il est utilisé pour déterminer la direction dans laquelle l’utilisateur souhaite se déplacer en l’examinant par rapport à m_panFirstDown.
  • m_panCommand est la dernière commande calculée pour le contrôleur de la caméra : haut, bas, gauche ou droite. Dans la mesure où nous utilisons une caméra fixée au plan x-y, il pourrait s’agir d’une valeur float2 à la place.

Nous utilisons ces 3 gestionnaires d’événements pour mettre à jour les informations sur l’état du contrôleur de la caméra.

  • OnPointerPressed est un gestionnaire d’événements que notre application appelle lorsque le joueur appuie un doigt sur la surface tactile et que le pointeur est déplacé vers les coordonnées du point sur lequel il a appuyé.
  • OnPointerMoved est un gestionnaire d’événements que notre application appelle lorsque le joueur balaye du doigt la surface tactile. Il effectue la mise à jour avec les nouvelles coordonnées du chemin de glissement.
  • OnPointerReleased est un gestionnaire d’événements que notre application appelle lorsque le joueur retire le doigt de la surface tactile.

Enfin, nous utilisons les méthodes et propriétés suivantes pour accéder aux informations sur l’état du contrôleur de la caméra, les initialiser et les mettre à jour.

  • Initialize est un gestionnaire d’événements que notre application appelle pour initialiser les contrôles et les associer à l’objet CoreWindow qui décrit la fenêtre d’affichage.
  • SetPosition est une méthode que notre application appelle pour définir les coordonnées (x, y et z) des contrôles dans l’espace de scène. Notez que la coordonnée z a la valeur 0 tout au long de ce didacticiel.
  • get_Position est une propriété à laquelle notre application accède pour obtenir la position actuelle de la caméra dans l’espace de scène. Vous utilisez cette propriété comme méthode de communication de la position actuelle de la caméra à l’application.
  • get_FixedLookPoint est une propriété à laquelle notre application accède pour obtenir le point actuel vers lequel la caméra du contrôleur est orientée. Dans cet exemple, il est verrouillé perpendiculairement au plan x-y.
  • Update est une méthode qui lit l’état du contrôleur et met à jour la position de la caméra. Vous appelez continuellement cet <élément> à partir de la boucle principale de l’application pour actualiser les données de contrôleur de la caméra et la position de la caméra dans l’espace de scène.

Vous disposez à présent ici de tous les composants nécessaires pour implémenter les contrôles tactiles. Vous pouvez détecter quand et où les événements de pointeur de souris ou tactile se sont produits, et identifier l’action. Vous pouvez définir la position et l’orientation de la caméra par rapport à l’espace de scène et assurer le suivi des modifications. Enfin, vous pouvez communiquer la nouvelle position de la caméra à l’application appelante.

Rassemblons maintenant tous ces éléments.

Créer les événements tactiles de base

Le répartiteur d’événements Windows Runtime fournit 3 événements qui doivent être gérés par notre application :

Ces événements sont implémentés sur le type CoreWindow. Nous supposons que vous disposez d’un objet CoreWindow à manipuler. Pour plus d’informations, voir Comment configurer une application C++ Windows Store pour afficher une vue DirectX.

Comme ces événements sont déclenchés pendant que notre application est en cours d’exécution, les gestionnaires mettent à jour les informations sur l’état du contrôleur de la caméra définies dans nos champs privés.

Remplissons d’abord les gestionnaires d’événements de pointeur tactile. Dans le premier gestionnaire d’événements, OnPointerPressed, nous obtenons les coordonnées x-y du pointeur à partir du CoreWindow qui gère notre affichage lorsque l’utilisateur clique sur la souris ou touche l’écran.

OnPointerPressed


void CameraPanController::OnPointerPressed(
                                           _In_ CoreWindow^ sender,
                                           _In_ PointerEventArgs^ args)
{
    // get the current pointer position
    uint32 pointerID = args->CurrentPoint->PointerId;
    float2 position = float2( 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 location of initial contact
       m_panPointerPosition = position;
       m_panPointerID = pointerID;				// store the id of pointer using this control
       m_panInUse = TRUE;
    }
    
}


Nous utilisons ce gestionnaire pour indiquer à l’instance CameraPanController actuelle que le contrôleur de la caméra doit être considéré comme actif en affectant à m_panInUse la valeur TRUE. Ainsi, lorsque l’application appelle Update, elle utilise les données de la position actuelle pour mettre à jour la fenêtre d’affichage.

Maintenant que nous avons établi les valeurs de base pour le mouvement de la caméra lorsque l’utilisateur touche l’écran ou clique/appuie dans la fenêtre d’affichage, nous devons identifier les actions à effectuer lorsque l’utilisateur fait glisser le point sur lequel il a appuyé ou déplace la souris avec le bouton enfoncé.

Le gestionnaire d’événements OnPointerMoved se déclenche chaque fois que le pointeur se déplace, sur chaque graduation que le joueur le fait glisser sur l’écran. Nous devons tenir l’application informée de l’emplacement actuel du pointeur et voici comment procéder pour cela.

OnPointerMoved


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

    m_panPointerPosition = position;
}

Enfin, nous devons désactiver le mouvement panoramique de la caméra lorsque le joueur cesse de toucher l’écran. Nous utilisons OnPointerReleased, qui est appelé lorsque PointerReleased est déclenché, pour affecter à m_panInUse la valeur FALSE et désactiver le mouvement panoramique de la caméra, et pour affecter la valeur 0 à l’ID de pointeur.

OnPointerReleased


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

    m_panInUse = FALSE;
    m_panPointerID = 0;
}

Initialiser les contrôles tactiles et l’état du contrôleur

Rassemblons les événements et initialisons tous les champs des états de base du contrôleur de la caméra.

Initialize


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

    // Start recieving 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 state of the controller
    m_panInUse = FALSE;				
    m_panPointerID = 0;

    //	Initialize this as it is reset every frame
    m_panCommand = float3( 0.0f, 0.0f, 0.0f );

}

Initialize fait référence à l’instance CoreWindow de l’application en tant que paramètre et inscrit les gestionnaires d’événements développés dans les événements appropriés sur ce CoreWindow.

Obtention et définition de la position du contrôleur de la caméra

Définissons certaines méthodes pour obtenir et définir la position du contrôleur de la caméra dans l’espace de scène.


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

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

float3 CameraPanController::get_FixedLookPoint()
{
    // For this sample, we don't need to use the trig functions because our
    // look point is fixed. 
    return m_position + float3( 0, 0, 1 );
}

SetPosition est une méthode publique que nous pouvons appeler à partir de notre application si nous devons définir un point spécifique comme position du contrôleur de la caméra.

get_Position est la propriété publique la plus importante : elle permet à l’application d’obtenir la position actuelle du contrôleur de la caméra dans l’espace de scène et donc de mettre à jour la fenêtre d’affichage en conséquence.

get_FixedLookPoint est une propriété publique qui, dans cet exemple, obtient un point de mire qui est perpendiculaire au plan x-y. Vous pouvez modifier cette méthode pour utiliser les fonctions trigonométriques, sin et cos, lors du calcul des valeurs des coordonnées x, y et z si vous voulez créer d’autres angles obliques pour la caméra fixe.

Mise à jour des informations sur l’état du contrôleur de la caméra

Effectuons maintenant nos calculs pour convertir les informations de coordonnées du pointeur suivies dans m_panPointerPosition en nouvelles informations de coordonnées respectives de notre espace de scène 3D. En règle générale, notre application appelle cette méthode à chaque actualisation de la boucle principale de l’application et nous y calculons les nouvelles informations de position à transmettre à l’application pour la mise à jour de la matrice globale avant projection dans la fenêtre d’affichage.




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

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

	   float3 command = m_panCommand;
   
    // our velocity is based on the command
    float3 Velocity;
    Velocity.x =  command.x;
    Velocity.y =  command.y;
    Velocity.z =  0.0f;

    // integrate
    m_position = m_position + Velocity;

    // Clear the movement input accumulator for use during next frame
    m_panCommand = float3( 0.0f, 0.0f, 0.0f );

}

Comme nous ne voulons pas que les sautillements tactiles ou de souris donnent un mouvement saccadé au panoramique de la caméra, nous définissons une zone morte autour du pointeur avec un diamètre de 32 pixels. Nous avons également une valeur de vitesse, qui est ici de 1:1 avec la traversée de pixels du pointeur au-delà de la zone morte. Vous pouvez ajuster ce comportement pour ralentir ou accélérer la vitesse de mouvement.

Mise à jour de la matrice globale avec la nouvelle position de la caméra

Nous pouvons maintenant obtenir une coordonnée d’espace de scène sur laquelle la caméra fait le point et qui est mise à jour chaque fois que vous demandez à l’application de le faire (toutes les 60 secondes dans la boucle principale de l’application, par exemple). Ce pseudo code suggère le comportement d’appel à implémenter :


 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
        float3( 0, 1, 0 )					// the axis that is "up" in our space
        );	

Félicitations ! Vous avez implémenté un ensemble simple de contrôles tactiles de panoramique de la caméra dans l’application du Windows Store en C++ à l’aide de DirectX.

 

 

Afficher:
© 2014 Microsoft