Déplacer le personnage

Dans le chapitre sur le shooter, vous avez appris à déplacer un vaisseau pixel par pixel. Nous pourrions refaire la même chose ici, mais je vous propose plutôt de varier les plaisirs et de voir comment se déplacer en case par case ! C'est très utile pour les roguelike et les RPG en tout genre, ainsi que pour les jeux de stratégie par exemple.

Afficher le personnage

Commencez par dessiner votre héroïne ou héros comme il se doit.

Sprite d'héroïne

Ensuite, dans un nouvel onglet "Player", créez un tableau pour préciser la position X et Y de départ du personnage et le sprite utilisé.

Comme nous faisons un jeu en case par case, les coordonnées n'indiqueront pas la position à l'écran mais bien la position sur la grille de la carte. Ici, le personnage se situe donc sur la 7ème case en X et la 4ème en Y, puisque les coordonnées de la carte commencent à 0.

Pour afficher le sprite en jeu, nous devons utiliser la commande que vous connaissez bien, spr(sprite, x, y). Problème : elle prend une position d'écran alors que les coordonnées du personnage correspondent à la carte ! Mais comme une case fait 8 pixels, il suffit de multiplier les coordonnées par 8 pour obtenir la bonne position à l'écran.

Appelons ces deux fonctions dans notre game loop :

Testez votre jeu pour voir votre personnage s'afficher ! N'hésitez pas à changer ses coordonnées pour vérifier que le système fonctionne.

Programmer le mouvement

La première méthode qui vous viendra à l'esprit pour réaliser le mouvement sera probablement celle-ci :

Simple, efficace. Cela dit, si vous créez cette fonction et l'appelez dans update, vous verrez que le personnage peut passer à travers les obstacles, donc nous devons affiner le système. Au lieu de directement déplacer le personnage, nous allons plutôt stocker la nouvelle position souhaitée afin de vérifier qu'elle soit valide.

La position à tester sera appelée "New X" et "New Y".

Maintenant, nous devons vérifier si le tile "New X Y" est un obstacle, c'est-à-dire vérifier si ce tile a le flag 0 !

Vérifier l'état d'un flag

Nous allons créer une fonction qui nous servira souvent, pour vérifier si une case de la carte a un certain flag activé. Quand on écrira check_flag(flag, x, y), le résultat sera true si le flag en question est activé, false sinon. Voici le code :

Avant toute chose, dites-vous que techniquement, une case de la carte n'a pas de flag : c'est le sprite qui les a. Donc la commande fget qui vérifie l'état d'un flag ne peut pas être utilisée directement sur une case de la carte. Nous devons d'abord récupérer le numéro de sprite qui correspond à cette case avec mget.

Le fait de créer une variable locale avec local est simplement une bonne pratique car nous n'aurons pas besoin de la variable sprite en dehors de cette fonction.

Maintenant que nous connaissons le sprite, nous pouvons utiliser fget(sprite, flag) qui renvoie true ou false selon l'état du flag choisi. Grâce à return, notre fonction renvoie donc true ou false.

Gérer la collision

Revenons à player_movement() et récapitulons... check_flag renverra true si la case examinée est un obstacle, donc nous voulons avancer uniquement si check_flag renvoie false. On peut l'écrire de deux façons : la façon ennuyeuse, et la façon cool.

if check_flag(0, newx, newy) then
    -- c'est un obstacle
else
    -- on peut avancer
end
if not check_flag(0, newx, newy) then
    -- on peut avancer
end

Comme not inverse le signal de ce qui suit, la condition est validée quand il n'y a pas d'obstacle. Très pratique ! Plus qu'à mettre à jour la position du personnage en conséquence.

Testez le jeu et cela devrait fonctionner ! Si vous allez vers la droite ou le bas, la caméra ne vous suit pas encore mais nous nous en occuperons à l'étape suivante. Par contre, si vous allez vers le haut ou la gauche, vous dépasserez les limites de la carte de PICO-8 en ayant des coordonnées négatives, et il vaudrait mieux l'empêcher. Là aussi, il y a une façon barbante et une façon cool de l'écrire :

p.x = newx
p.y = newy
if (p.x < 0) p.x = 0
if (p.x > 127) p.x = 127
if (p.y < 0) p.y = 0
if (p.y > 63) p.y = 63

Voilà ce que ça donnerait si votre map est de 128×64 cases. Pas très fun, hein... Heureusement, il existe la fonction mid : si vous lui donnez 3 nombres, elle vous renverra le nombre entre les deux autres.

p.x = mid(0, newx, 127)
p.y = mid(0, newy, 63)

Généralement, la valeur du milieu sera newx. Par contre, si vous allez trop à gauche et que newx devient -1, la valeur du milieu sera alors 0 ! p.x ne pourra donc jamais dépasser 0 ou 127.

Ajouter un feedback sonore

C'est la cerise sur le gâteau. Pour que le jeu soit plus fun et que votre joueur ou joueuse comprenne bien qu'elle essaie d'aller dans un mur, on peut ajouter un petit son.

Quelque chose de court et discret devrait faire l'affaire :

Boup.

Parfait ! Comme promis, dans la section suivante nous verrons comment faire suivre la caméra avec deux types de vues différentes !