Je travaille sur un roguelike de base en utilisant HTML5 et jQuery, et j'ai rencontré un problème.
Dans l'état actuel du jeu, le système enregistre uniquement l'état du jeu chaque fois que l'utilisateur se déplace entre les étages - pour minimiser les frais généraux. Le danger est que, si l'utilisateur a des ennuis, il peut simplement fermer la fenêtre et retourner à son jeu au début de l'étage actuel. Cela réduit considérablement la difficulté du jeu (et va presque à l'encontre du but d'un roguelike) - mais il est déraisonnable de sauvegarder l'état du jeu à chaque mouvement ou attaque d'un seul joueur.
J'ai cherché des moyens de sauvegarder l'état du jeu à la fermeture de la fenêtre du navigateur, mais je n'en suis pas satisfait. Ma question est la suivante: en supposant que "sauvegarder un état de jeu" signifie une demande ajax / post modérément lourde, comment puis-je contrecarrer ce comportement de triche? Existe-t-il une méthodologie connue pour quantifier les modifications incrémentielles / procédurales d'une carte 2D, au lieu d'enregistrer la totalité de l'état de la carte? Veuillez noter que je ne demande pas «le moyen le plus efficace» - je recherche des méthodologies existantes pour rectifier mon inexpérience.
la source
Réponses:
La solution évidente consiste à envoyer chaque commande de joueur au serveur au fur et à mesure de sa création et à ce que le serveur les enregistre; de cette façon, si le jeu est abandonné pour une raison quelconque, les commandes enregistrées peuvent être rejouées pour restaurer le jeu au point où il s'est arrêté.
Bien sûr, lorsqu'une sauvegarde correcte est effectuée, l'ancien journal des commandes peut être jeté (bien que vous puissiez également le sauvegarder pour autoriser la relecture d'anciens jeux; si vous le faites, vous souhaiterez peut-être inclure des horodatages dans le journal pour une relecture en temps réel ). Vous pouvez également vouloir effectuer automatiquement une sauvegarde complète après que n commandes ont été effectuées depuis la dernière sauvegarde (où, par exemple, n = 1000) pour éviter des replays trop longs si le joueur reste au même niveau trop longtemps avant de fermer ou de planter le jeu. .
Si votre jeu comporte des nombres aléatoires (et, étant un roguelike, il le fait probablement), vous devrez également vous assurer qu'ils peuvent être recréés correctement lors d'une relecture. Une solution consiste à inclure chaque nombre aléatoire dans le journal de relecture; une autre consiste à utiliser un générateur de nombres pseudo-aléatoires déterministes et à sauvegarder la graine lorsque le jeu est enregistré.
Notez que toutes ces méthodes peuvent être exploitées en altérant le client, mais c'est vraiment inévitable chaque fois que vous avez une logique de jeu sur le client. Comme alternative à la triche, vous pouvez exécuter le jeu réel sur le serveur et demander au client d'envoyer toutes les commandes des joueurs au serveur et de recevoir les mises à jour d'affichage. Pour un roguelike, cela peut être faisable. De toute évidence, cela résoudrait également votre problème d'enregistrement d'état (bien que vous souhaitiez toujours implémenter une forme de journalisation des commandes sur le serveur, à la fois pour la fonctionnalité de relecture et pour permettre la récupération après des pannes de serveur). L'inconvénient est que cela rendrait le jeu hors ligne impossible (à moins, bien sûr, que vous ne rendiez également le code côté serveur disponible pour que les joueurs puissent l'exécuter localement s'ils le souhaitent).
la source
Voir /programming/3888902/javascript-detect-browser-close-tab-close-browser pour une question plus générique de la même question.
Pensez également à enregistrer le jeu complet lors des changements de sol et des deltas incrémentiels à chaque coup. Ensuite, vous pouvez rejouer le jeu jusqu'au dernier coup.
En supposant qu'il existe une certaine utilisation de générateurs de nombres aléatoires, vous pouvez générer et redéfinir le générateur de nombres aléatoires au début de chaque nouvel étage, puis l'enregistrer avec l'étage. Ensuite, vous pouvez réensemencer à la charge et vous devriez pouvoir rejouer les mouvements avec la même séquence jusqu'au dernier.
la source
Approches, non pas des sauvegardes incrémentielles, mais de la recherche de temps pour une sauvegarde complète:
onunload
, comme mentionné précédemment. J'ai trouvé que c'était fiable (mais en utilisantlocalStorage
, pas en réseau, ce qui peut changer les choses).la source