Les collisions de Puppet War

Illustration du problème de collision Je continue mon jeu en Flash. Je me heurte cette fois à un problème de collision que je dois faire entièrement en code, sans détection graphique.

Le déplacement

Dans Puppet War, le déplacement des automates se fait par une action.

L'automate veut aller vers une coordonnée, il fait une requête de mouvement à l'arène pour se déplacer. Puis, l'arène prend en compte tous les paramètres qui entrent en jeu et déplace l'automate.

Mon problème a donc été de détecter les obstacles et de s'arrêter au bon endroit pendant un déplacement.

Détection d'un obstacle

Description

Tous les éléments de l'arène (dont les automates) ont des coordonnées et une taille. Ils peuvent être représentés par des ronds, leur centre étant le point qui définit leurs coordonnées et le diamètre leur taille.

Illustration du problème

A est l'automate qui se déplace vers B. M est l'obstacle et M' sa projection orthogonale sur AB.

Dans un déplacement, il faut déterminer si un élément va toucher l'automate.

On connaît les coordonnées d'origine, celles de destination et celles de l'obstacle. On a aussi leur taille.

Calcul

L'idée est d'obtenir l'équation de droite à partir des points A et B, puis de calculer la distance entre M et M'. Avec cette distance et la taille des éléments, on sait s'il y aura collision.

On a des méthodes mathématiques qu'on fait facilement sur papier, mais il faut le traduire en code.

// On connaît les coordonnées de A, B et M
var a:Point;
var b:Point;
var m:Point;
 
// Equation de droite: y = ox + p
// On cherche o et p
var o:Number = (b.y - a.y)/(b.x - a.x);
var p:Number = a.y - o*a.x;
    
// Autre forme de l'équation de droite: ux + vy + w = 0
// On cherche u, v et w
var u:Number = o;
var v:Number = -1;
var w:Number = p;
 
// Calcul de la distance à l'aide de la seconde équation
var distance:Number = Math.abs(mx*u + my*v + w)/Math.sqrt(u*u + v*v);

Là j'ai détaillé, mais on peut raccourcir.

Illustration

Illustration du calcul de la distance d'un point à un segment de droite.

M est l'obstacle et AB le parcours prévu par l'automate.

La source est à cette adresse : http://download.neolao.com/flash/distance_point_droite.fla (FLA de 58ko)

Distance de contact sur l'obstacle

Description

Maintenant que j'ai déterminé un obstacle qui va géner le déplacement, il faut que je trouve les nouvelles coordonnées de destination.

Il faut déterminer les coordonnées de A' qui est la position sur le déplacement initial où l'automate collisionne avec l'obstacle.

Calcul

En regardant bien le schéma, on voit 2 triangles rectangles. Hop, pythagore :)

// On connaît les coordonnées de A, B et M, et les distances AB, MM', MA' et MA
var a:Point;
var b:Point;
var m:Point;
var ab:Number = Point.distance(a, b);
var mm2:Number;
var ma2:Number; // la distance MA' est la somme des rayons des 2 éléments
var ma:Number;
 
// On trouve la distance AM'
var am2:Number = Math.sqrt(ma*ma - mm2*mm2);
 
// On trouve la distance A'M'
var a2m2:Number = Math.sqrt(ma2*ma2 - mm2*mm2);
 
// Donc la distance AA'
var aa2:Number = am2 - a2m2;
 
// Et enfin, les coordonnées de A'
var a2:Point = Point.interpolate(b, a, aa2/ab);

Conclusion

J'ai donc un algorithme pour un déplacement en prenant en compte les obstacles.

Je n'ai pas parlé de la récupération des obstacles potentiels. En lisant un autre article sur des tests de collision dans Flash 9, je vais tenter la technique brute pour l'instant. C'est à dire que pour chaque déplacement, je vais faire des tests sur tous les éléments. Je réfléchirai à autre chose si besoin.

Mais vous allez me dire que c'est pas suffisant, il faut que l'automate contourne l'obstacle. En fait, ce n'est pas le but de l'action déplacement. Je vais expliquer un autre fois comment fonctionnent les comportements que j'ai imaginé, et donc aussi comment un automate va contourner un obstacle.

Commentaires

1. Le samedi, janvier 20 2007, 20:34 par Chupon

Je ne sais pas si c'est important, mais le petit exemple en flash calcul la distance entre l'obstacle M et la droite AB et non le segment.
Par conséquent il est possible qu'il détecte une collision si les 3 points A B et M sont approximativement alignés alors que M n'est pas sur le trajet... non ?

2. Le dimanche, janvier 21 2007, 00:53 par neolao

En fait, je ne l'ai pas dit, mais il y a aussi d'autres choses qui déterminent facilement les obstacles potentiels.

L'automate en A veut aller en B. Une cible potentielle M, doit avoir une distance inférieur à AB. Donc, visuellement, si M n'est pas sur le trajet, je ne le prend pas en compte et ça se résume par un IF dans le code.

Il ne m'a pas semblé utile de détailler à ce point, mais ça me rassure que quelqu'un lise :)

3. Le dimanche, janvier 21 2007, 13:19 par ekameleon

hello :)

tu as regardé les sources de Andre Mitchelle avec sa démo de collision en AS3 : lab.andre-michelle.com/ph...

Je trouve son boulot super intéressant et cela pourrait peut être t'aider ? :) Faudra d'ailleurs que je les regarde aussi de prêt car pour le moment j'ai juste regardé l'exemple et jeté un oeil rapide dans les sources (un peu trop rapide lol)

Sinon de mon côté j'ai commencé à mettre en place dans une extension de mon framework des classes qui vont permettre à terme de gérer ce genre de manipulation physique et géométrique avec des classe Line, Point, Vector2, etc. : svn.riaforge.org/vegas/AS...

EKA+ :)

4. Le dimanche, janvier 21 2007, 14:40 par neolao

Si c'est des détections par code, ouais ça m'intéresse.

Je me suis posé la question si je voulais vraiment un truc physique, c'est compliqué ces choses lol.

Je vais réfléchir, le truc d'Andre a l'air pas mail. J'ai regardé un peu le code, et effectivement, j'ai l'impression que c'est par code.

Sinon, je n'ai pas vu de licence, je ne sais même pas si j'ai le droit de l'utiliser.