Bienvenue, Invité. Veuillez vous connecter ou vous inscrire.
Avez-vous perdu votre courriel d'activation?
Devsgen.com - Forums « PC « C# « Tutorial « Premier projet XNA
Pages: [1]   Bas de page
  Imprimer  
Auteur Fil de discussion: Premier projet XNA  (Lu 157 fois)
0 Membres et 1 Invité sur ce fil de discussion.
nano
Pro
Débutant
***
Hors ligne Hors ligne

Messages: 212


azraelster@gmail.com
Voir le profil
« le: Juillet 15, 2010, 13:51:07 »

Pour comprendre au mieux les tutos xna, des notions de développements objets sont un plus.
Dans les tutos xna, vous trouverez pas mal de vocabulaire lié au développement objet.

Création du projet.

On va commencez par créer un projet "jeu Windows".
Pour celà, on fait fichier -> Nouveau -> Projet ...

On sélectionne "Windows Game (3.1)", on lui donne un nom, "FirstWindowsGame" pour moi, et on clique "Ok"

On a donc un projet qui contient un certain nombre de fichier et dossier.

Dans notre projet

Nous allons nous intéresser à Game1.cs

il contient la classe Game1 qui hérite de Microsoft.Xna.Framework.Game (une classe du framework Xna).

La classe Game1 contient déjà quelque élément.

Nous avons 2 membres privés :

Code:
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

un constructeur :

Code:
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

Et quelque méthodes présentes par défaut :
(je ne vous remet pas les commentaires des documentations au dessus des méthodes)


dans ces prochaines méthodes, nous avons les mots protected et override.
override signifie que cette fonction remplace celle de la classe mère (je vous rappelle que Game1 hérite de Microsoft.Xna.Framework.Game).

protected décrit quand à lui le niveau d'accès de la méthode.
Nous avons plusieurs niveau d'accès:
  • Public : la méthode est accessible à tous
  • Private : la méthode n'est accessible que dans la classe ou elle est définit
  • Protected : la méthode n'est accessible que pour la classe ou elle est définit et sa descendance (les classes qui en hérite).

Code:
         protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

Cet méthode sert pour faire l'initialisation de notre classe.


Code:
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

Cette méthode va charger le contenu de notre jeu.(exécuter une seule fois à l'ouverture du jeu)
C'est ici que nous allons charger les musiques, images, modèles dans notre jeu.
Ceux ci  pourront alors être utiliser tout au long du jeu.


Code:
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

Celle ci va décharger le contenu du jeu. (exécuter une seule fois à la fermeture du jeu)


Code:
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

On placera dans cette méthode la logique de notre jeu. C'est ici que nous capterons les entrées des périphérique de l'utilisateur, que nous calculerons les déplacements, les collisions, etc ...


Code:
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }

Le but de cette fonction est de faire purement de l'affichage, séparant ainsi logique du jeu et logique d'affichage.


Ce découpage n'est certes pas obligatoire mais permet une bonne séparation dans l'architecture de notre jeu.


Quelques changements basiques

On peut compiler et lancer notre jeu, on voit apparaitre une fenêtre avec un fond bleu.

Changeons la couleur du fond

Cette couleur est définit dans la méthode Draw (c'est cool, ce qui concerne l'affichage, on sait ou le chercher ^^).

c'est cette ligne en particulier définit la couleur du fond :

Code:
GraphicsDevice.Clear(Color.CornflowerBlue);

Color est une énumération contenant un large panel de couleur à notre disposition.

Si on veut changer de couleur c'est simple on efface "CornflowerBlue", on appuie sur Ctrl+espace pour activer l'intellisense, on voit maintenant les différentes possibilité de notre énumération.
(l'intellisense fonctionne aussi quand on saisit le "." après l'énumération, la classe ou la structure utilisée)

Je remplace donc par :

Code:
GraphicsDevice.Clear(Color.Chartreuse);

J'obtiens un jolie fond vert dont la couleur n'est pas sans rappeler une boisson qui porte ce nom ^^.


Utilisons le clavier pour quitter le jeu

Ensuite, on va regarder dans notre méthode update, nous avons ces 2 lignes:

Code:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

Ici on vérifie l'appuie de la touche "back" du gamepad du joueur 1.
Mais moi, j'ai pas de manette sur mon pc Pleurs donc je ne peux pas fermer l'application comme ça.
Je suis obligé de cliquez sur la croix, trop dur.

Je vais donc modifier ça, pour que lors de l'appuie d'une touche définit de mon clavier, le jeu se ferme.

Je remplace donc par :

Code:
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

Donc là, si sur mon clavier la touche echap est appuyée, je ferme mon jeu.

On essaie ça tout de suite, F5, j'ai mon affreuse fenêtre verte XD, j'appuie échap, ça se ferme. Ouf!!!


Modifions la taille de notre fenètre

Après, c'est bien beau tout ça. mais je veux pas d'un jeu en mode fenêtré moi en plus elle est toute petite la fenêtre sur mon écran ><. Pas content!!

Heureusement Xna a penser à nous ^^ (enfin, ses développeurs).
Vous aurez peut-être remarquez le GraphicsDeviceMAnager qui est instancié dans le constructeur de notre classe Game1.

En effet, cet objet référencé par notre classe par la variable "graphics" va nous permettre de configurer la taille de notre fenêtre et de la mettre en plein écran.

On va donc choisir une taille de fenêtre, par exemple 800*600.

on va donc ajouter 2 instructions dans le constructeur :

Code:
public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            this.graphics.PreferredBackBufferHeight = 600;
            this.graphics.PreferredBackBufferWidth = 800;
            Content.RootDirectory = "Content";
        }

jusque là rien de bien compliqué

Bon maintenant, on veut pouvoir passer en mode plein écran depuis notre jeux.
On va dire que la toucher "Enter" va nous permettre de passer du mode fenêtré au mode plein écran (et vice versa).

On va donc ajouter un petit bout de code dans la méthode Update de notre classe Game1:

Code:
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            // Toggles between Full screen an windowed mode
            if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                this.graphics.ToggleFullScreen();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

Si vous voulez un jeu en plein dès le démarrage, il suffit d'ajouter cette ligne au constructeur :

Code:
            this.graphics.IsFullScreen = true;

c'est ligne doit bien sur être placer après l'instanciation de l'objet "graphics" sinon on se retrouve avec une belle erreur qui nous empêche de compiler.

Bien sur le passage mode fenêtré/plein écran n'existe pas sur la xbox360, on est toujours en plein écran.
« Dernière édition: Juillet 17, 2010, 23:28:30 par nano » Journalisée
nano
Pro
Débutant
***
Hors ligne Hors ligne

Messages: 212


azraelster@gmail.com
Voir le profil
« Répondre #1 le: Juillet 15, 2010, 13:51:21 »

Ajoutons une balle qui se déplace

C'est bien beau tout ça!!
Mais pour l'instant, j'ai rien à part un fond unis avec une couleur qui pique les yeux ...

Bon, je passe le fond en noir et en mode fenêtré 800*600.

Dessinons une balle

On va prendre notre logiciel de dessin favori.
Je m'équipe de mon paint.net (non, c'est pas mon favori mais ça suffit pour faire la balle rapidement ^^).
Je dessine un carré blanc de 20*20 px, et je l'enregistre dans mes images (le choix du dossier est libre hein Clin d'oeil ).

Maintenant, j'importe mon image dans mon projet. Pour le faire, dans mon arborescence du projet, je fais un clique droit sur "Content" puis ajouter -> élément existant.

Maintenant dans "Content", nous avons notre balle. Regardons un peu ses propriétés.

nous avons ceci :



On voit que l'action de génération (ce qui va être effectué à la compilation) est sur "compiler".
"Content Importer" et "Content Processor" va permettre de définir comment va se dérouler l'importation.
Ici nous n'avons pas besoin de le modifier.

Nous remarquerons aussi que le champs Asset Name est, par défaut, le nom du fichier sans extension. Ce champs nous permettra d'identifier la texture dans notre application.

Nous image va être compiler en un format optimiser pour le XNA, le XNB qui sera placer dans le répertoire de jeu.

le champs "Copier dans le répertoire de sortie" concerne le fichier original dont nous n'avons pas besoin dans notre jeux. On le laissera donc à "Ne pas copier".

Maintenant, nous allons charger notre image dans notre jeux.

Nous allons donc ajouter un membre à notre classe Game1 qui stockera notre image.
On la stockera dans un objet de type "Texture2D".

Nous allons donc déclarer notre objet dans notre classe:

Code:
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        //Ball's texture
        Texture2D balleTexture;

Il nous faut aussi charger la texture. Si vous avez bien suivit, on le fait dans la méthode "LoadContent()"

nous ajoutons cette ligne pour charger notre texture :

Code:
Content.Load<Texture2D>("balle");

Nous avons maintenant ceci :

Code:
protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //load ball's texture
            Content.Load<Texture2D>("balle");
        }

Citation
La méthode Load de Content est une méthode générique. C'est à dire qu'elle fonctionne pour différent type d'objet dont on précisera le type.
Syntaxe
Code:
Content.Load<T>(string assetName);
qui retourne un objet du type T et prends en paramètre le nom de notre asset (la valeur du champs "Asset Name" de notre contenu qui est ici une "Texture2D")

Si on compile maintenant, on ne verra toujours pas notre balle. En effet à aucun moment, nous ne disons à notre programme de l'afficher.

Nous allons donc le faire maintenant:

Nous avons une méthode dédiée à l'affichage, c'est donc ici que nous allons afficher notre balle.

Code:
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spriteBatch.Draw(balleTexture, new Vector2(50, 50), Color.White);
            spriteBatch.End();
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }

"spriteBatch.Begin()" prépare les mécanisme de dessin

"spriteBatch.Draw()" a plusieurs surcharge, nous utiliseront dans un premier temps celle ci
Code:
spriteBatch.Draw(Texture2D , Vector2, Color)

Nous avons un Vector2 pour définir la position de l'élément, nous allons donc utiliser un membre de type Vector2 pour stocker la position de notre balle.

Je vous laisse déclarer ce vecteur et l'initialiser (pourquoi pas dans la méthode Initialize() tiens  Roulement des yeux ).
Donc moi, je l'ai appelé ballePos et je l'ai initialisé à avec 100 en x et 100 en y.

J'ajoute donc ma ligne pour faire l'affichage de cette texture :

Code:
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spriteBatch.Draw(balleTexture, new Vector2(50, 50), Color.White);
            spriteBatch.Draw(balleTexture, ballePos, Color.White);
            spriteBatch.End();
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }

J'ai volontairement laisser mon premier affichage Clin d'oeil

Je compile et je lance, nous avons 2 carrés blanc sur un fond noir.

La même image peut donc être afficher plusieurs fois à des positions différentes. Ceci est intéressant car ça nous permettra de ne pas gaspillé en ressource quand nous auront plein d'image à afficher dont certaines qui se répète un certain nombre de fois (exemple, les zelda-like Clin d'oeil ).


Déplaçons cette balle

Il manque encore un peu de mouvement à cette balle.

Nous allons modifier la position de notre balle quand notre méthode "update()":

Code:
        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            ballePos.X++;

            base.Update(gameTime);
        }

Nous faisons rien de bien méchant ici. On se contente de déplacer la balle horizontalement.
on incrémente X qui la position sur l'abscisse.

Notre balle se déplace vers la droite de notre fenêtre et en sort sans s'arrêter.

Normal, nous n'avons pas gérer la collision avec le bord de l'écran Clin d'oeil .

De plus la méthode "update()" s'effectue en boucle avec une fréquence dépendant des performances du pc sur lequel le jeu tourne.
Donc sur un vieux pc, la balle se déplacera moins vite que sur un pc dernière génération.

Nous voulons que la balle se déplace à la même vitesse pour tout type de pc.
Xna nous aide ici, en fournissant en paramètre de la fonction update un objet de type GameTime.
Il nous permet, entre autre, de savoir combien de temps s'est écoulé depuis la dernière fois que la méthode s'est exécuté.

Nous pouvons donc définir une vitesse de déplacement horizontale et verticale grâce à un Vector2.

Nous ajoutons donc un membre ballVitesse de type Vector2 à notre classe Game1.
(Nous n'oublierons pas de l'initialiser)

Code:
protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();
            ballePos += gameTime.ElapsedGameTime.Milliseconds * ballVitesse;

            base.Update(gameTime);
        }

voilà, le déplacement à vitesse constante quelque soit la plateforme n'est pas si compliqué que ça.
ma vitesse est en pixel par Millisecondes et est représenter par un vecteur.
la position de ma balle est en fait un vecteur pour plus de facilité pour les calculs.


Gérer les collisions avec le bords de l'écran

Maintenant nous allons gérer les collisions de notre balle avec l'écran pour la faire rebondir ^^

pour, ça on va tester les position de notre balle si on applique le déplacement.

ce qui nous donne ceci

Code:
        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();
            int ms = gameTime.ElapsedGameTime.Milliseconds;

            float posX = ballePos.X + ms*ballVitesse.X;
            if (posX < 0 || posX > (graphics.PreferredBackBufferWidth - balleTexture.Width))
                ballVitesse.X *= -1;

            float posY = ballePos.Y + ms * ballVitesse.Y;
            if (posY < 0 || posY > (graphics.PreferredBackBufferHeight - balleTexture.Height))
                ballVitesse.Y *= -1;

            ballePos += ms * ballVitesse;

            base.Update(gameTime);
        }


Code:
            float posX = ballePos.X + ms*ballVitesse.X;
            if (posX < 0 || posX > (graphics.PreferredBackBufferWidth - balleTexture.Width))
                ballVitesse.X *= -1;

Ici, on évalue la future position de la balle sur l'axe des abscisses et on vérifie que la balle ne sorte pas de l'écran.
Si elle sort, on inverse le sens de déplacement sur l'axe.

On fait la même chose avec les ordonnées.

« Dernière édition: Juillet 16, 2010, 15:08:29 par nano » Journalisée
nano
Pro
Débutant
***
Hors ligne Hors ligne

Messages: 212


azraelster@gmail.com
Voir le profil
« Répondre #2 le: Juillet 15, 2010, 15:32:45 »

Programmons avec classe

Bon, au vu du début du programme, on est bien parti pour faire un pong Clin d'oeil
Mais avant de faire les raquettes, on va devoir améliorer un peu la structure de notre programme.

En effet, si pour chaque éléments du jeux, on a plusieurs membres dans notre classe Game1, ça va être un sacré bazar.

On va donc regrouper les informations dans des classes.

Nous allons commencer par créer notre classe de base qui indiquera la position, et la texture à utiliser.
Nous appellerons cette classe Sprite, ce nom vous dit quelque chose, non?

On va donc créer une nouvelle classe que l'on appellera Sprite. Pour cela, un clique droit sur le projet -> ajouter -> Classe.
On lui donne le nom désiré : Sprite.cs
Citation
.cs est l'extension des fichiers sources C# et par défaut le nom de la classe est celui du fichier sans extension

On va commencer par ajouter les using dont nous avons besoin.
Nous aurons besoin de "Microsoft.Xna.Framework", "Microsoft.Xna.Framework.Graphics" et "Microsoft.Xna.Framework.Content".
Citation
Les "using" permettent de déclarer les namespace dont nous avons besoin.
Une fois déclarer, nous pouvons utilisé les classes contenus dans le namespace.

Dans cette classe, nous allons ajouté 2 attribut texture et position qui seront respectivement de type Texture2D et Vector2.

On va aussi faire le constructeur qui prends en paramètre un objet de type Vector2.
On va aussi y mettre quelque méthode :

  • une méthode pour charger sa texture
  • une méthode pour mettre à jour sa position
  • une méthode pour le dessiner


Nous obtenons donc ceci :

Code:
class Sprite
    {
        public Texture2D texture;
        public Vector2 position;

        public Sprite(Vector2 pPosition)
        {
            position = pPosition;
        }

        public void LoadContent(ContentManager content, string assetName)
        {
            texture = content.Load<Texture2D>(assetName);
        }

        public void Update(Vector2 deplacement)
        {
            position += deplacement;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, position, Color.White);
        }
    }

Citation
Nous mettons la position et la texture en public car il devront être accessible depuis l'extérieur.
Ce n'est pas la solution la plus élégante en développement objet, mais l'encapsulation va entrainer plus d'opération qui ici nous seraient totalement inutile.


Notre balle n'est pas statique, elle a une vitesse et un angle de déplacement, et les coordonnées max, X et Y
Nous allons donc faire une classe "Balle" qui héritera de la classe "Sprite.
Elle contiendra donc les informations de la classe "Sprite" plus celles que nous allons lui ajouter.

On aura besoin en plus de ces quelques informations:

  • Une vitesse qui sera représenté par un float
  • Un angle de déplacement qui sera représenté par un Vector2
  • Y max
  • X max

Nous allons aussi mettre la logique de déplacement de la balle dans cette classe.


Nous obtenons donc ceci :

Code:
    class Balle : Sprite
    {
        float vitesse;
        Vector2 angle;
        int xMax, yMax;

        public Balle(Vector2 position, int xMax, int yMax) : base(position)
        {
            this.xMax = xMax;
            this.yMax = yMax;
            this.vitesse = 0.2f;
            this.angle = new Vector2(1, 1);
        }

        public void Update(GameTime gameTime)
        {
            //calcul de la nouvel position
            position = new Vector2(position.X + vitesse * angle.X * gameTime.ElapsedGameTime.Milliseconds,
                                    position.Y + vitesse * angle.Y * gameTime.ElapsedGameTime.Milliseconds);

            //collision avec le bord haut ou le bas de l'écran?
            if (position.Y <= 0 || position.Y + texture.Height >= yMax)
                angle = new Vector2(angle.X, -angle.Y);
            //collision avec le bord droit ou gauche
            else if (position.X <= 0 || position.X + texture.Width >= xMax)
                angle = new Vector2(-angle.X, angle.Y);

        }
    }



il faut aussi faire les modifications de notre classe Game1 pour que celle ci utilise la classe que nous venons de créer.

ce qui nous donne ceci :

Code:
public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        //Ball's texture
        Balle balle;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            this.graphics.PreferredBackBufferHeight = 600;
            this.graphics.PreferredBackBufferWidth = 800;

            Content.RootDirectory = "Content";
        }


        protected override void Initialize()
        {
            balle = new Balle(new Vector2(250f, 250f), this.graphics.PreferredBackBufferWidth, this.graphics.PreferredBackBufferHeight);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            balle.LoadContent(Content, "balle");
        }

        protected override void UnloadContent()
        {
            Content.Unload();
        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            balle.Update(gameTime);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            balle.Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }

Notre code est plus propre et on peut plus facilement ajouter d'autre objet graphique.
Essayer d'ajouter une seconde balle avec l'ancien code puis avec celui.
Il y a bien moins de travail à fournir Clin d'oeil
« Dernière édition: Juillet 17, 2010, 23:07:04 par nano » Journalisée
nano
Pro
Débutant
***
Hors ligne Hors ligne

Messages: 212


azraelster@gmail.com
Voir le profil
« Répondre #3 le: Juillet 16, 2010, 15:09:09 »

Mettons nos raquettes

Maintenant que nos bases sont bien posées.

Mettre les raquettes n'est pas bien compliqué.

Donc, nous allons créer une classe "Player"

Code:
    class Player : Sprite
    {
        float vitesse;
        int yMax;

        public Player(Vector2 position, int yMax)
            : base(position)
        {
            this.yMax = yMax;
            this.vitesse = 0.5f;
        }

        public void Update(GameTime gameTime, bool up)
        {
            if (up && position.Y > 0)
                position = new Vector2(position.X, position.Y - vitesse * gameTime.ElapsedGameTime.Milliseconds);
            if (!up && position.Y + texture.Height < yMax)
                position = new Vector2(position.X, position.Y + vitesse * gameTime.ElapsedGameTime.Milliseconds);
        }
    }

On ajoute le code nécessaire pour charger, déplacer et afficher la barre du joueur 1.

Code:
public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        //Ball's texture
        Balle balle;
        Player player1;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            this.graphics.PreferredBackBufferHeight = 600;
            this.graphics.PreferredBackBufferWidth = 800;

            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            balle = new Balle(new Vector2(250f, 250f), this.graphics.PreferredBackBufferWidth, this.graphics.PreferredBackBufferHeight);
            player1 = new Player(new Vector2(20f, 300f), this.graphics.PreferredBackBufferHeight);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            balle.LoadContent(Content, "balle");
            player1.LoadContent(Content, "barre");
        }

        protected override void UnloadContent()
        {
            Content.Unload();
        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();
            if (Keyboard.GetState().IsKeyDown(Keys.Up))
                player1.Update(gameTime, true);
            if (Keyboard.GetState().IsKeyDown(Keys.Down))
                player1.Update(gameTime, false);
            balle.Update(gameTime);
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            balle.Draw(spriteBatch);
            player1.Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }

Maintenant, il faut gérer les collisions entre la barre et la balle.
Nous laisserons la responsabilité du calcul de la collision à la classe balle.

Pour faire ceci, nous allons ajouter un paramètre la méthode Update de la classe Balle, ce qui nous donne cet entête:

Code:
public void Update(GameTime gameTime, Sprite player1)

Nous allons créer un rectangle avec les info des Sprite du player1 et de la balle :

Code:
            Rectangle ballRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
            Rectangle player1Rect = new Rectangle((int)player1.position.X, (int)player1.position.Y, player1.texture.Width, player1.texture.Height);

La structure "Rectangle" propose quelque fonction intéressante donc le test d'intersection entre 2 rectangles qui nous servira pour tester la collision ^^.

notre classe Balle est maintenant comme ceci:

Code:
class Balle : Sprite
    {
        float vitesse;
        Vector2 angle;
        int xMax, yMax;

        public Balle(Vector2 position, int xMax, int yMax) : base(position)
        {
            this.xMax = xMax;
            this.yMax = yMax;
            this.vitesse = 0.2f;
            this.angle = new Vector2(1, 1);
        }

        public void Update(GameTime gameTime, Sprite player1)
        {
            //calcul de la nouvel position
            position = new Vector2(position.X + vitesse * angle.X * gameTime.ElapsedGameTime.Milliseconds,
                                    position.Y + vitesse * angle.Y * gameTime.ElapsedGameTime.Milliseconds);

            Rectangle ballRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
            Rectangle player1Rect = new Rectangle((int)player1.position.X, (int)player1.position.Y, player1.texture.Width, player1.texture.Height);

            //collision avec le bord haut ou le bas de l'écran?
            if (position.Y <= 0 || position.Y + texture.Height >= yMax)
                angle = new Vector2(angle.X, -angle.Y);
            else if (player1Rect.Intersects(ballRect))
                angle = new Vector2(-angle.X, angle.Y);
            //collision avec le bord droit ou gauche
            else if (position.X <= 0 || position.X + texture.Width >= xMax)
                angle = new Vector2(-angle.X, angle.Y);

        }
    }

Je vous laisse faire le boulot pour la deuxième raquette. il n'y aura pas grands chose à faire ^^.

Je vous laisse aussi décider de ce qui se fera lorsque la balle sortira de l'écran Clin d'oeil

Nous verrons d'autre fonctionnalité dans d'autre tuto comme :

  • Afficher du texte sur notre fenêtre de jeu
  • Animer des Sprites
  • Afficher les FPS
  • jouer du sons
  • ...
« Dernière édition: Juillet 17, 2010, 23:28:18 par nano » Journalisée
nano
Pro
Débutant
***
Hors ligne Hors ligne

Messages: 212


azraelster@gmail.com
Voir le profil
« Répondre #4 le: Juillet 17, 2010, 23:30:03 »

Ce tuto est maintenant finit.
Tout commentaire est bienvenue.
Si vous avez des idées d'amélioration du tuto n'hésitez pas Clin d'oeil.
Journalisée
Lord Dead
Admin
Débutant
*****
Hors ligne Hors ligne

Messages: 1862



Voir le profil Courriel
« Répondre #5 le: Août 16, 2010, 02:38:37 »

Merci pour ce tuto plus qu'intéressant nano Clin d'oeil
Journalisée

pyroesp
Débutant
*
Hors ligne Hors ligne

Messages: 622


The Spanish Pyro


Voir le profil Courriel
« Répondre #6 le: Août 16, 2010, 12:18:41 »

Quel tuto  Choqu&eacute;, bravo et merci. ^^
Journalisée

There are only 10 types of people in this world:
  • Those who understand binary.
  • And those who don't.
nano
Pro
Débutant
***
Hors ligne Hors ligne

Messages: 212


azraelster@gmail.com
Voir le profil
« Répondre #7 le: Août 19, 2010, 12:22:18 »

Merci pour ces commentaires ^^.

J'ai d'autre tuto en cours, mais il arriveront pas tout de suites.

Il y en a qui sont bien plus conséquent.
Celui là, c'est un tuto moyen Clin d'oeil.
Journalisée
pyroesp
Débutant
*
Hors ligne Hors ligne

Messages: 622


The Spanish Pyro


Voir le profil Courriel
« Répondre #8 le: Août 20, 2010, 00:32:25 »

Un tuto moyen qui fait 4 post, a quoi ressemblera un tuto "plus conséquent" Choqu&eacute;
Journalisée

There are only 10 types of people in this world:
  • Those who understand binary.
  • And those who don't.
Pages: [1]   Haut de page
  Imprimer  
 
Aller à: