Jusqu'à présent, nos méthodes de détection de collision reposaient sur des bases mathématiques. Bien que cela soit utile, il existe des cas où l'approche mathématique n'en vaut tout simplement pas la peine, comme dans le cas d'une forme organique irrégulière: les calculs nécessaires sont trop complexes et coûteux à justifier. Au lieu de cela, nous pouvons vérifier chaque pixel individuel des formes. C'est aussi une approche coûteuse, mais elle peut au moins être optimisée.
C'est la dernière pièce que nous allons essayer de créer. Faites glisser le crochet sur le cocotier et notez ce que dit le texte en bas.
Supposons que nous ayons deux bitmaps et que nous voudrions vérifier si elles se rencontrent pixel par pixel: qu'est-ce que cela signifie? Eh bien, supposons que vos deux bitmaps soient 3x3px et que tous les pixels soient remplis.
Nous ferons littéralement ceci:
Il y a quelques observations que je voudrais souligner.
Observation | La description |
Pixels en haut à gauche | Les pixels en haut à gauche des deux bitmaps sont utilisés comme pixel de départ pour les vérifications. Par exemple, a1 est le pixel de départ vérifié par rapport à tous les pixels de b, qui commence par b1. Les deux pixels en haut à gauche. |
Progression de la ligne de balayage | Comme mentionné au point précédent, la vérification est effectuée dans l'ordre de a1, a2, a3… a9. Notez la façon dont ces pixels sont disposés. |
Espace de coordonnées commun | Supposons que les deux graphiques sont ajoutés à la liste d'affichage de la scène. L'emplacement de chaque pixel dans les deux bitmaps, dans l'espace de coordonnées de la scène, seront comparés pour voir s'il y a des chevauchements. |
Calcul coûteux | Pour deux bitmaps 3x3, un maximum de 9 répétitions est requis. Si ma taille de bitmap passe à 100x100, vous pouvez voir à quelle vitesse le calcul total augmente. Toutefois, si une vérification donne un résultat positif, le reste des vérifications peut être annulé, car lorsqu'un pixel se chevauche dans les deux bitmaps, on peut dire qu'une collision se produit entre les bitmaps. |
Maintenant, l'étape 1 peut être prise à la lettre si tous les pixels sont remplis. Avec les graphiques bitmap, nous définissons une zone de dimension rectangulaire. Mais tous les pixels ne sont pas remplis pour former le graphique.
L'exemple ci-dessous montre le bitmap de droite occupant uniquement b2, b4, b5, b6 et b8. Dans ce cas, nous devrions vérifier chaque pixel du bitmap de gauche (a1, a2, a3… a9) uniquement par rapport aux pixels b2, b4, b5, b6, b8 du bitmap de droite..
Maintenant, ActionScript nous fournit un autre paramètre, alpha
, qui définit la transparence du pixel, 0 étant complètement transparent et 1 complètement opaque. Pour b2, b4, b5, b6, b8, nous pouvons définir une valeur de seuil pour alpha
, dire 0,5.
Donc, supposons que b2 et b8 sont tous deux des pixels avec alpha
0,1; comme ils sont inférieurs à la valeur seuil de 0,5, nous ne les considérerons pas comme des pixels remplis et ne les vérifierons donc pas. Donc à la fin, chaque pixel du bitmap de gauche (a1, a2, a3… a9) est comparé à b4, b5, b6 uniquement dans le bitmap de droite.
En ActionScript, nous pouvons superposer des graphiques vectoriels dans BitmapData
les instances. Vous pouvez imaginer qu'ActionScript prenne une radiographie d'un graphique vectoriel et la transfère vers un fichier. BitmapData
, qui agit comme le film photographique.
(Astuce: si vous dessinez dans Flash IDE puis exportez vers FlashDevelop comme je le fais, assurez-vous que les dimensions du BitmapData
sont assez grands pour contenir le dessin.)
Ici, CTree
et Crochet
sont deux symboles MovieClip, dessinés en Flash; nous les "radiographions" pour obtenir une instance BitmapData pour chacun:
noix de coco de var privé: CTree, hk: Crochet; private var bdat1: BitmapData, bdat2: BitmapData; private var t1: TextField; fonction publique Matrix_Bitmap () coco = new CTree (); addChild (noix de coco); noix de coco.x = stage.stageWidth * 0,3; noix de coco.y = stage.stageHeight * 0,2; bdat1 = new BitmapData (150, 150, true, 0x00000000); bdat1.draw (noix de coco); hk = nouveau crochet (); addChild (hk); bdat2 = new BitmapData (100, 50, true, 0x00000000); bdat2.draw (hk); hk.addEventListener (MouseEvent.MOUSE_DOWN, début); hk.addEventListener (MouseEvent.MOUSE_UP, fin); t1 = new TextField (); addChild (t1); t1.x = stage.stageWidth * 0.2; t1.y = stage.stageHeight * 0.8; t1.width = 300; t1. hauteur = 100; stage.addEventListener (Event.ENTER_FRAME, à vérifier);
Donc, après cela, nous allons commencer les contrôles en utilisant le hitTest ()
méthode du BitmapData
classe.
Sur chaque image qui passe, nous mettrons à jour l’emplacement du pixel en haut à gauche pour chaque bitmap avant de placer des instances de BitmapData
à travers ces rigoureuses hitTest ()
chèques. Notez également que la plage de alpha
l’entrée ici est 0 ~ 255 - c’est-à-dire qu’il n’ya pas de seuil. Plus d'informations sur la transparence à l'étape suivante.
vérification de fonction privée (e: événement): void var point1: point = nouveau point (coconut.x, coconut.y); // pixel en haut à gauche de l'arbre var point2: Point = new Point (hk.x, hk.y); // pixel en haut à gauche de hook if (bdat1.hitTest (point1, 255, bdat2, point2, 255)) // vérifie si des pixels remplis se chevauchent t1.text = "Au moins un pixel est entré en collision" else t1 .text = "Pas de collision"
Voici un exemple de sortie d'ActionScript ci-dessus. Cliquez sur le crochet et rapprochez-le du cocotier et vérifiez la réponse dans la zone de texte. Jouez avec cela en plaçant l'extrémité du crochet près du bord des feuilles du cocotier pour voir si cette collision est d'une précision au niveau des pixels..
Si vous avez une image qui, par exemple, disparaît progressivement (devient transparente), vous pouvez indiquer à ActionScript le niveau de transparence que vous considérez comme un ajustement de pixel pour effectuer les contrôles de collision..
Prenons l'exemple ci-dessous: il existe plusieurs niveaux de transparence sur le sprite et, comme vous pouvez le constater, il est progressivement abaissé vers la droite. Si nous fixons le niveau de transparence à 0.5, alors tout pixel avec un alpha de 0.5 ~ 1 sera considéré comme opaque et apte à la détection de collision. Ceux inférieurs à 0.5 seront considérés comme transparents. Même lorsque ces pixels entrent en collision avec ceux d’un autre objet, ils ne peuvent pas enregistrer une véritable collision..
Un autre détail que je viens de mentionner est le fait qu’ActionScript BitmapData
La fonction hitTest de alpha
La valeur du paramètre est en réalité comprise entre 0 et 255. Donc, je multiplie simplement la valeur de seuil par 255 pour convertir la plage..
vérification de fonction privée (e: événement): void var point1: point = nouveau point (bar1.x, bar1.y); var point2: Point = nouveau Point (bar2.x, bar2.y); Seuil var: Number = 255 * 0,5 si (bdat1.hitTest (point1, seuil, bdat2, point2, seuil)) t1.text = "Au moins un pixel est entré en collision" else t1.text = "Pas de collision"
J'ai déjà mentionné que la détection de collision au niveau des pixels est onéreuse en termes de calcul. Cela signifie que nous ne devrions opter pour cela que lorsque cela est strictement nécessaire. Si deux objets sont très éloignés l'un de l'autre, il n'y a aucune raison d'utiliser cette approche et une détection de collision normale dans le cadre de sélection (hitTestObject ()
) ça ira.
Voici l'idée:
hitTestObject ()
pour voir si les boîtes englobantes de deux objets sont entrées en collision.vérification de fonction privée (e: événement): void var closeEnough: Boolean = coconut.hitTestObject (hk) if (closeEnough) var point1: Point = nouveau Point (cocout.x, cocout.y); var point2: Point = nouveau Point (hk.x, hk.y); if (bdat1.hitTest (point1, 255, bdat2, point2, 255)) t1.text = "Au moins un pixel est entré en collision" else t1.text = "Pas de collision"
Pour une référence ActionScript complète, consultez Matrix_Bitmap3.as
depuis la source télécharger.
Merci pour la lecture. Dans le prochain conseil, nous utiliserons des matrices pour transformer BitmapData
.