Journal de bord: création d’un RTS en HTML5, jour 17

Introduction
Ce billet fait suite au billet: http://blog.developpez.com/ducodeetdulibre/p12436/developpement/journal-de-bord-creation-dun-rts-en-html5-jour-16

Ce jour 17 a été utilisé surtout pour corriger les moultes bugs de la version multi player.
Au fur et à mesure de développement multi joueur, je me suis heurté à beaucoup de soucis.

L’effet Larsen
Premièrement: node.js/socket.io, j’avais identifié les actions coté client et coté serveur avec les mêmes noms, exemple: Unit.build.
Je me suis rendu compte d’un effet Larsen: j’emettais avec le client sur id pensant l’envoyer uniquement au serveur, puis coté serveur j’emmetais vers les clients avec le même identifiant pour que chacun mette à jour son écran.
J’ai donc différencier les identifiants client et serveur avec un suffixe « Broadcast »
Ainsi coté client on fait un

1
socket.emit('Unit.buildBroadcast',this.id,x,y);

Coté serveur, on écoute l’evenement et l’on broadcast un évenement différent (sans le suffixe Broadcast)

1
2
3
4
socket.on('oBuild.buildBroadcast',function(id,x,y){
    socket.broadcast.emit('oBuild.build',id,x,y);
    socket.emit('oBuild.build',id,x,y);
});

Et ainsi coté client, on écoute l’evenement pour intéragir avec l’écran du joueur

1
2
3
4
5
6
7
socket.on('oBuild.build',function(id,x,y){
    var oBuild=oGame.getBuildById(id);
    oBuild.clear();
    oBuild.x=x;
    oBuild.y=y;
    oBuild.build();
});

Persistance de la partie
Sur la première version multijoueur, il fallait lancer les deux navigateurs à peu près en meme temps, pour qu’ils se broadcaste l’un l’autre leurs unités respectives.
Mais ceci n’était pas une bonne idée, j’ai donc ajouté plusieurs choses:
Рon stocke sur le serveur deux tableaux: tBuild et tUnit qui stoque les entit̩s (unit̩s et batiments)
– lors de la connection d’un joueur, on boucle sur ces tableaux pour lui afficher l’état actuel de la partie
– pour le debug: 4 boutons pour choisir sa team
Pour info, c’est la team bleu qui mène la danse: c’est ce joueur qui possède la boucle de jeu (cycle de raffraichissement des unités et batiments)

Note: pour sauvegarder les informations de partie, on met à jour les données des tableaux tUnit et tBuild

1
2
3
4
5
6
7
8
socket.on('unit.buildBroadcast',function(id,x,y){
    var i=getUnitById(id);
    tUnit[i].x=x;
    tUnit[i].y=y;
    socket.broadcast.emit('unit.build',id,x,y);
    socket.emit('unit.build',id,x,y);
   
});

La fonction pour récupérer les données de l’unité:

1
2
3
4
5
6
7
function getUnitById(id){
    for(var i=0;i<tUnit.length;i++){
        if(tUnit[i].id==id){
            return i;
        }
    }
}

Le prototype qui sert juste à stoquer les informations d'unité et batiments:

1
2
3
4
5
6
7
8
9
10
function Data(){
    this.team;
    this.name;
    this.id;
    this.x;
    this.y;
};
Data.prototype={
   
};

Copie de Unit.js et Build.js
Pour permettre de gérer plus facilement certains éléments du jeu multiplateforme, j’ai du dupliquer les classes Unit et Build

Modification de la méthode build de la classe Unit pour broadcaster la création d’un batiment: en effet, à la création d’une unité et d’un batiment, il faut avertir les autres joueurs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//si l'unité doit construire un batiment, et qu'elle se trouve sur les lieux de la construction
if(this.oBuildOn && this.getX()+1==this.oBuildOn.x && this.getY()==this.oBuildOn.y){
   
    oGame.createBuildBroadcast(oGame.team,this.oBuildOn.name,this.oBuildOn.x,this.oBuildOn.y);
   
    var aBuild=new Build(this.oBuildOn.name,this.team);
   
    //on reset les propriétés de construction
    oGame.buildcreation='';
    this.buildOnX='';
    this.buildOnY='';
    this.oBuildOn='';
   
    //on décrément la ressource or et bois
    oGame.useRessource(this.team,'or',aBuild.costOr);
    oGame.useRessource(this.team,'wood',aBuild.costWood);
   
    //on réactualise les ressources
    oGame.buildRessource();
    //on reset la sélection
    oGame.clearSelect();
   
}

note: un bug que j’ai mis longtemps à identifier: le mauvais nom d’event, en effet, si vous vous trompez de nom d’évenement à emettre, vous ne le savez pas : pas d’erreur :(
si vous avez un doute, ajoutez des console.log() pour vérifier que vous passer bien dans vos évenements ;)

Voilà pour le résumé des derniers déboires ;)
J’espère que ce journal de bord vous évitera de perdre autant de temps que moi.

Je pense améliorer un peu leu jeu, en ajoutant un menu, permettre de créer une nouvelle partie mais ce sera tout pour ce jeu.

Le prochain jeu sera un bomberman-like multijoueur ;)

Le github
Le projet GitHub : https://github.com/imikado/rtshtml5