Plus de 14 ans plus tard, la vidéo de Martin Jonasson et Petri Purho Juice it or lose it reste toujours dans un coin de ma tête quand je développe un jeu.
Pour ceux qui ne l’ont pas vu, elle est toujours autant d’actualité aujourd’hui donc c’est le moment. Pour ceux qui l’ont vu, elle est toujours autant d’actualité et ça fait pas de mal de la revoir donc c’est le moment.
C’est marrant parce qu’en la cherchant, j’ai instinctivement regardé pour Jan Willem Nijman, persuadé que c’était l’auteur de la vidéo. Bien que ma recherche ressemblait plus à « William juice conf old« , j’ai quand même réussi à retrouver pourquoi c’est son nom qui me parlait plus. Il a fait une vidéo dans la même style un an plus tard, « The art of screenshake » sur un platformer 2D plutôt. Très bonne vidéo également.
Mais revenons-en au mini-golf. C’est souvent un projet de jeu cool à faire pour débuter ou à faire tout court d’ailleurs. Alors voici, quelques exemples de bonnes pratiques et de juice que l’on peut ajouter rapidement pour améliorer le gamefeel.
Explications bonus
Ce que j’explique en code ici, se réfère à Godot 4.7 mais j’essaie de rester large pour que ce soit applicable sur n’importe quel moteur de jeu.
– Shot line
J’ai décortiqué un exemple de prédiction de shot dans un article précédent si besoin. La seule chose qui change ici, c’est la texture. Pour ça, j’exporte ma texture avec figma que je mets en Texture Mode Tile dans le Line2D.
– Trails
Le plus simple, bien que pas le meilleur en performance serait d’enregistrer la position de la balle à chaque frame, et de dessiner le tout avec un Line2D :

Mais en plus d’être couteux, quand la balle s’immobilise, on se retrouve souvent avec des artefacts au niveau des angles. Et c’est normal, si deux points sont positionnés au même endroit, (quand la balle s’arrête par exemple) impossible de calculer l’angle entre les deux points
Pour éviter ça, on a deux solutions. On pourrait avant d’ajouter un point, comparer le dernier point ajouté et la position de la balle, pour voir s’il y a assez de distance entre les deux. Ça résout le problème et en plus on limite le nombre de points sur le trail, donc c’est un bon début.
Mais si on décortique ce qu’il se passe à l’écran, ça semble quand même dommage de créer autant de points pour créer des lignes droites.

A chaque frame, plutôt que de créer un point, on pourrait update le dernier créé sur la position de la balle. Et dès qu’elle change de direction, ou qu’elle rencontre une collision, on peut l’ajouter définitivement au trail.

– Speed trail
Parfois, les meilleurs effets sont les plus simples. Pour l’effet de vitesse. Je le fais avec un line2D à nouveau. Le premier point est mis à jour dans le _process pour toujours être sur le global_position de la balle. Le deuxième ? Exactement pareil, mais avec un léger lerp qui lui donne ce décalage qui crée l’effet de vitesse.

On peut imaginer beaucoup d’améliorations à partir de cette base (gestion des rebonds, trail plus joli, etc.). Mais je la trouve déjà largement suffisante pour pas mal d’applications
– Dynamic sounds
Un point qui ajoute énormément de vie, c’est de rendre les sons plus dynamiques. Ici, je n’utilise que deux sons: un pour les collisions, un pour le shot.
La première chose que j’implémente sur tous les sons par automatisme c’est des variations de pitch :sound_node.pitch_scale += randf_range(-0.1, 0.1)
Ça crée vraiment beaucoup plus de profondeur, on n’a pas l’impression d’entendre la même chose en continu. Surtout pour des sons qu’on va entendre des centaines de fois.
La deuxième idée pour plus de réalisme et de diversité, c’est de modifier le volume en fonction des la puissance du shot / vitesse des collisions.
Pour le son du shot, je le remap par rapport au vecteur de tir. Et pour les collisions je les remap par rapport à la vitesse de la balle.
Référénces dans l’article :
Juice it or lose it – a talk by Martin Jonasson & Petri Purho
Jan Willem Nijman – Vlambeer – « The art of screenshake » at INDIGO Classes 2013