Je veux développer une immense carte du monde; au moins 8000 × 6000 pixels. Je l'ai divisé en une grille 10 × 10 d'images 800 × 600 pixels PNG. Pour éviter de tout charger en mémoire, les images doivent être chargées et déchargées en fonction de la position du joueur dans la grille.
Par exemple, voici le joueur en position (3,3)
:
Alors qu'il se déplace vers la droite pour (4,3)
, les trois images à l'extrême gauche sont désallouées tandis que les trois images à droite sont attribuées:
Il devrait probablement y avoir un seuil à l'intérieur de chaque cellule de la grille déclenchant le chargement et le déchargement. Le chargement devrait probablement se produire dans un thread séparé.
Comment concevoir un tel système?
Réponses:
Il y a quelques problèmes à résoudre ici. La première est de savoir comment charger et décharger des tuiles. Le ContentManager par défaut ne vous permettra pas de décharger des éléments de contenu spécifiques. Cependant, une implémentation personnalisée de ceci:
Le deuxième problème est de savoir comment décider quelles tuiles charger et décharger. Ce qui suit résoudrait ce problème:
Le dernier problème est de savoir comment décider quand charger et décharger. C'est probablement la partie la plus simple. Cela pourrait simplement être fait dans la méthode Update () une fois que la position de l'écran du joueur a été déterminée:
Bien sûr, vous devrez également dessiner les tuiles, mais étant donné tileWidth, tileHeight et le tableau Tiles [], cela devrait être trivial.
la source
Ce que vous voulez faire est assez courant. Pour un joli didacticiel sur cette technique et d'autres techniques courantes, consultez cette série de moteurs de tuiles .
Si vous n'avez jamais rien fait de tel auparavant, je vous recommande de regarder la série. Cependant, si vous le souhaitez, vous pouvez obtenir le dernier code des didacticiels. Si vous le faites plus tard, consultez la méthode de dessin.
En un mot, vous devez trouver vos points X et Y min et max autour du lecteur. Une fois que vous avez cela, il vous suffit de parcourir chacun d'eux et de dessiner cette tuile.
Comme vous pouvez le voir, il se passe beaucoup de choses. Vous avez besoin d'une caméra qui va créer votre matrice, vous devez convertir votre emplacement de pixel actuel en un index de tuile, vous trouvez vos points min / max (j'ajoute un peu à mon MAX pour qu'il dessine un peu au-delà de l'écran visible ), puis vous pouvez le dessiner.
Je suggère vraiment de regarder la série de tutoriels. Il couvre votre problème actuel, comment créer un éditeur de tuiles, garder le joueur dans les limites, animation de sprites, interaction avec l'IA, etc.
Sur une note latérale TiledLib a cela intégré. Vous pouvez également étudier leur code.
la source
J'ai travaillé sur quelque chose de très similaire pour mon projet actuel. Voici un bref aperçu de la façon dont je le fais, avec quelques notes annexes sur la façon de vous faciliter la tâche.
Pour moi, le premier problème était de briser le monde en petits morceaux qui seraient appropriés pour charger et décharger à la volée. Puisque vous utilisez une carte basée sur des tuiles, cette étape devient beaucoup plus facile. Plutôt que de considérer les positions de chaque objet 3D dans le niveau, vous avez déjà bien divisé votre niveau en tuiles. Cela vous permet simplement de diviser le monde en morceaux de tuiles X par Y et de les charger.
Vous allez vouloir le faire automatiquement, plutôt qu'à la main. Puisque vous utilisez XNA, vous avez la possibilité d'utiliser le pipeline de contenu avec un exportateur personnalisé pour votre contenu de niveau. À moins que vous ne connaissiez un moyen d'exécuter le processus d'exportation sans recompilation, je vous le déconseille honnêtement. Bien que C # ne soit pas aussi lent à compiler que C ++ a tendance à l'être, vous ne voulez toujours pas avoir à charger Visual Studio et recompiler votre jeu chaque fois que vous apportez une modification mineure à la carte.
Une autre chose importante ici est de vous assurer que vous utilisez une bonne convention de dénomination pour les fichiers contenant des morceaux de votre niveau. Vous voulez pouvoir savoir que vous voulez charger ou décharger le bloc C, puis générer le nom de fichier que vous devez charger pour le faire au moment de l'exécution. Enfin, pensez à toutes les petites choses qui pourraient vous aider sur la route. C'est vraiment agréable de pouvoir changer la taille d'un morceau, de réexporter, puis d'en voir immédiatement les effets sur les performances.
Au moment de l'exécution, c'est encore assez simple. Vous aurez besoin d'un moyen pour charger et décharger des morceaux de manière asynchrone, mais cela dépend fortement du fonctionnement de votre jeu ou de votre moteur. Votre deuxième image est exactement correcte - vous devez déterminer quels morceaux doivent être chargés ou déchargés et faire les demandes appropriées pour que ce soit le cas si ce n'est pas déjà fait. Selon le nombre de morceaux que vous avez chargés à la fois, vous pouvez simplement le faire chaque fois que le joueur franchit une limite d'un morceau au suivant. Après tout, dans tous les cas, vous voulez vous assurer qu'il y a suffisamment de charge pour que même dans le pire temps de chargement (raisonnable), le morceau soit toujours chargé avant que le joueur puisse le voir. Vous allez probablement vouloir jouer beaucoup avec ce nombre jusqu'à ce que vous obteniez un bon équilibre entre les performances et la consommation de mémoire.
En ce qui concerne l'architecture réelle, vous souhaiterez faire abstraction du processus de chargement et de déchargement des données de la mémoire du processus de détermination de ce qui doit être chargé / déchargé. Pour votre première itération, je ne m'inquiéterais même pas des performances de chargement / déchargement et j'obtiendrais simplement la chose la plus simple qui pourrait éventuellement fonctionner, et vous assurer que vous générez les demandes appropriées aux moments appropriés. Après cela, vous pouvez envisager d'optimiser la façon dont vous chargez pour minimiser les déchets.
J'ai rencontré beaucoup de complexité supplémentaire en raison du moteur que j'utilisais, mais c'est assez spécifique à l'implémentation. Si vous avez des questions sur ce que j'ai fait, veuillez commenter et je ferai mon possible pour vous aider.
la source