Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
Publié parMarine Crouzet Modifié depuis plus de 9 années
1
Dév. d’application interactive III Tile Engine
2
Plan de leçon Moteur de tuiles (tile engine) Définition Classes Dans le cadre de ce cours, nous allons construire un moteur de tuile (tile engine) qui pourra être utilisé dans tous les projets XNA Ce sera un développement itératif, i.e. que l’on fera plusieurs versions
3
Moteur de tuile : Définition Un moteur de tuile (TE) est une technique qui permet de générer une grand objet graphique à partir de plus petits objets Cette technique permet d’économiser de l’espace mémoire (RAM) ainsi que d’améliorer le processus d’affichage
4
Moteur de tuile : Définition Le principe est d’utiliser une feuille de textures qui contient plusieurs tuiles ainsi qu’une matrice de deux dimensions qui contient des adresses de tuiles En adressant chaque tuile à chaque cellule de la matrice, on peut générer une grande image de façon efficace En plus de l’affichage, on peut ajouter des éléments de collision ainsi que plusieurs couches à l’intérieur de la même matrice
5
Moteur de tuile Dans la première version, nous allons utiliser une feuille de tuile simple avec seulement 1 rangée de 4 tuiles
6
Les classes Les classes utilisées seront les suivantes pour la version 1
7
Les classes MapCell représente une cellule de la carte MapRow représente une rangée de la carte et contient une liste de cellules TileMap représente la carte et contient une collection de MapRow Tile est la texture Camera est la vue de la carte
8
Classe : MapCell package models; public class MapCell { int tileID; public int getTileID() { return tileID; } public void setTileID(int tileID) { this.tileID = tileID; } public MapCell(int tileID) { super(); this.tileID = tileID; }
9
Classe : MapRow public class MapRow { ArrayList columns; public MapRow() { columns = new ArrayList (); } public MapCell getCell(int cellIndex) { return columns.get(cellIndex); }
10
Classe : TileMap public class TileMap { ArrayList rows = new ArrayList (); int mapWidth = 50; int mapHeight = 50; public TileMap() { super(); for (int y = 0; y < mapHeight; y++) { MapRow currentRow = new MapRow(); for (int x = 0; x < mapWidth; x++) { currentRow.columns.add(new MapCell(0)); } rows.add(currentRow); } generateTest(); } Fait une carte 2D Dimension de la carte en nombre de tuiles Initialisation de la carte
11
Classe : TileMap private void generateTest() { // Début de la création rows.get(0).columns.get(3).setTileID(2); rows.get(0).columns.get(4).setTileID(2); rows.get(0).columns.get(5).setTileID(2); rows.get(0).columns.get(6).setTileID(2); rows.get(0).columns.get(7).setTileID(2); rows.get(1).columns.get(3).setTileID(1); rows.get(1).columns.get(4).setTileID(1); rows.get(1).columns.get(5).setTileID(1); rows.get(1).columns.get(6).setTileID(1); rows.get(1).columns.get(7).setTileID(1); rows.get(2).columns.get(2).setTileID(3); rows.get(2).columns.get(3).setTileID(3); rows.get(2).columns.get(4).setTileID(3); rows.get(2).columns.get(5).setTileID(3); rows.get(2).columns.get(6).setTileID(3); rows.get(2).columns.get(7).setTileID(1); rows.get(3).columns.get(2).setTileID(3); rows.get(3).columns.get(3).setTileID(1); rows.get(3).columns.get(4).setTileID(1); rows.get(3).columns.get(5).setTileID(2); rows.get(3).columns.get(6).setTileID(2); rows.get(3).columns.get(7).setTileID(2); rows.get(4).columns.get(2).setTileID(3); rows.get(4).columns.get(3).setTileID(1); rows.get(4).columns.get(4).setTileID(1); rows.get(4).columns.get(5).setTileID(2); rows.get(4).columns.get(6).setTileID(2); rows.get(4).columns.get(7).setTileID(2); rows.get(5).columns.get(2).setTileID(3); rows.get(5).columns.get(3).setTileID(1); rows.get(5).columns.get(4).setTileID(1); rows.get(5).columns.get(5).setTileID(2); rows.get(5).columns.get(6).setTileID(2); rows.get(5).columns.get(7).setTileID(2); // Fin de la création }
12
Classe : Tile public final class Tile { static final int TILESIZE = 32; static Texture tileSetTexture; public static Rectangle getSourceRectangle(int tileIndex) { return new Rectangle(tileIndex * TILESIZE, 0, TILESIZE, TILESIZE); } public static Texture getTileSetTexture() { return tileSetTexture; } public static void setTileSetTexture(Texture tileSetTexture) { Tile.tileSetTexture = tileSetTexture; } Retourne le rectangle représentant la position de la tuile en index
13
Classe : Camera /// /// Classe statique permettant de définir la position de la vue sur /// la carte /// public final class Camera { static Vector2 location = Vector2.Zero; public static Vector2 getLocation() { return location; }
14
Test //Dans la zone de déclaration de variables SpriteBatch batch; TileMap map = new TileMap(); int carreLargeur = 5; int carreHauteur = 5; int tileSize = 32; //Dans le Create Tile.setTileSetTexture (new Texture("part1_tileset.png")); Ce que l’on veut afficher de la carte
15
Test Gdx.gl.glClearColor(1, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); /** * Calculs pour le premier carré en haut à gauche */ Vector2 firstSquare = new Vector2( Camera.getLocation().x / (float)tileSize, Camera.getLocation().y / (float)tileSize); int firstX = (int) firstSquare.x; int firstY = (int) firstSquare.y; /** * Calcul pour le décalage pour la camera pour les côtés */ Vector2 squareOffset = new Vector2( Camera.getLocation().x % tileSize, Camera.getLocation().y % tileSize); int offsetX = (int)squareOffset.x; int offsetY = (int)squareOffset.y; //…
16
Test //… for (int y = 0; y < carreHauteur; y++) { int positionY = (y * tileSize) - offsetY; for (int x = 0; x < carreLargeur; x++) { // Va chercher le rectangle de la tuile à afficher Rectangle srcRect = Tile.getSourceRectangle(map.getRow(y + firstY).getCell(x + firstX).getTileID()); batch.draw(Tile.getTileSetTexture(), (x * tileSize) - offsetX, positionY, (int)srcRect.x, (int)srcRect.y, (int)srcRect.width, (int)srcRect.height); } batch.end(); Après ce code, il devrait être exécutable
17
Test 2 Dans le Update KeyboardState ks = Keyboard.GetState(); // Allows the game to exit if (ks.IsKeyDown(Keys.Escape)) this.Exit(); if (ks.IsKeyDown(Keys.Left)) Camera.Location.X = MathHelper.Clamp(Camera.Location.X - 2, 0, (myMap.MapWidth - squaresAcross) * tileSize); if (ks.IsKeyDown(Keys.Right)) Camera.Location.X = MathHelper.Clamp(Camera.Location.X + 2, 0, (myMap.MapWidth - squaresAcross) * tileSize); //…
18
Test 2 Dans le Update if (ks.IsKeyDown(Keys.Up)) Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y - 2, 0, (myMap.MapHeight - squaresDown) * tileSize); if (ks.IsKeyDown(Keys.Down)) Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y + 2, 0, (myMap.MapHeight - squaresDown) * tileSize); } On déplace la caméra en X et Y en limitant entre deux bornes
19
Résultats On observe que la carte affichée est de 5 x 5, soit les valeurs de carreHauteur et carreLargeur Ainsi on limite l’affichage dans le Draw La limite est de 50 tuiles de largeur et hauteur Cette valeur est définie dans TileMap
20
Moteur de tuiles Version 2 Tuile transparente
21
Description Dans la version 1, le jeu de tuiles n’avait qu’une seule rangée avec des tuiles de dimensions fixes Dans un premier temps nous allons utiliser un autre jeu de tuiles. Ensuite mettre à jour la classe Tile et le Update du jeu pour éliminer les valeurs « hardcodées »
22
Jeu de tuiles Ajouter ce jeu dans le même que le premier jeu
23
Classe : Tile Modifier les dimensions pour qu’elles soient de 48x48 en ajoutant les propriétés TileWidth et TileHeight Maintenant que c’est un jeu de tuile 2D, il faudra modifier la méthode GetSourceRectangle pour retourner la bonne position int tileY = tileIndex / (TileSetTexture.Width / TileWidth); int tileX = tileIndex % (TileSetTexture.Width / TileWidth); return new Rectangle(tileX * TileWidth, tileY * TileHeight, TileWidth, TileHeight);
24
Game Dans Game Update, modifier le code où est utilisé la variable tileSize pour utiliser les nouvelles propriétés publics de Tile Faire de même pour la méthode Draw Si on exécute, on devrait avoir un résultant un peu désorganisé Pourquoi et comment on corrige?
25
Les couches Dans la première version, on ne pouvait qu’afficher qu’une seule texture par cellule Ce n’était pas un problème car chaque tuile occupait l’espace entier Cependant la transition entre deux terrains était brusque Plusieurs options existent, mais certaines sont meilleures que d’autres
26
Les couches On pourrait dessiner chaque transition existante pour chaque tuile C’est commun et ce n’est pas un problème si le nombre de tuiles est petit Dans le cas de 4 tuiles différentes, il faudrait 16 transitions et ce seulement dans le sens des transitions horizontales Pas efficace… Si on augmente le nombre de tuiles, il faudrait faire le carré pour obtenir le nombre de transitions possibles (horizontales)
27
Les couches Une autre méthode serait de programmer des règles pour limiter les choix Par exemple la transition désert/glace serait impossible Une autre façon est d’utiliser la transparence des tuiles. Ainsi ces tuiles pourraient être dessinées par dessus d’autres tuiles de base Cette méthode sera préconisée car elle réduit considérablement le nombre de tuiles
28
Classe : MapCell Pour faire en sorte que l’on accepte plusieurs tuiles empilées, il faudra modifier la définition de la cellule Modifier la classe MapCell pour ajouter la liste suivante public List BaseTiles = new List (); Cela permettra d’empiler un nombre infini de tuiles sur la même cellule
29
Classe : MapCell Modifier la propriété TileID de la classe MapCell public void setTileID(int tileID) { if (baseTiles.size() > 0) { baseTiles.set(0, tileID); } else baseTiles.add(tileID); }
30
Classe : MapCell Ajouter la méthode suivante public void AddBaseTile(int tileID) { BaseTiles.Add(tileID); } Cette commande permet d’empiler les tuiles La première tuile sera celle de base
31
Dessiner les tuiles Une fois que la classe des cellules a été modifiée, on voudrait dessiner chaque tuile de chaque cellule Dans la méthode Draw, trouver le draw du batch et modifier celle-ci par le code suivant for (int tileId : map.getRow(y + firstY).getCell(x + firstX).getBaseTiles()) { // Va chercher le rectangle de la tuile à afficher Rectangle srcRect = Tile.getSourceRectangle(tileId); batch.draw(Tile.getTileSetTexture(), (x * Tile.tileWidth) - offsetX, positionY, (int)srcRect.x, (int)srcRect.y, (int)srcRect.width, (int)srcRect.height); }
32
Dessiner les tuiles On se retrouve à parcourir 3 boucles pour dessiner la carte En gros, on enveloppe batch.draw pour qu’elle dessine chaque tuile
33
Classe : TileMap Pour tester la transition, ajoutons des tuiles à la carte actuelle À la fin de la création de la méthode drawTest() dans TileMap, ajouter les tuiles suivantes Rows[3].Columns[5].AddBaseTile(30); Rows[4].Columns[5].AddBaseTile(27); Rows[5].Columns[5].AddBaseTile(28); Rows[3].Columns[6].AddBaseTile(25); Rows[5].Columns[6].AddBaseTile(24); Rows[3].Columns[7].AddBaseTile(31); Rows[4].Columns[7].AddBaseTile(26); Rows[5].Columns[7].AddBaseTile(29); Rows[4].Columns[6].AddBaseTile(104);
34
Exercices Dans le fichier de jeu, modifiez la dimension d’affichage de la caméra pour qu’elle s’adapte à la dimension de l’écran Créez une carte avec les tuiles à votre disposition
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.