TourDeJeu, le portail des jeux en ligne alternatifs, les articles 
TourDeJeu, le réseau des jeux en ligne alternatifs : jeux web multijoueurs, jeux par forum. En savoir +
En ligne : 518 jeux, 7177 news, 26754 commentaires
 

Recherche de jeu par critères - Un jeu au hasard !

Les Focus

Tech. : Le programmeur écologique
Tech. : automatisation et mails
Salon MondeDuJeu 2002
Revue de presse des JpC
Humour : 1001 raisons pour jouer
Ludique : le joueur parfait
Ludique : découverte du JpC
PHP : accès base de données
PHP : structure du site
Ludique : JpC et Temps réel
Jeux de rôles sans règles
Humour : astrologie du JpC
Tech. : Bases de données
MJ : les joueurs multiples
PHP : utilité pour un JpC
PHP : c'est quoi ?
Tech. : l'analyse des ordres
Ludique : débutants et vétérans
Tech. : archi Ultraball 2100
Ludique : les jeux de pronos
Tech. : le site Web d'un JpC
Humour : football et wargame
Présentation de TourDeJeu

Devenir un développeur écologiste

Partez sur une bonne base

Partir sur une bonne base
Vertiges de la base de donnée ! Merveille que ces petites cases qui se remplissent et qui constituent le coeur de votre jeu. Jusqu'à ce qu'elle sature ; qu'elle déborde ; et que la moindre recherche demande plusieurs minutes. Là encore, il y a des réflexes importants pour ne pas gaspiller l'énergie du serveur.

Ne charger que le nécessaire
Une base de données permet de stocker à la fois des données d'usage fréquent et d'usage très rare. Il est important de les dissocier, pour que, dans le déroulement du jeu, seules les informations utiles soient rechargées. Prenons le cas d'un jeu impliquant un personnage. Il sera important de dissocier les données du joueur (identifiant, mot de passe, e-mail) qui ne sont utiles qu'à la connexion, et les données portant sur son personnage (points de vie, points d'action...) qui font l'objet d'un rechargement régulier. L'idéal, c'est de créer autant de bases qu'il y a de types de données dans le jeu : une base pour les objets, une pour les amis du joueur, que sais-je ? N'oubliez pas de faire correspondre chaque table, par exemple avec le même numéro d'identifiant pour le joueur et le personnage correspondant.

La même question doit se poser pour de nombreux détails. Est-il nécessaire de charger la liste complète des joueurs alors qu'il n'y en a que trois à proximité ? Est-il nécessaire de charger la liste complète des objets transportés par le joueur alors qu'on peut les "cacher" dans un sac à dos qui s'ouvre dans ce but ?

Le choix pertinent des données à afficher impose parfois des contorsions techniques (par exemple calculer les coordonnées minimales et maximales de visibilité d'un joueur pour afficher les personnages dont les coordonnées sont comprises dans cet intervalle). Au chapitre de l'arbitrage entre mySQL et PHP, il est parfois difficile de choisir le plus efficace. Un conseil : minimiser la charge PHP en faisant porter les calculs et le tris de données sur la base, qui est optimisée pour. Il faut par exemple proscrire l'usage de "SELECT *" si seul un nom est nécessaire "SELECT nom" sera plus approprié. Il y a d'autres petits trucs pratiques. Si vous souhaitez afficher les 10 premiers enregistrements (par ex. les en-têtes des 10 derniers messages), pas la peine de charger toute la table en mémoire : "SELECT en_tete FROM jeu_messages LIMIT 10" permettra d'économiser beaucoup de chargements puisque la recherche s'arrête dès que le 10e enregistrement est chargé.

Le cas le plus critique est celui des messages : ça enfle, ça gonfle et ça devient très difficile à compacter. Demandez-vous si la liste des messages doit être chargée systématiquement en début de page. Une page dédiée sera peut-être appropriée. Au besoin, il est possible de n'afficher que le dernier message, ou d'avertir le joueur qu'un message est arrivé. Une requête "SELECT id FROM jeu_message LIMIT 1" permet de "détecter" un nouveau message sans surcharger la base.

Compacter les données dans la base
On ne le répètera jamais assez : quand on n'a pas de pétrole, il faut avoir des ID (hum hum...). L'ID (pour index), c'est la clé de l'efficacité dans une base mySQL. Ce n'est pas facile à admettre pour un débutant, mais chaque joueur, chaque message, chaque objet du jeu ne doit être représenté que par un chiffre. Pourquoi ? Pour des raisons de rapidité et de liberté. J'ai moi-même débuté en faisant référence à chaque personnage par son pseudonyme, qui me paraissait suffisamment unique pour être représentatif. Mon code PHP comportait des tableaux de type $points["Roberto L'écolo"]. Oui mais voilà : tout d'abord j'ai eu de nombreux bugs à cause des apostrophes et guillemets, notamment dans les requêtes mysql. D'autre part le temps nécessaire pour une requête est bien plus important lorsqu'il s'agit de rechercher "Roberto L'écolo" que pour rechercher "4055" dans un index. Cela tient à la nature des données stockées dans la base.

Dans un champ "text" (ou "char" ou "blob"), chaque caractère est codé par 1 octet. Notre nom "Roberto L'écolo" occupe donc 15 octets. Supposons qu'il soit défini* par un index compris entre 0 et 65535 : cette valeur se code sur 3 octets. Cela signifie que, chaque fois que vous ferez référence à ce personnage par son ID dans une requête ou un calcul PHP, la quantité de données à calculer sera 5 fois plus petite qu'en utilisant son pseudo. Et croyez-moi, s'il y a 5000 joueurs sur votre partie, votre hébergeur vous remerciera de cet effort. * Cela ne signifie pas que le pseudo doive disparaître, mais il ne doit pas servir d'identifiant pour un joueur

Cette réduction s'applique aux autres données. Pour chaque valeur que vous souhaitez stocker dans la base, choisissez judicieusement le type de données. Comment faire ? Evaluez simplement la valeur MAXIMUM qui sera utile. Sans rentrer dans le détail des types de données mySQL, voici quelques indications générales :

  • ID (identifiant de joueur) : MEDIUMINT UNIQUE -> permet de stocker 65536 joueurs avec un index automatique (en auto-increment, c'est mieux). Et si jamais vous atteignez les 65000 joueurs vous pouvez passer en INT (mySQL convertit sans problème les valeurs lorsqu'on augmente la longueur), ce qui vous autorisera 16 millions de joueurs, mais vous devriez le voir venir.
  • ID (autre identifiant) : s'il y a plusieurs parties dans votre jeu, utilisez par exemple un TINYINT (256 valeurs) pour les repérer. Pour les identifiants de messages, le type INT s'impose. Mieux vaut partir sur une valeur basse, quitte à l'augmenter quand on constate que ça ne va pas suffire.
  • Pseudonyme de personnage : c'est une valeur "lourde" qui pourrait être placée dans une table à part si les accès à la table des persos sont fréquents ; par exemple dans la table des joueurs. Pour la longueur, préférer un champ de type CHAR avec une longueur de 25 (ça évitera les délires de joueurs qui créent des noms de 500 caractères).
  • Valeur alternative oui/non ou 0/1 : SET avec pour valeur '0','1' ou 'oui','non' -> permet de définir les valeurs possibles pour un champ : chaque champ peut alors occuper 1 seul bit de données (un huitième d'octet) dans la base. Par comparaison à un champ texte avec "oui" ou "non" occupe 24 fois plus d'espace.
  • Valeur numérique (points de vie, etc) : à vous de déterminer le maximum acceptable, sans bloquer les joueurs puissants. En général, on optera pour du MEDIUMINT (65536).
  • Date : je n'ai pas de données précises à ce sujet : je préfère stocker les dates sous forme de timestamp (obtenue par un mktime() en PHP) dans un champ INT (ça donne le nombre de secondes écoulées depuis le 1/1/1970, par exemple 1055190185), ce qui permet de manipuler les dates plus simplement qu'avec les fonctions DATE() de mySQL. Il est possible que je me plante sur ce sujet ; je reste ouvert aux suggestions.

    Enfin, si votre système s'y prête, il peut être intéressant de multiplier les références, même si ça impose une gestion très rigoureuse. Dans Tératogénèse, on peut envoyer un même message à 10, 30, 40 personnes à la fois. Au départ, j'ai créé un message pour chaque destinataire. Si l'on compte l'ID de l'émetteur, celle du récepteur, le texte et la date d'émission du message, ma base est très vite devenue astronomique (3 Mo de données pour "seulement" 12000 messages hebdomadaires). Puisque la seule donnée qui changeait pour chaque récepteur était son ID, j'ai décidé de créer UN SEUL message de référence, pour 30 ou 40 messages qui "pointaient" vers ce message en ne comportant qu'un numéro de récepteur. Avec ce système un peu compliqué, j'ai réduit la table à 700ko, ce qui a considérablement accéléré les accès à la base. Ensuite, ça complique un peu la réception et le "nettoyage" des messages trop vieux, mais on s'en sort.

    Retour au sommaire de l'article 
  • (c) TourDeJeu 2000-2024