JavaScript ist in den letzten Jahren ein großer Teil der Webentwicklung und -designerfahrung geworden. Es ermöglicht es uns, langweilige, statische Seiten zu sprudeln, Seitenauffrischungen zu vermeiden und einige erstaunliche Leistungen der Schnittstellentechnik zu leisten - Dinge, die mit HTML und CSS nicht möglich gewesen wären. Natürlich wird AJAX und DOM Scripting jetzt als Run of the Mill angesehen und ist Teil des Tool -Kits eines Webentwicklers beim Erstellen von Websites. Aber wie weit können wir es schieben? Es ist eine leistungsstarke, objektorientierte Sprache, die einen reichhaltigen Ausgangsmechanismus aufweist. Wir können sie also sicher verwenden, um Popup -Fenster zu starten?
Was macht ein Selbstachtungs-Geek, wenn er mit einer solchen Frage konfrontiert wird? Sie schreiben natürlich ein 2-D-Spiel mit einer Side-Scrolling-Plattform!
In dieser zweiteiligen Serie lernen Sie genug HTML, CSS und JavaScript, damit Sie Ihr eigenes JavaScript-Plattformspiel erstellen können. Ich habe die Prototype JavaScript -Bibliothek in den Beispielen verwendet, einfach weil es das war, was ich weiß - viele der anderen verfügbaren JavaScript -Bibliotheken haben möglicherweise gleichwertige Funktionen.
Bevor wir zu den lustigen Zügen kommen, müssen wir einige der erweiterten JavaScript-Techniken durchlaufen, mit denen wir Ihren Browser dazu bringen können, zu denken, dass es sich um eine 8-Bit-Spielekonsole handelt.
Schauen wir uns einen JS -Code an, der eine neue Klasse erstellt und dann ein neues Objekt erstellt:
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Ein flüchtiger Blick über diesen Code zeigt, dass wir eine neue Klasse namens Walksprit mit drei Eigenschaften (Element, X und Y) und einer Funktion namens Walk erstellt haben. Wenn wir
eine neue Version des Objekts instanziieren und es als Walk -Funktion nennen, befindet sich unser Koopa -Objekt nun am Koordinatenpunkt (20, 30). Das Deklieren von Klassen auf diese Weise ist ein wenig umständlich - wir müssen eine Klasse erstellen und dann den Prototyp aktualisieren. Zum Glück hat der Prototyp (die Bibliothek) es in eine praktische Funktion namens class.create eingekapselt. Der obige Code wird Folgendes:var WalkingSprite = Class.create({ <br> x: 0, <br> y: 0, <br> element: null, <br> <br> initialize: function(element, x, y) { <br> this.element = element; <br> this.x = x; <br> this.y = y; <br> }, <br> <br> walk: function(steps) { <br> this.x += steps; <br> } <br> }); <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Eine weitere grundlegende Komponente von OOP ist das Konzept der Vererbung. Wenn Sie eine Basisklasse haben, die bestimmte Variablen und Funktionen hat, alle Klassen, die diese Klasse diese Variablen und Funktionen erweitern. Sie können dann zusätzliche Funktionen hinzufügen und diese Funktionen sogar überschreiben, um etwas anderes zu tun. Dies könnte in unserem Spiel sehr nützlich sein, da alle unsere Charaktere wahrscheinlich einige allgemeine Attribute aufweisen - sie können möglicherweise alle durch den Bildschirm laufen -, aber vielleicht kann nur eine Art von Charakter springen. Klingt nach einem perfekten Kandidaten für die Vererbung.
Leider unterstützt JavaScript die Erbschaft nicht nativ. Also, warum habe ich den letzten Absatz verschwendet, der dir davon erzählt hat? Nun, mit ein wenig Trick können wir die Erbschaft der Klasse in JavaScript nachahmen.
Da alles in JavaScript (einschließlich Funktionen in unseren Klassen) Variablen sind, können wir ihre Werte anderen Variablen zuweisen. Wenn wir also darüber nachdenken, was die Erbschaft für eine Sekunde ist, müssen wir nur die Eigenschaften und Funktionen aus der übergeordneten Klasse in die Kinderklasse kopieren. Wenn wir von der oben erstellten Klasse erben wollen, könnten wir dies tun:
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> // Create the child class <br> JumpingAndWalkingSprite = WalkingSprite; <br> JumpingAndWalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> walk: WalkingSprite.prototype.walk <br> jump: function() { <br> y += 20; <br> } <br> }
Führen Sie den Code aus, und Sie haben eine neue Klasse, die die beiden Eigenschaften und eine Funktion von seinem Elternteil sowie eine neue Funktion hat: Sprung. Das einzige ist, dass das Codieren nicht wirklich skaliert wird. Was ist, wenn Sie der Elternklasse eine Entenfunktion hinzufügen? Sie müssten jede Kinderklasse durchgehen und die Funktionssignatur hinzufügen. Noch einmal, Prototyp zur Rettung! Die Klasse.Create -Funktion, über die wir zuvor gelernt haben, kann eine andere Klasse als erstes Argument nehmen. Diese gelieferte Klasse wird über Eltern und findet dynamisch alle Eigenschaften und Funktionen für uns und injiziert sie automatisch in die Kinderklasse. Also wird das obige:
var JumpingAndWalkingSprite = Class.create(WalkingSprite); <br> <br> mario = new JumpingAndWalkingSprite(null, 10, 10); <br> mario.walk(10): <br> alert(mario.x + "," + mario.y); <br> mario.jump(); <br> alert(mario.x + "," + mario.y); <br>
Wie erwartet hat die neue Klasse alle die gleichen Eigenschaften der übergeordneten Klasse! Was ist also mit dem Hinzufügen und Überschreiben von Eigenschaften und Funktionen? Wir haben oben gezeigt, wie dies manuell geht, aber der Prototyp ermöglicht es uns, neue Funktionen mit Class.create zu definieren:
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Hier haben wir die Walk -Funktion außer Kraft gesetzt und eine Sprungfunktion hinzugefügt. Hängen Sie den LKW auf - woher ist diese $ super variable angekommen? Gute Frage! Bei Verwendung der Vererbung kann es manchmal nützlich sein, die Version der übergeordneten Klasse der Funktion auszuführen. In diesem Fall machen wir den Charakter zweimal so weit wie ursprünglich angefordert, indem wir die Eingangsvariable verdoppelt und diesen neuen Wert an die übergeordnete Klasse weitergeben. Der Prototyp liefert die Version der übergeordneten Klasse der Funktion in der $ Super Variablen, wenn Sie $ super als erstes Argument der Signatur der Funktion deklarieren. Auf diese Weise können Sie die übergeordnete Version der Funktion in der überschriebenen Version problemlos aufrufen. Sie werden feststellen, dass die neue Sprungfunktion nicht über die $ Super Variable verfügt. Wir benutzen es nicht, daher müssen wir es nicht liefern. Wenn wir es brauchten, könnten wir es einfach als erstes Argument der Funktionssignatur hinzufügen.
Jetzt haben wir die JavaScript -Klasse schriftlich. Wäre es nicht cool, wenn wir ein HTML -Element sagen könnten, dass er zu einem Walksprit -Objekt wird, indem wir ihm einen bestimmten Klassennamen geben? In JavaScript 1.6 finden Sie problemlos alle DOM -Elemente mit einem bestimmten Klassennamen mithilfe des Dokuments.GetElementByClassName -Funktion. Die meisten Browser unterstützen jedoch noch keine Version 1.6. Glücklicherweise bietet der Prototyp uns die $$ -Funktion - übergeben Sie ihm einen CSS -Selektor und gibt ein Array aller passenden Elemente zurück.
Schauen Sie sich den folgenden Code an:
var WalkingSprite = Class.create({ <br> x: 0, <br> y: 0, <br> element: null, <br> <br> initialize: function(element, x, y) { <br> this.element = element; <br> this.x = x; <br> this.y = y; <br> }, <br> <br> walk: function(steps) { <br> this.x += steps; <br> } <br> }); <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Zuerst erstellen wir die Walksprit -Klasse und dann die Koopasprite -Klasse, die die Walksprit -Klasse als Eltern verwendet. Als nächstes erstellen wir eine Reihe von Koopasprite -Objekten, indem wir alle Elemente innerhalb des Dokuments auswählen, die den Klassennamen „Koopa“ haben.
Jetzt haben wir eine Reihe von Koopasprite -Objekten mit Verweisen auf entsprechende DOM -Elemente (dies wird später wichtig). Was wir hier getan haben, ist die Grundlage für unauffälliges JavaScript . Jetzt, da wir die HTML -Elemente, an denen wir interessiert sind, dynamisch gefunden haben, können wir Ereignisse (wie Onclick und Onfokus) binden, sie neu gestalten oder sie verschwinden lassen!
Da wir kein textgetriebenes Abenteuerspiel schreiben, werden wir unsere Charaktere animieren. Dies geht darüber hinaus, sie um den Bildschirm zu bewegen, der später abgedeckt wird. Es wäre auch gut, wenn wir die Charaktere so aussehen lassen könnten, als würden sie gehen, springen oder ducken. Dazu werden wir einen alten CSS -Trick anrufen: den Hintergrundpositionshack.
Die Idee ist einfach: Wir bauen ein Band von Bildern, die die Frames unserer Animation bilden, und fahren dann durch sie durch, indem sie sie links und rechts x Anzahl der Pixel verschieben. Hier ist ein Beispiel Hintergrundbild:
Wie Sie sehen können, haben wir 12 Frames in einem Bild, jeweils 48 Pixel. Wenn wir eine DIV von Klassen Mario hätten, können das CSS für einige der verschiedenen Frames wie folgt aussehen:
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Möglicherweise haben Sie diese Technik schon einmal gesehen, um flackernde Rollovers zu erstellen. In den alten Tagen erstellen Sie Bildrollover -Effekte mit einem kleinen Stück JavaScript, das den SRC -Wert eines Bild -Tags beim Abfeuern des Onmouseover -Ereignisses veränderte. Als Sie es jedoch zum ersten Mal getan haben, musste der Browser das Bild vom Server herunterladen, was häufig zu Flackern geführt hat. Es war möglich, die Bilder vorzuladen, aber es war alles ein bisschen klobig. Die überlegene CSS-Technik ermöglichte es dem Designer, alle Rollover-Zustände in einem Bild zu laden und mit der Hover-Pseudo-Klasse eine separate CSS-Regel zu erstellen, um den Hintergrund zu verschieben, wodurch reibungslose Übergänge ohne JavaScript angegeben werden.
In unserer Game Engine werden wir die Position des Hintergrundbildes mit JavaScript ändern. Um die Hintergrundposition in JS festzulegen, manipulieren Sie das Elementstil. BackgroundPosition -Attribut. Der folgende Code erstellt eine neue Klasse namens Mariosprite, die der übergeordneten Walkingsprite -Klasse eine Renderfunktion hinzufügt. Diese neue Funktion wird wiederholt mit einer Zeitverzögerung aufgerufen und wird Mario mit zwei Frames animieren:
var WalkingSprite = Class.create({ <br> x: 0, <br> y: 0, <br> element: null, <br> <br> initialize: function(element, x, y) { <br> this.element = element; <br> this.x = x; <br> this.y = y; <br> }, <br> <br> walk: function(steps) { <br> this.x += steps; <br> } <br> }); <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Offensichtlich ist die Render -Funktion ziemlich nutzlos, wenn sie nicht für das gesamte Spiel wiederholt aufgerufen wird. Um sicherzustellen, dass es ein paar Mal pro Sekunde entlassen wird, müssen wir JavaScript -Timer einsetzen. Es gibt zwei Arten von Timern: eine, die einmal nach Ablauf des Timers feuern wird, und eine, die wiederholt jedes t Millisekunden abfeuert, bis wir es sagen sollen. Wir werden das letztere mithilfe der SetInterval -Funktion implementieren:
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> // Create the child class <br> JumpingAndWalkingSprite = WalkingSprite; <br> JumpingAndWalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> walk: WalkingSprite.prototype.walk <br> jump: function() { <br> y += 20; <br> } <br> }
Dies führt dazu, dass Mario zweimal pro Sekunde einen Schritt unternimmt (500 Millisekunden entspricht einer halben Sekunde). Da SetInterval eine Funktion als erster Parameter benötigt, müssen wir eine anonyme Funktion erstellen, die die Funktion mario.render aufruft.
Es könnte sich lohnen, eine Einschränkung von JS zu erklären, die später zurückkehren werden, um uns zu beißen: JavaScript ist nicht multi-threaded. Dies bedeutet, dass es keine Möglichkeit gibt, zwei Codeblöcke gleichzeitig auszuführen. Sie können ein weiteres Stück Code unterbrechen, indem Sie einen einzelnen Timer mit einem Intervall von einer Millisekunde einrichten, das Ihren Browser dazu zwingt, die Rückruffunktion bei der nächsten Gelegenheit auszuführen, aber das unterbrochene Stück Code wird gestoppt und wird die Ausführung erst fortsetzen, bis die Ausführung der Ausführung abgeschlossen ist. Wenn Sie also einen Timer so einstellen, dass jede Millisekunde nicht garantiert, dass Ihre Funktion so schnell aufgerufen wird. Wir werden die Folge davon sehen, wenn ich über die Schleife spreche.
Natürlich erfordern Spiele eine Art menschliche Eingabe, sei es über Tastatur, Maus oder Joystick. Damit unser Spiel mehr als stationäre Sprites, die vor Ort laufen, müssen wir auf Eingaben des Benutzers reagieren. In JavaScript heißt dies Ereignishörer .
Es gibt zwei verschiedene Ereignismodelle, je nachdem, welchen Geschmack von Browser Sie haben (Überraschung, Überraschung), und obwohl der Prototyp einen fantastischen Job bei der Einkapselung der Nuancen der beiden leistet, lohnt es sich, zu wissen, was unter der Motorhaube vor sich geht.
Sie können auswählen, ob Ereignisse durch das DOM zu dem Element gehen, das es abgefeuert hat (Ereigniserfassung), aus dem Element (Ereignisblasen) oder einer Kombination aus beiden (dem offiziellen W3C -Modell). Unten finden Sie eine grafische Darstellung dessen, was passiert. Diejenigen von Ihnen im Internet Explorer -Land sind mit Ereignissprudeln festgefahren, während andere Browser beides unterstützen.
Wenn Sie schon eine Weile im Web gespielt haben, sind Sie möglicherweise mit der Handhabung von Inline -Ereignissen mit Attributen wie Onmouseover oder Onclick vertraut. Diese Technik entspricht der Verwendung des Stilattributs in CSS - es ist böse, tun Sie es nicht. Zum Glück gibt es verschiedene Möglichkeiten, Ereignisse in JavaScript dynamisch an Elemente zu binden. Betrachten Sie den folgenden Code:
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
Hier haben wir drei verschiedene Methoden zum Anbringen von Ereignissen an Elemente im DOM. Die erste - mit AddEventListener - ist die W3C -Standardmethode, um Dinge zu tun. Der erste Parameter ist der Name des Ereignisses, der zweite der Name der Rückruffunktion, und der dritte ist ein Boolescher, der angibt, ob wir (falsch) oder sprudeln (wahr) erfassen. Die zweite - Verwendung von AttachEvent - ist der Internet Explorer -Weg; Es ist im Grunde genommen die gleiche Signatur wie die W3C -Version ohne den dritten Parameter, da der IE nur das Ereignis sprudelt. Die letzte - mit der Onclick -Eigenschaft des Elements - ist eine Methode, die in allen Browsern funktioniert.
Ereignisse wie Mouseover und Mouseout sind ziemlich einfach, aber Tastaturereignisse sind etwas komplexer, da wir wissen müssen, welche Taste gedrückt wurden. In diesem Fall müssen wir die Informationen aus dem JavaScript -Ereignisobjekt erhalten. Entweder wird ein Ereignisobjekt in die Rückruffunktion übergeben, oder wenn Sie sich im IE -Land befinden, wird im Fensterobjekt: Window.event ein globales Ereignisobjekt erstellt, das die Informationen enthält, die wir benötigen.
Hier ist ein Beispiel:
var WalkingSprite = Class.create({ <br> x: 0, <br> y: 0, <br> element: null, <br> <br> initialize: function(element, x, y) { <br> this.element = element; <br> this.x = x; <br> this.y = y; <br> }, <br> <br> walk: function(steps) { <br> this.x += steps; <br> } <br> }); <br> <br> koopa = new WalkingSprite(null, 10, 10); <br> koopa.walk(20); <br> alert(koopa.x + "," + koopa.y);
// Declare the class <br> function WalkingSprite(element, x, y) { <br> this.x = x; <br> this.y = y; <br> this.element = element; <br> } <br> <br> WalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> element: null, <br> <br> walk: function(direction) { <br> this.x += direction; <br> } <br> } <br> <br> // Create the child class <br> JumpingAndWalkingSprite = WalkingSprite; <br> JumpingAndWalkingSprite.prototype = { <br> x: 0, <br> y: 0, <br> walk: WalkingSprite.prototype.walk <br> jump: function() { <br> y += 20; <br> } <br> }
var JumpingAndWalkingSprite = Class.create(WalkingSprite); <br> <br> mario = new JumpingAndWalkingSprite(null, 10, 10); <br> mario.walk(10): <br> alert(mario.x + "," + mario.y); <br> mario.jump(); <br> alert(mario.x + "," + mario.y); <br>
Einrichten unseres Ereignishandlers mit Ereignis. MitOBSERVE ermöglicht es uns, den bedingten Test abzugeben, der überprüft, ob wir über einen Funktionsparameter oder über das Fensterereignis über ein Ereignisobjekt verfügen. Es ist alles nahtlos für uns durch Prototyp gehandhabt.
Zu diesem Zeitpunkt haben wir JavaScript -Objekte und Klassen (einschließlich OOP -Konzepte wie Vererbung) untersucht, wie man JavaScript- und CSS -Klassen verwendet, um Elemente Verhaltensweisen zu verleihen, wie Timer verwendet werden, um uns wiederholt eine Aufgabe (z. B. Animation) und die Grundlagen des Anhörens von Ereignissen zu ermöglichen. Dies gibt uns genügend JavaScript in unserer Toolbox, damit wir den Kern des Erstellens eines Plattformspiels erreichen können. Im nächsten Artikel werde ich das Erstellen einer einfachen Kollisions-Engine-die Animationsschleife-erstellen und Ihnen ein paar Tricks zum Scrollen des Browserfensters zeigen, um den authentischen 80er-Jahre-Seiten-Scrolling-Effekt zu erhalten.
Schauen Sie sich in der Zwischenzeit die Demo an, die die obige Theorie in die Praxis umzusetzt (Hinweis: Drücken Sie die Pfeiltasten und sehen Sie, was passiert). Sie können das Codearchiv für diesen Artikel herunterladen. Sehen Sie, ob Sie es selbst erweitern können, da Sie verstehen müssen, was für den zweiten Artikel in dieser Serie los ist. Bis zum nächsten Mal…
Kann JavaScript zum Erstellen von Bots verwendet werden? Wie?
Das obige ist der detaillierte Inhalt vonHacking JavaScript zum Spaß und Gewinn: Teil I.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!