L'objectif de cette partie sera de savoir comment déterminer une région qui n'est pas traversable, et les différentes réactions qu'il est possible d'en attendre (simple blocage, glissement...). Première pensée, un personnage ne traverse pas le sol... jusque là tout est normal. Mais comment 'dire' à notre programme que l'on souhaite bloquer le joueur sur telle ou telle région d'une carte ? Dans un premier temps, il faut déjà que le joueur soit capable de retourner ses coordonnées sur le niveau (entre autre, savoir sur quelle case du niveau le joueur se trouve). Cela dépend de la façon dont le joueur et le niveau sont gérées, mais dans un cas simple, il suffira de s'arranger pour que la position (0, 0) corresponde au bas-gauche du niveau, et (max, max) corresponde au haut-droite du niveau. Ainsi on peut savoir à tout moment où se trouve le joueur, et donc, savoir sur quelle 'case' il est (en divisant sa position par la taille d'une case).
Ensuite, il ne reste plus qu'à lire les informations de collisions du Tile (la 'case'). Ces informations là doivent être générer lors du chargement d'un niveau. Par exemple, en spécifiant dans un fichier le type de collision pour chaque type de Tile (GROUND, BORDER, NONE ...).
Puis, il s'agit d'un traitement au cas par cas:
Cela marche très bien pour un 'Mario-Like'.
Mais qu'en est-il pour des collisions plus complexes, comme par exemple une pente ?
Ou une bordure ?
Il nous faut juste une couche supplémentaire de précision.
En effet, dans le cas précédent, on se limite à savoir sur quelle case on est. La précision dépend donc de la taille d'une case. Maintenant, le but est d'augmenter la précision. Cela est surtout vrai pour une pente (il n'est pas concevable de réaliser une pente sous forme d'escalier, en descendant par 'pas', et non progressivement). Nous aurons donc besoin d'une fonction qui devra être capable de nous retourner les coordonnées du joueur sur le Tile.
Précédemment, nous avons parlé d'une fonction retournant les coordonnées du joueur sur le niveau (sur quelle case), maintenant, on rentre plus dans le détail, à savoir qu'on aura comme référentiel le Tile courant, et non le niveau. Rien de bien compliqué ici. Une fois que l'on a les coordonnées du joueur sur le niveau (au Point près), il suffit d'y soustraire les coordonnées du Tile sur lequel le joueur est. Ainsi on aura une valeur entre 0 et la taille du Tile. A partir de la, il ne reste plus qu'à appliquer une courbe géométrique pour avoir la collision voulue (classiquement, une courbe linéaire pour une pente, de type '2x'). X étant une valeur comprise entre 0 et la taille du Tile, Y sera calculé à partir de la fonction réalisant le type de collision voulu (linéaire pour une pente par exemple).
Petite illustration avec un exemple tiré de mon remake de Lionheart:
En mémoire, il y a les Tiles, le Joueur, et la courbe que doit décrire chaque Tile. En visuel on ne voit pas la courbe bien évidement, c'est juste pour voir ce que 'verra' le programme. Ici le rendu est complet, mais il faut imaginer cette image avec une grille correspondant à la taille des Tiles. C'est seulement l'assemblage qui donne l'impression de continuité.
Avant de poursuivre sur autre chose, j'introduis une nouvelle approche des collisions, car nous allons voir que le traitement réalisé précédemment atteint ses limites rapidement. En effet, la détection des collisions se base sur la récupération du Tile courant. Celui-ci possède une certaine taille. Le joueur tombe à une certaine vitesse, qui augmente au fur et à mesure qu'il tombe (accélération). Imaginez un cas, où la vitesse du joueur est tout juste plus grande que la taille du Tile.
Par exemple, le Tile a une taille de 16 pixels, et la vitesse de chute actuelle du joueur est de 16 pixels par tour de boucle. Le joueur se trouve un peu avant le Tile désigné comme étant de type 'GROUND' (il ne doit donc pas le traverser), et au prochain tour de boucle, le joueur tombe de 16. Dans ce cas présent, on détectera le Tile, et tout se passera comme si on était tombé pile poil dessus. Cependant, prenons un autre exemple où le joueur se trouve juste avant le Tile avec une vitesse de 17 pixels. Au tour de boucle suivant, il se retrouvera à Tile.x - 1 + 17, soit tout juste de l'autre coté du Tile. Aucune collision n'aura été détectée ! Le joueur passera donc au travers... or cela n'est pas sensé arriver ! La limitation réside dans le fait que tester uniquement la position courante est insuffisant pour garantir que cette situation précédente n'arrive jamais.
Il faut pour cela procéder à une analyse entre la position d'arrivée et la position précédente. Entre autre, tester la zone de mouvement, et donc, pas seulement l'arrivée. Une autre approche consisterai à se baser sur la prédiction de la prochaine position, pour savoir si on va traverser une zone de collision ou non, cependant, cette technique présente des risques selon le fonctionnement interne du programme. En effet, si on utilise ou non l'extrapolation, l'environnement entre le moment où l'on a prédit, et l'instant ou le personnage y est vraiment, ne sera pas le même, compte tenu des compensations ou non faites par le moteur.
Lire la suite: Les Jeux de Plateforme - Conclusion