JeuWeb - Crée ton jeu par navigateur
Article Centralisation et séparation des données - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Article Centralisation et séparation des données (/showthread.php?tid=8216)



Centralisation et séparation des données - Xenos - 14-09-2020

Centralisation et séparation des données

Aide concernant ce tuto

Introduction

L'objectif de ce tutorial est d’éviter l'erreur classique d'insérer des données dans du traitement.
Il montre à l'aide d'un exemple les problèmes engendrés par cette erreur et donne quelques solutions.

Pourquoi centraliser les données?

Un jeu par navigateur représente souvent une quantité de code importante.
Il est souvent nécessaire de faire des mises à jour durant plusieurs années.

Si l'on ne pense pas à centraliser les données du jeu, il arrive un moment où faire une mise à jour est un risque, car on oublie tous les endroits où une donnée est inscrite dans le code!

Exemple :

L'exemple est un jeu (fictif) en tour par tour du nom de "war", ce jeu est l'équivalent de milliers de lignes de code et de dizaines voire centaines de fichiers.

Dans ce jeu, on attribue des caractéristiques aux joueurs qui se renouvellent à chaque tour (un classique) !

On a donc entre autre:
  • un fichier inscription.php, où l'on enregistre le joueur avec ses caractéristiques

<?php
//...
$sql="INSERT INTO `war_perso`
( `id` , `nom` , `xp` , `ville` , `arme` , `energie` , `Vision`, `force`, `potion`)
VALUES ('$id', '$nom', '0', '$ville', '', '1', '10', '0.1', '0')";
 
//...
echo 'Votre perso est crée';
//...
?>

Attention: Une des colonnes de la table war_perso est nommé "force", force est un mot-clef réservé à mysql, c'est pourquoi il est impératif de l'entourer de ` .
  • un fichier nouveau_tour.php où l'on renouvèle les caractéristiques

<?php
//...
$sql="UPDATE `war_perso`
SET `energie`='1', `vision`='10', `force`='0.1'
WHERE `id`='$id'";
 
//...
$historique='Votre perso perd son bonus de potion éphémère';
//...
?>
  • un fichier potion.php où l'on augmente les caractéristiques pour un tour lorsque l'on prend une potion

<?php
//...
$carac_basique=array(
'energie' => 1,
'vision' => 10,
'force' => 0.1
);
$ajout=$carac_basique[$potion_type]*mt_rand(50,100)/100;
$sql="UPDATE `war_perso`
SET `$potion_type`=`$potion_type`+'$ajout'
WHERE `id`='$id'";
 
//...
echo 'Gloup Gloup';
//...
?>

Tout çà en gardant en tête que nous avons des dizaines ou centaines de scripts et des milliers de lignes de code.

Le problème c'est que si à un moment donné par exemple un an plus tard on se rend compte qu'il faudrait plus de force, il faudra alors reprendre tous les scripts qui utilisent la donnée de force initiale et les mettre à jour, ce qui peut prendre beaucoup de temps!

Il est surtout probable d'oublier un des fichiers et donc de générer des incohérences !

De même si vous vous rendez compte que vous avez fait une faute d'orthographe, ou que vous vouliez traduire votre jeu pour ouvrir le jeu à d'autre pays, ça prendra du temps !

La solution : séparer et centraliser les données

Il y a plusieurs méthodes pour le faire ce qui importe c'est d'y penser et de le faire. Voici quelques approches :

Stocker dans des fichiers à part

Les données peuvent être enregistrées sous différents formats (php, xml, javascript, txt etc…).

Attention toutefois le temps d'accès à une variable ne doit pas être trop long !

C'est pourquoi dans l'exemple qui suis le format php est retenu, car il est naturellement court !

Cela dit avec de nombreuses données, il peut être judicieux de les séparer en plusieurs paquets de façon à ne pas charger des données inutiles au script qui les utilise !

De plus il est imaginable de faire une console d'administration qui modifie ces fichiers et ainsi de permettre à des Mjs de pouvoir opérer des réglages sans avoir besoin de demander à un programmeur !

Voici donc notre exemple, avec des données centralisées :
  • un fichier var_carac_basique.php, où l'on centralise les réglages concernant les caractéristiques

<?php
//...
$cb= array(
//...
'energie' =>1,
'vision' =>10,
'force' =>0.1,
'min_potion' =>0.5
);
//...
?>
  • un fichier fr.php, où l'on centralise les textes français (Attention il peut être utile de séparer les textes par paquets afin d'éviter de charger des textes qui n'ont rien à faire dans le script !)

<?php
//...
$textes= array(
'perso_creer' =>'Votre perso, %s, est crée!',
'perte_bonus' =>'Votre perso, %s, perd son bonus de potion éphémère',
'utilise_potion'=>'Gloup Gloup'
);
//...
?>
  • un fichier inscription.php, où l'on enregistre le joueur avec ses caractéristiques

<?php
//...
require_once($file_lang);
require_once('var_carac_basique.php');
//...
$energie=$cb['energie'];
$vision=$cb['vision'];
$force=$cb['force'];
$sql="INSERT INTO `war_perso`
( `id` , `nom` , `xp` , `ville` , `arme` , `energie` , `Vision`, `force`)
VALUES ('$id', '$nom', '0', '$ville', '', '$energie', '$vision', '$force')";
 
//...
echo sprintf($textes['perso_creer'],$nom);
//...
?>
  • un fichier nouveau_tour.php où l'on renouvelle les caractéristiques

<?php
//...
require_once($file_lang);
require_once('var_carac_basique.php');
//...
$energie=$cb['energie'];
$vision=$cb['vision'];
$force=$cb['force'];
$sql="UPDATE `war_perso`
SET `energie`='$energie', `vision`='$vision', `force`='$force'
WHERE `id`='$id'";
 
//...
echo sprintf($textes['perte_bonus'],$nom);
//...
?>
  • un fichier potion.php où l'on augmente les caractéristiques pour un tour lorsque l'on prend une potion

<?php
//...
require_once($file_lang);
require_once('var_carac_basique.php');
//...
$min_potion=$cb['min_potion'];
$precision=100;
$ajout=$cb[$potion_type]*mt_rand(round($min_potion*$precision),$precision)/$precision;
$sql="UPDATE `war_perso`
SET `$potion_type`=`$potion_type`+'$ajout'
WHERE `id`='$id'";
 
//...
echo sprintf($textes['utilise_potion']);
//...
?>

Stocker toutes les données dans une table d'une base de données

Une autre solution est de tout mettre dans une table, cela dit attention l'accès aux bases de données est assez long !

En revanche, c'est peut être plus simple à mettre en place.

Il faut donc bien peser le pour et le contre

Faire un peu des 2 précédents

Il peut être judicieux de faire un mélange des 2 effectivement. L'idée c'est d'éviter d'avoir des fichiers énormes et donc d'utiliser des ressources inutilement. Pour ce faire on met dans la base de données les données occasionnelles et dans les fichiers les données très courantes.

Il semble judicieux de rassembler le tout avec une fonction ou une classe pour éviter de salir le script de traitement.

Il y a sûrement d'autre façon

Oui là je vous ai montré quelques façons que j'ai utilisées maintenant il y a sûrement d'autres approches pour le faire.

Conclusion

Voilà le but de ce tutorial était surtout d'attirer l'attention sur le problème de redondance des données dans les scripts.
J'espère que maintenant vous essayerez de mettre en place quelques choses afin d'éviter cette erreur récurrente !

NB: Le problème est identique dans les bases de données, il y a d'ailleurs un tutorial à ce sujet.

orthographe — pascaltje 2007/12/11 16:48
Question : il faudrait modifier le nom du champ 'force', qui est un mot clé réservé de MySQL, non ?
cf le tuto "bonnes pratiques SQL"

Zamentur : En fait l'exemple fonctionne parce qu'il y a utilisation de `` , mais c'est vrai qu'on devrait peut etre changer çà.

LexLxUs : Si tu tiens à conserver ce nom, je pense que dans ce cas, il faut au moins un avertissement SmileAdrien Giboire 2007/12/11 19:20
Zamentur : c'est fait.