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'); } }, |
Le dépôt github
Le dépôt https://github.com/imikado/bomberhtml5