Ajoutons une balle qui se déplaceC'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 balleOn 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

).
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:
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 :
Content.Load<Texture2D>("balle");
Nous avons maintenant ceci :
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");
}
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
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.
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
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

).
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 :
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

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

).
Déplaçons cette balleIl manque encore un peu de mouvement à cette balle.
Nous allons modifier la position de notre balle quand notre méthode "update()":
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

.
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)
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'écranMaintenant 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
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);
}
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.