Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Chapitre 3 : La classe Tile

Par gnicos (Nicolas Gauville), le 13 juillet 2012
Navigation rapide :

<< Chapitre 2 - Sommaire - Chapitre 4 >>

Dans les prochains chapitres, nous allons entamer la réalisation de notre moteur isométrique JavaScript, puis réaliser un petit jeu. Par la suite, les annexes se baseront toutes sur le moteur isométrique réalisé dans ces quelques chapitres.

I. Organisons notre code

A. La POO en JS

a) Implémentation de la POO en JavaScript

Le JavaScript permet d'utiliser la Programmation Orienté Objet, et c'est donc ce que nous allons faire, de façon à avoir un code plus clair et surtout plus flexible. Malheureusement, l'implémentation de la programmation orienté objet en JavaScript est bien moins complète qu'en ActionScript 3. Nous tenterons d'obtenir un code clair et strict malgré les quelques imprécisions du JavaScript sur ce point.

Certains d'entre vous n'ont peu être jamais utilisé la POO en JavaScript. Si c'est le cas, ne vous en faites pas, la grosse difficulté de la POO étant de comprendre la logique, et non apprendre une nouvelle syntaxe, vous devriez vous y faire sans trop de difficulté.

Si vous n'avez jamais utilisé de POO dans aucun langage par contre, je vous conseille vivement de suivre un tutoriel sur le sujet (en JavaScript ou un autre langage).

b) Choix du tutoriel

Dans ce tutoriel, de façon à obtenir un code clair et bien lisible, nous allons :

- Utiliser un fichier javascript unique par classe.

- Commenter clairement le code (pour compléter mes explications).

Lorsque l'on développe un projet, c'est probablement la meilleure façon de faire pour s'y retrouver. Cependant, lorsque vous publiez un projet, pensez au fait qu'il est préférable, avant de le publier, de faire ceci :

- Utiliser un compresseur JavaScript qui permettra de supprimer les commentaires, espaces inutiles, … de façon à réduire significativement la taille de vos fichiers JS.

- Rassembler tout votre code dans un seul fichier JS, de façon à ne pas rendre le chargement très lent à ceux qui ont un fort ping (même une connexion haut débit peut prendre énormément de temps à charger un site avec de trop nombreux fichiers, si ladite connexion à un ping important).

- Garder la version “fichiers séparés/code non compressé” parallèlement, en gardant ainsi une version pour le développement, et une version publiée.

B. Trois classes de base

Au niveau de l'organisation, nous utiliserons pour le moment cinq fichiers JavaScript, dont trois qui définirons des classes.

assets/

core.js

Comme dans les chapitres précedents, ce sera le fichier “de base” qui utilisera nos trois classes pour réaliser le rendu.

gfx.js

Dans ce fichier, on placera les fonctions qui généreront les graphiques vectoriels.

src/

tile.js

Classe Tile: Classe de base pour toutes les tuiles du jeu. Nous allons créer cette première classe dans ce chapitre.

map.js

Classe Map : Classe de gestion de la carte du jeu (ensemble de tuiles).

player.js

Classe Player: Classe pour la création de personnage.

tiletype.js

Objet TileType : Objet définissant deux types de tuiles : PNG ou Vectorielle.

Vous pouvez déjà créer ces deux dossiers et tout ces fichiers, nous les utiliserons dans les prochains chapitres. On pense bien sur à les inclure dans le fichier HTML :

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<!-- CSS -->
		<style>
                body
                {
                        background-color: black;
                	text-align: center;
                }
                </style>
 
                <script src="http://code.createjs.com/easeljs-0.4.1.min.js"></script>
		<title>TBG HTML/JS</title>
	</head>
	<body>
		<!-- BODY -->
		<canvas id="gameview" width="800" height="600">
  			Désolé, votre navigateur ne supporte pas la technologie Canvas.
		</canvas>
 
		<!-- JS -->
        	<script type="text/javascript" src="src/tiletype.js"></script>
                <script type="text/javascript" src="src/tile.js"></script>
                <script type="text/javascript" src="src/map.js"></script>
                <script type="text/javascript" src="src/player.js"></script>
                <script type="text/javascript" src="assets/gfx.js"></script>
        	<script type="text/javascript" src="assets/core.js"></script>
	</body>
</html>

Maintenant, nous allons nous intéresser au fichier tile.js, contenant notre futur classe Tile.

II. Classe Tile

A. Structure de la classe Tile

Comme dit plus haut, la classe “Tile” permettra de gérer les tuiles du jeu.

Voici la structure que cette classe va adopter :

Propriétés

string type

Pour commencer, nos tuiles pourront être faites de dessins ou d'images PNG. La propriété type définira donc quel est le type de tuile (PNG ou dessin).

shape content

Contenu graphique de la tuile.

bool walkable

Boolean qui indique si le joueur peut marcher sur la tuile, ce qui permettra de délimiter facilement la carte.

int offsetX

Décalage graphique en X. Cette propriété sera particulièrement utile pour ajuster la position d'une image PNG par exemple.

int offsetY

Décalage graphique en Y.

map map

Carte dans laquelle la tuile à été ajoutée.

int posX

Position en X sur ladite carte (en nombre de tuiles).

int posY

Position en Y sur ladite carte (en nombre de tuiles).

int posZ

Position en Z. Cette propriété n'a pas d'incidence sur la position de la tuile, mais permettra de gérer les profondeurs lorsque deux tuiles ont les même coordonnées en X et Y.

Méthodes

void dispose ()

Méthode permettant de détruire l'objet concerné. Dans ce tutoriel, toutes les classes auront une méthode dispose.

B. Objet "TileType"

Puisque, comme nous l'avons vu, nous aurons besoin de l'objet TileType, autant le définir maintenant, dans le fichier tiletype.js. C'est simple et rapide, mais bien pratique.

/**
 * TileType
 */
var TileType =
{
        PNG: "PNG",
        DRAW: "DRAW"
};

C. Définition et Constructeur

Nous allons maintenant commencer à coder notre classe :

/**
 * Class Tile
 */
var Tile = function ( $type, $content, $walkable, $offsetX, $offsetY )
{
        this.construct ( $type, $content, $walkable, $offsetX, $offsetY );
};

Pour des raisons de clarté, le constructeur est définit à la suite, par une méthode “construct”. On va ensuite créer une variable “p” qui sera une référence au prototype de notre classe, de façon à réduire le code.

var p = Tile.prototype;

Nous pouvons maintenant déclarer les propriétés de notre classe. Pour l'instant, nous allons les assigner à leur valeur par défaut :

/**
 * string TileType
 * Type de tuile. Egal à TileType.PNG où TileType.DRAW.
 */
p.type = TileType.DRAW;
 
/**
 * object content
 * Contenu graphique (shape).
 */
p.content = null;
 
/**
 * bool walkable
 * Indique si les joueurs peuvent marcher sur la tuile.
 */
p.walkable = true;
 
/**
 * int offsetX
 * Décalage de l'image en X.
 */
p.offsetX = 0;
 
/**
 * int offsetY
 * Décalage de l'image en Y.
 */
p.offsetY = 0;
 
/**
 * Map Map
 * Carte à laquelle la tuile à été ajoutée.
 */
p.map = null;
 
/**
 * int posX
 * Position de la tuile sur la carte en X (nb de tuiles).
 */
p.posX = 0;
 
/**
 * int posY
 * Position de la tuile sur la carte en Y.
 */
p.posY = 0;
 
/**
 * int posZ
 * Position de la tuile sur la carte en Z.
 */
p.posZ = 0;

Pour le constructeur, le JavaScript n'étant pas un langage très strict, nous allons prendre quelques précautions en assignant les variables.

Pour les variables type et walkable, deux cas sont possibles (true/false et PNG/DRAW), et l'un d'eux à été assigné par défaut. Il nous suffit donc de vérifier que ce n'est pas l'autre (celui qui n'est pas par défaut), et changer si c'est le cas.

Nous utiliserons ”===” et non ”==” pour vérifier à la fois le type et le contenu des variables.
if ( $type === TileType.PNG )
{
        this.type = $type;
}
 
if ( $walkable === false )
{
        this.walkable = false;
}

Pour les offsets, nous vérifierons simplement le type avant d'assigner la variable :

if ( typeof $offsetX === typeof 0 )
{
        this.offsetX = $offsetX;
}
 
if ( typeof $offsetY === typeof 0 )
{
        this.offsetY = $offsetY;
}

Pour le paramètre content, nous pouvons vérifier qu'il existe et qu'il s'agit bien d'un objet affichable (par exemple en vérifiant qu'il a une propriété “visible”).

if ( $content && $content.visible )
{
        this.content = $content;
}

Nous avons ainsi notre constructeur :

/**
 * Constructeur.
 */
p.construct = function ( $type, $content, $walkable, $offsetX, $offsetY )
{
        if ( $type === TileType.PNG )
        {
                this.type = $type;
        }
 
        if ( $walkable === false )
        {
                this.walkable = false;
        }
 
        if ( typeof $offsetX === typeof 0 )
        {
                this.offsetX = $offsetX;
        }
 
        if ( typeof $offsetY === typeof 0 )
        {
                this.offsetY = $offsetY;
        }
 
        if ( $content && $content.visible )
        {
                this.content = $content;
        }
};

D. A la corbeille !

On termine avec une méthode toute bête : la méthode dispose. Cette méthode à simplement pour fonction de “faire le nettoyage” quand nous n'avons plus besoin d'une instance. Ici, il n'y a pas de “setInterval” ou “setTimeOut”, pas d'écouteurs d'évènements, donc nous n'avons pas grand chose à faire :

/**
 * void dispose
 * @purpose : Détruit la tuile.
 */
p.dispose = function ()
{
        this.map = null;
        this.type = null;
        this.content = null;
        this.walkable = null;
        this.offsetX = null;
        this.offsetY = null;      
};

E. Notre classe

Notre classe Tile est maintenant terminée, et elle contient donc le code suivant :

/**
 * Class Tile
 */
var Tile = function ( $type, $content, $walkable, $offsetX, $offsetY )
{
        this.construct ( $type, $content, $walkable, $offsetX, $offsetY );
};
 
var p = Tile.prototype;
 
/**
 * string TileType
 * Type de tuile. Egal à TileType.PNG où TileType.DRAW.
 */
p.type = TileType.DRAW;
 
/**
 * object content
 * Contenu graphique (shape).
 */
p.content = null;
 
/**
 * bool walkable
 * Indique si les joueurs peuvent marcher sur la tuile.
 */
p.walkable = true;
 
/**
 * int offsetX
 * Décalage de l'image en X.
 */
p.offsetX = 0;
 
/**
 * int offsetY
 * Décalage de l'image en Y.
 */
p.offsetY = 0;
 
/**
 * Map Map
 * Carte à laquelle la tuile à été ajoutée.
 */
p.map = null;
 
/**
 * int posX
 * Position de la tuile sur la carte en X (nb de tuiles).
 */
p.posX = 0;
 
/**
 * int posY
 * Position de la tuile sur la carte en Y.
 */
p.posY = 0;
 
/**
 * int posZ
 * Position de la tuile sur la carte en Z.
 */
p.posZ = 0;
 
/**
 * Constructeur.
 */
p.construct = function ( $type, $content, $walkable, $offsetX, $offsetY )
{
        if ( $type === TileType.PNG )
        {
                this.type = $type;
        }
 
        if ( $walkable === false )
        {
                this.walkable = false;
        }
 
        if ( typeof $offsetX === typeof 0 )
        {
                this.offsetX = $offsetX;
        }
 
        if ( typeof $offsetY === typeof 0 )
        {
                this.offsetY = $offsetY;
        }
 
        if ( $content && $content.visible )
        {
                this.content = $content;
        }
};
 
/**
 * void dispose
 * @purpose : Détruit la tuile.
 */
p.dispose = function ()
{
        this.map = null;
        this.type = null;
        this.content = null;
        this.walkable = null;
        this.offsetX = null;
        this.offsetY = null;      
};

III. Concluons

Nous allons maintenant pouvoir attaquer la classe Map, qui va gérer les tuiles et leur affichage à l'écran !

Navigation rapide :

<< Chapitre 2 - Sommaire - Chapitre 4 >>