Esto sigue y concluye el correo anterior del Descubrimiento de Colisión perfecto por el Pixel Rápido para Cocos2D con el Ejemplo de código (1/2) artículo.

Las pruebas para colisión pixelMask con un rectángulo

Las pruebas para un punto individual son simples, probando de un rectángulo, como el cuadro delimitador de otro nodo requiere más trabajo. No sólo para escribir el código, sino también dirigirlo. Y es limitado con nodos que son ni hechos girar, ni escalados. And it is limited to nodes which are neither rotated nor scaled.

Lamentablemente, las pruebas de colisiones con rectángulos hechos girar (cuadros delimitadores orientados) no son triviales hasta sin considerar colisiones pixelMask. Aquí está un C ++ OBB y un C # OBB realización para el descubrimiento de colisión OBB. Y esto es sólo para los cuadros delimitadores, probando cada pixel en una máscara de pixel orientada sería probablemente prohibitivamente caro. And that’s just for the bounding boxes, testing each pixel in an oriented pixel mask would likely be prohibitively expensive.

Usted definitivamente quiere evitar un método de fuerza bruta que itera sobre la serie de pixelMask entera. En cambio, esta realización primero crea el rectángulo que se cruza del nodo pixelMask y el otro nodo, entonces sólo itera sobre la intersección para reducir bastante el número de iteraciones:

pruebe si pixelMask se cruza con un rect
Objetivo-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (BOOL) pixelMaskIntersectsRegularNode: (CCNode *) otro ) pixelMaskIntersectsRegularNode:(CCNode*)other
{
   CGRect intersectRect = [ intersectRectInPixels:self otherNode:other]; = [self intersectRectInPixels:self otherNode:other];
   
   //compruebe si alguna de las banderas en el pixelMask es puesta en la intersección
   NSUInteger maxX = intersectRect.origin.x + intersectRect.size.width; = intersectRect.origin.x + intersectRect.size.width;
   NSUInteger maxY = intersectRect.origin.y + intersectRect.size.height; = intersectRect.origin.y + intersectRect.size.height;
   para (NSUInteger y = intersectRect.origin.y; y <maxY; y ++) NSUInteger y = intersectRect.origin.y; y < maxY; y++)
   {
      para (NSUInteger x = intersectRect.origin.x; x <maxX; x ++) NSUInteger x = intersectRect.origin.x; x < maxX; x++)
      {
         Índice de NSUInteger = y * pixelMaskWidth + x; = y * pixelMaskWidth + x;
         devuelva el pixelMask [índice]; [index];
      }
   }
   
   vuelva NO; ;
}

Hay que notar que sólo tenemos que encontrar que un pixelMask mordía lo que es puesto. Esto significa que este método podría ser optimizado adelante en una variedad de caminos que aseguran que un pixel con mayor probabilidad será encontrado antes.

Por ejemplo puede sostenerse que más cerca al centro del pixelMask la probabilidad de un pixelMask mordía aumentos pondrás. Esto significa según la posición del intersectionRect la iteración sobre el pixelMask podría ser pellizcada para comenzar más cerca al centro del pixelMask y trabajo su camino hacia fuera. Pero esta optimización depende pesadamente de las imágenes usadas y a unos se extienden como los objetos se mueven. But this optimization depends heavily on the images being used and to some extend how the objects move.

El peor de los casos es que no hay ningún juego de brocas en el pixelMask para intersectRect dado. Sabiendo que, uno podría considerar la iteración sobre el pixelMask no BOOL por BOOL, pero buscando NSUInteger de 32 bites lleno (4 BOOL inmediatamente) del pixelMask. Si aquel valor de 32 bites es 0, entonces ninguno de los 4 trozos de colisión puede ser posiblemente puesto, reduciendo el número de pruebas e iteraciones de 4 a 1. Sólo si el valor es mayor que 0 usted tendría que comprobar que cada pixelMask individual mordía. Usando BitArray usted podría probar hasta 32 trozos inmediatamente de una moda similar. If that 32-Bit value is 0, then none of the 4 collision bits can possibly be set, reducing the number of tests and iterations from 4 to 1. Only if the value is greater than 0 you would have to check each individual pixelMask bit. Using a BitArray you could test up to 32 bits at once in a similar fashion.

Un vistazo en el método intersectRectInPixels revela que crea el rectángulo que se cruza de los cuadros delimitadores de los dos nodos que chocan. Importante para notar aquí está que el origen del rectángulo que se cruza debe ser convertido a nodeSpace del primer nodo y luego convertido a pixeles para asegurarse que esto trabaja con imágenes HD.

consiga la intersección rect de dos nodos
Objetivo-C
1
2
3
4
5
6
7
8
9
10
- (CGRect) intersectRectInPixels: (CCNode *) nodo otherNode: (CCNode *) otro ) intersectRectInPixels:(CCNode*)node otherNode:(CCNode*)other
{
   CGRect myBBox = [nodo boundingBox]; = [node boundingBox];
   CGRect otherBBox = [otro boundingBox]; = [other boundingBox];
   CGRect intersectRect = CGRectIntersection (myBBox, otherBBox); = CGRectIntersection(myBBox, otherBBox);
   
   //transforme el rect al espacio del elfo y el converso señala a pixeles
   intersectRect.origin = [nodo convertToNodeSpace:intersectRect.origin]; = [node convertToNodeSpace:intersectRect.origin];
   devuelva CC_RECT_POINTS_TO_PIXELS (intersectRect); (intersectRect);
}

Ser capaz de pasar dos nodos a este método permite que el rectángulo cruzar sea calculado para ambos nodos que chocan. Esto es necesario después, cuando determinamos la colisión de dos KKPixelMaskSprite que se cruzan posiblemente.

El descubrimiento de colisión de dos KKPixelMaskSprites

Es sólo un relativamente pequeño paso que va de pixelMask con la intersección de rectángulo a pruebas de dos pixelMasks para la intersección (el traslapo puede estar una mejor palabra aquí). Otra vez, usted no tiene que usar la fuerza bruta – es suficiente comprobar el traslapo (cruce) el rectángulo de los dos elfos. Otra vez esta prueba no trabaja con rectángulos hechos girar o escalados pero es un inconveniente que beneficia la realización de la prueba. Again this test doesn’t work with rotated or scaled rectangles but it’s a drawback that benefits the performance of the test.

las pruebas para colisión de dos pixelMasks
Objetivo-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- (BOOL) pixelMaskIntersectsPixelMaskSprite: (KKPixelMaskSprite *) otro ) pixelMaskIntersectsPixelMaskSprite:(KKPixelMaskSprite*)other
{
   CGRect intersectSelf = [ intersectRectInPixels:self otherNode:other]; = [self intersectRectInPixels:self otherNode:other];
   CGRect intersectOther = [ intersectRectInPixels:other otherNode:self]; = [self intersectRectInPixels:other otherNode:self];
   NSUInteger originOffsetX = intersectOther.origin.x - intersectSelf.origin.x; = intersectOther.origin.x - intersectSelf.origin.x;
   NSUInteger originOffsetY = intersectOther.origin.y - intersectSelf.origin.y; = intersectOther.origin.y - intersectSelf.origin.y;
   NSUInteger otherPixelMaskWidth = other.pixelMaskWidth; = other.pixelMaskWidth;
   BOOL* otherPixelMask = other.pixelMask; otherPixelMask = other.pixelMask;
   //compruebe si alguna de las banderas en el pixelMask es puesta en el área de intersección
   NSUInteger maxX = intersectSelf.origin.x + intersectSelf.size.width; = intersectSelf.origin.x + intersectSelf.size.width;
   NSUInteger maxY = intersectSelf.origin.y + intersectSelf.size.height; = intersectSelf.origin.y + intersectSelf.size.height;
   para (NSUInteger y = intersectSelf.origin.y; y <maxY; y ++) NSUInteger y = intersectSelf.origin.y; y < maxY; y++)
   {
      para (NSUInteger x = intersectSelf.origin.x; x <maxX; x ++) NSUInteger x = intersectSelf.origin.x; x < maxX; x++)
      {
         Índice de NSUInteger = y * pixelMaskWidth + x; = y * pixelMaskWidth + x;
         
         si (pixelMask [índice]) pixelMask[index])
         {
            //compruebe si hay un juego de pixel en la misma posición
            //en el pixelMask del otro elfo
            NSUInteger otherX = x + originOffsetX; = x + originOffsetX;
            NSUInteger otherY = y + originOffsetY; = y + originOffsetY;
            NSUInteger otherIndex = otherY * otherPixelMaskWidth + otherX; = otherY * otherPixelMaskWidth + otherX;
            
            si (otherPixelMask [otherIndex]) otherPixelMask[otherIndex])
            {
               devuelva ; ;
            }
         }
      }
   }
   vuelva NO; ;
}

Comparado con la prueba de rectángulo anterior, el rectángulo que se cruza de otro KKPixelMaskSprite que choca fue añadido y una referencia a otherPixelMask junto con otros valores escondidos en líneas 4-9. La idea esencial de la función todavía realiza la misma prueba hasta la línea 22. En vez de devolver el primer trozo que es puesto en el pixelMask, tenemos que asegurarnos que este trozo también es puesto en el otherPixelMask. Instead of returning the first bit that is set in the pixelMask, we have to make sure that this bit is also set in the otherPixelMask.

Ya que el índice en el otherPixelMask puede ser fácilmente calculado compensándolo con el origen del rectángulo intersectOther, sólo tenemos que generar un nuevo índice para mismo x, y coordenadas, pero con relación al sistema coordenado de otro KKPixelMaskSprite. Las líneas 26 y 27 realizan aquella operación usando originOffset predeliberado de líneas 6 y 7. En la esencia esto compensa el x, y coordenadas a la misma posición dentro del rectángulo de intersección del otro elfo. Lo que permanece convierte las coordenadas al índice y prueba si el trozo de otherPixelMask en aquel índice también es puesto. De ser así, tenemos una colisión. In essence this offsets the x,y coordinates to the same location within the other sprite’s intersection rectangle. What remains is converting the coordinates to the index and testing if the otherPixelMask bit at that index is also set. If so, we have a collision.

Reunión de las pruebas de intersección

Hay un método que excluí hasta ahora. Es el método de interfaz público que los usuarios de KKPixelMaskSprite llamarán. Esto funciona varios tempranos prueban y también escogen la prueba correcta para funcionar basado en la clase del otro nodo. It performs several early out tests and also picks the right test to perform based on the class of the other node.

determine que prueba de intersección funcionar
Objetivo-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- (BOOL) pixelMaskIntersectsNode: (CCNode *) otro ) pixelMaskIntersectsNode:(CCNode*)other
{
   si (¡rotation_! = 0.0f || ¡other.rotation! = 0.0f || rotation_ != 0.0f || other.rotation != 0.0f ||
        ¡self.scale! = 1.0f || ¡other.scale! = 1.0f) != 1.0f || other.scale != 1.0f)
   {
      CCLOG ("¡o ambos nodos son hechos girar y/o escalados, volviendo NO!"); ");
      vuelva NO; ;
   }
   
   si ([mí intersectsNode:other]) [self intersectsNode:other])
   {
      si ([otro isKindOfClass:PixelMaskSpriteClass]) [other isKindOfClass:PixelMaskSpriteClass])
      {
         KKPixelMaskSprite* maskSprite = (KKPixelMaskSprite *) otro; = (KKPixelMaskSprite*)other;
         vuelva [ pixelMaskIntersectsPixelMaskSprite:maskSprite]; self pixelMaskIntersectsPixelMaskSprite:maskSprite];
      }
      más
      {
         vuelva [ pixelMaskIntersectsRegularNode:other]; self pixelMaskIntersectsRegularNode:other];
      }
   }
   
   vuelva NO; ;
}

Mencioné antes que las pruebas de intersección no trabajan con nodos hechos girar o escalados. En este caso el método inmediatamente no vuelve y registra esto para evitar a alguien que se hace frustrado porque las pruebas “no siempre trabajan”. También ahorrarme muchas tales preguntas. :) Also to spare me many such questions. :)

Por supuesto la intersección sólo prueba tienen sentido si los cuadros delimitadores se cruzan. El método intersectsNode es una función de conveniencia que usted encontrará en Kobold2D, y en la clase de CCNodeExtensions añadido al proyecto.

El pixelMask contra la prueba de pixelMask sólo es realizado si el otro nodo también es KKPixelMaskSprite, en todos otros casos el rectángulo que se cruza pixelMask prueba es realizado en cambio. La variable de PixelMaskSpriteClass es una variable estática inicializada en el método init como [mí clase] simplemente porque el envío del mensaje de clase cada vez es un poco pródigo comparado con 4 bytes de la memoria adicional para la variable de PixelMaskSpriteClass.

Las pruebas de la intersección de dos elfos, o KKPixelMaskSprite o no, son tan simples como la escritura:

1
si ([spriteA pixelMaskIntersectsNode:spriteB])...[spriteA pixelMaskIntersectsNode:spriteB]) ...

Rendimiento de Máscara de pixel: BitArray contra. Serie de BOOL

BOOL array

Ahora a una pregunta interesante: ¿si BitArray es capaz de reducir el uso de memoria al 1/8vo (el 12.5 %), es también más rápido? Déjeme revelar esto ya que un diseño obtenido realizando el pixelMask contra pixelMask comprueba varios cientos de miles de tiempos repetidamente, y midiendo la duración total: Let me reveal this as a graphic obtained by performing the pixelMask vs pixelMask check several hundred thousand times repeatedly, and measuring the total running time:

En otras palabras: es una compensación entre uso de memoria y rendimiento de tiempo de ejecución. Las pruebas de intersección de máscara de pixel son 27 % más lentas en un iPod 4, y 18 % más despacio en un I-Phone 3G usando BitArray. Y por si acaso usted se pregunta: si usted debiera usar un UInt16 o hasta serie de UInt32 en vez de la serie de BOOL usted verá una disminución muy menor en el rendimiento (menos del 5 %), pero doblará respectivamente cuatro veces el uso de memoria. Pixel mask intersection tests are 27% slower on an iPod 4, and 18% slower on an iPhone 3G when using the BitArray. And just in case you’re wondering: if you were to use a UInt16 or even UInt32 array instead of the BOOL array you’ll see a very minor decrease in performance (less than 5%) but double respectively four times the memory usage.

Cuarto para Mejora

Escribiendo la clase de KKPixelMaskSprite descubrí mucho cuarto para la mejora. No quiero ahorrarle la lista porque también revela algunos defectos de la clase que creo que usted debería ser consciente de. Si usted realmente pone en práctica una de estas mejoras por favor compártalos, y de ser posible compártalos según una licencia permisiva, como el MIT. If you do implement one of these improvements please share them, and if possible share them under a permissive license such as MIT.

Mejoras posiblemente útiles, por orden de utilidad
  • el escondite pixelMasks, por ejemplo en una cosa única de CCPixelMaskCache, o los añade a CCTexture2D
  • permita la creación de máscara de pixel de nombres de spriteframe o spriteframes
  • permita pruebas de colisión si el elfo es hecho girar a exactamente 90, 180 o 270 grados
  • permita el uso del no poder de dos imágenes para pixelMasks en 1ros/2dos dispositivos de generación
  • permita colisiones entre Dakota del Sur y elfos de imagen HD
Optimizaciones potenciales por orden de eficacia esperada
  • reduzca la talla pixelMask combinándose 2×2, 3×3, 4×4, etc. pixeles en un trozo solo
  • O: sólo use imágenes de Dakota del Sur para pixelMask, forzando colisiones en dispositivos de Retina señalar límites
  • optimize iteraciones probando UInt32 (4x BOOL) o Trozos múltiples inmediatamente para el valor> 0
  • optimize iteraciones comenzando a iterar de la esquina el más cercana al centro

En particular la optimización para reducir la talla pixelMask combinando pixeles múltiples debería resultar ser muy eficiente, y es relativamente fácil a poner en práctica. La mayoría de las colisiones perfectas por el pixel realmente no tienen que ser perfectas por el pixel, una aproximación bastante cercana es más que bastante para la mayor parte de aplicaciones. En particular en dispositivos de Retina ningún jugador será capaz de distinguir si el no tan el pixel las colisiones perfectas sólo son exactas dentro de dos, tres, o posiblemente hasta más pixeles. El enfoque más simple debería considerar sólo sólo las imágenes de Dakota del Sur para máscaras de pixel, hasta en dispositivos de Retina. La ventaja añadida que es que pixelMask más pequeño iguala menos iteraciones y así pruebas de colisión más rápidas. In particular on Retina devices no player will be able to make out if the not-so-pixel-perfect collisions are accurate only within two, three, or possibly even more pixels. The simplest approach would be to just consider only the SD images for pixel masks, even on Retina devices. The added advantage being that a smaller pixelMask equals fewer iterations and thus quicker collision tests.

Descargue el proyecto de ejemplo por KKPixelMaskSprite


¡Descargue el proyecto de demostración de KKPixelMaskSprite!

Este proyecto también está disponible en mi depósito github donde recibo todo el código fuente iDevBlogADay.

¡PiXmas alegre!

Esto es mi último puesto de iDevBlogADay antes de Xmas. Es extra grande, extra crujiente, cubierto en chocolate, olores como la canela, gustos como manzanas y nueces y salsa y galletas y pavo, y es prohibido en los EE. UU porque esto contiene pixeles no comestibles y es un riesgo sofocante para cada uno que tiene la intención de leerlo en uno va.

¡En aquel sentido, Merry Xmas cada uno! :)


¡Ayúdeme a ayudarle!

Paso mi tiempo entero subiendo con nuevas ideas que le ayudarán a hacerse un mejor revelador app. Muchísimo disfruto del proceso de aprendizaje, empujar de límites (mío y suyo y aquella de la tecnología), teniendo la libertad de perseguir independientemente de lo que está en mi mente o suya, a vigorosamente el programa lo que nadie ha programado antes, y escribir sobre que he aprendido. Ayúdeme a ayudarle hojeando los productos en Aprender la Tienda de Cocos2D. Help me help you by browsing the products in the Learn Cocos2D Store.


¡Cada venta permite que yo siga escribiendo mejor código, más seminarios y respuestas provechosas!

13 Respuestas a “Descubrimiento de Colisión perfecto por el Pixel rápido para Cocos2D con Ejemplo de código (2/2)”

  1. [...] LearnCocosTV – el Episodio 1: Como yo maed su Kobold Descubrimiento de Colisión Rápido perfecto por el Pixel para Cocos2D con Ejemplo de código (2/2) [...]

  2. Ross dice:

    ¿Ha probado usted el rendimiento con relación a bibliotecas de física, como Box2d o Ardilla listada? Yo estaría interesado para saber – supongo que mucha gente sólo los usa para su funcionalidad de descubrimiento de colisión.

    • Esto no puede ser razonablemente comparado porque los motores de física no hacen pruebas de colisión perfectas por el pixel, ellos confían en polígonos (formas) para hacer las pruebas de colisión. Y el número de vértices en cada forma a menudo es con severidad limitado, por ejemplo Box2D permite como máximo 8 vértices por forma.

      • Ken Carpenter dice:

        Realmente, creo que ellos pueden ser razonablemente comparados.

        Las técnicas de desarrollo animosas a menudo son una compensación entre lo que está "bien" y lo que está “bastante bien”.

        Añadiendo el pixel las colisiones perfectas hacen su juego mejor para jugar, pero cortan el framerate en la mitad, muchos reveladores elegirán el más alto framerate y bajarán la exactitud de colisión.

        Como tal, sabiendo la realización del descubrimiento de colisión para Box2D ayudaría a un revelador a hacer una opción informada. Por supuesto usted debería tratar de hacer las comparaciones tan cerca como sea posible y le gustaría usar todos aquellos 8 vértices.

        • Usted es correcto en principio. Pero en este caso yo diría que la decisión tiene que ser tomada por el diseño. El rendimiento sólo no es crucial para esta decisión. Performance just isn’t crucial to this decision.

          Por ejemplo, las colisiones perfectas por el pixel son muy exactas, pero no trabajan en ninguno de los elfos es hecho girar o escalado. Mientras que si usted considera el descubrimiento de la colisión con un motor de física sus elfos pueden ser hechos girar o escalados. Y las posibilidades consisten en que si usted quiere o tiene que usar un motor de física de todos modos, usando la física para descubrir todas las colisiones es simplemente un requisito. And chances are that if you want or have to be using a physics engine anyway, using physics to detect all collisions is simply a requirement.

  3. Ernesto Corvi dice:

    Steffen, me alegro de que usted construyó en mi puesto de muchos-años. En mi defensa, realmente declaré que fijé el pseudocódigo. :)

    Soy a menudo deliberadamente vago sabio por el código, expresamente porque lo que realmente importa es el concepto bajo, y me gusta la gente estudiarlo detenidamente y subir con sus propias soluciones y realizaciones.

    Por lo que la utilidad del código contra dice, un motor de física, esto realmente depende de lo que usted hace. Recuerdo que cuando fijé aquella idea yo no trabajaba en un tipo de los Lemminges de clon para iOS (nunca soltado), y esto implicó la deformación de tiempo real del terreno en formas semicirculares que terminaron en muchos vértices, que hicieron tanto que la Ardilla listada como que OpenGL ES se ahogaran completamente rápidamente (hablamos 1ros dispositivos de gen aquí).

    Usando este método en cambio, yo simplemente entrecortado la textura "de terreno" con un círculo, actualiza el mapa de colisión, y la única retardación mínima cargaba de nuevo la textura de la CPU al GPU (que sólo pasó cuando el terreno realmente fue modificado, no que común de un acontecimiento).

    BTW, ajustando el código para trabajar en nodos hechos girar o escalados no es esto complicado. Usted tendría que transformar simplemente el punto de entrada antes de hacer la consulta.

    • Seguí creyendo que el siguiente paso lógico sería una deformación de terreno de estilo de los Lemminges. :)

      En cuanto a la transformación del punto de entrada, hice esto en el primer ejemplo. Las pruebas si un punto es dentro de un mapa de colisión escalado y hecho girar son un asunto de convertir el punto al espacio de nodo. Pero esto falla si usted quiere probar dos mapas de colisión el uno contra el otro, y ambos pueden ser escalados o alternados. Tal vez es posible aunque transformar primero el punto actualmente analizado de un nodo al espacio mundial, y luego al espacio del otro nodo, no seguro si esto dará el resultado correcto. But this fails if you want to test two collision maps against each other, and both may be scaled or rotated. Maybe it’s possible though to first transform the currently analyzed point from one node to world space, and then to the other node’s space, not sure if that will give the correct result.

      • Ernesto Corvi dice:

        Usted tendría que presentarse múltiple transforma. Es todo realmente dependiente de necesidades.

        Si a algún punto usted tiene que saber la dirección precisa, el ímpetu, la apatía o alguno de aquellos vectores como la parte de la colisión, entonces usted es probablemente mejor de dinero con el motor de física.

  4. Søren Krogh Neigaard dice:

    Hola Steffen

    ¿Y si los dos elfos para comprobar la colisión estén en CCLayers diferente, podría su código ser actualizado para manejar esto también? ¿De modo que la posición de los elfos de máscara sea convertida al espacio mundial o algo en el control de colisión?

    Recuerdos
    Søren

    • ¿Ha verificado usted que el código deja de relatar las colisiones correctamente en este caso? Como por lo que entiendo esto, convirtiendo coordenadas al espacio de un nodo (sistema coordenado) tendrá en cuenta (o simplemente no importa) que el nodo puede ser un niño de un o varios otros nodos.

  5. JARV dice:

    Hola Steffen

    He estado usando KKPixelMaskSprite con éxito con mi juego (¡es grande!), pero he cambiado mis elfos a spriteWithSpriteFrameName … y ahora realizo que no trabaja con marcos de elfo :(

    Voy a tratar de adaptar KKPixelMaskSprite para trabajar con marcos de elfo (supongo que no ha sido hecho). ¿Alguna pista para comenzar con?

    Gracias!!
    JARV

    • JARV dice:

      Finalmente lo consigo trabajando con pequeño workaround … que está okey con mi objetivo (de couse, puede ser mejorado)

      1. - Crean CCRenderTexture con la talla del elfo.
      2. - Posición de elfo de Cambio a 0,0 para visitar CCRenderTexture y luego restaurar su posición original:
      sprite.anchorPoint = ccp (0,0);
      sprite.position = ccp (sprite.offsetPositionInPixels.x * (-1)
      , sprite.offsetPositionInPixels.y * (-1));
      3. - Crean un UIImage con CCRenderTexture:
      UIImage *image = [rt getUIImageFromBuffer];

      Ahora tenemos un UIImage y podemos reutilizar el código de KKPixelMaskSprite (initWithFile).

      Sólo una consideración final, antes de la llamada a pixelMaskContainsPoint tenemos que ajustar el punto debido a la compensación:
      CGPoint señalan = ccp (point.x-sprite.offsetPositionInPixels.x, point.y-sprite.offsetPositionInPixels.y);

      ¡Esto trabaja grande!!

Deje una Respuesta