Pixelperfekte Kollisionserkennung in HTML5 Canvas

8

Ich möchte eine Kollision zwischen zwei Sprites in HTML5-Canvas überprüfen. Nehmen wir also an, dass beide Sprites IMG-Objekte sind und eine Kollision bedeutet, dass der Alpha-Kanal nicht 0 ist. Nun können beide Sprites eine Rotation um das Zentrum des Objekts haben, aber keine andere Transformation, falls dies der Fall ist irgendwie einfacher.

Nun wäre die offensichtliche Lösung, die ich mir ausgedacht habe, folgende:

  • Berechne die Transformationsmatrix für beide
  • Ermitteln Sie eine grobe Schätzung des Bereichs, in dem der Code getestet werden soll (wie der Versatz beider + berechneten zusätzlichen Platz für die Rotation)
  • für alle Pixel in dem sich schneidenden Rechteck, transformiere die Koordinate und teste das Bild an der berechneten Position (gerundet auf den nächsten Nachbarn) für den Alpha-Kanal. Dann beim ersten Treffer abbrechen.

Das Problem, das ich damit sehe, ist, dass a) es keine JavaScript-Klassen in JavaScript gibt, was bedeutet, dass ich das in JavaScript tun muss, was ziemlich langsam sein kann. Ich muss jeden Frame auf Kollisionen testen, was das ziemlich teuer macht. Außerdem muss ich etwas replizieren, was ich beim Zeichnen schon tun muss (oder was Canvas für mich tut, indem ich die Matrizen aufstelle).

Ich frage mich, ob ich hier etwas vermisse und ob es eine einfachere Lösung für die Kollisionserkennung gibt.

    
Armin Ronacher 30.04.2010, 10:03
quelle

3 Antworten

7
  

Ich muss etwas wiederholen, was ich beim Zeichnen schon machen muss

Nun könnten Sie einen neuen Renderkontext erstellen, eine gedrehte Weißhintergrundmaske zeichnen, die Compositing-Operation auf lighter setzen und die andere gedrehte Maske oben auf den gegebenen Offset zeichnen.

Wenn jetzt ein nicht-weißes Pixel übrig ist, gibt es einen Treffer. Sie müssten immer noch getImageData und die Pixel durchsehen, um das herauszufinden. Sie können diese Arbeitslast möglicherweise etwas reduzieren, indem Sie das resultierende Bild nach unten skalieren (indem Sie auf Anti-Aliasing setzen, um einige Pixel nicht weiß zu halten), aber ich denke, dass es wahrscheinlich immer noch ziemlich langsam ist.

  

Ich muss jeden Rahmen auf Kollisionen testen, was das ziemlich teuer macht.

Ja, ich denke realistisch, dass Sie vorberechnete Kollisionstabellen verwenden werden. Wenn Sie Platz dafür haben, können Sie für jede Kombination aus Sprite a, Sprite b, relative Drehung, relativ-x-normalisiert-zu-rotation und relativ-y-normalisiert-zu-Rotation ein Treffer / kein Treffer-Bit speichern . Abhängig davon, wie viele Sprites Sie haben und wie viele Schritte der Rotation oder Bewegung, könnte dies ziemlich groß werden.

Ein Kompromiss wäre, die vorgedrehten Masken jedes Sprites in einem JavaScript-Array (von Number) zu speichern, das Ihnen 32 Bits / Pixel von leicht && -fähigen Daten oder als Zeichen in einem Sring gibt 16 Bits) und && jede Linie von sich kreuzenden Sprite-Masken zusammen.

Oder geben Sie Pixel auf und schauen Sie sich zB an. Pfade.

    
bobince 30.04.2010 10:43
quelle
6

Ich bin kein JavaScript-Programmierer, aber ich könnte mir vorstellen, dass die gleichen Optimierungstricks genauso gut für Javascript funktionieren wie für C ++.

Drehen Sie einfach die Ecken des Sprites anstelle jedes Pixels. Effektiv würden Sie so etwas wie Software Textur Mapping tun. Sie könnten die x, y-Position eines gegebenen Pixels unter Verwendung verschiedener Gradienteninformationen berechnen. Weitere Informationen finden Sie im Software-Textur-Mapping.

Wenn du quadtree das Sprite in "hit" und "non-hit" Bereiche zerlegt hast, dann könntest du effektiv prüfen, ob eine gegebene Quad-Tree Dekomposition "non-hit", "all hit" oder "mighty hit" ist (dh enthält Treffer und Nicht-Treffer-Pixel. Die ersten 2 sind trivial zu durchlaufen. Im letzten Fall gehst du dann runter zur nächsten Dekompositionsebene und wiederholst den Test. Auf diese Weise kontrollierst du nur die Pixel, die du auch brauchst und für groß Bereiche von "non-hit" und "hit" müssen nicht so komplexe Prüfungen durchführen.

Wie auch immer, das sind nur ein paar Gedanken.

    
Goz 30.04.2010 10:09
quelle
2

Das gleiche Problem, eine alternative Lösung. Zuerst verwende ich getImageData-Daten, um ein Polygon zu finden, das das Sprite umgibt. Vorsicht hier, weil die Implementierung mit Bildern mit transparentem Hintergrund arbeitet, die ein einzelnes Solid-Objekt haben. Wie ein Schiff. Der nächste Schritt ist Ramer Douglas Peucker Algorithmus , um die Anzahl der Scheitelpunkte im Polygon zu reduzieren. Ich bekomme endlich ein Polygon mit sehr wenigen Scheitelpunkten, das leicht und billig zu rotieren ist und Kollisionen mit den anderen Polygonen für jedes Sprite prüft.

Ссылка

%Vor%     
Emanuel Ve 28.02.2014 02:35
quelle

Tags und Links