Pixelgenaue Kollisionserkennung in HTML5-Canvas
Möchte ich überprüfen, eine Kollision zwischen zwei Sprites, die in HTML5 canvas. So zum Wohle der Diskussion, lassen Sie uns davon ausgehen, dass beide sprites sind, IMG-Objekte und eine Kollision bedeutet, dass der alpha-Kanal nicht 0 ist. Nun, diese beiden sprites haben kann, eine rotation um die Mitte des Objekts, aber keine weitere transformation in diesem Fall macht dies nicht leichter.
Jetzt die offensichtliche Lösung kam ich mit wäre dieser:
- berechnen Sie die Transformationsmatrix für beide
- herauszufinden, eine grobe Abschätzung des Bereichs, in dem der code getestet werden sollte (wie offset der beiden + berechnet extra Raum für die rotation)
- für alle Pixel in dem sich überschneidenden Rechteck, transformieren Sie das Koordinatensystem und testen Sie das Bild an der berechneten position (gerundet auf den nächsten Nachbar) für den alpha-Kanal. Dann Abbruch auf den ersten Treffer.
Das problem, das ich sehe, ist, dass a) es gibt keine matrix-Klassen in JavaScript, das heißt, ich habe zu tun, dass in JavaScript, das könnte sehr langsam sein, ich habe zum test für Kollisionen jeder Rahmen, der macht das schon ziemlich teuer. Außerdem habe ich zu replizieren, etwas, was ich bereits zu tun haben, auf die Zeichnung (oder das, was die Leinwand für mich tut, einrichten der Matrizen).
Frage ich mich, ob ich etwas fehlt hier, und wenn es eine einfachere Lösung für die Kollisionserkennung.
- Ich kann nicht finden, eine Antwort, ich Stelle diese Frage auch 🙁
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin kein javascript-Programmierer, aber ich könnte mir vorstellen, dass die gleiche Optimierung tricks funktionieren genauso gut für Javascript wie für C++.
Drehen Sie einfach die Ecken der sprite anstatt jedes pixel. Effektiv würden Sie etwas tun, wie software-texture-mapping. Sie können die x -, y-position eines pixels unter Verwendung verschiedener Gradienten-Informationen. Look-up-textur-mapping-software für mehr info.
Wenn Sie quadtree zerlegt das sprite in "Treffer" und "nicht-Treffer" Bereiche, dann konnte man effektiv überprüfen, um festzustellen, ob ein quad-tree-ZERLEGUNG ist alle "nicht-Treffer", "alle Treffer" oder "möglichen Treffer" (dh enthält die Treffer und nicht-Treffer Pixel. Die ersten 2 sind trivial zu passieren. Im letzten Fall gehen Sie dann bis zur nächsten Aufspaltung Ebene und wiederholen Sie den test. Auf diese Weise Sie überprüfen nur die Pixel, die Sie zu brauchen und für große Bereiche der "nicht-Treffer" - und "Treffer", die Sie nicht zu tun haben, wie eine komplexe Reihe von Prüfungen.
Eh das ist nur ein paar Gedanken.
Gut, könnten Sie eine neue rendering-Kontext, die Geschichte einer gedreht, weiß-hintergrund-Maske an, legen Sie die compositing-Vorgang
lighter
- und plot-die andere gedreht Maske auf, die am angegebenen offset.Nun, wenn es eine nicht-weiße pixel Links, da ist ein Treffer. Sie würden noch
getImageData
und durchforsten die Pixel, um das herauszufinden. Sie könnten in der Lage sein zu reduzieren, dass die Arbeitsbelastung ein wenig durch die Skalierung das resultierende Bild nach unten (unter Berufung auf anti-aliasing zu halten einige Pixel nicht weiß), aber ich dachte, dass es wahrscheinlich noch ziemlich langsam.Yeah, ich denke realistisch wirst du mit vorberechneten Kollision Tabellen. Wenn Sie haben für ihn den Platz, den Sie speichern könnte ein Treffer/kein-Treffer-bit für jede Kombination von ein sprite, sprite b, relative rotation relative-x-normiert-auf-rotation und-relativen-y-normiert-auf-rotation. Je nachdem, wie viele sprites Sie haben und wie viele Schritte von der rotation oder Bewegung, dies könnte ziemlich groß werden.
Ein Kompromiss wäre zum speichern der pre-gedreht Masken jedes sprite in ein JavaScript-array (Anzahl, geben Sie 32 bits/Pixel leicht
&&
-in der Lage, Daten, oder als ein Zeichen in einem String, indem Sie 16 bit) und der&&
jede Zeile der Schnittmenge sprite Masken zusammen.Oder geben Sie bis auf Pixel und beginnen, zB. Pfade.
Gleiche problem, eine alternative Lösung. Zuerst benutze ich getImageData Daten zu finden, die ein polygon um das sprite. Hier aufpassen, da die Implementierung arbeitet mit Bildern mit transparentem hintergrund, die einen einzelnen festen Gegenstand. Wie ein Schiff. Der nächste Schritt ist Ramer Douglas-Peucker-Algorithmus zu reduzieren, die Anzahl der Ecken im polygon. Ich bekomme endlich ein polygon mit sehr wenigen vertices einfach und Billig zu drehen und zu prüfen, Kollisionen mit den anderen Polygonen für jedes sprite.
http://jsfiddle.net/rnrlabs/9dxSg/