
Une collision... physique
Après quelques déboires pour faire tourner Omeganaut sur Android, le développement du jeu a repris de plus belle. Transitions de folie, nouveaux décors, nouveaux power-ups, beaucoup de debug et d'optimisations... Je pourrais continuer sur cette belle lancée mais je commence à être limité par la manière dont sont gérées les collisions dans ZGameEditor.
Pour définir la zone de collision d'un objet 3D, nous avons le choix entre une boîte et une sphère. En soit, cela devrait largement suffire. Seulement ces zones suivent le déplacement du modèle, mais pas sa rotation :
Aucun souci pour une sphère. Par contre, le problème est flagrant sur un vaisseau rectangulaire. Voilà pourquoi la plupart des ennemis se déplacent uniquement en ligne droite sur l'axe Z... Alors comment faire avec le vaisseau du joueur qui peut se déplacer et tourner librement sur les trois axes ?
Je lui ai attaché des nodes aux endroits cruciaux : nez et pointes des ailes (en vrai il y en a un peu plus). Les nodes sont de simples sphères de collisions et leur positions sont calculées en fonction des coordonnées et de la rotation du vaisseau.
Merci à Leonhard Euler (1717-1783) et Kjell du forum ZGameEditor, qui sont bien plus chauds que moi en mathématiques :
float X, Y, Z, SX, CX, SY, CY, SZ, CZ;
X = PlayerShip.Rotation.X*PI*2;
Y = PlayerShip.Rotation.Y*PI*2;
Z = PlayerShip.Rotation.Z*PI*2;
SX = sin(X); CX = cos(X);
SY = sin(Y); CY = cos(Y);
SZ = sin(Z); CZ = cos(Z);
X = NodeOffset[0]; // Position X du node sur le vaisseau
Y = NodeOffset[1]; // Position Y
Z = NodeOffset[2]; // Position Z
CurrentModel.Position.X = PlayerShip.Position.X + CY*CZ*X + (SX*SY*CZ-CX*SZ)*Y + (CX*SY*CZ+SX*SZ)*Z;
CurrentModel.Position.Y = PlayerShip.Position.Y + CY*SZ*X + (SX*SY*SZ+CX*CZ)*Y + (CX*SY*SZ-SX*CZ)*Z;
CurrentModel.Position.Z = PlayerShip.Position.Z + SX*CY*Y - SY*X + CX*CY*Z;
Des ennemis qui volent tout droit, des nodes invisibles qui virevoltent aux extrémités... C'est de la bidouille mais jusqu'ici la magie opère, on vole en plein "suspension of disbelief", jusqu'à l'arrivée récente des montagnes aux formes triangulaires aléatoires.
Aïe. Là ça devient n'importe quoi. On peut exploser en hauteur sans avoir touché la montagne, ou passer sans encombre à travers la base qui dépasse. Et puis j'aimerais bien ajouter des poteaux qui tombent, des carcasses de vaisseaux qui tournent sur elles-mêmes, des boss géants aux formes complexes comme... 🐙 un octopus cosmique !?
Je penche donc vers la librairie ZgeBullet, portée par Rado1 à partir de PyBullet (Bullet Real-Time Physics Simulation). Les exemples fournis sont plutôt faciles à comprendre et ça tourne très rapidement, même sur Android.
Par contre les réglages pour obtenir la même jouabilité et réactivité que la version actuelle d'Omeganaut risquent de prendre du temps. Mais je pense que le résultat final en vaut la chandelle. Imaginez-vous tirer sur un bâtiment qui s'effondre en plusieurs morceaux au-dessus d'un escadron ennemi. C'est tout de suite plus rigolo ! Et avec la physique, il peut se passer beaucoup de choses aléatoires qui vont caresser Random Number God dans le sens du poil.