Questo continua e conclude il posto precedente della Scoperta di Collisione perfetta il Pixel Rapida per Cocos2D con articolo di Example Code (1/2).
Prova di collisione pixelMask con un rettangolo
Prova di un punto individuale è semplice, facendo sondaggi alla ricerca di un rettangolo come la scatola di limitazione di altro nodo richiede più lavoro. Non soltanto per scrivere il codice, ma anche dirigerlo. E è limitato a nodi che non sono né fatti girare, né scalati. And it is limited to nodes which are neither rotated nor scaled.
Sfortunatamente, prova di collisioni con rettangoli fatti girare (orientato presso limitazione di scatole) non è banale perfino senza considerare collisioni pixelMask. Qui è un C ++ OBB e un C # OBB l'esecuzione per scoperta di collisione OBB. E questo è soltanto per le scatole di limitazione, mettendo alla prova ogni pixel in una maschera di pixel orientata sarebbe probabilmente in modo proibitivo caro. And that’s just for the bounding boxes, testing each pixel in an oriented pixel mask would likely be prohibitively expensive.
Lei certamente vuole evitare un metodo di forza brutale che reitera sopra l'assortimento di pixelMask intero. Invece, quest'esecuzione prima crea il rettangolo intersecante del nodo pixelMask e l'altro nodo, allora solo reitera sopra l'intersezione per ridurre considerevolmente il numero d'iterazioni:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
- (BOOL) pixelMaskIntersectsRegularNode: (CCNode *) altro
) pixelMaskIntersectsRegularNode:(CCNode*)other
{
Il CGRect intersectRect = [stesso intersectRectInPixels:self otherNode:other];
= [self intersectRectInPixels:self otherNode:other];
//chieda se alcuna delle bandiere nel pixelMask è messa in intersezione Il NSUInteger maxX = intersectRect.origin.x + intersectRect.size.width;
= intersectRect.origin.x + intersectRect.size.width;
Il NSUInteger maxY = intersectRect.origin.y + intersectRect.size.height;
= intersectRect.origin.y + intersectRect.size.height;
per (NSUInteger y = intersectRect.origin.y; y <maxY; y ++)
NSUInteger y = intersectRect.origin.y; y < maxY; y++)
{
per (NSUInteger x = intersectRect.origin.x; x <maxX; x ++)
NSUInteger x = intersectRect.origin.x; x < maxX; x++)
{
L'indice di NSUInteger = y * pixelMaskWidth + x;
= y * pixelMaskWidth + x;
restituisca il pixelMask [l'indice];
[index];
}
}
ritorni NO;
;
} |
Si deve annotare che solo abbiamo bisogno di trovare che un pixelMask ha morso quello che è messo. Questo significa che questo metodo poteva esser più lontano ottimizzato in una varietà di strade che garanticono che un pixel sarà più probabilmente trovato ancora prima.
Ad esempio si può sostenere che più vicino al centro del pixelMask la probabilità di un pixelMask ha morso aumenti mettenti. Questo significa secondo la posizione dell'intersectionRect che l'iterazione sopra il pixelMask poteva esser pizzicata per iniziare più vicino al centro del pixelMask e azionare la sua strada verso l'esterno. Ma quest'ottimizzazione dipende pesantemente dalle immagini usate e ad alcuni si estendono come gli oggetti si muovono. But this optimization depends heavily on the images being used and to some extend how the objects move.
Lo scenario di caso più cattivo è che non c'è nessuna serie di pezzettino nel pixelMask per intersectRect dato. Sapendo che, uno potrebbe considerare l'iterazione sopra il pixelMask non BOOL da BOOL, ma cerca NSUInteger di 32 bit pieno (4 BOOL subito) dal pixelMask. Se quel valore di 32 bit è 0, allora nessuno dei 4 pezzettini di collisione può forse esser messo, riducendo il numero di prove e iterazioni da 4 a 1. Solo se il valore è più grande che 0 Lei dovrebbe controllare che ogni pixelMask individuale ha morso. Utilizzando un BitArray Lei poteva mettere alla prova fino a 32 pezzettini subito in una moda simile. 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'occhiata veloce del metodo intersectRectInPixels rivela che questo crea il rettangolo intersecante di scatole di limitazione dei due nodi scontranti. Importante per annotare qui è che l'origine del rettangolo intersecante deve esser convertita in nodeSpace del primo nodo e poi convertita in pixel per assicurarsi che questo lavora con immagini HD.
|
1 2 3 4 5 6 7 8 9 10 |
- (CGRect) intersectRectInPixels: (CCNode *) il nodo otherNode: (CCNode *) altro
) intersectRectInPixels:(CCNode*)node otherNode:(CCNode*)other
{
Il CGRect myBBox = [il nodo boundingBox];
= [node boundingBox];
Il CGRect otherBBox = [altro boundingBox];
= [other boundingBox];
Il CGRect intersectRect = CGRectIntersection (myBBox, otherBBox);
= CGRectIntersection(myBBox, otherBBox);
//trasformi il rect a spazio del folletto e converta punti in pixel l'intersectRect.origin = [il nodo convertToNodeSpace:intersectRect.origin];
= [node convertToNodeSpace:intersectRect.origin];
restituisca CC_RECT_POINTS_TO_PIXELS (intersectRect);
(intersectRect);
} |
Capacità di di passare due nodi a questo metodo permette al rettangolo intersecare di esser calcolato per entrambi i nodi scontranti. Questo è necessario poi, quando determiniamo la collisione di due forse incrociamento KKPixelMaskSprite.
Rivelazione di collisione di due KKPixelMaskSprites
È solo un passo relativamente piccolo che va da pixelMask con intersezione di rettangolo a prova di due pixelMasks per intersezione (la sovrapposizione può essere una parola migliore qui). Di nuovo, Lei non deve usare la forza brutale – è sufficiente controllare la sovrapposizione (l'incrociamento) il rettangolo dei due folletti. Di nuovo questa prova non lavora con rettangoli fatti girare o scagliosi ma è un inconveniente che giova allo svolgimento della prova. Again this test doesn’t work with rotated or scaled rectangles but it’s a drawback that benefits the performance of the test.
|
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 *) altro
) pixelMaskIntersectsPixelMaskSprite:(KKPixelMaskSprite*)other
{
Il CGRect intersectSelf = [stesso intersectRectInPixels:self otherNode:other];
= [self intersectRectInPixels:self otherNode:other];
Il CGRect intersectOther = [stesso intersectRectInPixels:other otherNode:self];
= [self intersectRectInPixels:other otherNode:self];
Il NSUInteger originOffsetX = intersectOther.origin.x - intersectSelf.origin.x;
= intersectOther.origin.x - intersectSelf.origin.x;
Il NSUInteger originOffsetY = intersectOther.origin.y - intersectSelf.origin.y;
= intersectOther.origin.y - intersectSelf.origin.y;
Il NSUInteger otherPixelMaskWidth = other.pixelMaskWidth;
= other.pixelMaskWidth;
Il BOOL* otherPixelMask = other.pixelMask;
otherPixelMask = other.pixelMask;
//chieda se alcuna delle bandiere nel pixelMask è messa in area d'intersezione Il NSUInteger maxX = intersectSelf.origin.x + intersectSelf.size.width;
= intersectSelf.origin.x + intersectSelf.size.width;
Il NSUInteger maxY = intersectSelf.origin.y + intersectSelf.size.height;
= intersectSelf.origin.y + intersectSelf.size.height;
per (NSUInteger y = intersectSelf.origin.y; y <maxY; y ++)
NSUInteger y = intersectSelf.origin.y; y < maxY; y++)
{
per (NSUInteger x = intersectSelf.origin.x; x <maxX; x ++)
NSUInteger x = intersectSelf.origin.x; x < maxX; x++)
{
L'indice di NSUInteger = y * pixelMaskWidth + x;
= y * pixelMaskWidth + x;
se (pixelMask [l'indice])
pixelMask[index])
{
//chieda se c'è una serie di pixel alla stessa posizione //nel pixelMask dell'altro folletto Il NSUInteger otherX = x + originOffsetX;
= x + originOffsetX;
Il NSUInteger otherY = y + originOffsetY;
= y + originOffsetY;
Il NSUInteger otherIndex = otherY * otherPixelMaskWidth + otherX;
= otherY * otherPixelMaskWidth + otherX;
se (otherPixelMask [otherIndex])
otherPixelMask[otherIndex])
{
restituisca SÌ;
;
}
}
}
}
ritorni NO;
;
} |
Rispetto alla prova di rettangolo precedente, il rettangolo intersecante dell'altra collisione KKPixelMaskSprite fu aggiunto e un riferimento a otherPixelMask insieme con altri valori nascosti in linee 4-9. Il nocciolo della funzione ancora compie la stessa prova fino a linea 22. Invece restituire il primo pezzettino che è messo nel pixelMask, dobbiamo assicurarci che questo pezzettino è anche messo nell'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.
Poiché l'indice nell'otherPixelMask può esser facilmente calcolato compensandolo con origine del rettangolo intersectOther, solo abbiamo bisogno di generare un nuovo indice per stesso x, y le coordinate, ma relativo a sistema di coordinate dell'altro KKPIXELMASKSPRITE. Le linee 26 e 27 compiono quell'operazione usando originOffset precalcolato da linee 6 e 7. Essenzialmente questo compensa lo x, y le coordinate alla stessa posizione dentro rettangolo d'intersezione dell'altro folletto. Quello che rimane sta convertendo le coordinate nell'indice e facendo sondaggi alla ricerca se il pezzettino dell'otherPixelMask a quell'indice è anche messo. Se così, abbiamo una collisione. 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.
Riunione delle prove d'intersezione
C'è un metodo che omisi finora. È il metodo d'interfaccia pubblico che gli utenti di KKPixelMaskSprite chiameranno. Questo si comporta parecchio primi fuori mettono alla prova e anche scelgono la prova giusta per comportarsi basato sulla classe dell'altro nodo. It performs several early out tests and also picks the right test to perform based on the class of the other node.
|
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 *) altro
) pixelMaskIntersectsNode:(CCNode*)other
{
se (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 entrambi i nodi sono fatti girare e/o scalati, ritornando NO!");
");
ritorni NO;
;
}
se ([stesso intersectsNode:other])
[self intersectsNode:other])
{
se ([altro isKindOfClass:PixelMaskSpriteClass])
[other isKindOfClass:PixelMaskSpriteClass])
{
Il KKPixelMaskSprite* maskSprite = (KKPixelMaskSprite *) altro;
= (KKPixelMaskSprite*)other;
ritorni [stesso pixelMaskIntersectsPixelMaskSprite:maskSprite];
self pixelMaskIntersectsPixelMaskSprite:maskSprite];
}
altro
{
ritorni [stesso pixelMaskIntersectsRegularNode:other];
self pixelMaskIntersectsRegularNode:other];
}
}
ritorni NO;
;
} |
Menzionai prima di che le prove d'intersezione non azionano con nodi fatti girare o scagliosi. In questo caso il metodo immediatamente non ritorna e registra questo sul giornale di bordo per evitare qualcuno diventando frustrato perché le prove “non sempre lavorano”. Anche risparmiarmi molte tali domande.
Also to spare me many such questions. ![]()
Certamente l'intersezione fa sondaggi alla ricerca solo hanno il senso se le scatole di limitazione si intersecano. Il metodo intersectsNode è una funzione di comodità che Lei troverà in Kobold2D, e nella classe CCNodeExtensions aggiunta al progetto.
Il pixelMask contro prova di pixelMask è solo compiuto se l'altro nodo è anche un KKPixelMaskSprite, in tutti gli altri casi il rettangolo che si interseca pixelMask la prova è compiuto invece. La variabile PixelMaskSpriteClass è una variabile statica inizializzata nel metodo init come [stesso la classe] semplicemente perché mandando il messaggio di classe ogni volta è un po' sprecone rispetto a 4 byte di memoria supplementare per la variabile PixelMaskSpriteClass.
Prova d'intersezione di due folletti, o KKPixelMaskSprite o non, è così semplice come scrittura:
|
1 |
se ([spriteA pixelMaskIntersectsNode:spriteB])...[spriteA pixelMaskIntersectsNode:spriteB]) ... |
Svolgimento di Maschera di pixel:
BitArray contro. Assortimento di BOOL BOOL arrayAdesso a una domanda interessante: se il BitArray è capace di ridurre l'uso di memoria a 1/8o (il 12.5 %), è questo anche più velocemente? Mi permetta di rivelare questo siccome una grafica ottenuta compiendo il pixelMask contro pixelMask chiede diverse centinaia di migliaia volte ripetutamente, e misurando il tempo di percorso totale: 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:
In altre parole: è un tradeoff tra uso di memoria e svolgimento nel corso dell'elaborazione. Le prove d'intersezione di maschera di pixel sono 27 % più lente su un iPod 4, e 18 % più lentamente su un iPhone 3G usando il BitArray. E casomai Lei si sta chiedendo: se Lei doveva usare un UInt16 o perfino un assortimento di UInt32 invece dell'assortimento di BOOL Lei vedrà una diminuzione molto minore in svolgimento (il meno di 5 %), ma raddoppierà rispettivamente quattro volte l'uso di 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.
Camera per Miglioramento
Scrivendo la classe KKPixelMaskSprite scoprii molta camera per miglioramento. Non voglio risparmiarLa la lista perché anche rivela alcune mancanze della classe che penso che Lei deve essere conscio di. Se Lei proprio attua uno di questi miglioramenti per favore li condivida, e se possibile li condividono secondo una licenza permissiva come MIT. If you do implement one of these improvements please share them, and if possible share them under a permissive license such as MIT.
I miglioramenti forse utili, all'ordine d'utilità
- il nascondiglio pixelMasks, ad esempio in una carta unica di una serie CCPixelMaskCache, o li aggiunge a CCTexture2D
- permetta la creazione di maschera di pixel da nomi di spriteframe o spriteframes
- permetta prove di collisione se il folletto è fatto girare a esattamente 90, 180 o 270 gradi
- permetta l'uso di nonpotere di due immagini per pixelMasks su 1i/2i dispositivi di generazione
- permetta collisioni tra SD e folletti d'immagine HD
Ottimizzazioni potenziali all'ordine d'efficacia aspettata
- riduca dimensioni pixelMask unendosi 2×2, 3×3, 4×4, eccetera i pixel in un pezzettino solo
- O: solo usi immagini SD per pixelMask, forzando collisioni su dispositivi di Retina indicare confini
- ottimizzi iterazioni mettendo alla prova UInt32 (4x BOOL) o i Pezzettini multipli subito per valore> 0
- ottimizzi iterazioni iniziando a reiterare da angolo il più vicino per concentrarsi
Soprattutto l'ottimizzazione per ridurre le dimensioni pixelMask unendo pixel multipli deve risultare essere molto efficiente, e è relativamente facile da attuare. La maggior parte di collisioni perfette il pixel non hanno bisogno di essere veramente perfette il pixel, una fine che sufficiente approssimazione è più che sufficiente per la maggior parte applicazioni. Soprattutto su dispositivi di Retina nessun giocatore sarà capace di distinguere se non così pixel le collisioni perfette sono esatte solo dentro due, tre, o forse perfino più pixel. L'approccio più semplice dovrebbe soltanto considerare solo le immagini SD per maschere di pixel, perfino su dispositivi di Retina. Il vantaggio aggiunto che è che più piccolo pixelMask uguaglia a meno iterazioni e prove di collisione così più veloci. 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.
Scarichi il progetto d'esempio da KKPixelMaskSprite
Scarichi il progetto demo KKPixelMaskSprite!
Questo progetto è anche disponibile sul mio deposito github dove ospito tutto il codice sorgente iDevBlogADay.
PiXmas allegro!
Questo è il mio ultimo posto di iDevBlogADay prima di Natale. È supplementare grande, supplementare croccante, coperto in cioccolato, odori come cannella, gusti come mele e noci e sugo e biscotti e tacchino, e è proibito in Stati Uniti perché questo contiene pixel non commestibili e è un pericolo strozzante per tutti che hanno intenzione di leggerlo in uno va.
In quel senso, il Natale Allegro tutti! ![]()
| Segua @gaminghorror | Segua @kobold2d |
|










[...] LearnCocosTV – l'Episodio 1: Come io maed il Suo Kobold la Scoperta di Collisione Velocemente perfetta il Pixel per Cocos2D con il Codice (2/2) d'Esempio [...]
Ha messo alla prova Lei lo svolgimento relativo a biblioteche di fisica come Box2d o Tamia? Avrei interesse per sapere – immagino che molta gente solo li usa per la loro funzionalità di scoperta di collisione.
Questo non può esser ragionevolmente confrontato perché i motori di fisica non fanno prove di collisione perfette il pixel, loro contano su poligoni (le forme) per fare la prova di collisione. E il numero di vertici in ogni forma è spesso severamente limitato, ad esempio Box2D permette al massimo 8 vertici per forma.
Veramente, penso che loro possono esser ragionevolmente confrontati.
Le tecniche di sviluppo di gioco sono spesso un commercio - via tra quello che è "buono" e quello che è “abbastanza buono”.
Aggiungendo il pixel le collisioni perfette fanno il Suo gioco meglio per giocare, ma tagliano il framerate in metà, molti progettisti sceglieranno più in alto framerate e abbasseranno l'accuratezza di collisione.
Come tale, sapendo lo svolgimento di scoperta di collisione per Box2D aiuterebbe un progettista a fare una scelta informata. Certamente Lei deve provare a fare i confronti come vicino per quanto possibile e Le piacerebbe star usando tutti quei 8 vertici.
Lei è corretto in linea di principio. Ma in questo caso direi che la decisione deve esser presa da progetto. Lo svolgimento soltanto non è cruciale per questa decisione. Performance just isn’t crucial to this decision.
Ad esempio, le collisioni perfette il pixel sono molto esatte, ma non lavorano in alcuno dei folletti è fatto girare o scalato. Considerando che se Lei considera la scoperta della collisione con un motore di fisica i Suoi folletti possono esser fatti girare o scalati. E le probabilità sono quelle che se Lei vuole o deve star usando un motore di fisica comunque, usando la fisica per scoprire tutte le collisioni è semplicemente 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.
Steffen, sto contento che Lei costruì sul mio posto di multi anni. Nella mia difesa, proprio ho dichiarato che annunciai lo pseudocodice.
Sono spesso di proposito vago saggio il codice, chiaramente perché quello che veramente importa è il concetto basso, e mi piace la gente riflettere a fondo su lui e raggiungere le loro soluzioni ed esecuzioni.
Al punto dell'utilizzabilità del codice contro dicono, un motore di fisica, questo veramente dipende da quello che Lei sta facendo. Ricordo che quando annunciai quell'idea non lavoravo in un tipo dei Lemming di clone per SOLUZIONE INTEGRATA PER UFFICIO (mai rilasciato), e questo comportò la deformazione in tempo reale di terreno in forme semicircolari che finirono in una pletora di vertici, che indussero sia la Tamia sia OpenGL ES a strozzarsi abbastanza rapidamente (stiamo parlando 1i dispositivi d'informazioni qui).
Utilizzando questo metodo invece, io semplicemente tagliato fuori la struttura "di terreno" con un cerchio, aggiornano la carta geografica di collisione, e l'unico rallentamento minimo riscaricava la struttura dall'unità centrale al GPU (quale solo avvenne quando il terreno fu veramente modificato, non che comune di un evento).
BTW, aggiustando il codice per lavorare in nodi fatti girare o scagliosi non è questo complicò. Lei dovrebbe semplicemente trasformare il punto d'impiego prima di fare del lookup.
Continuai a pensare che il vicino passo logico sarebbe una deformazione di terreno di stile dei Lemming.
Quanto a trasformazione del punto d'impiego, feci questo nel primo esempio. Prova se un punto è dentro una carta geografica di collisione scagliosa e fatta girare è una questione di convertire il punto nello spazio di nodo. Ma questo fallisce se Lei vuole mettere alla prova due carte geografiche di collisione contro l'un l'altro, ed entrambi possono esser scalati o fatti girare. Forse è possibile sebbene prima trasformare il punto attualmente analizzato da un nodo a spazio mondiale, e poi a spazio dell'altro nodo, non sicuro se questo darà il risultato corretto. 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.
Lei rivolgersi multiplo trasforma. È tutto veramente dipendente da necessità.
Se in alcun punto Lei ha bisogno di sapere la direzione precisa, l'impulso, l'inerzia o alcuno di quei vettori come parte della collisione, allora Lei è probabilmente più ricco con il motore di fisica.
Ciao Steffen
Che se i due folletti per chiedere per collisione è su CCLayers diverso, poteva esser aggiornato il Suo codice per toccare questo anche? In modo che la posizione dei folletti di maschera sia convertita in spazio mondiale o qualcosa nel conto di collisione?
Migliori saluti
Søren
Ha verificato Lei che il codice non riesce a riferire delle collisioni correttamente in questo caso? Perché per quanto capisco questo, convertendo coordinate in spazio di un nodo (il sistema di coordinate) prenderà in considerazione (o questo semplicemente non importa) che il nodo può essere un bambino di un o parecchi altri nodi.
Ehm è proprio ha fallito, ma questo si lamentò di nodi fatti girare e prima vidi questo adesso.. Faccio girare i miei folletti molto tristemente
Ciao Steffen
Stavo usando KKPixelMaskSprite con successo con il mio gioco (è grande!), ma ho cambiato i miei folletti con spriteWithSpriteFrameName … e adesso mi rendo conto che non lavora con strutture di folletto
Sto per provare ad adattare KKPixelMaskSprite per lavorare con strutture di folletto (suppongo che non è stato fatto). Qualche indicazione per cominciare da?
Grazie!!
JARV
Finalmente lo ricevo lavorando con piccolo workaround … che va bene per il mio scopo (di couse, può esser migliorato)
1. - Creano un CCRenderTexture con le dimensioni del folletto.
2. - La posizione di folletto di Cambiamento a 0,0 per visitare il CCRenderTexture e poi restaurare la sua posizione originale:
lo sprite.anchorPoint = ccp (0,0);
lo sprite.position = ccp (sprite.offsetPositionInPixels.x * (-1)
, lo sprite.offsetPositionInPixels.y * (-1));
3. - Creano un UIImage con il CCRenderTexture:
L'UIImage *image = [rt getUIImageFromBuffer];
Adesso abbiamo un UIImage e possiamo riutilizzare il codice da KKPixelMaskSprite (initWithFile).
Soltanto una considerazione finale, prima di telefonata pixelMaskContainsPoint dobbiamo aggiustare il punto a causa del compenso:
CGPoint indicano = ccp (point.x-sprite.offsetPositionInPixels.x, point.y-sprite.offsetPositionInPixels.y);
Questo lavora grande!!