Journal de bord: création d’un bomberman-like en HTML5, jour 2

Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetdulibre/p12443/developpement/journal-de-bord-creation-dun-bomberman-like-en-html5-jour-1

Ici nous allons voir les classes des personnages et des bombes

bombermanM_Perso.js
Ici la classe de personnage qui va permettre d’afficher chacun des personnages sur la map du jeu.
Elle permet également de gérer son animation: pour simuler la marche de celui-ci en direction de la touche de curseur pressée.
Regardons de plus près la méthode build:

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
build:function(){
               
    var sDirection=oGame.tDirection[this.team];
       
    //si pas de direction, on affiche l'image statique 
    if(sDirection==''){
        tmpImg=this.idImg;
    //si l'image précédente était marche 2, on affiche marche 1
    }else if(this.tmpIdImg==this.idImg+'_walking2'+sDirection){
        tmpImg=this.idImg+'_walking'+sDirection;
    //sinon on affiche la marche 2
    }else{
        tmpImg=this.idImg+'_walking2'+sDirection;
    }
    this.tmpIdImg=tmpImg;
       
    //partie affichage de l'image du personnage sur le canvas
    oImages.drawImageOnLayer(tmpImg,(this.x*widthCase)-20,(this.y*heightCase)-20,widthCase,widthCase,'perso');
       
    //on affiche ici un carré représentant la couleur de la team
    oLayer_perso.fillRect((this.x*widthCase),(this.y*heightCase)-25,8,8,this.team);
       
    //on enregistre les nouvelles coordonnées du joueur
    oGame.savePerso(this);
       
},

Comme vous pouvez le voir, on récupère la direction du personnage qui est déduite dans la classe Game (lors du pressage de la touche)
Si aucune direction: le joueur attend, on affiche l’image statique (de face), sinon il y a une direction d’engagée.
Dans ce cas on gère une animation de marche: pour cela on a par direction 2 images, et on va les alterner à chaque affichage du personnage.
Vous voyez également qu’on affiche un petit carré en haut à gauche du personnage pour signaler son équipe.

bombermanM_Bomb.js
Une nouvelle classe fait ici son apparition afin de gérer des objets « Ã©phémères »: les bombes: en effet, à partir de leur création, elles ont une durée limitée sur la map.
De plus, elles doivent à la fin exploser: créer une image de flamme sur plusieurs cases adjacentes et supprimer les eventuels joueurs sur le passage.

Premièrement, au niveau de l’affichage des bombes, on va gérer une animation:

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
refreshBomb:function(){
           
    for(var i=0;i< this.tBomb.length;i++){
        var oBomb= this.tBomb[i];
        if(oBomb.life < 14){
            //pendant 14 iterations, on va alterner entre deux sprites
            if(oBomb.life % 2 ){
                oBomb.idImg='bomb-0';
            }else{
            oBomb.idImg='bomb-1';
            }  
        }else if(oBomb.life < 17){
            //puis animation d'explosion
            if(oBomb.life % 2 ){
                oBomb.idImg='explosion';
            }else{
                oBomb.idImg='explosion-1';
            }
        }else if(oBomb.life < 19){
            oBomb.idImg='explosion-2';
        }else{
            oBomb.idImg='explosion-finish';          
        }
           
        oBomb.life++;
           
        //on broadcast l'animation de la bombe
        oBomb.animateBroadcast(oBomb.idImg);
    }
               
},

Ensuite au niveau de la classe bombe, on gère l’affichage

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
build:function(){
       
    if(this.idImg=='explosion' || this.idImg=='explosion-1' || this.idImg=='explosion-2'){
        for(var i=-2;i< 3;i++){
            oLayer_bomb.clearRect(((this.x+i)*widthCase),(this.y*heightCase),widthCase,widthCase);
            oLayer_bomb.clearRect(((this.x)*widthCase),((this.y+i)*heightCase),widthCase,widthCase);
           
            if(map.tMap[this.y][this.x+i]==1){
                oImages.drawImageOnLayer(this.idImg,((this.x+i)*widthCase),(this.y*heightCase),widthCase,widthCase,'bomb');
            }
            if(map.tMap[this.y+i][this.x]==1){
                oImages.drawImageOnLayer(this.idImg,((this.x)*widthCase),((this.y+i)*heightCase),widthCase,widthCase,'bomb');
            }
        }
   
    }else if(this.idImg=='explosion-finish'){
        for(var i=-2;i< 3;i++){
            oLayer_bomb.clearRect(((this.x+i)*widthCase),(this.y*heightCase),widthCase,widthCase);
            oLayer_bomb.clearRect(((this.x)*widthCase),((this.y+i)*heightCase),widthCase,widthCase);
           
            var oPersoVictim=oGame.getPerso(this.x+i,this.y);
            if(oPersoVictim){
                oGame.removeBroadcastPersoById(oPersoVictim.id);
                console.log('remove '+oPersoVictim.id);
            }
            oPersoVictim=oGame.getPerso(this.x,this.y+i);
            if(oPersoVictim){
                oGame.removeBroadcastPersoById(oPersoVictim.id);
                console.log('remove '+oPersoVictim.id);
            }
           
        }
       
        oGame.removeBroadcastBombById(this.id);
        return;
    }else{
        oLayer_bomb.clearRect((this.x*widthCase),(this.y*heightCase),widthCase,widthCase);
    }
           
    oImages.drawImageOnLayer(this.idImg,(this.x*widthCase),(this.y*heightCase),widthCase,widthCase,'bomb');
       
    oGame.saveBomb(this);
   
},

Gestion intersection
Afin d’eviter d’avoir un bug graphique de chevauchement: lorsqu’un joueur est à cheval entre deux cases, il ne peut pas descendre/monter au risque de « marcher sur un mur »
Pour cela, dans la gestion du déplacement, on verifie que l’on est pas à cheval:

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
refreshPerso:function(){
   
    //on boucle sur les persos existants
    for(var i=0;i< this.tPerso.length;i++){
        var oPerso= this.tPerso[i];
        if(oPerso.life <=0){ continue;}
       
            var vitesse=0.5;
           
            if(!this.tDirection[oPerso.team]){
                continue;
            }
           
            var sDirection=this.tDirection[oPerso.team];
           
            //on efface le dessin sur le calques
            oPerso.clear();
           
            //on initialise les nouvelles coordonnées
            var newX=oPerso.x;
            var newY=oPerso.y;
            var newXcheck=oPerso.getX();
            var newYcheck=oPerso.getY();
           
           
            if(newY != parseInt(newY)){
                //si entre deux cases, on ne peut pas descendre/monter
            }else if(sDirection=='right'){
                newX+=vitesse;
                newXcheck+=1;
            }else if(sDirection=='left'){
                newX-=vitesse;
                newXcheck-=1;
            }
            if(newX != parseInt(newX)){
                //si entre deux cases, on ne peut pas descendre/monter
            }else if(sDirection=='up'){
                newY-=vitesse;
                newYcheck-=1;
            }else if(sDirection=='down'){
                newY+=vitesse;
                newYcheck+=1;
            }
           
            if(this.checkCoord(newXcheck,newYcheck)){
                //si les coordonnées est libre
                oPerso.x=newX;
                oPerso.y=newY;
               
            }
           
            //on dessine le personnage
            oPerso.buildBroadcast('walking');
           
       
    }
   
   
},

En image
bomber4

Le dépôt github
Le dépôt https://github.com/imikado/bomberhtml5