2010-07-07 3 views
1

Je sais qu'il y a des gens qui créent des classes pour cela (par exemple, http://coreyoneil.com/portfolio/index.php?project=5). Mais je veux apprendre à le faire moi-même pour pouvoir créer tout ce dont j'ai besoin.ActionScript 3 pixels collision parfaite. Comment? (à des fins d'apprentissage)

J'ai lu à propos de BitMap et BitMapData. Je devrais être capable de retirer les MovieClips sur une BitMap pour pouvoir ensuite faire défiler les pixels à la recherche des collisions. Cependant, il est bizarre et confus de traiter les décalages .. Et il semble que le MyBitMap.rect a toujours x = 0 et y = 0 ... et je ne peux pas couper pour trouver la position d'origine des choses ...

Je pense d'abord faire un hitTestObject, puis si c'était positif, j'explorerais l'intersection entre les rectangles movieclips pour les collisions de pixels. Mais il y a aussi un autre problème (la rotation des clips vidéo) ...

... J'ai besoin d'un peu d'éclairage ici sur la façon de le faire. S'il vous plaît, toute aide serait appréciée ..

Répondre

0

j'ai réussi à le faire après tout, et je l'ai déjà écrit ma classe pour détections de collision,/angle de collisions et autres extras.

Le processus le plus déroutant est peut-être d'aligner les bitmaps correctement pour comparer.Lorsque whe dessine() un MovieClip dans un bitmapData, si nous ajoutonsChild() le Bitmap correspondant, nous pouvons voir qu'une partie de celui-ci n'est pas visible. il semble être tiré du centre vers la droite et vers le bas seulement, laissant les parties supérieure et gauche loin d'être tiré. La solution donne une matrice de transformation dans le second argument de la méthode draw qui aligne le bitmap et le fait tous être dessinés.

ceci est un exemple d'une fonction dans ma classe pour créer une image bitmap pour comparer:

static public function createAlignedBitmap(mc: MovieClip, mc_rect: Rectangle): BitmapData{ 
       var mc_offset: Matrix; 
       var mc_bmd: BitmapData; 

       mc_offset = mc.transform.matrix; 
       mc_offset.tx = mc.x - mc_rect.x; 
       mc_offset.ty = mc.y - mc_rect.y; 
       mc_bmd = new BitmapData(mc_rect.width, mc_rect.height, true, 0); 
       mc_bmd.draw(mc, mc_offset); 

       return mc_bmd; 
} 

afin de l'utiliser, si vous êtes sur la ligne de temps, vous faites:

className.createAlignedBitmap(myMovieClip, myMovieClip.getBounds(this)) 

Notez l'utilisation de getBounds qui renvoie le rectangle dans lequel le clip est incorporé. Cela permet le calcul de la matrice de décalage.

Cette méthode est tout à fait similaire à celle montrée ici sur http://www.mikechambers.com/blog/2009/06/24/using-bitmapdata-hittest-for-collision-detection/

Par les façons, si cela est une question intéressante pour vous, vérifier mon autre question que je vais poster dans quelques instants.

1

Si vous utilisez des objets BitmapData avec transparence, vous pouvez utiliser BitmapData.hitTest(firstPoint:Point, firstAlphaThreshold:uint, secondObject:Object, secondBitmapDataPoint:Point = null, secondAlphaThreshold:uint = 1):Boolean.

Vous devrez passer des coordonnées globales aux coordonnées BitmapData locales, ce qui nécessitera un peu de maths si vous les faites pivoter. C'est facile à réaliser (look up affines transformer pour plus d'informations sur le wiki):

var coordTransform:Matrix = new Matrix(); 

coordTransform.rotate(rotationRadians); 
coordTransform.translate(x, y); 

coordTransform.transformPoint(/* your point */); 
+0

Je ne veux pas simplement tester si elles entrent en collision. Je veux apprendre à le faire manuellement, parce que je vais devoir trouver des informations comme l'angle de collision qui n'est pas retourné par la fonction que vous avez mentionnée, pour autant que je sache. mais .. dans votre code, parlez-vous de changer l'emplacement de tous les pixels dans le bitmap en utilisant une matrice de rotation? est-ce que c'est ça? – jmacedo

+0

L'angle de collision? Pourriez-vous élaborer (c'est-à-dire la normale à la tangente de l'endroit où ils sont entrés en collision). La façon de le faire manuellement est de faire défiler chaque pixel d'un bitmap et de voir s'il touche le pixel d'un autre bitmap. Ensuite, si un pixel touche un autre pixel de l'autre, les bitmaps se chevauchent quelque part. Maintenant vous devriez utiliser une heuristique pour limiter les pixels que vous testez parce que cette méthode est extrêmement, extrêmement inefficace. – Mahir

+0

La transformation de coordonnées a été donnée dans le cas où votre image bitmap est tournée. Ex: Votre bmd est un carré de 20x20 pixels avec son coin supérieur gauche situé à (0,0). Vous le faites pivoter de 45 degrés dans le sens des aiguilles d'une montre pour en faire un diamant (encore une fois le coin supérieur gauche est à (0,0)). Si vous voulez voir si l'emplacement de la scène (0, 25) touche le bmd, (ce qui est le cas), vous ne pouvez pas frapper le test avec (0, 25) parce que le hitTest mesure les emplacements par rapport au bmd. Vous devez transformer cet emplacement en (25/sqrt (2), 25/sqrt (2)), ce à quoi le code dans mon exemple est destiné. – Mahir

1

Une référence classique pour la détection de collision parfaite pixel en flash est ce Grant Skinner's article. C'est AS2, mais la logique est la même pour AS3 (il y a des ports disponibles si vous google un peu). Si je me souviens bien, cette implémentation particulière a fonctionné tant que les deux objets testés avaient le même parent, mais cela peut être corrigé. À propos des valeurs BitmapData x et y, je comprends que cela pourrait être source de confusion; Cependant, la façon dont cela fonctionne est logique pour moi. Un BitmapData est juste ce que le nom implique: les données de pixel. Ce n'est pas un objet d'affichage et ne peut pas figurer dans la liste d'affichage. donc avoir x ou y différent de 0 n'a pas vraiment de sens, si vous y réfléchissez. La façon la plus simple de gérer cela est probablement de stocker le décalage (x,y) de l'objet source (l'objet d'affichage que vous avez dessiné) et de le traduire dans l'espace de coordonnées global afin de pouvoir comparer tous les objets quelle que soit leur position dans la liste d'affichage (en utilisant quelque chose comme var globalPoint:Point = source.parent.localToGlobal(new Point(source.x,source.y))

+0

Je rappelle que la méthode de Grant Skinner ne fonctionne correctement que si les deux objets sont des enfants directs de la scène. – Cameron

1

Je l'ai déjà utilisé la détection de collision pixel de Troy Gilbert parfaite classe (adapté d'André Michelle, Skinner Grant et Boulevart) qui fonctionne très bien (poignées rotation, parents différents, etc.).

http://troygilbert.com/2007/06/pixel-perfect-collision-detection-in-actionscript3/
http://troygilbert.com/2009/08/pixel-perfect-collision-detection-revisited/

et à partir de là, il a également lié à ce projet (que je ne l'ai pas utilisé, mais il semble vraiment impressionnant):

http://www.coreyoneil.com/portfolio/index.php?project=5