[Plan du site]
Vous êtes ici ---
> Le Site du Zéro
> Les tutoriels
> Non-Officiels
> Programmation
> ActionScript / Flash / Flex
> Régler les problèmes de collisions
> Lecture du tutoriel
Régler les problèmes de collisions
Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Bonjour amis zéros

Dans ce tuto, je vais vous expliquer en détail comment régler certains problèmes dus aux collisions en Flash.
Nous allons commencer avec un petit exemple tout simple

Vous êtes un personnage, et vous décidez de vous arrêter lorsque vous rencontrer un obstacle.
Vous comprendrez que je ne me suis pas attardé sur le design
Alors voilà, votre personnage avance vers la droite. Il rencontre un obstacle et s'arrête.
Code : Autre1
2
3
4
5
6
7
8
9
10
11
12
13
| var deplacement = 1;
var vitesse = 5;
_root.personnage.onEnterFrame = function() {
if(deplacement) {
if(this.hitTest(_root.obstacle)) {
deplacement = 0;
}
if(Key.isDown(Key.RIGHT) && deplacement) {
this._x += 1 * vitesse;
}
}
}; |
Avez-vous vu le problème ?
Voici un zoom de la collision :
Techniquement, que se passe-t'il ?
Dans mon exemple, vous avez sans doute vu que j'ai initialisé ma variable
vitesse à 5.
Par conséquent, l'occurrence de clip
personnage (le petit truc bleu ^^) avance de 5 pixels 12 fois par secondes (cadence par défaut).
On vérifie s'il y a collision.
S'il n'y en a pas, le personnage peut se déplacer vers la droite.
Mais si les deux occurrences sont écartées par un écart de 3 pixels ?
Il n'y a pas collision, on peut donc se déplacer de 5 pixels vers la droite. Et là : superposition
Voilà le problème. Dans certains cas, ce n'est pas très gênant, dans d'autre ça peut le devenir.
Que faire alors pour régler le problème ?
Vous pourrez augmenter la cadence de 40 à 50 images par seconde, et réduire la vitesse à 1, l'occurrence du clip avancera de 1 pixel 40 à 50 fois par seconde, et là il n'y aura plus de superposition, mais c'est un peu brutal comme technique
Et puis, pensez à ceux qui n'ont pas un ordinateur très puissant

(j'ai un P3 à 866 MHz et mon ordi doit avoir mon âge, alors j'y pense continuellement

)
Alors que faire ?
Rassurez-vous, il existe plusieurs solutions

Je vais vous en donnez quelques-unes, mais il en existe sûrement beaucoup plus
Voici la première solution.
Lorsqu'on détecte la collision, on revient à sa position précédente.
Code : Autre1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| var deplacement = 1;
var vitesse = 4;
_root.personnage.onEnterFrame = function() {
if(this.hitTest(_root.obstacle)) {
this._x -= vitesse;
deplacement = 0;
}
else {
deplacement = 1;
}
if(deplacement) {
if(Key.isDown(Key.RIGHT) && deplacement) {
this._x += 1 * vitesse;
}
}
}; |
C'est pas génial, comme vous le voyez, le personnage "rebondit" sur l'obstacle
Bref, on oubli cette solution
Nous en arrivons à la deuxième solution

Dès lors qu'une collision est détectée, au lieu de reculer le personnage, on va le repositionner.
Voici un
jeu que j'avais commencé qui utilise ce procédé.
Que se passe-t'il ?
Le personnage avance. Dès qu'il rencontre un obstacle, on ne le fait pas reculer, on le repositionne.
Pour cela, on lui donne les coordonnées de l'obstacle auxquelles on soustrait la largeur du personnage (dans le cas de collisions horizontales) ou sa hauteur (dans le cas collisions verticales).
Voici à quoi devrait ressembler vos commandes de repositionnement :
Code : Autre1
2
| personnage._y = _root.sol._y - personnage._height;
personnage._x = _root.obstacle._x - personnage._width; |
Bien sur, si vous avez suivi, la première ligne repositionnera le personnage
au dessus du sol, la deuxième à gauche d'un obstacle.
Encore une fois, cette technique n'est pas parfaite, car si on a pas un ordi très puissant (

), l'animation sera ralentie, et on verrait le personnage "s'enfoncer" dans le sol pour en ressortir aussitôt.
Voici la troisième et dernière solution qui me parait la plus appréciable

Elle va permettre d'arrêter le personnage sans qu'il ne se superpose.
Partons de cet
exemple.
Code : Autre1
2
3
4
5
6
7
8
9
10
11
12
13
| var deplacement = 1;
var vitesse = 1;
_root.personnage.onEnterFrame = function() {
if(deplacement) {
if(this.hitTest(_root.obstacle)) {
deplacement = 0;
}
if(Key.isDown(Key.RIGHT) && deplacement) {
this._x += 1 * vitesse;
}
}
}; |
Le personnage avance d'un pixel après l'autre, et s'arrêtera donc pile au moment où il touchera l'obstacle. Pas de superposition donc

.
Seul problème : le personnage n'avance pas vite....
On pourrait augmenter la valeur de la variable vitesse, mais à ce moment-là, le personnage risque de se superposer à l'obstacle. On pourrait aussi augmenter la cadence, mais comme je l'ai dit dans l'introduction, c'est pas génial comme méthode, et surtout, ça empêche de modifier la vitesse au cour de l'animation (imaginez un jeu où le personnage pourrait marcher ou courir, ça ne serait pas réalisable sans modifier la vitesse).
Que peut-on faire alors ?

On va quand même essayer d'augmenter la vitesse
Essayons ça :
Code : Autre1
2
3
4
5
6
7
8
9
10
11
12
13
| var deplacement = 1;
var vitesse = 5;
_root.personnage.onEnterFrame = function() {
if(deplacement) {
if(this.hitTest(_root.obstacle)) {
deplacement = 0;
}
if(Key.isDown(Key.RIGHT) && deplacement) {
this._x += 1 * vitesse;
}
}
}; |
Pas de nouveautés, c'est le code du premier exemple, et ça ne marche pas plus qu'avant.
Il va falloir ruser : on va utiliser
une boucle
En fait, au lieu d'avancer le personnage d'un nombre équivalent à la valeur de la vitesse, on va l'avancer d'un pixel, mais autant de fois que la valeur vitesse nous l'indiquera.
On va utiliser une boucle for, qui s'exécutera "vitesse" fois, dans laquelle nous ferons avancer notre personnage d'un pixel, puis dans cette même boucle on vérifiera si le personnage peut toujours avancer.
Allez, à vos
crayons ordis
Correction :
Secret (cliquez pour afficher)Code : Autre1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| var deplacement = 1;
var vitesse = 5;
_root.personnage.onEnterFrame = function() {
if(deplacement) {
for(i=0; i<vitesse; i++) {
if(this.hitTest(_root.obstacle)) {
deplacement = 0;
}
if(Key.isDown(Key.RIGHT) && deplacement) {
this._x += 1;
}
}
}
}; |
Voilà

Le code n'est pas bien dur, j'espère que vous avez trouvé

.
Voilà, je pense que c'est la meilleur solution, parmi celle que je connais tout du moins

A vous de trouver la votre

.
Bon, je vous avoue quelque chose, je n'utilise presque pas de hitTest, pour vérifier les collisions en flash
QUOI ?????
M'en voulez pas

, c'est pas de ma faute

En fait, hitTest, peut être pratique dans certains cas, mais lorsque vous avez beaucoup d'éléments différents, et que vous voulez vérifier les collisions, c'est pas facile

.
Bon, allez, je vous mets sur la voie

Lorsque j'ai beaucoup d'éléments, j'utilise le principe de "tuiles".
C'est un peu plus compliqué, mais rien d'impossible, et c'est ce principe qui est à la base de vieux jeux, comme Zelda Link's Awakening, ou Sword of Mana.
Je ne vais pas m'attarder sur le sujet, car ce n'est pas le thème de mon tuto, mais je vous conseille de chercher un peu sur le web comment ça fonctionne précisément, si jamais vous avez la phobie des hitTest
Voilà, ce tuto est terminé, j'espère qu'il vous aura été utile