Le guide des jeux en ligne alternatifs
Comment créer son jeu et le gérer ?
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 :
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.