Mal was neues … mit Asteroiden drin!
Samstag, 13 November 2010
(Äh … das sieht lang aus, ich will direkt zu den Asteroiden!)
Etwas neues steht vor der Tür! Ok, eigentlich ist es schon in die Wohnung eingefallen, hat sich in den bequemsten Sessel geflätscht und geht jetzt einfach nicht mehr.
Ich hab in letzter Zeit viel über Javascript gelernt .. und bin total fasziniert von dieser Sprache. Und was gibt es besseres, als ein Projekt zu beginnen, um wirklich in die tiefen vorzudringen?
Mir schwirren sowieso immer irgendwelche Ideen im Kopf rum, also hab ich eine genommen, mir ne Spielidee daraus zusammengebastelt und angefangen, sie umzusetzen.
Und gerade ist mir die Idee gekommen, dass es vielleicht interessant wäre, meine ersten tapsigen Schritte im Spieleentwicklungsbereich zur allgemeinen Erheiterung zu protokollieren. Also: Los geht’s!
Worum geht’s denn jetzt genau?
- Ich will Javascript!
- Ich will ein Multiplayerspiel!
- Ich will schnelle Echtzeitgrafik!
Javascript? Echtzeit? Multiplayer? Jaha .. das geht – wenn man denn ein paar Abstriche machen kann. Und ich kann und bin wild entschlossen.
Technologien
Ich werde folgende Technologien einsetzen und versuchen, das ganze so performant wie nur eben möglich umzusetzen – um eventuell noch komplexere Dinge damit anstellen zu können.
- Websockets (Wikipedia)
- HTML 5 Canvas (Wikipedia)
- Node.js (Homepage)
Das bedeutet, dass für dieses Projekt nur folgende Browser in Frage kommen,
alle anderen – vor allem der Internet Explorer – bleiben draussen.
Browserunterstützung
- Google Chrome 4
- Opera 10.70
- Safari 5 (noch nicht von mir getestet)
- Firefox 4 (noch nicht von mir getestet)
Was bedeuteten diese Begriffe?
Erklärung der eingesetzten Technologien
Websockets
Websockets sind eine (sehr neue) Möglichkeit, eine persistende, bidirektionale Verbindung von einer normalen Website zu einem Server aufbauen zu können. Das bedeutet tatsächlich, dass man einen direkten Kanal hat, über den sowohl der Client als auch der Server ständig Daten austauschen können, ohne jedes mal eine neue Verbindung aufbauen zu müssen. Das macht Websockets wesentlich schneller sind, als “normale” HTTP-Anfragen, da vieles wegfällt, was langsam ist:
- Ein eventueller DNS-Lookup – passiert beim IE alle 30 Minuten, beim Firefox jede Minute, siehe http://developer.yahoo.com/performance/rules.html unter ”Reduce DNS Lookups”
- Overhead, der für kurze Statusupdates (habe meine Maus jetzt nach x:120,y:500 bewegt) bei jedem HTTP-Request mitgesendet wird, siehe http://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol#HTTP_GET
- Eventuell muss der Server erst einen Prozess spawnen, um die HTTP-Anfrage zu beantworten (Dazu auch der Node.js Teil unten)
Man muss vielleicht noch dazu sagen, dass gerade die Websockets es sind, die den IE und alle älteren Browser ausschliessen. Allerdings kann man bei Spielen nicht darauf warten, dass ein Mausklick eine halbe Sekunde zum Server und wieder zurück braucht.
HTML 5 Canvas
Das Canvas Element wird schon länger von vielen Browsern – und vor allem auch vom IE – unterstützt.Wichtig für mein Vorhaben ist es, da es dynamische Grafiken auf dem Client ermöglicht. Beim Canvas ist es möglich, z.B. eine Linie von x1,y1 nach x2,y2 oder einen Kreis mit Radius r an position x,y zu zeichnen. Ausserdem können Bitmaps eingefügt und alles nach belieben gedreht und transformiert werden.
Den Kreis könnte man mit HTML zur Not auch noch mit einem skalierenden Bild simulieren – was eher doof aussieht – aber spätestens bei einer einfachen Linie ist man am Ende seiner Möglichkeiten. (Ja, ich weiss, man kann auch 1 Pixel grosse Div-Boxen einen Pfad lang absolut positionieren – aber bitte!).
Node,js
Habe ich nicht gesagt, dass ich Javascript will? Bittesehr, jetzt sogar auf dem Server
Scherz beiseite. Node.js bringt einen noch viel grösseren Vorteil mit: Es ist darauf ausgelegt, eine grosse Anzahl an Anfragen gleichzeitig zu bearbeiten, ohne dabei in die Knie zu gehen. Da ich den Server auf meiner kleinen Miet-VPS aufsetze ist das ein nicht zu unterschätzender Vorteil. Aber warum wie kann Node.js viele Verbindungen bearbeiten? Ich vergleiche Node.js dabei mit PHP.
Bei einem standard Apache mit PHP würde für jede Verbindung ein Prozess gespawnt, der dann für diesen Client zuständig ist. Wenn dieser Prozess 20mb an RAM verbraucht (was nicht viel ist) verbrauchen 10 Clients 200mb. Ausserdem hängt jeder Prozess in seiner eigenen Schleife fest und wartet darauf, dass etwas geschieht, um dann darauf reagieren zu können.
Bei Node.js ist das anders. Hier gibt es genau einen Prozess (oder eher pro Prozessor einen – wenn konfiguriert) mit einer Schleife, die läuft. Die Programmierung in Node.js basiert auf einem Event Modell. Will man zum Beispiel auf Daten vom Websocket warten, registriert man ein “onData” Event, das gefeuert wird, sobald Daten ankommen.
Bei PHP kann man man nur eine Schleife durchlaufen und jedes mal am Socket nachfragen, ob schon Daten da sind. Will man parallel auch noch etwas anderes mit diesem Prozess anstellen – zum Beispiel Berechnungen für Positionierungen anstellen – muss man dafür die “horch” Schleife pausieren. Erst wenn die Berechnungen durch sind, kann wieder nachgefragt werden, ob schon Daten da sind.
Node.js hingegen würde einfach beim “onData” Event den dafür registrierten Handler aufrufen und für sich arbeiten lassen. Kommen während der Berechnung, die der Handler anstellt, weitere Daten an, werden einfach weitere Handler gestartet.
Ein weiterer Vorteil ist die Kommunikation der verschiedenen Handler untereinander. Man speichert die für alle zugreifbaren Daten einfach im global Namespace ab und fertig. Bei PHP müsste man da schon auf Semaphoren oder eigens dafür angelegte Sockets vom Betriebssystem zurückgreifen.
Zugegebenermassen ist eventbasierende Programmierung verwirrender als die von einfachen Abläufen, da man immer aufpassen muss, ob eventuell noch andere Dinge abgearbeitet werden müssen, bevor man mit dem gerade gefeuerten Handler starten kann, allerdings hat das auch so seinen Reiz
Doof
Das hier ist leider alles noch etwas oberflächlich und ich würde gerne in Zukunft noch näher auf die einzelnen Punkte eingehen, allerdings wirds langsam spät. Deswegen möchte ich langsam zum Abschluss dieses Artikels kommen.
Das Produkt
Die zwei Themen, an denen ich meine Idee und alle Entscheidungen festgemacht habe sind:
- Asteroiden
- Gravitation
Der Spieler ist ein Asteroid unter mehreren auf einem vom Canvas begrenzten Spielfeld. Ziel ist es, zu wachsen.
Das kann man, indem man kleinere Asteroiden berührt. Damit geht ein Teil der Masse des anderen Asteroiden auf einen selbst über. Trifft
man auf einen grösseren Asteroiden, wird man von ihm verschlungen und das Spiel ist fürs erste aus. Das gleiche gilt, wenn man das Spielfeld verlässt.
Es gibt von Spielern gelenkte und vom Spiel kontrollierte, ungelenkte Asteroiden (Opfer
).
Alle Asteroiden ziehen sich gegenseitig an, sodass auch ungelenkte Asteroiden zu etwas grossen werden können.
Mass des Erfolgs ist eine Punkteskala. Punkte erreicht man, indem man überlebt (momentan alle 3 Sekunden 25 Punkte) und indem man seine Masse erhöht (Eine Masseeinheit sind 2 Pixel breite des Asteroiden).
Der Spieler muss eine Balance finden zwischen: nicht geschluckt zu werden ( grösser als andere zu sein) und nicht zu schnell zu wachsen (weniger Punkte über die Zeit).
Der Spielerasteroid kann über ein Gummiband gesteuert werden. Der Spieler-asteroid ist bestrebt, immer auf den Mauscursor der Spielers zuzufliegen. Allerdings besitzt der Asteroid auch Trägheit, was bedeutet, dass Kursänderungen länger dauern können, je drastischer sie sind und je schneller der Asteroid bereits in eine Richtung fliegt.
So, das wars jetzt aber erstmal,
hier darf ich jetzt endlich mein neuestes Baby vorstellen! Der Arbeitstitel dieses Projektes lautet:
Wenn ich gross bin, werd’ ich Planet!
(Eine Multiplayerreise durch einen Canvashimmel, der von Node.js berechnet wird.)
Version 0.1 ist innerhalb von knapp 6 Stunden entstanden. Version 0.2 hat inklusive der Pixelgrafik nochmal 4 Stunden gebraucht
Ich würd mich natürlich über jeden Kommentar freuen. Ausserdem bin ich fest entschlossen, dieses Projekt bis zu seinem Ende zu verfolgen, also einfach immer mal wieder Vorbeischauen!
Viel Spass beim Ausprobieren!
No. 1 — Dezember 16th, 2010 at 22:29
[...] this post (in german) and this experiment (hm, multilanguage?) were the first signs that something like this [...]
No. 2 — Oktober 17th, 2011 at 19:49
Hello. {Great|fantastic|splendid|impressive|magnificent|excellent|remarkable} job. I did not {expect|imagine|anticipate} this. This is a {great|fantastic|splendid|impressive|excellent|remarkable} story. Thanks!…
You made several nice points there. I did a search on the subject and found a good number of folks will go along with with your blog….