Farseer Physic : Un moteur physique pour XNA

Cela faisait quelque mois que je voulais m’y remettre. Ce fut fait ces 2 derniers Week End( bien remplis il faut l’avouer :-) )

J’avais en effet avoir buté sur un de mes projets de jeux sur le moteur de collision (j’avoue n’avoir pas eu alors le temps nécessaire à prendre en compte des cas complexe de collision) J’avais alors identifié le moteur physique Farseer comme une (la?) bonne solution… Je m’y suis donc attelé tout récemment.

Le projet est dispo sur CodePlex, quelques samples et une documentation… disons perfectible :-) Donc ce blog a pour but de vous présenter ce que propose ce moteur et un pas à pas pour le prendre en main de manière simple.

XNA

Inutile de présenter XNA, tout le monde connait :-) L’objectif de XNA est de proposer un outil de développement (Visual C# Express, ou une version “Pro”), un Framework de développement (XNA Framework) et une runtime d’exécution (en fait un “dérivée” du Compact Framework .NET) présente sur Windows, XBox360 Zune et depuis cette semaine sur … Windows Phone serie 7 (cf annonce à Mix Las Vegas relayée par David Cloud Walker sur son blog) Autre info sur Windows Phone et XNA dispo ici.

Bref à l’heure ou Windows Phone commence a faire parler de lui, XNA et Silverlight vont bien vous occuper dans les mois qui viennent.

Rappelons que par défaut, un code XNA n’est rien d’autre qu’une boucle de jeu, boucle qui tourne à la vitesse des frame per second (FPS). Cette boucle n’est pas visible en tant que telle dans le code, mais 2 événements sont levés a chaque tour de boucle (Update et Draw), on va ainsi coder dans Update toute les calculs de position des objets (3D ou sprite en 2D) et dans le Draw les afficher.

Pour en savoir plus sur XNA, voir le site “officiel” du “creator club”. Vous y trouverez un ensemble de ressources, d’exemple, un forum… bref ce dont vous avez besoin pour commencer ! Ajoutons le blog de Valentin, grand maitre du XNA en France.. et qui se met aussi au Windows Phone 7 :-)

Farseer

Des que vous allez vous lancer dans l’écriture de votre premier jeu, et des lors que celui-ci va modéliser des “mouvements” d’objets, vous allez être confrontés au codage d’un moteur physique. Certes dans bon nombre de cas la logique de translation de vos objets et sprite n'est pas très complexe ou réaliste..; mais des lors que vous voudrez vous rapprocher des loi de la physique “classique” il devient vite une gageur de ré écrire l’ensemble d’un moteur … c’est déjà fait par et pour la communauté via (en autre, il en existe bien évidement d’autre) Farseer dans leur projet shared source sur CodePlex.

Farseer implémente un ensemble de lois physique qui s’applique a des “mobiles” définit dans votre scène. Farseer implémente bien évidement un moteur solide de collision. Rien que pour la gestion des collision, qui est en soit un véritable écueil a votre projet, Farseer doit retenir votre attention. En effet la gestion des collisions est potentiellement (et fréquemment de fait) une source d’erreur, d’imprécision qui altère à la fois la “jouabilité” de votre jeu, et son développement (j’ai moi même échoué sur des projet de jeux, par une implémentation trop “faible'” de la gestion des collisions… ou du moins y ai alloué trop de temps par rapport au reste…).

XNA et Farseer dans un premier code

La première chose à faire, est de donwloader la dernière build du moteur Farseer (au passage récupérer les exemples… il vont vous être utile !)

Une fois fait, vous pouvez créer votre premier projet. Créez une application Windows Game 3.1 (en attendant la version 4 du XNA, dispo en CTP )

image

Vous voila à pied d’œuvre ! Avec la fameuse boucle évoquée plus haut:

image

Reste maintenant à prendre une référence sur Farseer :

image  et les using qui vont bien :image

(je sais je ne fait pas dans la dentelle, mais bon ca mange pas de pain non plus et ca montre qu’il y a plein de chose dans ce Framework :-))

Quand on regarde la documentation sur codeplex ou mieux un quasi tuto la et surtout l’aide dispo ici et info le blog de Farseer (qui lui aussi s’est mis à Windows Phone cette semaine ! cf. ce post blog). On s’aperçoit qu’il faut capter quelques notions avant de commencer.

La modélisation physique est basé sur 2 classes clés: Body et Geométrie.

La première Body, va nous permettre de décrire le “comportement” de l’objet dans le “monde physique” (tel que appliquer des forces, moment, vitesse… ).

La seconde Geom(étrie) caractérise les éléments comme la position les dimension, rotation, collision … de l’objet.

Il faut donc “embarquer” ces 2 classes dans votre modélisation/code (la bonne idée ici serait de définir sa propre class pour modéliser vos “mobiles” et d’y embarquer sous forme de données propres ces deux classes)

           boxBody1 = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, 190, 190, 1);

           (Création d’un body pour un rectangle, grace aux méthode statiques du “BodyFactory”)

           boxBody1.Position = new Vector2(400, 100);
           boxBody1.IsStatic = true;

           (position et “mobilité” de l’objet, ici ca bougera pas ! du béton :-)

            boxGeom1 = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, boxBody1, 190, 190);

            (idem sur la Geométrie, ca vaut le coup de regarder les paramètres…)

Ensuite, bien sur, il faut un objet pour piloter la simulation et le “monde” physique. C’est à quoi sert l’objet suivant : PhysicsSimulator physicsSimulator; C’est sur cet objet que l’on intervenir pour régler quelques constantes de l’espace physique (gravité, type de friction…)

             physicsSimulator = new PhysicsSimulator(new Vector2(0, 200));

            (la gravité s’exprime par un vecteur à 2 dimension, ici 200 sur les Y, ca va tomber franchement !)

Coté temps (!) on peut fixer par exemple le FPS (ce qui a l’avantage de rendre votre code moins sensible aux perturbations CPU ) en jouant avec des objets statiques du Framework XNA

         IsFixedTimeStep = true;
         TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 10); //10ms => 100fps

Au moment du Update, il faut penser a transmettre le “tempo” au simulateur:

            physicsSimulator.Update(gameTime.ElapsedGameTime.Milliseconds * 0.001f);

           (le dernier paramètres se cale sur le 100 FPS demandé plus tôt…)

       Ca vaut le coup, au passage, d’appliquer une force sur l’objet, Update c’est fait pour cela, via:

                  if (Keyboard.GetState().IsKeyDown(Keys.Left)) boxBody2.ApplyForce(new Vector2(-400, 0));

Enfin le draw, très simplement utilise les données calculés dans le simulateur et affecté au Body: Toute la beauté du moteur :-)

                spriteBatch.Draw(box1, boxBody1.Position, null, Color.White, boxBody1.Rotation,
                new Vector2(box1.Width / 2, box1.Height / 2), 1, SpriteEffects.None, 0);

Le moteur de collision est très performant. Chaque Geom va pouvoir décrire avec qui il entre en collision ou non et son type de collision. On va ainsi fixer via la propriété MonGem.CollidesWith = CollisionCategory.All; Les collisions génère une évenements OnCollision sur la classe Geom. C’est très utile pour savoir qui est rentré en collision avec qui ! Inutile de s’abonner à l’événement pour gérer les mouvements physique, ca c’est le moteur qui s’en charge; Utile uniquement pour rajouter de la logique de jeu…

 

Le mot de la fin :

XNA reste de la balle et les annonces de ces dernières semaine à MIX (Las Vegas) sur le support d’XNA sur Windows Phone serie 7 vont certainement motiver plus d’un développeur a se lancer dans l’écriture de code et de jeux et nombre d’entre eux auront besoin d’un moteur Physique robuste… Farseer semble une bonne alternative.

Pour ma part je continue de développer quelques tableaux de jeux… je re posterai sur ce blog des infos complémentaires a la mise en œuvre de ce moteur…. à bientôt donc sur ce sujet !

 

Eric