27. Februar 2014 von Yhoko
Es hilft eben nichts; was man immer wieder vor sich herschiebt, wird einen irgendwann einholen. Ich rede diesmal von den Objekten wie Amboss, Schrank, Herd und Bett. Diese Dinge haben eines gemeinsam; man kann sie benutzen bzw. bedienen und zwar solange sie in Reichweite sind. Anfangs war das nur eine Distanz-Prüfung; ein simpler Pythagoras. Aber was, wenn das Objekt ausser Reichweite war? Um die Sache einfach zu halten versuchte das Skript, die Spielfigur möglichst nahe zum Objekt zu bewegen und es dann erneut zu bedienen. Das klappt auch - meistens. Nicht so bei der Statue, denn die war ziemlich gross und belegte mehrere Felder in der Kollision-Map. Kam der Spieler also von der Seite oder von hinten heran, lag der Mittelpunkt immer noch ausser Reichweite. Da der Mittelpunkt glücklicherweise meist unten in der Mitte der Grafik liegt, war es dann naheliegend, das als Zielpunkt der Bewegung festzulegen. Und falls die Figur am Ende doch von der Seite her kam, etwa weil der Weg zur Mitte blockiert war, liess ich weiterhin die Abstandsberechnung nicht mehr nur zum Mittelpunkt sondern auch zu jedem Kollisionsfeld hin gelten. Und siehe da, auch Statuen waren nun nutzbar.
Gestern jedoch wollte ich einen Schrank öffnen, und dieser Schrank stand seitlich, man sah also nur die Seitenwand und der Mittelpunkt lag bei dieser unten zentriert. Klickte man den Schrank an, wanderte die Figur dorthin und öffnete von da den Schrank. Sah komisch aus. Schlimmer noch; stand die Figur schön korrekt vor dem Schrank, war der Mittelpunkt ausser Reichweite und sie marschierte wieder erst neben den Schrank. Gut, damit könnte man leben, aber was passiert wohl, wenn neben dem Schrank ein Tisch steht? Richtig, dann wäre der Mittelpunkt des Schranks quasi im Tisch und damit unerreichbar. Gut, der Server hätte das akzeptiert, denn er berechnete die Distanz nun ja auch zu jedem Kollisionsfeld, aber der Client wusste ja nicht, welche Felder zum Schrank gehören. Konnte er nicht, und wird er auch nie. Das war also eine Sackgasse.
Lösung? Schweren Herzens musste ich das Umsetzen, was von Anfang an hätte sein sollen: Aktionspunkte. Bei jedem Objekt ist nun festgelegt, von wo aus man es bedienen kann. Der Schrank hat z.B. je einen Aktionspunkt links und rechts, der Amboss davor und dahinter, das Zeichenbrett nur einen davor. Es kostete mich deutlich mehr Arbeit (und die CPU jeweils deutlich mehr Rechenzyklen), aber wenn man jetzt ein Objekt anklickt, sucht die Engine den Pfad zum nächsten Aktionspunkt, bewegt die Figur dorthin, dreht sie passend zum Objekt und führt dann die Tätigkeit aus.
Als kleiner Bonus hat sich nun noch etwas ergeben: War ein Objekt bisher von mehreren Spielern gleichzeitig bedienbar (sagen wir mal ein Tisch für 4 Personen), so konnten diese bei der Benutzung irgendwo in Reichweite stehen - selbst übereinander, bzw. sogar sehrwahrscheinlich übereinander, da sich aufgrund des Clients alle in der Nähe des Mittelpunkte befanden. Nun aber besetzt jeder einen eigenen Aktionspunkt und es ist vorgegeben, wo sich diese befinden (mit einem kleinen Spielraum, falls man bereits in der Nähe steht). Zudem weiss der Client nun bereits im Vorfeld, ob überhaupt noch ein Platz am Objekt frei ist.
Manchmal macht man die Arbeit eben doppelt, wenn man sie sich spart.