Wie die Mosaik Steinchen “zusammenschnappen” – die Snapping Funktion

Saturday, 15. April, 2006

Eines unserer Ziele war es, es den Spieler zu erlauben, die Steinchen mit einer perfekten Pixel-Präzision zu positionieren und aneinander zu reihen. Wir wollten, dass es möglich ist, dass die Steinchen automatisch an die danebenliegenden Steinchen “snappen”, also das sie sich quasi anziehen und sich nebeneinander ausrichten, wenn der Spieler das so will: Wenn du die Shift-Taste gedrückt hälst, wenn du ein Steinchen dort hinlegst, wo du es haben willst, dann richtet sich das Steinchen automatisch an dem nächstgelegenen Steinchen aus. Du musst nicht mehr Schielen, um das Steinchen exakt neben ein anderes zu legen! Dieser Artikel beschreibt wie wir diese Funktionalität mit Hilfe von JavaScript auf der Client Seite implementiert haben.

Wie funktioniert das?

Der Code für das Snapping oder Ausrichten ist ein Algorithmus, der in einen mouseUp Handler eingebaut wurde – eine Funktion namens mU(). Sie läuft durch eine Serie von Checks und Kalkulationen, um herauszufinden, wohin du das Steinchen legen willst.

Überprüfung der SHIFT-Taste

Die erste Aufgabe ist es zu überprüfen, ob die Shift-Taste gedrückt wird. Das wird bestimmt, indem die shiftKey Eigenschaft des Ereignis-Objekts überprüft wird. Wenn es wahr ist, dann wissen wir, dass der Spieler die Steinchen aneinander snappen lassen will und der Algorithmus läuft.

Hier ist ein Code Fragment aus der mU() Funktion:

if (window.event) e=window.event;
	if (e.shiftKey) {
            // we need to snap

Finde das nächstgelegene Steinchen

Die nächste Aufgabe besteht darin, das Steinchen zu finden, dass deinem Steinchen, dass du hingelegt hast, am nächsten ist. Wir gehen jetzt durch alle Steinchen durch (loop) und überprüfen deren Distanz zu dem Steinchen, das du gerade hingelegt hast. Ist ein Steinchen nicht innerhalb der eineinhalbfachen Breite des Steinchens, nimmt der Algorithmus an, dass du das Steinchen nicht an das andere Steinchen snappen lassen willst. (Warum drückst du dann die Shift-Taste, Mann?)

Diese Methode zur Auffindung des nächstgelegenen Steinchens beinhaltet ein paar IF Aussagen. Wir überprüfen, ob das Steinchen sich innerhalb der eineinhalbfachen Breite des Steinchens auf der X und Y Achse befindet. Für jedes Steinchen, dass diesen Test durchläuft, überprüfen wir seine Distanz vom bewegten Steinchen, indem wir den berühmten Satz des Pythagoras anwenden:

distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);

Wir lassen diese Gleichung für jedes Steinchen laufen, das sich in der nahen Umgebung befindet (so definiert, dass es nicht weiter weg sein darf, als die eineinhalbfache Breite des Steinchens). Das Steinchen mit der kürzesten Distanz ist jenes mit dem wir uns ausrichten wollen.

Wir könnten die Pythagoras Gleichung für jedes Steinchen laufen lassen und die kürzeste Distanz finden. Allerdings würde das ziemlich CPU-intensiv sein, vor allem wenn es viele Steinchen im Mosaik gibt. In unserem Fall hat jedes Mosaik 1000 Steinchen. Die X und Y IF Aussagen engen die Zahl der in Frage kommenden Steinchen ein, ohne viele Ansprüche an die CPU zu stellen. Die teurere, aber genauere Pythagoras Gleichung läuft dann bei einer kleineren Anzahl an nahegelegenen Steinchen.

Ausrichtung des hingelegten Steinchens

Jetzt gilt es herauszufinden, an welchem Rand des liegenden Steinchens wir uns ausrichten wollen.

Es gibt acht mögliche Positionen: jede der vier Ecken und die vier Seiten des liegenden Steinchens. Wir verwenden ein anderes Set an IF Aussagen, um den nächstgelegenen Rand herauszufinden. Wenn die Steinchen diagonal ausgerichtet sind, dann richtet sich das bewegte Steinchen an der nächsten Ecke aus. Ansonsten richtet es sich an der nächsten Kante aus.

Ausrichtung an den Spielflächengrenzen

Wenn wir einmal wissen, wohin sich das Steinchen ausrichten will, stehen wir vor der letzten Aufgabe. Wir müssen sicherstellen, dass die neue, ausgerichtete Position des Steinchens nicht außerhalb der Spielfläche liegt. Das wird mit einer einfachen Überprüfung gemacht, die die neue Position mit den Rändern der Spielfläche vergleicht. Wenn es außerhalb ist, wird das Steinchen einfach wieder in die Spielfläche geschoben, so dass es am Rand der Fläche zum Liegen kommt.

Die Ausrichtung ist fertig! – Snapping complete!

Wir haben nun eine neue ausgerichtete Position für unser Steinchen. Da das Ausrichten auf der Client Seite passiert, wird die ausgerichtete Steinchenposition im nächsten Update Zyklus zum Server und an alle Spieler gesendet.