Création d'un jeu de stratégie en temps réel en HTML5 avec les canvas
Imikado nous confie son journal de bord

Le , par imikado, Rédacteur
Introduction
Ce billet fait suite au billet précédent: http://blog.developpez.com/ducodeetd...n-html5-jour-1

Dans ce billet je vais vous détailler les fichiers rts.js et canvas.js , leur utilisation, leur construction.

Faire une application HTML5/canvas
Mais avant, je dois vous expliquer le fonctionnement global d’une application HTML5: pour ceux qui ont déjà fait des jeux en flash, il faut se dire vous dire que l’HTML5 est plus austère: oubliez la scène, la timeline et les clips, ici juste un canvas, soit une image fixe.
Ce que l’on fait pour créer une animation, selectionner un élement.. ce sont des maths : aucun objet sur un canvas, juste des pixels de couleurs différentes imprimés ou éffacés sur une image (le canvas).
Pour simplifier un peu la gestion et les performances, on créé autant de canvas que de calques nécéssaires:
Un canvas pour le sol, un canvas pour les batiment, un autre pour les personnage, le brouillard, la selection…

lib3/canvas.js
Cette classe est très importante dans ce projet, elle permet de faciliter les interactions avec les canvas.
Vous pouvez ainsi coder plus facilement:
Code javascript : Sélectionner tout
1
2
var oCanvas = new Canvas('idDeMonCanvas'); 
oCanvas.drawRectStroke(x,y,largeur,hauteur,epaisseur,couleur);
Au lieu de :
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
  
var canvas = document.getElementById('idDeMonCanvas'); 
var ctx = canvas.getContext('2d'); 
ctx.beginPath(); 
ctx.lineWidth=epaisseur; 
ctx.strokeStyle=couleur; 
ctx.strokeRect(x,y,largeur,epaisseur); 
ctx.closePath();

La suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-2


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse

Avatar de SylvainPV SylvainPV - Rédacteur/Modérateur https://www.developpez.com
le 31/12/2013 à 9:16
Salut,

Sympa l'idée d'un journal de bord, ça sert à la fois de tuto et de retour d'expérience
A une époque, j'ai commencé un projet de RTS en HTML5, mais j'ai abandonné par manque de temps et d'ambition. J'utilisais alors des <div> et des background-image pour gérer tous mes sprites, tandis qu'un <canvas> superposé servait à tous les effets HUD (barres de vie, de chargement etc...). L'avantage d'utiliser le DOM et des <div>, c'est qu'on pouvait très facilement associer une instance JS à un élément HTML et manipuler l'élément en utilisant les animations CSS. Mais utiliser canvas partout est généralement plus performant, bien qu'un peu plus compliqué à gérer niveau code.
Si ça intéresse quelqu'un, le jeu est encore en ligne ici et le code source n'est pas obfusqué.
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 31/12/2013 à 9:20
Merci
Votre jeu est pas mal du tout, effectivement le problème avec les canvas, mais j'en parlerai dans le prochain journal c'est le fait qu'on ai pas d'objets:

Avec un div, on ajoute un onclick et l'on peut indiquer de faire ceci en cliquant sur tel div, par exemple changer ses coordonnées x/y

Avec un canvas, il faut recuperer les coordonéés, en soustraire le scroll du navigateur puis diviser par la largeur des cases pour en déduire des coordonnées
Enfin il faut stoquer les elements js dans un tableau indexé puis effacé et réafficher au nouvel emplacement
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 02/01/2014 à 13:48
Introduction
Ce billet fait suite au billet précédent: http://blog.developpez.com/ducodeetd...n-html5-jour-2

Dans ce billet je vais vous détailler le fichiers rts_Game.js et son utilisation, sa construction.

Faire une application HTML5/canvas : les interactions
J’expliquai lors du dernier billet que l’utilisation du canvas était un peu moins confortable que de faire du flash.
Une chose toute bête c’est d’identifier où l’on clique: sur une unité, sur un batiment, un arbre ou dans le vide.
Pour cela plusieurs choses: on recupère l’evenement clic, ses coordonnées, on leur soustrait le scroll du navigateur.
Puis on cherche à savoir si on trouve dans un tableau indexé par coordonnées x y un élément.

Cette méthode se trouve dans la classe Game.

La classe Game, fichier rts_Game.js
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  
//Game 
function Game(){ 
    //tableau de coordonnées des unités 
    this.tCoordUnit=Array(); 
    //tableau de corrdonnées des batiments/arbres/mine d'or 
    this.tCoordBuild=Array(); 
    //le mode en cours  
    this.mode=''; 
    //l'element selectionné (unité/batiment...) 
    this.selected=''; 
    //le batiment selectionné à construire 
    this.buildcreation=''; 
    //le tableau des cases visibles sur la carte 
    this.tVisible=Array(); 
    //tableau contenant tous les batiments (utilisé pour reconstruire la map lors d'un scroll) 
    this.tBuild=Array(); 
    //idem pour les unités 
    this.tUnit=Array(); 
  
    //ressources 
    this.iOr=250; 
    this.iWood=150; 
}
Je ne vais pas ici coller la classe Game en entier (plus de 400 lignes), je vais plutot présenter bloc par bloc pour expliquer certains principe de développement
Pour rappel, l’ensemble du projet est disponible sur github (voir en bas d’article)

La récupération des coordonnées
Lorsque l’on clique sur un endroit du canvas, il faut faire plusieurs choses: récupérer l’evenement, recupérer les coordonnées du clic, puis diviser par la taille des cases pour récupérer les coordonnées du tableau.
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
//recuperation de X + le decalage de la scrollbar 
getXmouse:function(e){ 
    if(e && e.x!=null && e.y!=null){ 
        return e.x +document.body.scrollLeft; 
    }else{ 
        return e.clientX +document.body.scrollLeft; 
    } 
}, 
//recuperation de X + le decalage de la scrollbar 
getYmouse:function(e){ 
    if(e && e.x!=null && e.y!=null){ 
        return e.y + document.body.scrollTop; 
    }else{ 
        return e.clientY + document.body.scrollTop; 
    } 
}, 
//recuperation de la coordonnée de tableau: divisition de x par la largeur d'une case 
getX:function(e){ 
    var x=this.getXmouse(e); 
    x=parseInt( x/widthCase); 
  
    //ajout du decallage (scrolling sur la map) 
    return x+currentX; 
}, 
getY:function(e){ 
    var y=this.getYmouse(e); 
    y=parseInt( y/widthCase); 
  
    return y+currentY; 
},

Lire la suite dans le billet:
http://blog.developpez.com/ducodeetd...n-html5-jour-3

Le clic gauche
Lorsque l’on veut séléctionner une unité, on doit cliquer sur l’image de celle-ci.
Mais malheureusment, cette image est un dessin sur le canvas, il n’y donc pas possibilité de mettre un evement sur l’image.
On doit récupérer les coordonnées du clic pour retrouver l’image en dessous.
Pour cela, on recupere les coordonnées « tableau » puis l’on demande si il y a une unité ou un batiment en dessous.

Lors du clic gauche, si on a demandé à l’unité de construire un batiment, on va vérifier que l’on peut le construire sur ces coordonnées
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  
 getUnit:function(x,y){ 
        //console.log('search x:'+x+' '+y); 
        if(this.tCoordUnit[y] &&  this.tCoordUnit[y][x]){ 
            return this.tCoordUnit[y][x]; 
        } 
        return null; 
    }, 
    getBuild:function(x,y){ 
        if(this.tCoordBuild[y] &&  this.tCoordBuild[y][x]){ 
            return this.tCoordBuild[y][x]; 
        } 
        return null; 
    }, 
    //appelée lors d'un clic gauche sur le canvas (sélection d'une unité/batiment) 
    click:function(e){ 
        //recuperation des coordonnées "tableau" x y 
        var x=this.getX(e); 
        var y=this.getY(e); 
  
        //si l'utilisateur a séléctionné un batiment à construire 
        if(this.buildcreation!=''){ 
  
            //on veririfie ensuite les coordonnées  
            //des 4 cases nécéssaires à la construction du batiment 
            var ok=1; 
            if(!oGame.checkCoordVisible(x,y) || !oGame.checkCoord(x,y) ){ 
                ok=0; 
            }else if(!oGame.checkCoordVisible(x+1,y) || !oGame.checkCoord(x+1,y) ){ 
                ok=0; 
            }else if(!oGame.checkCoordVisible(x,y+1) || !oGame.checkCoord(x,y+1) ){ 
                ok=0; 
            }else if(!oGame.checkCoordVisible(x+1,y+1) || !oGame.checkCoord(x+1,y+1) ){ 
                ok=0; 
            } 
  
            if(!ok){ 
                //si une des cases indisponible, on annule 
                return; 
            } 
  
            //si c'est ok, on efface la selection d'emplacement 
            this.buildcreation.clear(); 
            //on indique à l'unité qui doit construire 
            //le batiment à construire 
            this.selected.buildOn(this.buildcreation); 
  
            //on annule la construction en cours 
            this.buildcreation=''; 
  
            return; 
  
        }  
  
        //on recherche si il y a quelquechose aux coordonnées 
        var oUnit=this.getUnit(x,y); 
        var oBuild=this.getBuild(x,y); 
  
        //si il y a une unité 
        if(oUnit){ 
            //on selectionne celle-ci 
            this.select(oUnit); 
        }else if(oBuild){ 
            //si  il y a un batiment, 
            //on le selectionne 
            this.select(oBuild); 
        }else{ 
            //sinon on supprime la selection sur le canvas 
            console.log('pas trouve'); 
            this.clearSelect(); 
        } 
    },

La suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-3
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 05/01/2014 à 13:35
Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-3

Dans ce billet je vais vous détailler le fichier rts_Map.js, son utilisation, sa construction.

Faire une application HTML5/canvas: construire la Map
Dans ce jeux de stratégie, comme dans beaucoup d’autres jeux, la carte est trop grande pour être affichée dans son ensemble,.
Il faut donc afficher une partie de la carte, et permettre de visualiser ce que l’on regarde par rapport à la carte complète.

C’est là qu’intervient la classe Map (fichier rts_Map.js)
Comme pour la classe Game, nous allons ici voir bloc par bloc

Création de la map
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
build:function(){ 
  
        for(var y=0;y< maxY;y++){ 
            for(var x=0;x< maxX;x++){ 
  
                //decalage x/y en fonction du scrolling 
                var x2=x+currentX; 
                var y2=y+currentY; 
  
                if(this.tMap[y2] && this.tMap[y2][x2]){ 
                    //si c&#039;est un arbre 
                    if(this.tMap[y2][x2]==4){ 
                        //on dessine un case normale 
                        this.drawImage( 3 ,x,y); 
                        //puis on créé un objet arbre par dessus 
                        var oWood=new Wood(); 
                        oWood.x=x; 
                        oWood.y=y; 
                        oWood.build(); 
  
                        //on ajoute cette arbre au tableau des batiments 
                        //pour les reconstruire lors du scrolling 
                        oGame.tBuild.push(oWood); 
                    } 
                    //on dessine sur le canvas la valeur du tableau 
                    this.drawImage( this.tMap[y2][x2] ,x,y); 
  
                } 
            }    
        }  
  
    }, 
    //la methode pour dessiner sur le canvas 
    drawImage:function(iImg,x,y){ 
        if(!this.tOImg[iImg]){ 
            var oImg=new Image(); 
            oImg.src=&#039;img3/&#039;+this.tImg[iImg]; 
            oImg._x=x; 
            oImg._y=y; 
            oImg.onload=function(){ 
                oLayer_map.drawImage(this,this._x*widthCase,this._y*heightCase,widthCase,widthCase); 
  
            } 
            this.tOImg[iImg]=oImg; 
  
        }else{ 
            oLayer_map.drawImage(this.tOImg[iImg],x*widthCase,y*heightCase,widthCase,widthCase); 
        } 
  
    },
Petite parenthèse sur les images
Pensez bien que lorsque vous souhaitez dessiner une image sur un canvas, vous n’etes pas en local: les images de votre jeu ne sont pas chargées.
Pour gerer ce mode asynchrone: on créé un objet image, on lui assigne des propriétés comme ces coordonnées et enfin on lui indique du code à éxécuter au moment du chargement avec « onload »
Mais il faut également prévoir le fait que l’image ai déjà été chargée précédement.
C’est pour cela que je stoque ici l’objet image dans un tableau de propriété de la classe, ainsi, si l’objet existe on le dessine tout de suite.
En revanche si il n’existe pas on instancie avec les propriétés ainsi que la méthode onload.

La suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-4
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 06/01/2014 à 20:51
Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-4

Dans ce billet, nous verrons la classe Unit, qui permet de gerer des unités

Le constructeur d’unité
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function Unit(name,src){ 
    //le nom type d'unité 
    this.name=name; 
    //l'adresse de l'image 
    this.src='img3/'+src; 
    this.oImage=''; 
  
    //les coordonnées + les vies 
    this.x=0; 
    this.y=0; 
    this.life=100; 
  
    //la destination cible 
    this.targetX=''; 
    this.targetY=''; 
  
    //la largeur/hauteur de l'unité 
    this.width=widthCase; 
    this.height=widthCase; 
  
    //contiendra le moment venu un batiment à construire 
    this.oBuildOn=null; 
  
    //compteur utilisé lors de la récupération de ressource 
    this.counter=0; 
    //ressources or/bois transporté 
    this.or=0; 
    this.wood=0; 
  
    //pour une ronde point de départ 
    this.cycleFromX=''; 
    this.cycleFromY=''; 
  
    //pour une ronde point d'arrivée 
    this.cycleToX=''; 
    this.cycleToY=''; 
  
    //tableau contenant les batiments que l'unité peut construire 
    this.tBuildCreation=Array(); 
  
    if(this.name=='soldat'){ 
        this.tBuildCreation[0]=new Buildcreation('buid2','build2.png'); 
    } 
}

L’affichage de l’unité
Méthode utilisée pour afficher l’unité
Comme vous pouvez le voir il y a également une partie pour la construction effective d’un batiment.
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
build:function(){ 
    //partie affichage de l'image de l'unité sur le canvas 
    if(this.oImage==''){ 
        this.oImage=new Image(this); 
        this.oImage.src=this.src; 
        this.oImage._x=this.x; 
        this.oImage._y=this.y; 
        this.oImage.onload=this.drawImage; 
    }else{ 
        oLayer_perso.drawImage(this.oImage ,((this.x-currentX)*widthCase),((this.y-currentY)*heightCase),widthCase-2,widthCase-2); 
  
        oLayer_perso.fillRect((this.x-currentX)*widthCase,((this.y-currentY)*heightCase)+heightCase-2,widthCase,2,'#00ff00'); 
  
    } 
  
    //si l'unité doit construire un batiment, et qu'elle se trouve sur les lieux de la construction 
    if(this.oBuildOn && this.x+1==this.oBuildOn.x && this.y==this.oBuildOn.y){ 
  
        //création du batiment à l'emplacement 
        var aBuild=new Build(this.oBuildOn.name,this.oBuildOn.src); 
        aBuild.x=this.oBuildOn.x; 
        aBuild.y=this.oBuildOn.y; 
        aBuild.build(); 
  
        //ajout du batiment à la liste des batiments (pour la reconstruction lors des scroll) 
        oGame.tBuild.push(aBuild); 
        //on sauvegarde les coordonnées du batiments 
        oGame.saveBuild(aBuild); 
  
        //on reset les propriétés de construction 
        oGame.buildcreation=''; 
        this.buildOnX=''; 
        this.buildOnY=''; 
        this.oBuildOn=''; 
  
        //on décrément la ressource or 
        oGame.iOr-=100; 
        //on réactualise les ressources 
        oGame.buildRessource(); 
        //on reset la sélection 
        oGame.clearSelect(); 
  
    } 
    //on enregistre les nouvelles coordonnées de l'unité 
    oGame.saveUnit(this); 
},

La suite: http://blog.developpez.com/ducodeetd...n-html5-jour-5
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 06/01/2014 à 23:24
Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-5

Nous avons dans les précédents billets expliqué chaque fichier du projet, nous allons à partir d’aujourd’hui continuer ce rts pour arriver à un jeu fini

Gerer les couts des batiments
Plutot que d’avoir écrit en dur 100 d’or pour les batiments, on va stoquer dans l’objet batiment le cout en or et en bois de chaque batiment

Pour cela on va editer la classe Build, on y ajoute 2 propriétés costOr et costWood
J’en ai profité pour remanier un peu le constructeur: cette fois on ne recoit que le type de batiment et le constructeur fait le reste (adresse de l’image, cout…)

Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//build 
function Build(name,src){ 
    this.name=name; 
    this.oImage=''; 
  
    this.x=0; 
    this.y=0; 
    this.life=100; 
  
    this.width=widthCase*2; 
    this.height=widthCase*2; 
  
    this.color='#064474'; 
    this.bVisibility=1; 
  
    this.costOr=0; 
    this.costWood=0; 
  
    if(this.name=='or'){ 
        this.color='#e8bb08'; 
        this.bVisibility=0; 
        this.shortname='Mine d\'or'; 
        this.src='img3/mine-or.png'; 
        this.unitCreation =''; 
    }else if(this.name=='QG'){ 
        this.shortname='Quartier g&eacute;n&eacute;ral'; 
        this.src='img3/build1.png'; 
  
        this.unitCreation =new Unit('Worker'); 
    }else if(this.name=='SoldierHouse'){ 
        this.shortname='Batiment des soldats'; 
        this.src='img3/build2.png'; 
  
        this.costOr=100; 
        this.costWood=100; 
  
        this.unitCreation =new Unit('Soldier'); 
    }else if(this.name=='ArcherHouse'){ 
        this.shortname='Batiment des archers'; 
        this.src='img3/build3.png'; 
  
        this.costOr=200; 
        this.costWood=50; 
  
        this.unitCreation =new Unit('Archer'); 
    } 
  
}

J’ai également remanié la classe unit, c’est également le constructeur qui fait tout: image, nom et batiments constructibles.

Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function Unit(name){ 
    this.name=name; 
    this.oImage=''; 
  
    this.x=0; 
    this.y=0; 
    this.life=100; 
  
    this.targetX=''; 
    this.targetY=''; 
  
    this.width=widthCase; 
    this.height=widthCase; 
  
    this.oBuildOn=null; 
  
    this.counter=0; 
    this.or=0; 
    this.wood=0; 
  
    this.cycleFromX=''; 
    this.cycleFromY=''; 
  
    this.cycleToX=''; 
    this.cycleToY=''; 
  
    this.tBuildCreation=new Array(); 
  
    if(this.name=='Soldier'){ 
        this.shortname='Soldat'; 
        this.src='img3/WPface.png'; 
  
    }else if(this.name=='Archer'){ 
        this.shortname='Archer'; 
        this.src='img3/WC.png'; 
  
    }else if(this.name='Worker'){ 
        this.shortname='Ouvrier'; 
        this.src='img3/WK.png'; 
  
        this.tBuildCreation.push(new Build('SoldierHouse')); 
        this.tBuildCreation.push(new Build('ArcherHouse')); 
    } 
}

Limitation du scroll à la carte
Pour éviter que l’on puisse scroller à l’infini, on va ajouter un garde fou à la classe Game

Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Game.prototype={ 
    drawDirection:function(){ 
        oLayer_cadre.clear(); 
        //left 
        oLayer_cadre.drawRect(0,0,10,oLayer_map.height,'#eeaf17','#eeaf17'); 
        //right 
        oLayer_cadre.drawRect(oLayer_map.width-10,0,10,oLayer_map.height,'#eeaf17','#eeaf17'); 
        //bottom 
        oLayer_cadre.drawRect(0,oLayer_map.height-10,100,10,'#eeaf17','#eeaf17'); 
        oLayer_cadre.drawRect(500,oLayer_map.height-10,300,10,'#eeaf17','#eeaf17'); 
        //top 
        oLayer_cadre.drawRect(0,0,oLayer_map.width,10,'#eeaf17','#eeaf17'); 
    }, 
    goLeft:function(){ 
        if(currentX-1  map.tMap[0].length){ 
            return ; 
        } 
  
        currentX+=1; 
        this.rebuild(); 
        oLayer_cadre.drawRect(oLayer_map.width-10,0,10,oLayer_map.height,'#eeaf17','#eeaf17'); 
    }, 
    goDown:function(){ 
        if(currentY+1+maxY > map.tMap.length){ 
            return ; 
        } 
  
        currentY+=1; 
        this.rebuild(); 
        oLayer_cadre.drawRect(0,oLayer_map.height-10,100,10,'#eeaf17','#eeaf17'); 
        oLayer_cadre.drawRect(500,oLayer_map.height-10,300,10,'#eeaf17','#eeaf17'); 
    }, 
    goUp:function(){ 
        if(currentY-1 < 0){ 
            return ; 
        } 
  
        currentY-=1; 
        this.rebuild(); 
        oLayer_cadre.drawRect(0,0,oLayer_map.width,10,'#eeaf17','#eeaf17'); 
    },


Voir la suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-6
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 07/01/2014 à 23:38
Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-6

Modification de la selection d’unités
Si on veut par la suite pouvoir faire une multiple selection, on va remplacer la variable selected par un tableau tSelected
Et ainsi en selectionnant une unité on l’ajoute à ce tableau
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
select:function(oMix){ 
    //on enregistre l'unité/batiment 
    this.tSelected.push(oMix); 
  
    //on demande son dessin 
    this.drawSelected(); 
  
    //on affiche la navigation 
    oMix.buildNav(); 
},
Et lors de l’affichage des unités sélectionnés, on va boucler sur celui-ci
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
drawSelected:function(){ 
    //on efface le calque 
    oLayer_select.clear(); 
  
    for(var i=0;i<this.tSelected.length;i++){ 
        //on dessine un cadre sur un des calques au dimension de l&#039;élement 
        oLayer_select.drawRectStroke((this.tSelected[i].x-currentX)*widthCase,(this.tSelected[i].y-currentY)*heightCase,this.tSelected[i].width,this.tSelected[i].height,&#039;#880044&#039;,3); 
    } 
},

suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-7
Avatar de pouli pouli - Membre à l'essai https://www.developpez.com
le 08/01/2014 à 12:09
Bonne initiative Mika !
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 09/01/2014 à 0:16
Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-7

Ajourd’hui nous allons passer aux sprites
L’idée est d’éviter d’avoir une image par éléments, mais 2-3 images qui contiendrait l’ensemble afin d’avoir peu de fichiers à télécharger
On va créer 2 images: une qui contiendra les images 1×1 (map, unités, arbres…) cases et l’autre les images 2×2 (batiment, mine d’or…)

Ensuite on va créer une classe qui permettra dans un premier temps de charger les 2 images, et dans un second temps d’identifier chaque élément du sprite

Création de la classe de gestion de sprites
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function Images(){ 
    this.tOImg=new Array(); 
    this.tDetail=new Array(); 
    this.counter=0; 
} 
Images.prototype={ 
    //methode qui permet de charger une image 
    load:function(src,idImg){ 
        this.tOImg[idImg]=new Image(); 
        this.tOImg[idImg].src=src; 
        this.tOImg[idImg].onload=function(){ 
            oImages.counter++; 
            preload2(); 
        } 
    }, 
    //methode qui permet d'identifier un élément du sprite 
    setDetailOnId:function(id,y,x,width,height,idImg){ 
        this.tDetail[id]=new Array(); 
        this.tDetail[id]['x']=x; 
        this.tDetail[id]['y']=y; 
        this.tDetail[id]['width']=width; 
        this.tDetail[id]['height']=height; 
        this.tDetail[id]['idImg']=idImg; 
    }, 
    //methode qui permet de dessiner un element sur un des canvas 
    drawImageOnLayer:function(id,x,y,width,height,sLayer){ 
        var oCanvasTmp; 
        if(sLayer=='map'){ 
            oCanvasTmp=oLayer_map; 
        }else if(sLayer=='apercu'){ 
            oCanvasTmp=oLayer_apercu; 
        }else if(sLayer=='perso'){ 
            oCanvasTmp=oLayer_perso; 
        }else if(sLayer=='building'){ 
            oCanvasTmp=oLayer_building; 
        } 
  
        oCanvasTmp.drawImage2(this.tOImg[ this.tDetail[id]['idImg'] ],this.tDetail[id]['x'],this.tDetail[id]['y'],this.tDetail[id]['width'],this.tDetail[id]['height'],x,y,width,height); 
  
    }, 
};

Chargement des sprites et identification
Il faut ensuite identifier chaque éléments:
On créé un tableau qui représente virtuellement les éléments sur le sprite
En bouclant dessus, on identifie dans la classe Images ceux-ci

Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
oImages=new Images(); 
  
	var tDetailTmp=new Array(); 
	tDetailTmp=[ 
		['case-beige2','case-water','case-beige','case-wood'], 
		['unit-worker'], 
		['unit-soldier'], 
		['unit-archer'], 
	]; 
	for(var y=0;y<tDetailTmp.length;y++){ 
		for(var x=0;x<tDetailTmp[y].length;x++){ 
			oImages.setDetailOnId(tDetailTmp[y][x],y*40,x*40,40,40,'1x1'); 
		} 
	} 
	var tDetailTmp=new Array(); 
	tDetailTmp=[ 
		['build-SoldierHouse','build-SoldierHouse_-2','build-SoldierHouse_-1'], 
		['build-QG','build-QG_-2','build-QG_-1'], 
		['build-ArcherHouse','build-ArcherHouse_-2','build-ArcherHouse_-1'], 
  
		['build-mineOr'], 
	]; 
	for(var y=0;y<tDetailTmp.length;y++){ 
		for(var x=0;x<tDetailTmp[y].length;x++){ 
			oImages.setDetailOnId(tDetailTmp[y][x],y*80,x*80,80,80,'2x2'); 
		} 
	} 
  
	oImages.load('img3/sprite1x1.png','1x1'); 
	oImages.load('img3/sprite2x2.png','2x2');
Dessin d’une image issu du sprite
Pour dessiner, il suffit d’appeler l’objet ainsi.
Exemple pour la classe Build: on dessine l’id « this.idImg sur le canvas « building »
Code javascript : Sélectionner tout
oImages.drawImageOnLayer(this.idImg+this.sSprite,(this.x-currentX)*widthCase,(this.y-currentY)*heightCase,widthCase*2,widthCase*2,'building');

Lire la suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-8
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 10/01/2014 à 0:21
Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-8

Gérer un mouse over
Il serait utile de pouvoir, au survol afficher un curseur particulier en fonction de l’unité/batiment présent sous la souris

Après avoir ajouté une variable onMouseOver à la classe Game, on va indiquer dans la méthode mousmove quand l’initialiser à 1
Code javascript : Sélectionner tout
1
2
3
}else if(this.mouseX > 0 && this.mouseX  0 && this.mouseY < oLayer_map.height){ 
    this.onMouseOver=1; 
}

On ajoute également dans la méthode refreshunit de dessiner la selection sous la souris
Code javascript : Sélectionner tout
1
2
//on dessine le mouseover 
this.drawMouseOver();

Qui ressemble à ceci:
Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
drawMouseOver:function(){ 
    oLayer_cursor.clear(); 
    if(this.onMouseOver==0){ 
        return; 
    } 
  
    if(!this.checkCoordVisible(this.mouseCoordX,this.mouseCoordY)){ 
        return false; 
    } 
  
    var oBuild=this.getBuild(this.mouseCoordX,this.mouseCoordY); 
    var oUnit=this.getUnit(this.mouseCoordX,this.mouseCoordY); 
  
    var sColor='#ffffff'; 
  
    if(oBuild){ 
        if(oBuild.name=='or'){ 
            sColor='yellow'; 
        }else if(oBuild.name=='wood'){ 
            sColor='#01ad4e'; 
        }else if(oBuild.team!=this.team){ 
            sColor='red'; 
        } 
        this.strokeMouseOver(oBuild,sColor); 
    }else if(oUnit){ 
        if(oUnit.team!=this.team){ 
            sColor='red'; 
        } 
        this.strokeMouseOver(oUnit,sColor); 
    } 
},

Ajout de la gestion d’équipe
On va ajouter une propriété team à la classe Build et Unit afin de différencier ses unités et les unités enemies.

On modifie également le process pour que le brouillard ne soit éclairci que par les unités de notre équipe

Code javascript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
saveUnit:function(oUnit){ 
    //on recupere les coordonnées de l'unité 
    var y=oUnit.y; 
    var x=oUnit.x; 
  
    //on enregistre dans un tableau indexé 
    //les nouvelles coordonnées 
    if(!this.tCoordUnit[y]){ 
        this.tCoordUnit[y]=Array(); 
    } 
    this.tCoordUnit[y][x]=oUnit; 
  
    //on rend la zone visible  
    //que si c'est une unité de notre équipe 
    if(oUnit.team==this.team){ 
        this.setVisibility(x,y); 
    } 
},

Ajout de gestion d’attack
Pour l’instant on va gerer l’attaque si une unité est à proximité, on va également indiquer de se rapprocher si une unité enemie est à proxmimité

La suite dans le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-9
Offres d'emploi IT
Ingénieur analyste programmeur (H/F)
Safran - Auvergne - Montluçon (03100)
Ingénieur développement fpga (traitement vidéo) H/F
Safran - Ile de France - 100 rue de Paris 91300 MASSY
Expert décisionnel business intelligence H/F
Safran - Ile de France - Évry (91090)

Voir plus d'offres Voir la carte des offres IT
Responsable bénévole de la rubrique JavaScript : Xavier Lecomte -