24 janvier 2019

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 :


Sphère de collisionBoite de collision


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 ?


Nodes de collision

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.


Montagne avec collision foireuse

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.


Omeganaut - PC
Omeganaut - Android


Beerus disguised as Monaka in Dragon Ball Devolution

Fill that progress bar to 100% before the end of the month to get the next version of Dragon Ball Devolution ❤️


I'm fed up with "pongan" people. Add this, do that... This website is dying because only 1% of the players actually help. If the progress bar does not reach at least 50% by the end of the month, I'll start disabling the games. Starting with Dragon Ball Devolution.


Estoy harto de la gente que diga "pongan". Agregue esto, haga eso ... Este sitio web está muriendo porque solo el 1% de los jugadores ayudan. Si la barra de progreso no alcanza al menos el 50% para fin de mes, comenzaré a deshabilitar los juegos. Comenzando con Dragon Ball Devolution.