Une discussion a récemment eu lieu sur la façon de créer un jeu multijoueur à défilement horizontal 2D pouvant avoir une conception de niveau en boucle (pensez à Starbound et à la façon dont leurs mondes sont en boucle).
Je pensais que le moyen le plus simple serait d'avoir une carte rectangulaire avec des zones de déclenchement qui pourraient téléporter les joueurs d'un côté à l'autre. Cependant, le problème évident de cette approche est le fait d'avoir plusieurs joueurs à la fois sur le bord de la carte. Vous ne voulez pas simplement téléporter les joueurs les uns devant les autres et vous auriez besoin d'un moyen de transporter les joueurs sans faire disparaître d'autres joueurs.
Pour ajouter cette idée et résoudre le problème, j'ai proposé ce qui suit: avoir une zone de déclenchement (carré rouge dans l'image) où les joueurs pourront voir une "zone de clonage" (carré vert). Dans ce carré vert, les objets du côté opposé de la zone de déclenchement seraient copiés dans sa zone de clonage correspondante (visible avec les formes A et B). Lorsqu'un joueur arrive au bord de départ de la "zone clone", il est téléporté de l'autre côté de la carte.
Dans cet exemple, le joueur 2 penserait voir le joueur 1, mais il verrait en fait son clone et vice versa.
Cela semblait un peu extrême et complexe pour le problème à résoudre. Ma question est maintenant de savoir si cette solution est une bonne approche pour résoudre le problème, ou existe-t-il un moyen plus simple de résoudre ce problème?
la source
Réponses:
Ce système avec tous ces déclencheurs semble un peu trop compliqué et sujet aux erreurs.
Vous pouvez envelopper la position du joueur en utilisant modulo avec quelque chose comme
playerPositionX = playerPositionX % mapWidth
De cette façon, lorsque votre joueur atteindra
playerPosition == mapWidth
leplayerPosition
sera réinitialisé à 0.Cette solution pourrait être étendue à l'ensemble du système de rendu.
la source
pos - map_width
).La solution canonique consiste à utiliser des portails . Dans votre exemple, il n'y a qu'un seul niveau, sauf qu'il existe un portail reliant les extrémités gauche et droite.
Tout ce qui se déplace à travers ce portail aura ses coordonnées traduites à l'autre extrémité du portail, de sorte que si quelque chose se déplace vers la gauche à travers le portail, il réapparaîtra sur le côté droit du niveau et vice versa.
Votre caméra doit également prendre en charge les portails; si le portail est à l'intérieur de la caméra, il doit restituer des parties du niveau de chaque côté du portail. Si vous connaissez les éditeurs d'images pour les graphiques en mosaïque sans couture, c'est la même chose ici.
La partie fastidieuse est que tout ce qui concerne la distance ou le cheminement devra également prendre en charge les portails. Cela comprend l'IA, les algues en ligne de visée, l'atténuation du son, etc.
Ce qui est bien avec les portails, c'est qu'ils sont très puissants. Le moteur de construction l'a utilisé pour simuler des niveaux à plusieurs étages, bien qu'il ne s'agisse pas d'un "vrai" moteur 3D. Certains moteurs modernes utilisent également des portails pour créer des espaces non euclidiens; Portal et Antichamber sont des exemples notables en 3D.
la source
N'oubliez pas que ce que vous affichez à l'écran et ce qui est en mémoire sont deux choses totalement différentes. Imaginez que vous ayez une fenêtre que vous devez remplir avec des données sur le monde. Vous remplissez la fenêtre de gauche à droite. Pendant que vous analysez vos données pour remplir le monde, si vous atteignez la fin du monde, retournez simplement au début de vos données. Utilisant un opération modulo est idéale. N'oubliez pas que vous devez le faire pour tout . Projectiles, rayons, joueurs, physique; ils ont tous besoin d'avoir leurs positions enveloppées lors du franchissement des frontières du monde.
Chaque joueur partage des données, mais a sa propre perspective des données. Leurs fenêtres sont remplies différemment selon leur position dans le monde.
Cela signifie qu'il n'est pas nécessaire de créer des clones ou de téléporter qui que ce soit. Essentiellement , vous êtes en train de créer des clones, tout en rendant les caractères sur les écrans les uns des autres.
la source
Déconnectez le rendu du monde et vous pouvez effectuer un rendu enveloppant et correct sans recourir à des artefacts de clonage ou de téléportation.
Premièrement, dans votre monde, vous avez un monde de taille fixe, de
0
àWidth
. Chaque fois qu'un objet descend en dessous de 0, vous l'enveloppez jusqu'à la fin, et chaque fois qu'un objet est terminé,Width
enveloppez-le au début. Cela signifie que tous les objets logiques de votre monde sont toujours à portée0...Width
.Deuxièmement, pour le rendu, vous modulerez la position. Ainsi, le côté gauche de l'écran est "Base" et le côté droit est "Base + Taille". Vous regardez donc à travers votre monde pour tout ce qui se trouve dans cette plage. Vous rechercherez en fait la plage modulo, qui la remappe
0...Width
.L'astuce lors de la recherche consiste à renvoyer la position de l'objet par rapport à la
Base
côté gauche. Cela se convertit en coordonnées locales de l'écran afin que le rendu lui-même n'ait pas à se soucier du modulo, seule la recherche le fait.Vous n'avez pas besoin de cloner quoi que ce soit car chaque moteur de rendu ne traite que l'objet en un seul emplacement.
Si votre monde est produit en segments ou en utilisant des structures 3D, vous devrez le segmenter. Il ne s'agit donc pas d'un bloc cohérent, mais il peut être déplacé pour s'adapter à ce rendu. Vous n'avez pas besoin de beaucoup de blocs, au minimum 2.
la source
Je pense que la seule approche raisonnable serait d'implémenter votre monde enveloppé dans une structure de données sous-jacente complètement transparente pour le jeu et l'utilisateur. Donc, sur certains bas niveau, vous avez une fonction mapCoordinate () qui enveloppe vos coordonnées réelles dans votre ressource de carte sous-jacente ...
Donc, si votre monde actuel ne fait que 10 unités de large, le joueur et le jeu ne le sauront pas. Pour le joueur, le monde est infini - et si le jeu demande ce qui est en position 15 - la fonction sous-jacente traduira cette demande, modulo10 et donnera pack à l'objet en position 5.
Donc, pour toute la logique du jeu et tout le reste, c'est comme si vous aviez un grand monde infini, où il se trouve qu'il y a des copies de tout.
la source
Ce n'est pas tout à fait la même chose, mais j'ai implémenté quelque chose de similaire lors d'un game jam. Le jeu avait des joueurs se déplaçant sur un petit niveau circulaire, enroulé autour lorsque le joueur a atteint une position «x» de pi. Le rendu a été facile car nous venons de tout rendre, puis tournons une caméra offset pour suivre ce qui se passe. Vous pouvez implémenter quelque chose de similaire, comme cela a été suggéré ci-dessus:
la source