Intégration de XNA dans une application WPF

XNA, basé sur DirectX, offre de nombreux avantages pour le développement de jeux en C# sur la plateforme .NET, notamment la compatibilité avec la Xbox 360. Cependant, combiner XNA avec WPF pour créer des interfaces graphiques avancées présente des défis. Voici une approche pour héberger une application XNA au sein d'une fenêtre WPF.

Étape 1 : Créer une application de jeu XNA

Commencez par développer une application XNA basique. Par exemple, un jeu qui change la couleur de l'écran à chaque image. Ce processus est fondamental mais hors du périmètre détaillé ici.

Étape 2 : Configurer la fenêtre WPF avec un hôte WinForms

Puisque l'intégration directe de XNA dans WPF n'est pas native, utilisons un contrôle hôte WinForms comme intermédiaire. Créez un projet WPF et ajoutez une référence à l'assemblage System.Windows.Forms. Le code XAML suivant illustre une fenêtre avec un panneau pour le rendu XNA :

<Window x:Class="MonApplication.FenetrePrincipale"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        Title="Éditeur de Jeu" Height="Auto" Width="Auto">
    <DockPanel>
        <Menu Name="menuPrincipal" DockPanel.Dock="Top"/>
        <StatusBar Name="barreStatut" DockPanel.Dock="Bottom">
            <StatusBarItem>
                <TextBlock Name="texteStatut">Prêt à charger ou créer un projet.</TextBlock>
            </StatusBarItem>
        </StatusBar>
        <WindowsFormsHost DockPanel.Dock="Bottom" Width="800" Height="600">
            <wf:Panel x:Name="zoneRendu"/>
        </WindowsFormsHost>
    </DockPanel>
</Window>

Ce code place le jeu XNA entre le menu et la barre d'état, démontrant l'intégration avec les éléments WPF.

Étape 3 : Adapter la classe de jeu pour accepter un handle de fenêtre

Modifiez la classe de jeu XNA pour recevoir un handle de fenêtre lors de l'initialisation. Utilisez l'événement PreparingDeviceSettings pour configurer le périphérique garphique :

public class JeuXna : Game
{
    private IntPtr handleFenetre;
    private GraphicsDeviceManager gestionnaireGraphiques;

    public JeuXna(IntPtr handle)
    {
        this.handleFenetre = handle;
        gestionnaireGraphiques = new GraphicsDeviceManager(this);
        gestionnaireGraphiques.PreparingDeviceSettings += SurParametragePeripherique;
        this.IsMouseVisible = true;
    }

    private void SurParametragePeripherique(object sender, PreparingDeviceSettingsEventArgs args)
    {
        args.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = handleFenetre;
    }
}

Étape 4 : Lancer le jeu depuis la fenêtre WPF sur un thread séparé

Pour éviter de bloquer l'interface WPF, exécutez le jeu XNA sur un thread distinct. Dans le code-behind de la fenêtre WPF, récupérez le handle du panneau et démarrez le jeu dans un nouveau thread :

public partial class FenetrePrincipale : Window
{
    private JeuXna instanceJeu;

    public FenetrePrincipale()
    {
        InitializeComponent();
        IntPtr handle = zoneRendu.Handle;
        DemarrerJeuEnArrierePlan(handle);
    }

    private void DemarrerJeuEnArrierePlan(IntPtr handleFenetre)
    {
        Thread threadJeu = new Thread(() =>
        {
            instanceJeu = new JeuXna(handleFenetre);
            instanceJeu.Run();
        });
        threadJeu.Start();
    }
}

Cette méthode utilise une expression lambda pour démarrer le jeu, mais vous pouvez aussi définir une méthode nommée pour plus de clarté. L'essentiel est que le jeu s'exécute en parallèle de l'interface WPF, permettant une interaction fluide.

Considérations techniques supplémentaires

L'utilisation de threads et de delegates en C# permet une gestion efficace des tâches concurrentes. Une expression lambda comme () => { } est une syntaxe concise pour créer des fonctions anonymes, équivalente à définir une méthode distincte. Par exemple, la méthode DemarrerJeuEnArrierePlan pourrait être réécrite avec une fonction classique, mais la version lambda est plus compacte pour des opérations simples. Assurez-vous de gérer correctement la synchronisation des threads si nécessaire, bien que dans ce cas, l'isolation du jeu dans un thread dédié minimise les conflits.

Étiquettes: XNA WPF CSharp WinForms DirectX

Publié le 1 juin à 02h40