Startseite | Anpassen | Blog | Extras | Anmelden | Info
Handbuch | D&D icons | GML Parser | Archiv | Iso City
Benutzername: Passwort:  
Über | Funktionen | Verzeichnis | Banner | Kontakt

Den Game Maker benutzen
Den Game Maker benutzen

Spiele designen
mit dem
Game Maker

Version 6.1
Geschrieben von Mark Overmars

Übersetzt von gm-d.de (ehemals gMaker.de)
06.08.2005
/library/manual/images/logo.jpg

Was ist neu

Version 6.1 des Game Maker ist ein relativ kleines Upgrade von 6.0. Die folgenden Veränderungen wurden gemacht:

Inkompatibilitäten

Die Hauptinkompatibilität ist das Partikelsystem. Einige Funktionen wurden entfernt und die Größe der internen Sprites wurde geändert. Auch wurden die eingebauten Formen geändert. Siehe unten für mehr Informationen.

Eine kleine Inkompatibilität liegt im folgen des Views. Weil das Sprite nun nicht mehr berücksichtigt wird, könnte ein größerer Rand gebraucht werden.

Die Dateien sind aufwärts- und abwärtskompatibel. Das heißt, Version 6.1 kann mit Version 6.0 erstellte Dateien lesen und umgekehrt. 100% funktioniert das natürlich nur, wenn keine der neuen 6.1 Funktionen benutzt wird.

Effekte

Ein sehr einfacher Mechanismus für Effekte und Explosionen wurde hinzugefügt. Es gibt nur eine Aktion die in jedem Event genutzt werden kann. Es erstellt Effekte, wie Explosionen, Rauch, Feuerwerk, Regen oder Schnee. Es gibt 12 verschiedene Arten von Effektnen in drei verschiedenen Größen und in der Farbe deiner Wahl. Die Effekte können auch mit einem einfachen Funtkionsaufruf erstellt werden.

Partikelsystem

Das Partikelsystem wurde verbessert, was zu einigen Inkompatibilitäten führt. Die Hauptänderung ist, das die Partikel nun automatisch aktualisiert und gezeichnet werden. Es muss nun kein Objekt mehr dafür erstellt werden. Die alten Funktionen hierfür gibt es nicht mehr und müssen entfernt werden. Auch wurde das Erstellen von Partikeltypen geändert.
  • Partikelsysteme haben nun eine Zeichentiefe und -position.
  • Es gibt mehr eingebaute Partikeltypen, inklusive Ringe, Rauch, Wolken, und Explosionen. Es gibt auch mehr Möglichkeiten für Farben, Partikel können eine (wechselnde) Ausrichtung haben, ihr Seitenverhältnis kann bestimmt werden und ihre Farben können additiv gemischt werden.
  • Zufällige Änderungen in Größe, Geschwindigkeit und Richtung wurden ersetzt durch "wackeln", was zu weitaus interessanteren Effekten führt, beispielsweise blinkenden Sternen.
  • Die Benutzung des Partikelsystems per Drag&Drop wurde weiter ausgebaut, erlaubt nun das nutzen von Sprites, Farbänderungen und Alpahwerte.
  • Die Partikeldemo wurde aus der Distribution entfernt, aber auf der Webseite gibt es eine schöne Demo inkl. Quellcode..

Bildeditor

Der Bildeditor erfuhr einige Verbesserungen. Die Möglichkeit des Erstellens, Bewegens, und Kopierens von Auswahlen wurde hinzugefügt. Auch der Textmechanismus wurde überarbeitet, nun ist es möglich Text umherzubewegen. Du kannst ganz einfach horizontale, vertikale und diagonale Linien, Quadrate und Kreise zeichnen. Mit gedrückter <Strg> Taste kann nun aus dem Bild eine Farbe gewählt werde. Und es gibt Befehle um einen Umriss aus dem Bild zu zeichnen und die Farben zu invertieren. Auch wurden neue, bessere Cursorbilder verwendet.

Bewegungsplanung

Potentielle Feldbewegungsplanungsfunktionen können nun Instanzen eines bestimmten Typs vermeiden. Durch die Benutztung von Parents führt dies zu extrem flexibler Bewegungsplanung.

3D Graphikmodelle

Ein neues Set Funktionen wurde hinzugefügt um 3D Modelle zu Erstellen, zu Zeichnen, zu Speichern und zu Laden. Sie sind zwar etwas eingeschränkt aber beschleunigen 3D immens..

Zeichnen auf Oberflächen

Anstatt auf dem Bildschirm zu zeichnen kann man nun auch Oberflächen definieren und darauf zeichnen. Solche Oberflächen können dann auf den Bildschirm gezeichnet oder als Textur verwandt werden. Oberflächen können teilweise transparent mit Alpa Werten sein. Sie können in eine Datei gespeichert werden. Sie können auch in Sprites oder Hintergründe umgewandelt werden.

Andere Änderungen

Es gibt noch mehr Veränderungen und Neuerungen. Hier noch die wichtigsten.
  • Ein besserer Installer wird nun verwendet.
  • Eine Aktion wurde hinzugefügt, um ein Objekt am Rand umzuklappen.
  • Eine Aktion wurde hinzugefügt, um zufällig eines aus 4 Objekten zu erstellen.
  • Eine neue Raster Datenstruktur wurde hinzugefügt.
  • Die Zahl der Alarmevents wurde auf 12 und die der Benutzerdefinierten Events auf 16 gehoben.
  • Funktionen choose(val1,val2,...) und median(val1,val2,...) hinzugefügt.
  • Aktionsblöcke in Objekten und Zeitleisten werden nun eingerückt.
  • Beim Hinzufügen von Bildern in ein Sprite gibt es mehr Möglichkeiten.
  • Mausradevents wurden hinzugefügt.
  • Du kannst beginnend mit $ nun Hexadezimalwerte verwendet, z.B. $0000FF ist rot.
  • Die Synchronisationsoption arbeitet nun besser.
  • Momente in den Zeitleisten können dupliziert werden.
  • Funktion screen_wait_vsync() um auf vertikale Synchronisation zu warten wurde hinzugefügt.
  • Du kannst nun <Shift> zum Auswählen mehrere Tiles gedrückt halten, oder <Strg> um ein Vielfaches der Raumrastergröße zu verwenden.
  • ...

Korrigierte Fehler

Die folgenden größeren Bugs wurden behoben.
  • Kollisionen laufen nun korrekt mit gesetztem notme.
  • Beim Erstellen von Räumen während des Spieles ist die Geschwindigkeit nun 30.
  • Der Puffer wird auf scharz geschaltet wenn das Spiel gestartet wird oder die Auflösung geändert wird.
  • Ein Bug in der Funktion d3d_vertex_normal_texture_color() behoben.
  • Ein Bug beim Erstellen von Hintergründen und Sprites vom Bildschirm behoben.
  • Globale Variablen werden im Debug-Modus korrekt angezeigt.
  • Fehler korrigiert beim Einfügen von Momenten in leere Zeitleisten.
  • Fehler beim Ursprung in replace_sprite() behoben.
  • Ein View kann auch einer Instanz ohne Sprite folgen.
  • Einige Soundprobleme wurde behoben.
  • Real Werte in Ini Dateien werden nun mit , und . als Trennzeichen gelesen.
  • Einige Fehler in der Hilfedatei wurden behoben.
  • Die Aktion zum zufälligen Springen an eine Position setzt die Instanz nicht mehr ausserhalb des Raumes.
  • Der Any Key Eevent reagiert nun auch auf Zeichen wie ~ . , [ etc.
  • Bug mit eliptischen Deflectors und Destroyern behoben.
  • Bug behoben, der manchmal beim Drag&Drop auftrat.
  • Beim Zusammenfügen von Spielen bleibt das Objekt, dem ein View folgen muss, erhalten.
  • Die Standardlautstärke ist nun immer das Maximum.
  • Art der ein View einem Objekt folgt geändert (nur noch die Position wird berücksichtigt). Dies umgeht die Wackelprobleme, benötigt aber einen größeren Rand.
  • Pfadgeschwindigkeit kann nun negativ sein.
  • Probleme mit der Scrolleiste im Raumeditor behoben.
  • ...

Den Game Maker benutzen

Game Maker ist ein einfach zu benutzendes Programm zum Erstellen eigener Computerspiele. Dieser Teil der Hilfe gibt dir Information über und Hilfestellung zum Erstellen deines ersten Spieles. Später werden fortgeschrittenere Themen besprochen, wie man ein Spiel fertig macht und vertreibt, und die eingebaute Programmiersprache GML.

Du willst dein eigenes Computerspiel erstellen

Computerspielen macht Spaß. Aber es macht noch mehr Spaß, ein Computerspiel selbst zu erstellen und es anderen zum Spielen zu geben. Leider ist das Erstellen solch eines Spieles nicht so einfach. Kommerzielle Computerspiele (solche die du kaufst) brauchen oft sogar 1 - 3 Jahre Entwicklungszeit, obwohl in einem Team von meist 10 - 50 Leuten gearbeitet wird. Die Budgets steigen oft bis in die Millionen-Höhe. Und all diese Leute sind bestens ausgebildet: Programmierer, Designer, Klangtechniker, usw.

Soll das jetzt heißen, dass es unmöglich ist ein eigenes Computerspiel zu erstellen? Sicher nicht. Natürlich kannst du nicht davon ausgehen, dass du dein eigenes Quake oder Age of Empires in ein paar Wochen erstellst. Dies ist aber auch nicht nötig. Ein paar einfachere Spiele wie Tetris, Pacman, Space Invaders, usw. reichen auch schon aus. Auch solche Spiele machen Spass beim Spielen und sind viel einfacher zu erstellen. Natürlich braucht man auch dafür gute Programmierkenntnisse um Sounds, Grafiken usw. einzubinden.

Aber hier kommt der Game Maker ins Spiel. Der Game Maker wurde programmiert, um das Erstellen solcher Spiele einfacher zu machen. Du brauchst nicht einmal eine Programmiersprache zu beherrschen. Eine intuitive und einfach handzuhabende Drag & Drop Technik erlaubt es dir dein Spiel relativ schnell zu erstellen. Du kannst Bilder importieren oder sogar selbst erstellen, Sprites (animierte Bilder), Sounds und vieles Andere nutzen. Du bestimmst ganz einfach die Eigenschaften der Objekte in deinem Spiel und zeigst ihnen, wie sie sich verhalten sollen. Du kannst sogar Bilder auf einer Karte bewegen lassen. Wenn du die volle Kontrolle über alles haben willst, gibt es auch noch eine einfach handzuhabende Programmiersprache, mit der du genauestens bestimmen kannst, was in deinem Spiel geschehen soll.

Der Game Maker beschäftigt sich mit 2 dimensionalen Spielen. Also keine 3D-Welten wie in Quake. Aber lass dich davon nicht abhalten. Viele großartige Spiele wie Age of Empires, die Command & Conquer Serie und Diablo benutzen 2 dimensionale Sprite-Technologien und sehen manchmal trotzdem 3 dimensional aus. Ausserdem ist das designen von 2 dimensionalen Spielen viel einfacher und schneller.

Du kannst den Game Maker völlig kostenlos nutzen. Und du kannst deine selbst erstellten Spiele gratis weitergeben, oder auch verkaufen. Schau dir die beiliegenden Lizenzbestimmungen für nähere Details an. Du solltest aber den Game Maker registrieren. Mit deiner Registrierung förderst du die Weiterentwicklung des Game Makers, einige seiner erweiterten Funktionen werden freigeschaltet und das kleine Logo beim Starten des Spieles verschwindet.

Dieses Dokument wird dir alles über den Game Maker berichten, was du wissen musst, sogar wie du dein eigenes Spiel erstellst. Bitte denke daran, dass sogar mit Programmen wie dem Game Maker das Erstellen von Computerspielen nicht anspruchslos ist. Es gibt so viele wichtige Aspekte die bei der Programmierung solcher Spiele wichtig sind, z.B.: Spielablauf, Grafik, Sound, das Benutzerinterface, usw. Fange mit einfachen Spielen an und du wirst merken, dass das Programmieren von Spielen sehr viel Spaß macht. Komme auch mal auf unsere Internetseite

http://www.gamemaker.nl/

für viele Beispiele, Tutorials, Ideen und Links zu anderen Seiten und Foren (alles englischsprachig, die dt. Community ist unter http://www.gmaker.de/ zu finden). Bald wirst du ein Meister im Spiele erstellen sein. Viel Spaß

Installation

Vermutlich hast du den Game Maker schon installiert, falls dem nicht so ist, hier kommt eine Erklärung zum Installationsprozess des Game Makers. Führe einfach die Datei gmaker.exe aus. Folge den Installationsanweisungen des Setups. Du kannst das Programm installieren wohin du möchtest, aber am einfachsten ist es den vorgegebenen Pfad zu verwenden. Ist die Installation beendet, wirst du eine neue Programmgruppe im Startmenü finden. In dieser Programmgruppe kannst du den Game Maker starten oder die Hilfe durchlesen.

Wenn du den Game Maker zum ersten Mal startest, wirst du gefragt, ob du das Programm im einfachen oder im erweiterten Modus starten möchtest. Wenn du vorher noch nie mit solch einem Programm gearbeitet hast, also noch keine Erfahrungen damit hast, solltest du lieber den normalen Modus wählen (also wähle No). Im normalen Modus werden mehrere Optionen versteckt. Du kannst ganz einfach zum erweiterten Modus wechseln indem du im File-Menü auf Advance Mode klickst.

Im Installationsordner (normalerweise C:\Programme\Game_Maker6\) gibt es noch ein paar andere Ordner:

  • examples dieser Ordner beinhaltet Beispiel Spiele zur Anschauung.
  • lib beinhaltet die Aktionsbibliotheken. Wenn du zusätzliche Aktionen installieren willst, musst du sie in diesen Ordner kopieren.
  • sprites in diesem Ordner gibt es ein paar Sprites die du benutzen kannst. Durch die normale Installation werden ein paar Standardsprites installiert, aber von der Game Maker Website (http://www.gamemaker.nl/) kannst du weitere Ressourcen-Packs mit Hintergründen, Sounds, Sprites etc. herunterladen
  • backgrounds, sounds das sind die Ordner, in denen die Hintergrundbilder und Sounds beinhaltet sind.

Systemvorraussetzungen

Game Maker benötigt einen modernen Pentium PC mit Windows 98SE, 2000, Me, XP oder höher. Eine Grafikkarte mit mindestens 16MB Speicher wird für die meisten Spiele vorausgesetzt. (Für einfache Spiele kann eine 8MB Grafikkarte ausreichend sein.) Die Mindestauflösung beträgt 800x600 und 65535 (16-bit) Farben. Er benötigt DirectX Version 8.0 oder höher auf dem PC. (Du kannst die neueste DirectX Version von der Microsoft Webseite herunterladen: http://www.microsoft.com/windows/directx/.) Wenn an Spielen arbeitest und diese testest sind die Speicheranforderungen recht hoch (mindestens 64MB, besser mehr). Wenn du nur spielen möchtest sind die Speicheranforderungen weniger drastisch und hängen vom Spiel ab.

Registrierung

Game Maker kann ohne eine Bezahlung genutzt werden. Die unregistrierte Version hat jedoch ein paar Einschränkungen und zeigt ein kleines Logo wenn das Spiel läuft. Um die zusätzlichen Funktionen freizuschalten, das Logo zu entfernen und die Weiterentwicklung des Programmes zu unterstützen wirst du gebeten deine Kopie des Game Makers zu registrieren. Die Registrierung fügt Folgendes hinzu:
  • Kein Game Maker Logo beim spielen eines Spieles.
  • Rotierte, umgefärbte und transparente Sprites.
  • Zusätzliche Aktionen für z.B. CD Musik, rotierten Text und eingefärbte Formen.
  • Spezielle Soundeffekte und positionierter Klang.
  • Einige Zeichenfunktionen, beispielsweise texturierte Polygone.
  • Ein Partikelsystem um Feuerwerk, Flammen, Regen und andere Effekte zu erzeugen.
  • Funktionen für 3D Grafiken.
  • Die Möglichkeit, Multiplayer Netzwerkspiele zu erzeugen.
  • Funktionen um Ressourcen zu erzeugen und zu verändern (Sprites, Hintergründe, etc.) während das Spiel läuft.
  • Eine Sammlung an Funktionen um Daten-Strukturen zu erzeugen und zu verwenden.
  • Funktionen zur Bewegungsplanung.
  • Die Möglichkeit,Game Maker mit DLLs zu erweitern.

Die Registrierung des Game Makers kostet nur 15 Euro oder den Gegenwert in einer anderen Währung , momentan z.B. US $ 18. Es gibt eine Vielzahl von Möglichkeiten, wie du deine Kopie der Software Registrieren kannst. Der einfachste Weg, um zu Registrieren, ist ein sicheres online Kreditkartensystem oder ein PayPal Konto zu nutzen. Alternativ kannst du den Betrag auf unser Bankkonto überweisen, einen Scheck oder das Geld per Post senden. Details dazu können auf der Game Maker Registrierungs-Webseite gefunden werden:

http://www.gamemaker.nl/registration.html

Um deine Kopie des Game Makers zu Registrieren, benutze die obige Webseite oder wähle Registration im Help Menü. Auf der linken Seite des erscheinenden Formulares klicke auf den Knopf Go to Registration Webpage. Du wirst zu unserer Registrierungs-Webseite weitergeleitet, wo die verschiedenen Möglichkeiten näher genannt werden , inklusive der online Registrierung.

Wenn deine Registrierung empfangen wurde wird dir eine Mail mit dem Namen, dem Schlüssel und der Information, wo der Schlüssel im Programm eingegeben werden muss, gesendet. Um den Schlüssel einzugeben, wähle nochmals Registration im Help Menü. Auf der linken Seite des Fensters drücke Enter a Registration Key. Gebe den Namen und den Schlüssel ein und betätige OK. Solltest du keinen Fehler gemacht haben, bist du jetzt registriert.

Wenn du eine registrierte Version des Game Maker 5 auf deinem System installiert hattest kannst du deinen Version 5 Registrierungsschlüssel gegen einen Registrierungsschlüssel der Version 6 tauschen. Dazu wähle Registration im Help Menü. Auf der linken Seite des Fenster sollte in diesem Fall Exchange a Version 5 Key sichtbar sein. (Falls nicht existiert auf dem System keine gültige Registrierung für Version 5 oder deine Version 6 ist schon registriert.) Es wird auch ein Text angezeigt der den Austauschvorgang erklärt. Lese die Anweisungen aufmerksam durch, folge ihnen und dann drücke den Knopf.

Der Grundgedanke

Bevor du dich eingehender mit den Möglichkeiten des Game Makers befasst, ist es von Vorteil, wenn du erstmal den Grundgedanken des Programmes kennen lernst. Spiele, die mit dem Game Maker erstellt wurden, finden in einem oder mehreren rooms (Räumen) statt (Räume sind flach, nicht dreidimensional, aber sie können dreidimensional aussehende Grafiken enthalten). In diesen Räumen platzierst du objects (Objekte), die du innerhalb der Software definieren kannst. Typische Objekte sind Wände (walls), sich bewegende Bälle, die Spielerfigur, Monster, usw. Manche Objekte, wie beispielsweise Wände, sind einfach nur da und machen gar nichts. Andere Objekte, wie die Spielerfigur, bewegen sich umher und reagieren auf die Eingaben des Spielers (Tastatur, Maus, und Steuerknüppel) und aufeinander. Beispielsweise, wenn die Spielerfigur auf ein Monster trifft, "stirbt" sie möglicherweise. Objekte sind der wichtigste Bestandteil der mit Game Maker erstellten Spiele beschäftigen wir uns etwas eingehender mit diesen

Zu allererst benötigen die meisten Objekte ein Bild, um sie auf dem Bildschirm darzustellen. Solche Bilder werden sprites genannt. Ein sprite ist oftmals kein einzelnes Bild, sondern ein Reihe von Bildern, welche nacheinander angezeigt werden, um eine Animation zu erzeugen. Auf diese Art wird erreicht, dass es so scheint, als laufe die Spielerfigur, als rotiere ein Ball, als explodiere ein Raumschiff, usw. Während des Spiels kann das sprite für ein bestimmtes Objekt wechseln. (so sieht die Spielerfigur unterschiedlich aus, wenn sie nach links bzw. rechts läuft.) Du kannst deine eigenen Sprites im Game Maker erstellen oder sie aus Dateien laden (z. B. animierte GIF's).

Gewisse Dinge geschehen mit den Objekten. Solche Ereignisse nennt man events. Objekte reagieren mit bestimmten actions (Aktionen) auf eintretende events (Ereignisse). Es gibt eine Vielzahl von unterschiedlichen Ereignissen, die auftreten können und eine große Zahl von diversen Aktionen, mit denen die Objekte darauf reagieren können. Beispielsweise wird ein creation event ausgelöst, wenn ein Objekt Erschaffen wird. (genauer: Wenn eine Instanz eines Objektes erschaffen wird; es können mehrere Instanzen von einem Objektes erzeugt werden.) Wenn zum Beispiel ein ball object erzeugt wird, kannst du diesem eine Bewegungsaktion zuweisen, so dass er sich fortbewegt. Wenn zwei Objekte aufeinander treffen, wird ein collision event (Kollisionsereignis) ausgelöst. In solch einem Fall kannst du den Ball anhalten oder in die entgegengesetzte Richtung bewegen. Du kannst auch einen Soundeffekt (Klang-) abspielen. Zu diesem Zweck kannst du im Game Maker Sounds definieren. Wenn der Spieler eine Taste auf der Tastatur drückt, wird ein keyboard event (Tastaturereignis) ausgelöst und das Objekt kann darauf mit einer entsprechenden Aktion reagieren - zum Beispiel sich in die jeweilige Richtung bewegen. Ich hoffe, du hast das Prinzip verstanden. Für jedes Objekt, das du erstellst, kannst du für unterschiedliche "events" Aktionen fest legen und somit das Verhalten des Objektes definieren.

Wenn du deine Objekte definiert hast, ist es an der Zeit einen room (Raum) zu beschreiben, in dem die Objekte agieren werden. Räume können als Level in deinem Spiel verwendet werden oder als unterschiedliche Orte/Gebiete. Es gibt bestimmte Aktionen, um von einem Raum zu einem anderen zu gelangen. Räume besitzen einen Hintergrund. Das kann einfach eine Farbe sein oder ein Bild. Solche Hintergrundbilder können im Game Maker erstellt werden oder aus Dateien geladen werden. (Der Hintergrund kann eine Menge Sachen - aber vorläufig genügt es, wenn du ihn als etwas erachtest, was den Raum schöner aussehen lässt.) Als nächstes platzierst du die Objekte im Raum. Du kannst mehrere Instanzen desselben Objektes in einem Raum arrangieren. So kannst du beispielsweise nur einmal ein Wandobjekt definieren und es an verschiedenen Stellen im Raum einsetzen. Auch kannst du mehrere Instanzen desselben Monsterobjektes einsetzen - solange sie alle das gleiche Verhalten haben sollen.

Nun ist es soweit, dein Spiel zu starten. Der erste Raum wird angezeigt und die Objekte darin erwachen zum Leben, wegen der Aktionen in ihren creation events. Sie reagieren aufeinander aufgrund ihrer Aktionen in den collision events und sie reagieren auf den Spieler durch die Aktionen in "keyboard-" oder "mouse-event".

Zusammenfassend spielen folgende Dinge (oft als "resources" (~Spielkomponenten) bezeichnet) eine entscheidende Rolle:

  • Objekte: welche die wahren Bestandteile des Spieles sind
  • Räume: Die Orte (levels), in denen die Objekte "leben"
  • Sprites: (animierte) Grafiken die dein Objekt repräsentieren
  • Sounds: sie werden im Spiel entweder als Hintergrundmusik, oder als Effekte genutzt
  • Hintergründe: die Grafiken, die als Hintergründe für die Räume gedacht sind
Es gibt noch weitere Spielkomponenten (resources): Pfade, Skripte, Schriften und Zeitleisten. Sie sind wichtig für kompliziertere Spiele. Du kannst sie nur erreichen, wenn du den Game Maker im erweiterten Modus (advance mode) betreibst. Mit ihnen befassen wir uns später in den fortgeschrittenen Kapiteln dieses Dokumentes.

Lass' uns ein Beispiel ansehen

Es ist gut sich erstmal ein Bild darüber zu machen, wie man ein einfaches Beispiel erstellt. Wir gehen hier davon aus, dass du den Game Maker im einfachen Modus betreibst. Der erste Schritt ist das Spiel das du machen möchtest, zu beschreiben (Das solltest du immer zuerst tun; Es wird später eine Menge Zeit dadurch gespart.) Das Spiel wird sehr simpel sein: Ein Ball prallt zwischen Wänden hin und her. Der Spieler soll nun versuchen, mit der Maus auf den Ball zu klicken. Bei jedem Erfolg gibt es einen Punkt.

Wie du erkennen kannst, werden zwei verschiedene Objekte benötigt: Der Ball und die Wand. Wir benötigen auch zwei verschiedene Sprites: eines für das Wand-Objekt und eines für das Ball-Objekt. Und letztendlich wollen wir bei erfolgreichem klicken einen Sound hören. Es wird nur ein Raum benötigt, in dem das ganze Spielgeschehen stattfindet. (Wenn du das Spiel nicht selbst machen möchtest kannst du es im Examples Ordner unter dem Namen hit the ball.gm6 finden.)

Zuerst erstellen wir die Sprites. Im Add Menü wähle Add Sprite (Du kannst auch den dazugehörenden Knopf in der Toolbar benutzen.). Ein Formular öffnet sich. Gebe im Feld Name “wall” ein. Drücke den Load Sprite Knopf und wähle die passende Grafik aus. Das war alles, du kannst das Formular nun schließen. Erstelle den Ball auf dieselbe Weise.

Als nächstes erstellen wir den Sound. Im Add Menü wähle Add Sound. Ein anderes Formular öffnet sich. Gebe dem Sound einen Namen und wähle Load Sound . Suche etwas passendes und prüfe ob es sich gut anhört, indem du auf den "play" Knopf klickst. Wenn du zufrieden bist, schließe das Formular.

Der nächste Schritt ist, die zwei Objekte zu erstellen. Machen wir zuerst das Wand-Objekt. Wähle Add Object aus dem Add-Menü. Ein Fenster öffnet sich, das ein bisschen komplizierter als die zwei zuvor aussieht. Auf der linken Seite befinden sich allgemeine Informationen über das Objekt. Gib dem Objekt einen passenden Namen und wähle das "wall"-Sprite aus dem Drop-down aus. Weil eine Wand solide ist (der Ball kann nicht durch), setze einen Haken bei Solid. Das war alles. Erstelle ein weiteres neues Objekt, benenne es "ball" und gib ihm das Ball-Sprite. Der Ball soll nicht solide sein. Für ihn müssen wir nun das Verhalten definieren. In der Mitte siehst du eine leere Liste von Events (Ereignissen). Darunter befindet sich ein Button Add Event. Betätige ihn und du siehst alle möglichen Ereignisse. Wähle das Creation-Event. Es wird nun zur Liste hinzugefügt. Ganz rechts siehst du alle möglichen Actions (Aktionen, Befehle) in Gruppen zusammengefasst. Von der Move (bewegen) - Gruppe wähle die Aktion mit den acht roten Pfeilen und ziehe sie in die Aktionsliste in der Mitte. Nun erscheint ein Dialog, in dem du die Richtung der Bewegung wählen kannst. Klicke alle acht Pfeile an (jetzt wird eine zufällige Richtung gewählt). Den "speed" (Geschwindigkeit) kannst du bei 8 lassen. Schließe nun den Dialog. Jetzt beginnt sich der Ball zu bewegen, wenn er erstellt wird. Als zweites müssen wir definieren, was im Fall einer Kollision mit der Wand passieren soll. Drücke auf Add Event. Klicke auf den Button für Collision-Events und wähle im Drop-down das Wand-Objekt. Für dieses Event brauchen wir die bounce (abprallen) - Aktion (Du kannst dir ansehen, was eine Aktion macht, indem du den Cursor darüber hältst). Zum Schluss müssen wir noch einstellen, was passieren soll, wenn der Benutzer über dem Ball die linke Maustaste drückt. Füge das entsprechende Event hinzu, und wähle left mouse button aus dem Drop-down. Für dieses Event brauchen wir mehrere Aktionen: -eine, die einen Sound abspielt (in der main1-Gruppe), -eine, die die Punktzahl ("score") verändert (in der score-Gruppe) und zwei, die den Ball zu einer neuen, zufälligen Position bewegen und ihn wieder bewegen lassen (so wie im creation"-Event). Für die "score"-Aktion, tippe den Wert 1 ein und setze einen Haken bei Relative. Das bedeutet, dass 1 zur Punktzahl addiert werden soll. Übrigens: Wenn du einen Fehler machst, kannst du die Einstellungen ändern, indem du auf die Aktion in der Liste doppelklickst.

Unsere Objekte sind nun bereit. Was noch fehlt ist der Raum. Füge dem Spiel einen neuen Raum hinzu wieder im Add Menü. Auf der rechten Seite siehst du den leeren Raum. Auf der linken Seite sind einige Registerreiter, einer um den Hintergrund einzustellen , einer für allgemeine Einstellungen wie die Länge und Breite des Raumes und einer zum Hnizufügen von Instanzen. Unten kannst du im Pop-Up Menü ein Objekt auswählen. Wenn du in den Raum klickst werden Instanzen dieses Objektes dort erstellt. Du kannst sie mit der rechten Maustaste wieder entfernen. Erzeuge einen schönen Innenraum mit dem Wand-Objekt. Platziere schließlich 1 oder 2 Bälle im Raum. Unser Spiel ist fertig.

Nun ist es Zeit unser Spiel zu testen. Drücke den Run Knopf (den grünen, dreieckigen Pfeil am oberen Rand des Game Maker Fensters) und achte auf das, was passiert. Wenn du keine Fehler gemacht hast sollte der Ball sich nun umherbewegen. Versuche auf ihn zu klicken und schau, was passiert. Du kannst das Spiel mit der <Esc> Taste beenden. Nun könntest du noch einige Veränderungen vornehmen.

Glückwunsch! Du hast dein erstes kleines Spiel gemacht! Aber ich denke, es ist Zeit, etwas mehr über den Game Maker zu lernen...

Die Benutzerführung

Nach dem Start vom Game Maker erscheint folgendes Fenster:

/library/manual/images/form_main.jpg

(Hier siehst du den Anfänger-Modus vom Game Maker. Im erweiterten Modus (Advanced) gibt es einige zusätzliche Einträge). Links siehst du verschiedene Ressourcen, wie Sprites, Soundeffekte, Hintergründe, Objekte, Räume und noch zwei andere: Spielinformation und Spieloptionen. Oben gibt es ein für Windows typisches Menü und eine Symbolleiste. In diesem Kapitel werde ich die einzelnen Menüeinträge, Buttons usw. beschreiben. In den folgenden Kapitel werde ich einige davon genauer beschreiben. Es gibt immer verschiedene Wege für das gleiche Ziel: Benutzen eines Befehls des Menüs, Klicken eines Button oder Rechtsklicken auf eine Ressource.

File Menü

Im File Menü sind einige nützliche Befehle für das Laden und Speichern von Dateien, plus einige spezielle Befehle:
  • New. Benutze diesen Befehl um ein neues Spiel zu erstellen. Wenn das aktuelle Spiel geändert wurde, wirst du gefragt ob die Änderungen gespeichert werden sollen. Es gibt dafür auch einen Button in der Symbolleiste.
  • Open. Öffnet eine Spieldatei. Game Maker-Dateien haben die Dateierweiterung .gm6. (Du kannst auch die alten .gmd Dateien, die mit älteren Versionen des Game Maker erstellt wurden, öffnen. Diese könnten aber in der neuen Version nicht auf Anhieb funktionieren.) Hierfür existiert auch ein Button in der Symbolleiste. Wenn man eine Datei in Windows markiert und dann mit der Maus in das Hauptfenster vom Game Maker zieht, wird diese ebenfalls geöffnet.
  • Recent Files. Benutze dieses Untermenü um zuletzt geöffneten Dateien zu öffnen.
  • Save. Speichert die Datei unter dem aktuellen Namen. Wenn kein Name angegeben wurde, wird nach einem Neuen gefragt. Du kannst diesen Punkt nur benutzen wenn die Datei geändert wurde. Es gibt dafür auch einen Button in der Symbolleiste.
  • Save As. speichert das Spiel unter einem anderen Namen. Du wirst danach gefragt.
  • Create Executable. Wenn dein Spiel fertigt ist willst du es wahrscheinlich anderen zum Spielen geben. Mit diesem Befehl kannst du eine Version deines Spieles machen, welche nicht den Game Maker zum Spielen benötigt. Das ist einfach eine ausführbare Datei die du anderen geben kannst.
  • Advanced Mode. Dieser Befehl wechselt zwischen dem einfachen und dem erweiterten Modus des Game Makers. Im erweiterten Modus gibt es einige zusätzliche Befehle und Ressourcen.
  • Exit. Möglicherweise überflüssig. Klicke hier um den Game Maker zu beenden. Wenn du das aktuelle Spiel verändert hast, wirst du gefragt, ob du speichern möchtest.

Edit Menü

Das Edit Menü beinhaltet einige Befehle die sich auf die aktuell gewählte Ressource (Objekt, Sprite, Sound, usw.) beziehen. Abhängig von der Art der Ressource sind manche Befehle nicht verfügbar.
  • Insert resource. Fügt eine neue Instanz der aktuell gewählten Art der Ressource vor dem aktuellen hinzu. Ein Fenster öffnet sich wo du die Eigenschaften der Ressource ändern kannst. Darauf wird in späteren Kapiteln genauer eingegangen.
  • Duplicate. Dupliziert die aktuelle Ressource. Ein Fenster öffnet sich worin das Duplikat verändert werden kann.
  • Delete. Löscht die gewählte Ressource (oder Gruppe von Ressourcen). Sei vorsichtig, da dies nicht rückgängig gemacht werden kann. Du wirst aber vorher gewarnt werden.
  • Rename. Gibt der Ressource einen neuen Namen. Das kann auch im Eigenschaftsfenster der Ressource geschehen oder man kann die Ressource auswählen und dann auf den Namen klicken um ihn zu ändern.
  • Properties. Öffnet ein Fenster um die Eigenschaften der Ressource zu ändern. Bedenke alle Änderung werden im Hauptfenster übernommen. Du kannst viele gleichzeitig bearbeiten. Außerdem kannst du die Eigenschaften durch Doppelklicken auf die Ressource ändern.
Alle diese Befehle können auf verschieden Arten gewählt werden. Rechts klicken auf eine Ressource oder Ressourcengruppen und das gewünschte Pop-up Menu erscheint.

Add Menü

In diesem Menü können neue Ressourcen jeder Art hinzugefügt werden. Für jede dieser Ressourcen gibt es auch einen Button in der Symbolleiste und ein Tastenkürzel.

Run Menü

Dieses Menü dient dem Ausführen des Spieles. Es gibt zwei Möglichkeiten ein Spiel auszuführen.
  • Run normally. Führt das Spiel so wie es ist ganz normal aus. Das Spiel läuft im effizientesten Modus und verhält sich wie ein normales Programm.
  • Run in Debug mode.
  • Führt das Spiel im Debug Modus aus. In diesem Menü kannst du einige Aspekte des Spieles, wie Variablen, ansehen, es pausieren lassen oder schrittweise ausführen. Dies ist nützlich wenn etwas schwierigeres nicht richtig läuft.
Wenn das Spiel fertig ist kannst du mit dem "Create Executable" Kommando im Dateimenü eine Exe Datei erzeugen.

Window Menü

In diesem Menü kannst du nützliche Befehle für die verschiedenen Fenster im Hauptfenster finden:
  • Cascade. Ordnet alle Fenster kaskadiert hintereinander an.
  • Arrange Icons. Ordnet die verkleinerten Eigenschaftsfenster. (Nützlich wenn der Hauptbildschirm vergrößert wird.)
  • Close All. Schliesst alle Eigenschaftsfenster und fragt den Benutzer ob die Änderungen gespeichert werden sollen.

Help Menü

Einige Befehle über die Hilfe:
  • Contents. Hier kann die Game Maker Hilfe angesehen werden.
  • Registration. Auch wenn die Basis Version des Game Maker gratis benutzt werden kann, wirst du darum gebeten es zu registrieren. Dadurch werden einige weitere Funktionen freigeschaltet und die Weiterentwicklung des Programmes unterstützt. Hier findest du die Informationen zum Registrieren. Wenn du dich registriert hast, kannst du hier deinen Schlüssel eingeben.
  • Web site. Verbindet dich zur Webseite des Game Maker, wo du Informationen über die aktuelle Version des Game Maker und eine Sammlung von Spielen und Ressourcen finden kannst. Es wird empfohlen mindestens einmal im Monat nach neuen Informationen Ausschau zu halten.
  • About Game Maker. Zeigt eine kurze Informationen über die Version des Game Maker an.

Der Ressourcen-Explorer

Auf der linken Seite des Hauptfensters findest du den Ressourcen-Explorer. Hier siehst du eine Baumansicht aller Ressourcen in deinem Spiel. Er funktioniert so wie der Windows Explorer und du kannst ihn sicherlich schon Bedienen. Wenn ein Objekt ein + Zeichen vor sich hat, kannst du darauf klicken um um die Ressourcen darin zu sehen. Wenn du auf das - Zeichen klickst verschwinden diese wieder. Du kannst den Namen einer Ressource (ausser den Obersten) ändern, indem du sie Auswählst (mit einem einfachen Klick) und dann auf den Namen klickst. Doppelklicke auf eine Ressource, um deren Eigenschaften zu bearbeiten. Benutze die rechte Maustaste, um auf dieselben Kommandos wie im Edit Menü zuzugreifen.

Du kannst die Reihenfolge der Resourcen verändern, indem du auf sie klickst und sie mit gedrückter Maustaste umherbewegst. Nun kannst du die Ressource an den gewünschten Ort schieben. (Natürlich muss der Ort korrekt sein. Du kannst einen Sound nicht in die Liste der Sprites verschieben.)

Sprites Definieren

Sprites sind die visuellen Darstellungen aller Objekte im Spiel. Ein Sprite ist entweder ein Einzelbild mit irgendeinem Bildbearbeitungsprogramm gezeichnet, oder ein Set von Bildern, welche nacheinander abgespielt wie eine Animationsbewegung aussehen. Die folgenden vier Bilder zeigen ein Sprite für einen Pacman der sich nach rechts bewegt.

/library/manual/images/sprites1.gif

Wenn du dein Spiel machst, beginnst du eine Auswahl von schönen Sprites für die Objekte in deinem Spiel zu sammeln. Viele Sammlungen von interessanten Sprites können auch auf der Internetseite vom Game Maker gefunden werden. Sprites können auch im Internet gefunden werden, normalerweise in der Form von animierten Gif Dateien.

Um ein Sprite hinzuzufügen, wähle den Eintrag Add Sprite vom Add Menü, oder benütze den entsprechenden Button in der Symbolleiste. Das folgende Dialogfenster öffnet sich:

/library/manual/images/form_sprite.jpg

Ganz oben kann der Name des Sprites angegeben werden. Alle Sprites (und alle anderen Ressourcen) haben einen Namen. Am besten gibst du jedem Sprite einen beschreibenden Namen. Gehe sicher das alle Ressourcen verschiedene Namen bekommen. Obwohl dass nicht unbedingt notwendig ist, ist es sehr empfehlenswert nur Buchstaben und Ziffern und das Underscore Symbol ("_") im Namen des Sprites (und allen anderen Ressourcen) zu verwenden und ihn mit einem Buchstaben beginnen lassen. Besonders Leerzeichen sollten nicht enthalten sein. Das wird sehr wichtig sein, wenn du beginnst zu Coden.

Um ein Sprite zu laden, drücke den Knopf Load Sprite. Eine Dialogfenster öffnet sich, wo du das Sprite angeben kannst. Game Maker kann viele verschiedene Grafikdaten laden. Wenn du eine animierte Gif Datei lädst, bilden die verschiedenen Einzelbilder das Sprite mit Animation. Wenn das Sprite geladen ist, wird das erste Einzelbild rechts gezeigt. Wenn es mehrere Einzelbilder gibt, kannst du mit den Pfeiltasten das nächste Bild ansehen.

Die Auswahlbox Transparent zeigt, ob der Hintergrund transparent sein soll. Die meisten Sprites sind transparent. Der Hintergrund wird von der linken, unteren Farbe des Pixels im Bild bestimmt. Gehe sicher dass sonst kein Pixel im aktuellen Bild diese Farbe hat. (Bedenke, dass Gif-Dateien öfters ihre eigene Transparenzfarbe haben. Diese Farben werden nicht vom Game Maker genutzt.)

Mit dem Knopf Edit Sprite kannst du Sprites bearbeiten, oder sogar eine komplett neuen Sprite erstellen.

Sound und Musik

Viele Spiele benutzen bestimmte Soundeffekte und etwas Hintergrundmusik. Viele nützliche Soundeffekte können auf der Homepage vom Game Maker gefunden werden. Noch mehr können auf anderen Seiten im Internet gefunden werden.

Um deinem Spiel eine Soundressource hinzuzufügen, benutze den Add Sound Eintrag im Add Menu oder den entsprechenden Knopf in der Toolbar. Das folgende Dialogfenster öffnet sich.

/library/manual/images/form_sound.jpg

Drücke den Knopf Load Sound um einen Sound zu laden. Eine Dateiauswahlbox öffnet sich, wo die Sounddatei gewählt werden kann. Es gibt zwei Arten von Sounddateien, Wave-Dateien und MIDI-Dateien. Wave-Dateien werden für kurze Soundeffekte genutzt. Sie benötigen eine Menge Speicher aber werden sofort abgespielt. Benutze sie für alle Soundeffekte im Spiel. MIDI-Dateien gehen einen anderen Weg. Sie benötigen viel weniger Speicher, aber sie sind auf Hintergrundmusik beschränkt. Ausserdem kann nur eine MIDI-Datei gleichzeitig abgespielt werden.

Wenn die Musikdatei geladen ist wird die Art und Länge angezeigt. Drücke den Play Knopf um die Datei abzuspielen. Es gibt auch einen Save Sound Knopf, damit wird der aktuelle Sound gespeichert. Dieser Knopf wird zwar selten benötigt, aber er ist nützlich wenn die Originaldatei verloren gegangen ist.

Hintergründe

Die dritte Art von einfachen Ressourcen sind Hintergründe. Hintergründe sind üblicherweise große Bilder die als Hintergründe (oder Vordergründe) für einen Raum, wo das Spiel stattfindet, benutzt werden. Hintergrundbilder werden oft so erstellt, dass sie ein Feld ohne visuelle Beschränkungen teilen. Das ermöglicht es, mit einem Satz an kleinen Kacheln große Räume zu gestalten. Einige solcher Hintergründe gibt es auf der Internetseite vom Game Maker. Noch mehr davon gibt es auf vielen anderen Internetseiten.

Um deinem Spiel einen Hintergrund hinzuzufügen, benutze den Add Background Eintrag im Add Menu oder den entsprechenden Knopf in der Toolbar. Das folgende Dialogfenster öffnet sich.

/library/manual/images/form_background.jpg

Drücke den Load Background Knopf um eine Hintergrunddatei zu laden. Der Game Maker unterstützt viele Bildformate. Hintergründe können nicht animiert sein! Die Kontrollbox Transparent zeigt an, ob der Hintergrund teilweise transparent ist. Meistens sind Hintergründe nicht transparent, daher ist nicht vorgegeben. Als Transparenzfarbe wird der linke, unterste Pixel verwendet.

Du kannst den Hintergrund verändern oder einen neuen erstellen durch Drücken des Knopfes Edit Background.

Objekte Definieren

Mit Ressourcen, die du bisher kennengelernt hast, kannst du einige nette Bilder und Soundeffekte deinem Spiel hinzufügen, aber die machen gar nichts. Wir kommen jetzt zur wichtigsten Ressource vom Game Maker, den Objekten. Objekte sind Einträge im Spiel die Dinge machen. Die meisten von ihnen haben ein Sprite als grafische Darstellung. Sie haben ein Verhalten da sie auf bestimme Ereignisse reagieren. Alle Dinge die du im Spiel siehst (ausser Bildschirmhintergründe) sind Objekte. (Oder um genauer zu sein, sie sind Instanzen der Objekte). Der Charakter, die Monster, die Bälle, die Wände etc. sind alles Objekte. Es ist möglich, dass bestimme Objekte nicht sichtbar sind, sie steuern aber bestimmte Aspekte im Spielablauf.

Wichtig ist der Unterschied zwischen Sprites und Objekten. Sprites sind nur (animierte) Bilder die kein Verhalten haben. Objekte haben normalerweise auch ein Sprite aber Objekte besitzen ein Verhalten. Ohne Objekte gibt es kein Spiel.

Den Unterschied zwischen Objekten und Instanzen solltest du auch kennen. Ein Objekt beschreibt eine bestimmte Existenz, z.B. ein Monster. Es kann mehrere Instanzen eines Objektes im Spiel geben. Wenn wir über eine Instanz sprechen, meinen wir eine besondere Instanz eines Objektes. Wenn wir über ein Objekt sprechen meinen wir alle Instanzen eines Objektes.

Um ein Objekt deinem Spiel hinzuzufügen, wähle Add Object im Add Menü. Das folgende Fenster öffnet sich:

/library/manual/images/form_object.jpg

Das ist ziemlich komplex. Links gibt es allgemeine Informationen über das Objekt. In der Mitte ist eine Liste von Ereignissen welches dem Objekt passieren kann. Rechts gibt es verschieden Aktionen, die das Objekt ausführen kann. Über Ereignisse und Aktionen erfährst du etwas in den nächsten Kapiteln.

Wie immer kannst (und sollst) du deinem Objekt einen Namen geben. Dann kannst du das Sprite für das Objekt angeben. Klicke mit der linken Maustaste auf die Sprite Box oder dem Menü Knopf neben ihm. Ein Menü wird geöffnet, in dem du alle verfügbaren Sprites sehen kannst. Wähle das passende Sprite für das Objekt. Falls du noch kein Sprite haben solltest kannst du auf den New Knopf klicken um eine neue Sprite Ressource hinzuzufügen und zu bearbeiten. Auch der Knopf Edit kann genutzt werden um das Sprite zu verändern. Dies geht schneller als es erst in der Ressourcenliste zu suchen und dann zu bearbeiten.

Darunter sind zwei Kontrollboxen. Visible gibt an ob die Instanzen dieses Objektes sichtbar sind. Klar, die meisten Objekte sind sichtbar, aber manchmal ist es nützlich unsichtbare Objekte zu nutzen. Beispielsweise kannst du sie als Wegpunkte für ein sich bewegendes Monster einsetzen. Unsichtbare Objekte reagieren auf Events und Kollisionen genauso wie sichtbare. Solid gibt an ob das Objekt ein solides Objekt (wie eine Wand) ist. Kollisionen von soliden Objekten werden anders behandelt als die von nicht- soliden Objekten. Es wird empfohlen Solid nur bei Objekten zu setzen, die sich nicht bewegen.

Ereignisse

Der Game Maker ist ereignisgesteuert. Das funktioniert so: Wann immer etwas im Spiel geschieht, erhalten die Instanzen der Objekte Ereignisse (events). Die Instanzen können dann auf diese Ereignisse reagieren, indem sie bestimmte Aktionen (actions) auslösen. Für jedes Objekt muss fest gelegt werden, auf welche Ereignisse es reagiert und welche Aktionen ausgeführt werden sollen, wenn dieses Ereignis eintritt. Das hört sich kompliziert an, ist tatsächlich aber ganz einfach. Zuerst einmal müssen die Objekte für die meisten Ereignisse nichts machen. Für die Ereignisse, in denen Aktionen gefordert sind, steht ein simples "Drag&Drop-System" zur Verfügung, worin die entsprechenden Aktionen zugeordnet werden können.

In der Mitte der "object property form" (Eingabemaske der Objekteigenschaften) befindet sich eine Liste der Ereignisse (events), auf die das Objekt reagieren muss. Anfangs ist sie leer. Du kannst Ereignisse hinzufügen, indem du auf den Add event Knopf klickst. Ein kleines Auswahlmenü mit den diversen Ereignissen klappt auf. Hier kannst du das Ereignis auswählen, welches du hinzufügen möchtest. Manchmal klappt noch ein zusätzliches Menü auf, mit weiteren Auswahlmöglichkeiten. Beispielsweise musst du für ein "keyboard event" die Taste (key) festlegen. Weiter unten wird aufgelistet welche Ereignisse es gibt plus Beschreibung. Ein Ereignis wird aus der Liste ausgewählt. Dieses ist es, welches wir momentan bearbeiten. Um ein anderes anzuwählen, klicke es einmal mit der Maus an. Rechts befinden sich die ganzen Aktionen (actions), welche durch kleine Icons dargestellt werden. Sie sind in mehrere Gruppen unterteilt. Im nächsten Kapitel werden sie beschrieben. Das Feld zwischen der Ereignisliste und den Aktionen ist die Aktionsliste (action list). Hier werden die Aktionen für das angewählte Ereignis festgelegt. Um eine Aktion hinzuzufügen, ziehe sie (das Icon) mit der Maus einfach rüber in diese Liste. Sie werden mit einer Kurzbeschreibung untereinander einsortiert. Für jede Aktion werden einige Parameter erwartet. Dies wird auch im nächsten Kapitel erläutert. Wenn nun einige Aktionen hinzugefügt wurden, sieht die Situation wie folgt aus:

/library/manual/images/form_event_panel.jpg

Jetzt kannst du anfangen Aktionen anderen Ereignissen zuzuordnen. Klicke mit der linken Maustaste auf das entsprechende Ereignis, um es auszuwählen und ziehe die Aktionen in die jeweilige Liste.

Du kannst die Sortierung der Liste per "Drag-and-Drop" ändern. Wenn du die <Alt> Taste während des Ziehens gedrückt hälst, machst du eine Kopie der Aktion. Du kannst sogar zwischen den "action"-Listen verschiedener Objekte "Drag-and-Drop" verwenden. Wenn du eine Aktion mit der rechten Maustaste anklickst erscheint ein Menü, in welchem du die gewählte Aktion löschen (Dies kann auch mit der <Entf> Taste gemacht werden), kopieren oder ausschneiden kannst. (Du kannst zum Ausschneiden, Kopieren oder Löschen mehrere Aktion auswählen, indem du die <Shift> oder <Strg> Taste gedrückt hälst. Drücke <Strg><A> um alle Aktionen auszuwählen.) Wenn du den Mauszeiger länger über eine Aktion hälst erscheint eine längere Beschreibung dieser Aktion. Für mehr Informationen über Aktionen lese im nächsten Kapitel weiter.

Um das momentan markierte Ereignis zusammen mit all seinen Aktionen zu löschen, drücke den Delete Knopf. (Ereignisse ohne irgendwelche Aktionen in ihrer Liste werden automatisch beim Schließen der Eingabemaske entfernt, sodass man sie nicht extra von Hand aussortieren muss.) Wenn du die Aktionen einer Liste einem anderem Ereignis zuweisen willst (weil du Dich vielleicht für eine andere Taste entschieden hast), drücke einfach den Knopf Change und wähle ein anderes Ereignis. (Das neue Ereignis sollte nicht schon definiert sein!) In dem du das Menü benutzt, welches bei einem Rechtsklick auf ein Ereignis erscheint, kannst du ein Ereignis duplizieren, d.h. ein neues Ereignis mit denselben Aktionen hinzufügen.

Wie oben erwähnt erscheint folgendes Auswahlmenü, wenn du auf den Add event Knopf drückst:

/library/manual/images/form_event_selector.jpg

Hier wählst du das hinzuzufügende Ereignis aus. Bei manchen erscheint ein weiteres Menü, mit zusätzlichen Auswahlmöglichkeiten. Hier folgt eine Beschreibung der unterschiedlichen Ereignisse (Erinnere dich daran, dass man üblicherweise nur einige wenige verwendet).

create Create event
Dieses Ereignis wird ausgelöst, wenn eine Instanz eines Objektes erzeugt wird. Gewöhnlich verwendet man es, um die Instanz in Bewegung zu setzen oder bestimmte Variablen der Instanz zu festzulegen.

destroy Destroy event
Es wird ausgelöst, wenn die Instanz zerstört wird. Um genau zu sein - kurz vorher. Was bedeutet, dass die Instanz noch existiert, wenn das Ereignis ausgeführt wird! Die meiste Zeit über wird dieses Ereignis nicht verwendet aber man kann es beispielsweise nutzen, um den "score" (Punktestand) zu ändern oder ein anderes Objekt zu erschaffen.

timer Alarm events
Jede Instanz besitzt 12 Alarmuhren. Du kannst diese Alarmuhren durch verschiedene Aktionen einstellen (siehe nächstes Kapitel). Die Alarmuhr tickt dann runter bis sie 0 erreicht und in diesem Moment das "alarm event" auslöst. Um die Aktionen für eine Alarmuhr anzuzeigen, musst du sie zuerst im Menü anwählen. "alarm clocks" sind sehr nützlich. Du kannst sie verwenden, um gewisse Dinge von Zeit zu Zeit geschehen zu lassen. Beispielsweise kann ein Monster seine Bewegungsrichtung alle 20 "steps" ändern (in so einem Fall muss eine Aktion innerhalb des Ereignises die Alarmuhr wieder neu stellen).

step Step events
Das "step event" wird bei jedem "step" (Schritt) des Spiels ausgelöst. Hier kannst du Aktionen platzieren, die kontinuierlich ausgeführt werden müssen. Beispielsweise wenn ein Objekt einem anderen folgen soll, kannst du hier die Bewegungsrichtung des Verfolgers angleichen. Sei trotzdem vorsichtig mit diesem Ereignis. Packe nicht zu viele komplizierte Aktionen in die "step events" von Objekten, von welchen viele Instanzen vorhanden sind. Das könnte das Spiel verlangsamen. Um genau zu sein - es gibt drei verschiedene "step events". Normalerweise braucht man nur das voreingestellte. Aber mittels des Menüs kann man auch die Anderen verwenden ("begin step" (Schrittanfang) und "end step" (Schrittende)). Das "begin step"-Ereignis wird am Anfang eines Schrittes ausgelöst, bevor andere Ereignisse auftreten. Das voreingestellte/normale "step event" wird ausgelöst, kurz bevor die Instanzen auf ihre neuen Positionen gesetzt werden. Das "end step"-Ereignis wird am Endes eines Schrittes ausgelöst, kurz bevor gezeichnet wird. Es wird üblicherweise benutzt, um beispielsweise das "sprite" in Abhängigkeit von der Bewegungsrichtung zu ändern.

collision Collision events
Wann immer zwei Instanzen kollidieren (das geschieht, wenn ihre "sprites" überlappen), wird ein "collision event" ausgelöst. Genauer zwei - eins pro Instanz. Die Instanz kann auf dieses Ereignis reagieren. Wähle im Menü aus, bei welchem Objekt du ein Kollisionsereignis definieren willst. Danach platziere hier weitere Aktionen.

Es gibt Unterschiede was passiert, wenn Instanzen mit soliden bzw. nicht-"soliden" Objekten kollidieren. Zuerst einmal, wenn keine Aktionen im Kollisionsereignis definiert sind, passiert nichts. Die Instanz bewegt sich einfach weiter, auch wenn das andere Objekt "solid" ist. Wenn das Kollisionsereignis Aktionen enthält geschieht folgendes:

Wenn das andere Objekt "solid" ist, wird die an ihre vorherige Position Instanz  (vor der Kollision) zurückgesetzt. Dann erst wird das Ereignis ausgelöst. Anschliessend wird die Instanz an die neue Position bewegt. Wenn das Ereignis beispielsweise die Bewegungsrichtung umkehrt, prallt die Instanz gegen die Wand, ohne anzuhalten. Wenn dann immer noch eine Kollision vorliegt, wird die Instanz an der vorherigen Stelle gehalten. Sie hält effektiv an.

Wenn das andere Objekt nicht "solid" ist, wird die Instanz nicht zurückgesetzt. Das Ereignis wird einfach ausgelöst mit der Instanz an der aktuellen Position. Auch gibt es keine 2. Kollissionsabfrage. Wenn du darüber nachdenkst, ist es die logische Konsequenz, die eintreten sollte. Weil das andere Objekt ja nicht "solid" ist, kann es einfach durchquert werden. Das Ereignis informiert dich also darüber, dass dieses gerade geschehen ist.

Es gibt viele Anwendungsmöglichkeiten für das "collision event". Instanzen können es verwenden, um von Wänden abzuprallen. Du kannst es einsetzen, um Objekte zu vernichten, wenn sie z. B. von einer Kugel getroffen werden - und so weiter.

keyboard Keyboard events
Wenn der Spieler eine Taste drückt, wird ein Tastaturereignis für alle Instanzen aller Objekte ausgelöst. Für jede Taste ein anderes Ereignis. Im Menü kannst du die Taste bestimmen, für die du ein Tastaturereignis festlegen willst und anschliessend die Aktionen hinüberziehen. Klar ausgedrückt brauchen nur wenige Objekte solche Ereignisse für wenige Tasten. Ein Ereignis wird in jedem Schritt (step) erzeugt, solange der Spieler die Taste drückt. Es gibt zwei besondere Tastaturereignisse. Eines heißt <No key> (keine Taste). Es wird in jedem Schritt erzeugt, falls keine Taste gedrückt ist. Der zweite ist <Any key> (jede Taste) awas bei beliebigem Tastendruck ausgelöst wird. Wenn der Spieler mehrere Tasten drückt, wird für jede Taste ein Ereignis ausgelöst. Beachte, dass die Ereignisse des Ziffernblocks nur die korrespondierenden sind, wenn <NumLock> aktiviert ist.

mouse Mouse events
Ein "mouse event" wird immer dann für eine Instanz ausgelöst, wenn der Mauszeiger innerhalb dessen Sprite positioniert ist. Abhängig von der Maustaste erhälst du ein "no button"(keine Taste), ein "left button"(linke Maustaste), ein "right button"(rechte Maustaste) oder ein "middle button"(mittlere Maustaste) Ereignis. Die Ereignisse werden in jedem Schritt erzeugt, solange der Spieler die Taste drückt. Die "press events" (Taste drücken) werden nur einmal beim Herunterdrücken der Taste erzeugt. Die "release events" (Taste loslassen) nur beim Loslassen der Taste. Beachte, dass diese Ereignisse nur auftreten, wenn der Mauszeiger über der Instanz ist. Wenn diese Ereignisse für beliebige Mauspostionen gelten sollen, verwende die globalen "press/release" Ereignisse stattdessen. Es gibt zwei besondere Mausereignisse. Das "mouse enter" (Beginn der Überdeckung) Ereignis und das "mouse leave" (Verlassen der Überdeckung) Ereignis. Ersteres wird beim "Berühren" der Instanz ausgelöst, letzteres, wenn der Mauszeiger die Zone über der Instanz verlässt. Diese Ereigisse werden üblicherweise genutzt, um das Sprite zu ändern oder einen SFX zu erzeugen. Mouse wheel up und Mouse wheel down Events werden ausgeführt, wenn der Benutzer das Mausrad dreht. Schliesslich gibts noch Ereignisse für Steuerknüppel (Joysticks). Du kannst Aktionen für die 4 Richtungen angeben (diagonal werden beide Ereignisse ausgelöst). Bis zu 8 Knöpfe können verwaltet werden. Du kannst all das für 2 Spielgeräte verwenden (1. und 2. Steuerknüppel).

other Other events
Es gibt eine Anzahl anderer Ereignisse, welche in bestimmten Spielen nützlich sind. Man findet sie in diesem Menü. Folgende Ereignisse können hier gefunden werden:

  • Outside: Dieses Ereignis wird ausgelöst, wenn die Instanz komplett ausserhalb des Raumes liegt. Typischerweise ein guter Moment, sie zu vernichten.
  • Boundary: Dieses Ereignis wird ausgelöst, wenn die Instanz die Grenze des Raumes berührt.
  • Game start: Dieses Ereignis wird für alle Instanzen des ersten Raumes ausgelöst, wenn das Spiel beginnt. Es wird vor dem "room start event" (siehe unten) aber nach dem "creation event" für die Instanzen innerhalb des Raumes. Es wird typischerweise nur in einem "Steuerungsobjekt" verwendet, um Hintergrundmusik zu starten oder Variablen zu initialisieren oder ein paar Daten zu laden.
  • Game end: Dieses Ereignis wird für alle Instanzen am Ende des Spiels ausgelöst. Auch dieses wird in einem Objekt verwendet. Es wird verwendet, um beispielsweise Spieldaten zu speichern.
  • Room start: Dieses Ereignis wird am Anfang eines Raumes für alle Instanzen ausgelöst. Es geschieht nach den "creation events".
  • Room end: Wird für alle existierenden Instanzen am Ende des Raumes ausgelöst.
  • No more lives: Game Maker hat ein eingebautes Lebenssystem. Es gibt eine Aktion um die Anzahl der "lives" ("Leben"), zu setzen und zu verändern. Wann immer dieser Wert auf 0 sinkt (oder tiefer), wird dieses Ereignis ausgelöst. Es wird benutzt, um das Spiel zu beenden oder neu zu starten.
  • No more health: Game Maker hat ein eingebautes Lebensenergie. Es gibt eine "action", um diesen Wert zu setzen und zu verändern. Wann immer dieser Wert auf 0 oder weniger sinkt, wird dieses Ereignis ausgelöst. Es wird normalerweise verwendet. um die Anzahl der "lives " zu reduzieren oder das Spiel zu neu zu starten.
  • End of animation: Wie oben erwähnt, besteht eine Animation aus einer Anzahl Einzelbilder, welche nacheinander angezeigt werden. Wenn das Letzte angezeigt wurde beginnt es wieder von vorne. Das Ereignis wird genau hier ausgelöst. Es kann verwendet werden, um die Animation zu ändern oder die Instanz zu vernichten.
  • End of path: Dieses Ereignis wird ausgelöst, wenn die Instanz einem Pfad (path) folgt und an dessen Ende angelangt.
  • User defined: Es gibt 16 dieser Ereignisse. Sie werden normalerweise nie ausgelöst, solange du sie nicht via Programmcode auslöst.

draw Drawing event
Instanzen, wenn sie sichtbar sind, zeichnen ihr Sprite in jedem "step" auf den Bildschirm. Wenn du Aktionen im "drawing event" definierst, wird das sprite nicht gezeichnet aber stattdessen die Aktionen ausgeführt. Das kann verwendet werden, um etwas anderes, als das Sprite zu zeichnen oder erst die Parameter des Sprite zu ändern. Es gibt eine Anzahl von "drawing actions" welche extra für das "drawing event" bestimmt sind. Beachte, dass das "drawing event" nur ausgelöst wird, wenn das Objekt sichtbar ist. Beachte auch, das unabhängig von dem was du darstellst, Kollisionsereignisse auf dem zugehörigen Sprite basieren.

keypress Key press events
Dieses Ereignis ist dem Tastaturereignis ähnlich. Es wird ausgelöst beim Runterdrücken der Taste anstatt permanent bei Tastendruck. Es ist nützlich, wenn du nur einmal etwas bei Tastendruck geschehen lassen willst.

keyrelease Key release events
Dieses Ereignis ist dem Tastaturereignis ähnlich. Es wird ausgelöst beim Loslassen der Taste anstatt permanent bei Tastendruck.

In manchen Situationen ist es wichtig zu wissen, wie der Game Maker Ereignisse verarbeitet. Dies läuft so ab:

  • Begin step events
  • Alarm events
  • Keyboard, Key press, and Key release events
  • Mouse events
  • Normal step events
  • (nun werden alle Instanzen an ihre Positionen gesetzt)
  • Collision events
  • End step events
  • Drawing events

Die creation, destroy und anderen Ereignisse werden ausgelöst, wenn die korrespondierenden Umstände eintreten.

Aktionen

Aktionen beschreiben Dinge, die in einem Game Maker - Spiel passieren. Sie werden in Ereignissen von Objekten platziert. Immer, wenn das Ereignis stattfindet, werden sie ausgeführt, was ein bestimmtes Verhalten für Instanzen des Objekts hervorruft. Es gibt viele verschiedene Aktionen und es ist wichtig, dass du verstehst was sie tun. In diesem Kapitel werde ich die Standard-Aktionen beschreiben. Beachte das einige Aktionen nur in der registrierten Version des Game Maker genutzt werden können. Dies wird angemerkt.

Alle Aktionen kannst du in den Registern rechts im "object property"-Fenster finden. Es gibt sechs Sets. Wenn du den Cursor über eine Aktion hältst, erscheint eine kurze Beschreibung.

Ich wiederhole kurz: Um eine Aktion in ein Ereignis einzufügen, ziehe es einfach von der rechten Seite in die Aktionsliste. Du kannst die Reihenfolge der Aktionen in der Liste verändern - einfach wieder ziehen. Hältst du dabei die <Alt> Taste gedrückt, wird die Aktion kopiert. (Du kannst auch Aktionen zwischen Listen in verschiedenen Objektfenster ziehen.) Verwende die rechte Maustaste um Aktionen zu löschen (oder benutze die <Entf> Taste), kopieren oder einzufügen.

Wenn du eine Aktion in die Liste ziehst, öffnet sich ein Fenster (jedenfalls meistens), in dem bestimmte Parameter für die Aktion einstellen kannst. Die Parameter werden weiter unten, in den Aktionsbeschreibungen erklärt. Zwei Typen von Parametern kommen in vielen Aktionen vor, deswegen werde ich sie hier beschreiben. Oben kannst du angeben, zu welcher Instanz die Aktion gehören soll. Der Standard ist self, was die eigene Instanz ist. Meistens ist es das was du willst. Im Fall eines "collision event" kannst du hier auch die andere ("other") Instanz die an der Kollision beteiligt ist angeben. So kannst du z.B. die andere Instanz zerstören. Oder du kannst die Aktion für alle Instanzen eines bestimmten Objekts ausführen lassen. So kannst du z.B. roten Bälle in blaue Bälle verwandeln. Der zweite Parameter ist die Box Relative. Wenn du diese Box anwählst, sind die Werte, die du angibst, relativ zu den aktuellen Werten. Zum Beispiel kannst du so zur Punktzahl etwas dazu zählen, statt sie direkt zu verändern. Andere Parameter werden unten beschreiben. Du kannst Parameter später ändern, wenn du auf die Aktion doppelklickst.

Auf folgenden Seiten können Informationen über die verschiedenen Aktionen gefunden werden:

Aktionsset "Move"
Aktionsset "Main 1"
Aktionsset "Main 2"
Aktionsset "Control"
Aktionsset "Score"
Aktionsset "Draw"
Ausdrücke und Variablen verwenden

Aktionsset Move

Das erste Set besteht aus Aktionen, die die Bewegung beeinflussen. Die folgenden Aktionen gibt es hierfür:

move1 Start moving in a direction
Verwende diese Aktion, um die Instanz in eine bestimmte Richtung zu bewegen. Du kannst diese Richtung mit den Pfeilknöpfen bestimmen. Verwende den mittleren Knopf, um die Bewegung zu stoppen. Du musst auch die Geschwindigkeit (in Pixel pro Schritt) angeben. Der Standardwert ist 8. Verwende besser keine negativen Geschwindigkeiten. Wenn du mehrere Richtungen angibst, wird die Richtung zufällig gewählt. So kannst du z.B. ein Monster entweder nach rechts oder links starten lassen.

move2 Set direction and speed of motion
Das ist der zweite Art, eine Bewegung festzulegen. Hier kannst du eine genaue Richtung angeben. Das ist ein Winkel zwischen 0° und 360°. 0 ist nach rechts, die Richtung ist gegen den Uhrzeigersinn (90 ist daher nach oben). Wenn du eine zufällige Richtung willst, kannst du random(360) eingeben. Wie du noch sehen wirst, gibt die Funktion random eine zufällige Zahl kleiner als die Angegebene zurück. Wie du vielleicht bemerkt hast, gibt es auch noch eine Relative Box. Wenn du einen Haken hinein machst, wird die neue Bewegung zur alten dazu addiert. Zum Beispiel, wenn sich die Instanz nach oben bewegst und du addierst eine Bewegung nach links, bewegt sich die Instanz nun diagonal nach links oben.

movepoint Move towards a point
Diese Aktion ist noch eine Möglichkeit, eine Bewegung festzulegen. Du gibst die Position und eine Geschwindigkeit an und die Instanz bewegt sich auf den Punkt zu (Sie stoppt nicht auf dem Punkt!). Wenn du z.B. ein Geschoss auf das Raumschiff zu bewegen lassen willst, kannst du als Position Raumschiff.x, Raumschiff.y nutzen. (Du wirst später noch mehr über die Benutzung solcher Variablen lernen) Wenn du die Relative Box verwendest, wird die Position relativ zu der der aktuellen Instanz genommen (die Geschwindigkeit nicht!).

hspeed Set the horizontal speed
Die Geschwindigkeit einer Instanz besteht aus einem horizontalen und einem vertikalen Teil. Mit dieser Aktion kannst du die horizontale Geschwindigkeit ändern. (Die vertikale bleibt gleich.) Eine positive horizontale Geschwindigkeit ist eine Bewegung nach rechts, eine negative nach links. Verwende "Relative" um die horizontale Geschwindigkeit zu erhöhen (oder mit einer negativen Zahl zu vermindern).

vspeed Set the vertical speed
Wie oben, nur mit der vertikalen Geschwindigkeit.

gravity Set the gravity
Mit dieser Aktion kannst du die Anziehungskraft eines bestimmten Objektes erstellen. Du gibst die Richtung (Winkel zwischen 0 und 360 Grad) und die Geschwindigkeit ein, und in jedem Schritt wird die Anzahl der Geschwindigkeit in der gegebenen Richtung zu Bewegung der Objektinstanz hinzugefügt. Normal benötigst du eine kleine Geschwindigkeitssteigung (wie 0.01). Eine Bewegung nach unten ist typisch (270 Grad). Wenn du die Relative aktivierst, erhöhst du die Geschwindigkeit der Anziehungskraft in diese die Richtung. Bedenke, dass entgegen dem wirklichen Leben, verschiedene Objekte verschiedene Richtungen der Anziehungskräfte haben können.

hreverse Reverse horizontal direction
Mit dieser Aktion kannst du die horizontale Bewegung der Instanz umkehren. Verwende diese Aktion um z. B. ein Objekt, welches mit einer Wand kollidiert, umzukehren.

vreverse Reverse vertical direction
Mit dieser Aktion kannst du die vertikale Bewegung der Instanz umkehren. Verwende diese Aktion um z. B. ein Objekt, welches mit einer Wand kollidiert, umzukehren.

friction Set the friction
Reibung verlangsamt die Instanz bei der Bewegung. Du gibst die Menge der Reibung ein. In jedem Schritt wird diese Menge von der Geschwindigkeit abgezogen, bis die Geschwindigkeit bei 0 ist. Normal brauchst du hier eine sehr kleine Zahl (wie 0.01).´

jumpposition Jump to a given position
Mit dieser Aktion kannst du Instanzen an eine bestimmte Position platzieren. Du gibst einfach die x- und y-Koordinate an, und die Instanz wird mit seinem Referenzpunkt an die Position gesetzt. Wenn du die Relative Box aktivierst, ist die Position relativ zur aktuellen Position der Instanz. Diese Aktion wird oft benutzt um eine Instanz kontinuierlich zu bewegen. In jedem Schritt wird die Position ein bisschen gesteigert.

jumpstart Jump to the start position
Diese Aktion platziert die Instanz zurück an die Position, an der sie erstellt wurde.

jumprandom Jump to a random position
Diese Aktion bewegt die Instanz auf eine zufällige Position im Raum. Es werden nur Positionen  gewählt, an denen die Instanz keine solide Instanz überschneidet. Du kannst angeben, ob das Einrasten genützt wird. Wenn du positive Zahlen wählst, werden die gewählten Koordinaten mit ganzen Zahlen des gewählten Wertes multipliziert. Das kann benutzt werden, um Instanzen an einem Raster auszurichten. Du kannst den horizontalen und vertikalen Gitterabstand getrennt eingeben.

grid Snap to grid
Mit dieser Aktion kannst du die Position der Instanz an einem Raster ausrichten. Damit wird die Instanz in der nähesten Zelle eingerastet. Du kannst den horizontalen und vertikalen Gitterabstand getrennt eingeben. Das kann sehr nützlich sein.

wrap Wrap when moving outside
Mit dieser Aktion kannst du eine Instanz "wandern" lassen, das heißt, wenn sie den Raum auf der einen Seite verlässt kommt sie wieder auf der Anderen herein. Diese Aktion wird normalerweise im Outside Event genutzt. Beachte, das die Instanz dafür eine Geschwindigkeit bestitzen muss, weil das "Wandern" auf der Richtung der Geschwindigkeit basiert. Du kannst angeben, ob nur horizontal, vertikal, oder in beide Richtungen gearbeitet werden soll.

contact Move to contact position
Mit dieser Aktion kannst du die Instanz in eine gegebene Richtung bewegen, bis das Objekt eine Kontaktposition erreicht. Wenn bereits eine Kollision an der aktuellen Position, wird die Instanz nicht bewegt. Sonst wird die Instanz kurz bevor die Kollision passiert gesetzt. Du kannst die Richtung angeben, aber auch eine maximale Distanz bis sie mit einem Objekt zusammenstösst. Beispielsweise, wenn die Instanz fällt, kannst du die maximale Distanz nach unten bewegen, bis das Objekt erreicht ist. Du kannst auch angeben ob nur solide Objekte oder alle Objekte berücksichtigt werden. Typischerweise wird diese Aktion in collisions event eingegeben um sicherzugehen, dass das Objekt hält wenn es mit einer anderen Instanz in einer Kollision verwickelt ist.

bounce Bounce against objects
Wenn du diese Aktion im collision event mit irgendeinem Objekt gibst, prallt die Instanz von diesem Objekt in einem natürlichen Weg zurück. Wenn du den Parameter precise auf false setzt werden nur horizontale und vertikale Wände werden korrekt behandelt. Wenn du presice auf true setzt werden auch schräge (und auch kurvige) Wände zufriedenstellend behandelt. Das ist aber langsamer. Ausserdem kannst du angeben, ob nur gegen solide oder gegen alle Objekte abgeprallt wird. Bitte bedenke, dass das Abprallen nicht ganz korrekt ist, da es von vielen Eigenschaften abhängt. Aber in den meisten Situationen ist der Effekt gut genug.

Aktionsset Main 1

Die folgenden Aktionen behandeln das Erstellen, Ändern und Zerstören von Instanzen der Objekte und Benutzen von Sounds und Räumen.

create Create an instance of an object
Mit dieser Aktion kannst du eine Instanz eines Objektes erstellen. Du gibst an welches Objekt erstellt werden soll und die Position der neuen Instanz. Wenn du die Relative Box aktivierst wird die Position relativ zur Position der aktuellen Instanz gesetzt. Das Erstellen von Instanzen während eines Spieles ist extrem nützlich. Ein Raumschiff kann Schüsse erzeugen; eine Bombe kann Explosionen erstellen, usw. In vielen Spielen hast du ein Kontrollerobjekt, dass von Zeit zu Zeit Monster oder andere Objekte erstellt. Für die neu erstelle Instanz wird der creation event ausgeführt.

createspeed Create an instance of an object with a speed and direction
Diese Aktion funktioniert wie die Obere, hat aber noch 2 zusätzliche Felder. Du kannst auch die Geschwindigkeit und Richtung der neu erstellten Instanz angeben. Beachte das bei markierter Relative Box nur die Position, nicht die Richtung und Geschwindigkeit relativ ist. Um beispielsweise eine Kugel in die Schussrichtung der Person fliegen zu lassen muss ein kleiner Trick angewandt werden. Als Position gebe 0,0 an und markiere die Relative Box. Als Richtung benötigen wir die aktuelle Richtung der Instanz. Dies kann durch das Wort direction erreicht werden. (Dies ist eine Variable die immer die Richtung der aktuellen Instanz angibt.)

createrandom Create instance of random object
Diese Aktion erstellt eine Instanz eines aus 4 Objekten zufällig gewählten Objektes. Du gibst die vier Objekte und die Richtung an. Eine Instanz eines dieser vier Objekten wird an der angegebenen Position erstellt. Wenn du die Relative Box anwählst, ist die Position relativ zur Position des aktuellen Objektes. Wenn du weniger als vier Objekte angeben möchtest dann benutze "No Object" für einige Auswahlfelder. Dies ist z.B. nützlich um einen zufälligen Gegner zu erstellen.

change Change the instance
Mit dieser Aktion kannst du die aktuelle Instanz in eine Instanz eines anderen Objektes ändern. Du kannst z.B. die Instanz einer Bombe in eine Explosion ändern. Alle Einstellungen, wie die Bewegung und die Werte der Variablen, bleiben unverändert. Du kannst angeben ob der Destroy Event für das aktuelle Objekte und der creation Event für das neue Objekt ausgeführt wird.

destroy Destroy the instance
Mit dieser Aktion zerstörst du die aktuelle Instanz. Der Destroy Event wird für die Instanz ausgeführt.

killposition Destroy instances at a position
Mit dieser Aktion vernichtest du alle Instanzen, deren "bounding box" die angegebene Position enthält. Das ist z. b. nützlich wenn eine Bombe explodiert. Wenn du die Relative Box aktivierst wird die Position relativ zur aktuellen Position genommen.

sprite Change the sprite
Benutze diese Aktion, um das Sprite einer Instanz zu ändern. Du gibst das neue Sprite an. Du kannst auch das anzuzeigende Subimage bestimmen. Normalerweise würdest du dafür 0 verwenden (für das erste Subimage), sofern du kein bestimmtes anzeigen möchtest. Verwende -1, falls du nicht das aktuell gezeigte Subimage ändern möchtest. Schließlich kannst du die Geschwindigkeit der Animation ändern. Wenn du nur ein bestimmtes Subimage sehen möchtest, verwende die Geschwindigkeit 0. Ist die Geschwindigkeit höher als 1 werden ein paar Subimages übersprungen. Ist sie kleiner als 1 werden die Subimages länger angezeigt. Verwende keine negativen Geschwindigkeiten! Sprites zu verändern ist eine wichtige Funktion. Beispielsweise willst du oft das Sprite deiner Charaktere ändern, abhängig davon, in welche Richtung sie sich bewegt. Dies kann durch erstellen von verschiedenen Sprites erreicht werden, für alle (vier) Richtungen eines. In den "keyboard events" für die Pfeiltasten kannst du dann das Sprite ändern.

spritetransform Transform the sprite
Benutze diese Aktion, um die Größe und die Orientierung eines Sprites zu ändern. Nutze die Skalierungsfaktoren, um es größer oder kleiner zu machen. "angle" gibt die Orientierung des Sprites in Grad gegen den Uhrzeigersinn an. Z.B. kannst du das Sprite an der Bewegungsrichtung ausrichten, indem du direction verwendest. Dies kann für ein Auto nützlich sein. Du kannst auch angeben, ob das Sprite horizontal und/oder vertikal gespiegelt werden soll. Diese Aktion ist nur in der registrierten Version verfügbar.

spritecolor Set sprite blending
Normalerweise wird das Sprite so angezeigt, wie es ist. Mit dieser Aktion kannst du die Farbe eines Sprites ändern. Mit dieser Farbe wird das Sprite dann überblendet, d.h. sie wird mit den Farben des Sprites gemischt. Wenn du ein Sprite in verschiedenen Farben anzeigen möchtest, zeichne es besser in schwarz/weiß und benutze das Überblenden um die letztendliche Farbe zu bestimmen. Du kannst auch die Alpha-Transparenz festlegen. Bei einem Wert von 1 ist das Sprite komplett sichtbar, bei einem Wert von 0 komplett transparent. Bei einem Wert dazwischen scheint der Hintergrund durch. Dies ist ideal um Explosionen zu machen. Diese Aktion ist nur in der registrierten Version verfügbar.

sound Play a sound
Mit dieser Aktion kannst du eine Soundressource, die du deinem Spiel hinzugefügt hast, abspielen. Du kannst den gewünschten Sound angeben und ob er einmal (voreingestellt) oder in einer Schleife abgespielt wird. Nur eine Midi-Datei, aber mehrere Wave-Sounds können zur gleichen Zeit gespielt werden.

soundend Stop a sound
Diese Aktion stoppt den angegebenen Sound. Wenn mehrere Instanzen diesen Sound spielen, werden alle gestoppt.

ifsound If a sound is playing
Wenn der angegebene Sound gespielt wird, wird die nächste Aktion ausgeführt. Anderenfalls wird sie übersprungen. Du kannst Not auswählen um anzugeben dass die nächste Aktion ausgeführt wird, wenn der Sound nicht abgespielt wird. Beispielsweise kannst du prüfen, ob Hintergrundmusik abgespielt wird, wenn nicht starte eine Hintergrundmusik. Diese Aktion gibt true zurück nachdem der Sound abgespielt wird. Nachdem du die Aktion ausgeführt hast kommt der Sound aber nicht direkt an den Lautsprechern an, deswegen kann die Aktion vielleicht fälschlicherweise false zurückgeben. Dasselbe ist, wenn du einen Sound anhälst und der noch eine Weile spielt (z.B. wegen eines Echos) gibt die Aktion true zurück.

roomprevious Go to previous room
Geht zum vorherigen Raum. Du kannst den Typ des Übergangseffektes zwischen den Räumen auswählen. Am besten probierst du herum, um den schönsten für dich zu finden. Wenn du im ersten Raum bist, tritt ein Fehler auf.

roomnext Go to next room
Geht zum nächsten Raum. Du kannst den Übergangseffekt angeben.

roomcurrent Restart the current room
Der aktuelle Raum wird neu gestartet. Du kannst den Übergangseffektes angeben.

roomother Go to a different room
Mit dieser Aktion kannst du zu einem bestimmten Raum gehen. Gibt den Raum und den Typ des Übergangseffektes an.

ifroomprevious If previous room exists
Diese Aktion testet ob der vorherige Raum vorhanden ist. Wenn vorhanden, wird die nächste Aktion ausgeführt. Normal wird dies benutzt, bevor du zum vorherigen Raum wechselst.

ifroomnext If next room exists
Diese Aktion testet ob der nächste Raum vorhanden ist. Wenn vorhanden, wird die nächste Aktion ausgeführt. Normal wird dies benutzt, bevor du zum nächsten Raum wechselst.

Aktionsset Main 2

Hier sind mehr Hauptaktionen. Sie behandeln Timing, Nachrichten an den Benutzer und den Umgang mit dem Spiel als Ganzen.

alarm Set an alarm clock
Mit dieser Aktion kannst du zwölf Alarmuhren für die Instanz setzen. Du gibst die Anzahl der Schritte und die Alarmuhr an. Wenn die angegeben Anzahl der Schritte erreicht ist, bekommt die Instanz das entsprechende Alarm Event. Du kannst auch durch ankreuzen der Relative Box den Wert erhöhen oder vermindern. Wenn du eine Alarmuhr auf einen Wert kleiner als 0 setzt, schaltet du sie ab und es wird kein Event wird erstellt.

sleep Sleep for a while
Mit dieser Aktion kannst du das Spiel eine gewisse Zeit einfrieren. Das wird typischerweise beim Start oder Ende eines Levels verwendet oder wenn du dem Spieler eine Nachricht gibst. Du gibst die Millisekunden zum Schlafen an. Ausserdem kannst du angeben, ob der Bildschirm vorher neu gezeichnet werden soll, um die neuste Situation wiederzugeben.

info Display a message
Mit dieser Aktion kannst du eine Nachricht in einer Dialogbox anzeigen lassen. Du gibst einfach die Nachricht ein. Wenn du ein # Symbol im Nachrichtentext eingibst, wird es als neue Zeile interpretiert. (Benutze \# um das # Symbol zu erhalten.) Wenn der Nachrichtentext mit einem Anführungszeichen beginnt, wird es als Ausdruck interpretiert. Siehe Unten für nähere Informationen über Ausdrücke.

help Show the game information
Mit dieser Aktion öffnet sich das Spielinformationsfenster.

gamerestart Restart the game
Mit dieser Aktion startest du das Spiel wieder von Anfang an.

gameend End the game
Mit dieser Aktion beendest du das Spiel.

gamesave Save the game
Mit dieser Aktion kannst du den aktuellen Spielstatus speichern. Du gibst den Dateinamen für das Speichern an (die Datei wird im Arbeitsverzeichnis des Spieles erstellt). Später kann das Spiel mit der folgenden Aktion geladen werden. (Beachte bitte, das nur der einfache Spielzustand gespeichert wird. Dinge, die nicht gespeichert werden, sind z.B. der aktuell gespielte Sound und fortgeschrittenere Konstrukte, wie der Inhalt von Datenstrukturen, Partikel usw.)

gameload Load the game
Lädt den Spielstatus aus einer Datei. Du gibst den Dateinamen an. Gehe sicher dass dieses gespeicherte Spiel für das gleiche Spiel ist und mit der gleichen Version vom Game Maker erstellt wurde. Sonst gibt es eine Fehlermeldung. (Um genau zu sein, das Spiel wird am Ende des aktuellen Schrittes geladen. So werden einige Aktionen nach diesem noch im aktuellen Spiel ausgeführt, aber nicht das geladene!)

Aktionsset Control

Es gibt eine Anzahl von Aktion mit welchen du kontrollieren kannst, welche andere Aktionen ausgeführt wurden. Die meisten dieser Aktionen sind Fragen, z. B. ob eine Position leer ist. Wenn die Antwort ja (true) ist, wird die nächste Aktion ausgeführt, sonst wird sie übersprungen. Wenn du mehrere Aktionen ausführen oder überspringen willst, kannst du sie in einen Start und End Block integrieren. Sie können auch Teil eines Else Teiles sein welcher ausgeführt wird wenn die Antwort no ist. So eine typische Frage sieht so aus:

/library/manual/images/form_control_actions.jpg

Hier wird gefragt ob die Position der aktuellen Instanz kollissionsfrei ist. Wenn dies so ist beginnt die Instanz sich in die angegebene Richtung zu bewegen. Wenn nicht springt die Instanz zu einer angegebenen Position.

Für alle Frage gibt es das Feld NOT. Wenn du es aktivierst, wird das Resultat der Frage umgedreht. Also, wenn das Resultat wahr ist wird es falsch und wenn es falsch war wird es wahr. Das erlaubt eine bestimmte Aktionen auszuführen, wenn die Antwort nicht wahr ist.

Für viele Fragen kannst du angeben, ob sie für alle Instanzen eines bestimmten Objektes gelten. In diesem Fall ist das Resultat nur wahr wenn es für alle Instanzen des Objektes wahr ist. Beispielsweise kannst du prüfen, ob alle Bälle rechts neben der Position kollissionsfrei sind.

Bedenke dass sie alle eine andere Form des Icons und einen andere Hintergrundfarbe haben um sie leicht von anderen Aktionen zu unterscheiden zu lassen.)

iffree If a position is collision free
Diese Frage gibt true zurück, wenn die aktuelle Instanz an der angegeben Position keine Kollision mit einem Objekt verursacht. Du kannst die Position entweder absolut oder relativ angeben. Du kannst auch angeben, ob nur solide Objekte oder alle Objekte in Betracht gezogen werden. Diese Aktion wird meistens verwendet, um zu prüfen ob die Instanz an eine bestimmte Position verschoben werden kann.

ifcollision If there is a collision at a position
Das ist die Umkehrung der vorhergehenden Aktion. Sie gibt true zurück falls eine Kollision stattfindet, wenn die aktuelle Instanz an die gegebene Position gesetzt wird (wieder, entweder nur solide oder alle Objekte).

ifobject If there is an object at a position
Diese Frage gibt true zurück, wenn die Instanz an der angegebenen Position eine Instanz des angegebenen Objektes trifft.

ifnumber If the number of instances is a value
Du gibst das Objekt und die Zahl an. Wenn die aktuelle Anzahl der Instanzen des Objektes gleich mit den Zahl ist gibt die Frage true zurück, sonst false. Du kannst angeben, ob überprüft werden soll, ob die Anzahl der Instanzen größer oder kleiner der angegebenen Zahl ist. Häufig wird so eine Frage am Ende eines Levels oder Spieles gestellt.

ifdice With a change perform next action
Du kannst eine Zahl angeben. Es ist wie bei einem Würfel, bei dem du die Zahl der Seiten bestimmen kannst. Wenn die Zahl gewürfelt wird ist das Resultat ist wahr und die nächste Aktion wird ausgeführt. Das kann verwendet werden, um einen Zufallsmechanismus ins Spiel einzubauen. Beispielsweise, kannst du in jedem Schritt eine bestimmte Chance einbauen, dass die Bombe explodiert oder die Richtung ändert. Je grösser die Zahl, desto geringer die Wahrscheinlichkeit. Du kannst auch reelle Zahlen verwenden. Beispielsweise wenn du die Zahl auf 1.5 setzt, wird die Aktion in zwei von drei Fällen ausgeführt. Eine Zahl unter 1 macht keinen Sinn.

ifquestion If the user answers yes to a question
Du stellst eine Frage. Eine Dialog wird dem Spieler mit einem yes und einem no Button gezeigt. Das Resultat ist true, wenn der Spieler yes antwortet.

if If an expression is true
Das ist die allgemeinste Frage-Aktion. Du kannst einen willkürlichen Ausdruck eingeben. Wenn der Ausdruck wahr ist (der Wert entweder True oder <=0.5 ist), wird die nächste Aktion ausgeführt. Siehe unten für nähere Informationen über Ausdrücke.

ifmouse If a mouse button is pressed
Gibt true zurück, wenn die angegebene Maustaste gedrückt wird. Wird normalerweise im step event benutzt. Du kannst angeben, ob eine Maustaste gedrückt ist, und so z. B. die Position ändern (benutze den jump to a point Aktion mit den Werten mouse_x und mouse_y).

ifgrid If instance is aligned with grid
Gibt wahr zurück, wenn die Position der Instanz im Raster liegt. Du kannst die horizontale und vertikale Größe des Rasters angeben. Das ist nützlich, wenn bestimmte Aktionen, wie eine Drehung machen, nur erlaubt sind wenn die Instanz an einer bestimmten Rasterposition ist.

begin Start of block
Gibt den Beginn des Blockes von Aktionen an.

end End of block
Gibt das Ende des Blockes von Aktionen an.

else Else
Nach dieser Aktion folgt der else Teil, der ausgeführt wird wenn das Resultat der Frage false ist.

repeat Repeat next action
Diese Aktion wird benutzt, um die nächste Aktion (oder Block von Aktionen) einige Male wiederholen zu lassen. Du gibst einfach die Anzahl der Wiederholungen an.

exit Exit the current event
Wenn diese Aktion zutrifft, wird keine Aktion im Event mehr ausgeführt. Typischerweise benutzt du das nach einer Frage. Beispielsweise, wenn eine Position frei ist wird nichts mehr zu tun sein und der Event wird beendet. In diesem Beispiel werden die folgenden Aktion nur ausgeführt, wenn eine Kollision stattfindet.

Wenn du mehr Kontrolle über das Geschehen in deinem Spiel haben möchtest kannst du die eingebaute Programmiersprache benutzen, auf sie wird im 4. Teil der Dokumentation eingegangen. Sie ermöglicht mehr Flexibilität als die Aktionen. Einfacher zu Benutzen aber trotzdem wichtig sind die Aktionen, die Variablen verarbeiten. Die folgenden Aktionen gibt es hierfür.

code Execute a piece of code
Wenn du diese Aktion hinzufügst, erscheint ein Fenster, in welchem du deinen Code eingeben kannst. Die können simple Aufrufe bis hin zu komplizierten Algorithmen sein. Benutze die Code-Stücke nur für kleine Mengen Code. Für längere Stücke werden Skripte empfohlen, auf die in Teil 2 der Dokumentation eingegangen wird.

comment Comment
Benutze diese Aktion um eine Kommentarzeile in deiner Aktionsliste hinzuzufügen. Die Zeile wird in der Schriftart Italic gezeigt. Es hat keine Funktion, ist aber trotzdem noch eine Aktion. Deshalb setze sie nicht direkt nach Fragen. Das Hinzufügen von Kommentaren hilft dir dich zu erinnern was im Event geschieht.

variable Set the value of a variable
Es gibt viele eingebaute Variablen im Spiel. Mit dieser Aktion kannst du diese verändern. Ausserdem kannst du deine eigenen Variablen erstellen und ihnen einen Wert zuteilen. Du gibst den namen der Variablen und den neuen Wert an. Wenn du die Relative aktivierst, wird der Wert zum aktuellen Wert der Variable hinzugezählt. Bitte bedenke dass das nur möglich ist, wenn die Variable ein Wert zugeteilt wurde. Siehe unten für nähere Informationen.

ifvariable If a variable has a value
Mit dieser Aktion kannst du überprüfen, was der Wert einer bestimmten Variable ist. Wenn der Wert der Variablen gleich der angegeben Nummer ist, gibt die Frage true zurück. Andererseits gibt sie false zurück. Du kannst auch angegeben, ob überprüft werden soll ob die der Wert kleiner als der angegeben Wert oder grösser als der angegebenen Wert ist. Siehe unten für nähere Informationen über Variablen. Du kannst diese Aktion auch für den Vergleich von zwei Ausdrücke verwenden.

drawvariable Draw the value of a variable
Mit diese Aktion kannst du den Wert einer Variable an einer bestimmten Position am Bildschirm zeichnen. Beachte, das dies nur im draw event funktioniert.

Aktionsset Score

In den meisten Spieler hat der Spieler einen bestimmte Punktestand. Auch geben viele Spiele dem Spieler eine Zahl von Leben. Zuletzt haben Spieler eine bestimmte Gesundheit. Die folgenden Aktion machen es einfach mit Punkten, Leben und Gesundheit des Spielers zu arbeiten.

score Set the score
Game Maker hat einen eingebauten Punktemechanismus. Der Punktestand wird normal in der Titelleiste gezeigt. Du kannst diese Aktion verwenden um den Punktestand zu verändern. Oft willst du etwas zum Punktestand hinzufügen, in diesem Fall aktiviere die Relative Box.

ifscore If score has a value
Mit dieser Frage-Aktion kannst do prüfen ob der Punktestand einen gewissen Wert erreicht hat. Du gibst den Wert an und ob der Punktestand gleich der Wert, kleiner dem Wert oder grösser dem Wert sein soll.

drawscore Draw the value of score
Mit dieser Aktion kannst du den Wert des Punktestandes an einer bestimmten Position am Bildschirm zeichnen. Du gibst die Position und die Überschrift an, welche vor dem Punktestand angegeben wird. Der Punktestand wird in der aktuellen Schriftart gezeichnet. Diese Aktion kann nur im draw event des Objektes genutzt werden.

highscore Display the highscore table
Für jedes Spiel werden die zehn besten Punktestände aufbewahrt. Diese Aktion zeigt die Highscore-Liste. Wenn der aktuelle Punktestand unter den besten Zehn ist, wird der neue Punktestand eingefügt und der Spieler kann seinen Namen eingeben. Du kannst das Hintergrundbild angeben, ob das Fenster einen Rand haben soll, die Farbe des neuen Eintrages und wie die alten Einträge sein sollen und welche Schriftart verwendet wird.

highscoreclear Clear the highscore table
Diese Aktion löscht die Highscore-Tabelle.

lives Set the number of lives
Game Maker hat auch ein eingebautes Leben-System. Mit dieser Aktion kannst du die Nummer der übrig gebliebenen Leben ändern. Normal setzt du den Wert beim Start auf eine Wert wie 3 und dann erhöhst oder senkst du die Anzahl der Leben, je nachdem was im Spiel geschieht. Vergiss nicht die Relative Box, wenn du Leben hinzufügen oder abziehen willst. Wenn die Anzahl der Leben 0 ist,(oder kleiner als 0) wird ein "no more lives" event erstellt.

iflives If lives is a value
Mit dieser Frage-Aktion kannst du prüfen ob die Anzahl der Leben einen gewissen Wert erreicht hat. Du gibst den Wert an, und ob die Anzahl der Leben gleich dem Wert, kleiner dem Wert oder grösser dem Wert sein soll.

drawlives Draw the number of lives
Mit dieser Aktion kannst du die Anzahl der Leben an einer bestimmten Position am Bildschirm zeichnen. Du gibst die Position und die Überschrift an, welche vor der Anzahl der Leben angegeben wird. Es wird in der aktuellen Schriftart gezeichnet. Diese Aktion kann nur im draw event des Objektes genutzt werden.

drawlivesimage Draw the lives as image
Statt die Anzahl der Leben als Zahlen zu zeichnen, ist es meisten schöner eine Anzahl von kleinen Bilder dafür zu benutzen. Diese Aktion macht genau das. Du gibst die Position und das Bild an und an der angegebenen Position werden die Anzahl der Leben als Bilder gezeichnet. Diese Aktion kann nur im draw event eines Objektes verwendet werden.

health Set the health
Game Maker hat auch ein eingebautes Gesundheits-System. Mit dieser Aktion kannst du die Gesundheit ändern. Ein Wert von 100 bedeutet volle Gesundheit und ein Wert von 0 keine Gesundheit. Du gibst einfach den neuen Wert der Gesundheit ein. Oft willst du einen Wert von der Gesundheit abziehen. In diesem Fall vergiss nicht die Relative Box zu aktivieren. Wenn die Gesundheit kleiner oder gleich 0 ist wird ein "out of health" Event erstellt.

ifhealth If health is a value
Mit dieser Frage-Aktion kannst du prüfen ob die Anzahl der Leben einen gewissen Wert erreicht hat. Du gibst den Wert an, und ob die Anzahl der Leben gleich dem Wert, kleiner dem Wert oder grösser dem Wert sein soll.

drawhealth Draw the health bar
Mit dieser Aktion kannst du die Gesundheit in Form eines Gesundheitsbalken anzeigen. Wenn die Gesundheit 100 ist, wird ein voller Balken gezeichnet. Du gibst die Position und die Größe der Gesundheitsbalken an, die Farbe des Balkens und den Hintergrund.

caption Set the window caption information
Normalerweise wird in der Titelleiste der Name des Raumes und der Punktestand angezeigt. Mit dieser Aktion kannst du das ändern. Du kannst angeben, ob der Punktestand, die Leben und / oder die Gesundheit gezeigt werden soll oder nicht und wie die Beschriftung für jeden davon lauten soll.

Aktionsset Draw

Normalerweise wird in jedem Schritt das Sprite jeder Instanz im Raum gezeichnet. Du kannst das ändern, indem du Aktionen in das draw event einfügst. (Beachte, das diese nur ausgeführt werden, wenn das Objekt sichtbar ist!) Die folgenden Zeichenaktionen gibt es. Diese Aktionen ergeben nur im draw event Sinn. An anderen Stellen werden sie prinzipiell ignoriert.

drawsprite Draw a sprite image
Du gibst das Sprite, die Position (entweder absolut oder relativ zur aktuellen Position) und das Subimage (die Subimages sind von 0 aufwärts durchnummeriert) des Sprites an. (Das Einzelbild ist ein Nummer von 0 aufwärts). Wenn du das aktuelle Einzelbild zeichnen willst, benutze -1.

drawbackground Draw a background image
Du gibst das Hintergrund-Bild, die Position (absolut oder relativ) und ob das Bild über den ganzen Raum gekachelt werden soll oder nicht.

drawtext Draw a text
Du gibst den Text und die Position an. Ein # Symbol im Text wird als neue Zeile interpretiert. (Benutze \# um das # Symbol selber zu erhalten.) So kannst du mehrzeilige Texte erstellen. Wenn der Text mit einem Anführungszeichen beginnt, wird es als Ausdruck interpretiert. Beispielsweise kannst du

'X: ' + string(x)

benutzen um den Wert der x-Koordinate der Instanz anzuzeigen. (Die Variable x speichert die aktuelle x-Koordinate. Die Funktion string() wandelt die Zahl in eine Zeichenkette um. + kombiniert die zwei Zeichenketten.)

drawtextext Draw a text transformed
Diese Aktion ist der vorherigen gleich, aber hier kannst du auch horizontale und vertikale Skalierung, um die Größe zu ändern, und die Rotation bestimmen. Diese Aktion ist nur in der registrierten Version verfügbar.

drawrectangle Draw a rectangle
Du gibst die Koordinaten der zwei gegenüberliegenden Ecken des Rechteckes an, absolut oder relativ zur aktuellen Position.

drawhorgradient Draw a horizontal gradient
Diese Aktion zeichnet auch ein Rechteck, aber diesmal mit Farbverlauf von links nach rechts. Du gibst das Rechteck und die zwei Farben an. Diese Aktion ist nur in der registrierten Version verfügbar.

drawvertgradient Draw a vertical gradient
Diese Aktion zeichnet auch ein Rechteck, aber diesmal mit Farbverlauf von oben nach unten. Du gibst . Diese Aktion ist nur in der registrierten Version verfügbar.

drawellipse Draw an ellipse
Diese Aktion zeichnet eine Ellipse. Du gibst die Koordinaten der zwei gegenüberliegenden Ecken des umliegenden Rechteckes an, absolut oder relativ zur aktuellen Position.

drawellipsegradient Draw a gradient ellipse
Wieder eine Ellipse, aber diesmal mit Farbverlauf von innen nach aussen. Diese Aktion ist nur in der registrierten Version verfügbar.

drawline Draw a line
Du gibst die Koordinaten der zwei Endpunkte der Linie an; absolut oder relativ zur aktuellen Position.

drawarrow Draw an arrow
Zeichnet einen Pfeil. Du gibst die Endpunkte der Pfeilgeraden und die Größe der Pfeilspitze an.

color Set the colors
Damit wird die Farbe gesetzt, sie wird benutzt um Rechtecke und Ellipsen zu füllen und für die Linien um das Rechteck und die Ellipse und wenn eine Linie gezeichnet wird. (beeinflusst nicht das Zeichnen von Sprites und Hintergründen)

fullscreen Change fullscreen mode
Mit dieser Aktion kannst du den Bildschirm-Modus von Fenster- zu Vollbildmodus und zurück verändern. Du gibst an, ob der Modus umgeschaltet wird, oder ob du zum Fenster- oder Vollbildschirmmodus gehst.

snapshot Take a snapshot image of the game
Mit dieser Aktion kannst du ein Bild des aktuellen Geschehens als .bmp Datei speichern. Du gibst den Dateinamen an. Diese Aktion ist nur in der registrierten Version verfügbar.

explosion Create an effect
Mit dieser Aktion kannst du alle möglichen Effekte sehr einfach realisieren. Du gibst den Effekttyp an, beispielsweise eine Explosion oder Rauch, seine Position, seine Größe und ob er unter oder über den Objekten angezeigt werden soll. Der Rest läuft automatisch ab. (Für Regen und Schnee ist die Position irrelevant weil beides über den gesamten Bildschirm fällt. Um kontiunierlich Regen zu bekommen muss er in jedem Step generiert werden.) Diese Aktion ist nur in der registrierten Version verfügbar

Ausdrücke und Variablen verwenden

In vielen Aktionen musst du Werte für Parameter angeben. Anstatt einfach eine Zahl anzugeben kannst du auch eine Formel nehmen, z. B. 32*12. Aber du kannst auch kompliziertere Ausdrücke verwenden. Wenn du die horizontale Geschwindigkeit verdoppeln willst, kannst du sie auf 2*hspeed setzen. Hier ist hspeed eine Variable die die aktuelle horizontale Geschwindigkeit der Variable angibt. Es gibt eine Vielzahl von anderen Variablen die benutzt werden können. Die wichtigsten sind diese hier:

x die x-Koordinate der Instanz
y die y-Koordinate der Instanz
hspeed die horizontale Geschwindigkeit (in Pixel pro Schritt)
vspeed die vertikale Geschwindigkeit (in Pixel pro Schritt)
direction die aktuelle Richtung der Bewegung in Grad (0-360)
speed die aktuelle Geschwindigkeit in dieser Richtung
visible ist das Objekt sichtbar (1) oder unsichtbar (0)
image_index ist die Variable, die zeigt, welches Subimage gerade gezeigt wird. Wenn du sie änderst und die Geschwindigkeit auf 0 setzt (siehe unten) kannst du ein bestimmtes Subimage permanent anzeigen.
image_speed diese Variable gibt die Geschwindigkeit an mit der die Einzelbilder gezeigt werden sollen. Der eingestellte Wert ist 1. Wenn du diesen Wert größer als 1 machst, werden manche Einzelbilder überspringen und die Animation wird schneller. Wenn du den Wert kleiner als 1 machst, wird die Animation langsamer.
score der aktuelle Wert der Punkte
lives die aktuelle Anzahl der Leben
health die aktuelle Gesundheit(0-100)
mouse_x x-Position der Maus
mouse_y y-Position der Maus
Du kannst die meisten diese Variablen durch Setzen von Aktion verändern. Du kannst auch eigene Variablen durch Setzten der Werte definieren (Benutze nicht Relative, da sie noch nicht existieren). Dann kannst du diese Variablen in Ausdrücken benutzen. Die Variablen die du erstellst sind lokal zu der aktuellen Instanz. Jedes Objekt hat eine Kopie davon. Um eine globale Variable zu erstellen, nimm das Wort global und einen Punkt vor der Variable.

Du kannst auch die Wert andere Variablen referenzieren, gibt den Objektname und eine Punkt vor ihn. Beispielsweise wenn du eine Ball zu einem Platz wo die Münze ist bewegen willst, kannst du die Position (coin.x , coin.y)setzten. Im Falle eines collision event kannst du dich auf die x-Koordinate des anderen Objekt mit other.x beziehen. In bedingten Ausdrücken (expressions) kannst du Vergleiche wie < (größer als), >, etc. verwenden.

In deinen Ausdrücken kannst du auch Funktionen verwenden. Die Funktion random(10) gibt eine zufällige ganze Nummer unter 10 aus. So kannst du z. B. die Geschwindigkeit oder Richtung der Bewegung einen zufälligen Wert geben. Es existieren noch viel mehr Funktionen. Für nähere Informationen über Ausdrücke und Funktionen siehe Teil 4 der Dokumentation.

Räume erstellen

Nachdem du die Objekte mit ihren Eigenschaften in den Ereignissen und Aktionen erzeugt hast, ist es Zeit einen Raum oder Level zu erstellen, wo das Spiel stattfindet. Jedes Spiel benötigt mindestens einen Raum. In diesen Räumen platzieren wir die Instanzen der Objekte. Wenn das Spiel gestartet ist wird der erste Raum gezeigt und die Instanzen darin werden lebendig, weil ihre Aktionen im Creation Event ausgeführt werden.

Beim Erstellen von Räumen ergeben sich viele Möglichkeiten. Neben einer Anzahl an Einstellungen und dem Hinzufügen von Objekten kannst du auch Hintergründe hinzufügen, Views definieren und Tiles bestimmen. Die meisten Möglichkeiten werden später noch besprochen. In diesem Kapitel besprechen wir nur die grundlegenden Dinge, das hinzufügen von Objekten und das einstellen eines Hintergrundes.

Um einen Raum zu erstellen wähle Add Room aus dem Add Menü. Der folgende Dialog erscheint:

/library/manual/images/form_room.jpg

Am oberen Rand gibt es eine Toolbar. Dort kannst du die Größe des Rasters angeben, mit dem du deine Objekte Positionieren kannst. Auch kannst du bestimmen, ob das Raster, die Hintergründe usw. angezeigt werden. Es ist manchmal sehr nützlich einiges im Raum auszublenden. (Beachte aber, dass wenn du Instanzen von Objekten hinzufügst, die Objekte im Raum, unabhängig von den Einstellungen, angezeigt werden.) Es gibt auch einen Knopf um alle Instanzen zu löschen und einen um alle Instanzen um eine bestimmten Pixelwert zu verschieben. Verwende negative Werte um nach links oder oben zu verschieben. Dies ist nützlich, wenn du entscheidest einen Raum zu vergrößern. (Du kannst das auch verwenden, um Instanzen ausserhalb des Raumes zu Positionieren, was manchmal nützlich sein kann.). Schließlich gibt es den Undo Knopf um die letzte Änderung zu widerrufen und den OK Knopf um die Änderungen zu speichern. (Klicke auf das Kreuz in der rechten oberen Ecke um ohne Äderungen zu schließen.)

Links siehst du drei Registerkarten (fünf im erweiterten Modus). Im Register objects erstellst du Instanzen von Objekten im Raum. Im Register settings änderst du einige Einstellungen des Raumes. Im Register backgrounds setzt du die Hintergrundbilder des Raumes.

Instanzen hinzufügen

Im rechten Bereich kannst du den Raum sehen. Am Anfang ist er leer und hat einen grauen Hintergrund.

/library/manual/images/form_room_objects.jpg

Füge deinem Raum Instanzen hinzu indem du den Register objects wählst. Danach wähle das gewünschte Objekt durch Kicken auf den Knopf mit dem Menü Icon (oder durch klicken in das Bild links). Das Bild des Objektes erscheint links (Bedenke, dass ein Kreuz im Bild ist. Das zeigt wie die Instanz im Raster ausgerichtet wird). Nun klicke mit der linken Maustaste in das Raumfeld rechts. Eine Instanz des Objektes erscheint. Es rastet im angegebenen Raster ein. Wenn die <Alt> Taste gedrückt wird, wird die Instanz nicht am Raster ausgerichtet. Mit der rechten Maustaste kannst du die Instanz entfernen. Dadurch gibst du den Inhalt des Raumes an. Wenn die Maustaste während des Verschiebens im Raum gedrückt bleibt, werden mehrere Instanzen hinzugefügt oder gelöscht. Wenn du die <Shift> Taste während des Mausklicks gedrückt hälst, kannst mehrere Instanzen hinzufügen. Mit einem Rechtsklick kannst du Instanzen entfernen. Auf diese Weise bestimmst du den Inhalt des Raumes.

Wie wahrscheinlich schon bemerkt, verschwindet die originale Instanz, wenn eine Instanz über ein andere platziert wird. Normalerweise wird das gewünscht, aber nicht immer. Das kann vermieden werden durch Deaktivieren der Box Delete underlying.

Wenn du die Position einer Instanz verändern möchtest, halte die <Strg> Taste gedrückt und klicke mit der linken Maustaste auf das zu verschiebende Objekt. Nun kannst du es im Raum neu Positionieren. (Benutze die <Alt> Taste für präzises Positionieren.)

Wenn du die <Strg> Taste gedrückt hälst, während du mit der rechten Maustaste auf eine Instanz klickst, wird ein Menü erscheinen. Hier kannst du ein Objekt löschen, eine genaue Position eingeben oder die unterste Instanz nach oben holen oder umgekehrt.

Raum-Optionen

Jeder Raum hat Optionen die im settings Reiter eingestellt werden können.

/library/manual/images/form_room_settings.jpg

Jeder Raum hat einen Namen. Am besten ist ein aussagekräftiger Name. Es gibt auch einen Titel. Dieser Titel wird während des Spieles in der Titelleiste angezeigt. Hier kannst du auch die Breite und Höhe des Raumes (in Pixeln) angeben. Und der Room-speed kann hier auch eingestellt werden, welches die FPS darstellt. Je höher die Geschwindigkeit, desto flüssiger die Bewegung. Aber du wirst dafür einen schnelleren PC benötigen.

Den Hintergrund festlegen

In dem Register backgrounds setzt du das Hintergrundbild für den Raum. Es können auch mehrere Hintergründe gesetzt werden. Das Register sieht wie folgt aus:

/library/manual/images/form_room_backgrounds.jpg

Oben siehst du die Hintergrundfarbe. Du kannst darauf klicken um sie zu ändern. Die Hintergrundfarbe wird nur benötigt wenn du kein Hintergrundbild, welches den ganzen Raum überdeckt, verwendest. Andererseits wäre es besser die Box Draw background color auszuschalten, weil es sonst eine Verschwendung von Rechenzeit wäre.

Oben siehst du eine Liste von 8 Hintergründen. Du kannst jeden festlegen aber meistens benötigt man nur einen oder zwei. Um den Hintergrund festzulegen, wähle in der Liste. Danach kreuze die Box Visible when room starts sonst siehst du nichts. Der Name des Hintergrundes wird jetzt fett gedruckt. Nun gib ein Hintergrundbild im Menu an. Es gibt einige Einstellungsmöglichkeiten. Zuerst kannst du angeben, ob der Hintergrund horizontal/vertikal wiederholt werden soll. Du kannst auch die Position des Hintergrundes im Raum bestimmen (das beeinflusst die Wiederholung). Eine andere Möglichkeit ist es, den Hintergrund zu strecken. Der Hintergrund wird dann skaliert, um den ganzen Raum auszufüllen. Das Seitenverhältnis wird nicht berücksichtigt. Schließlich Kannst du den Hintergrund vertikal oder horizontal bewegen (in Pixeln pro Schritt). Es wird nicht empfohlen, das Scrollen mit gestrecktem Hintergrund zu machen. Das Ergebnis wird unschön werden.

Es gibt noch eine Auswahlbox, Foreground image genannt. Wenn du diese markierst, wird der Hintergrund zum Vordergrund, welcher vor anstatt hinter allem gezeichnet wird. Selbstverständlich sollte diese Grafik transparent sein, sonst hat sie keinen Sinn.

Dein Spiel verbreiten

Mit den Informationen aus den vorherigen Kapiteln kannst du schon Spiele erstellen. Wenn dein Spiel fertig ist wirst du garantiert wollen, dass andere Leute es spielen. Du kannst natürlich deine .gm6 Datei weitergeben und den Spieler Game Maker zum Spielen benutzen lassen, aber normalerweise ist dies nicht was du möchtest. Erstens möchtest du es nicht ermöglichen, das andere dein Spiel ändern und zweitens sollen auch Leute, die den Game Maker nicht besitzen, dein Spiel spielen können. Deswegen solltest du eine eigenständige exe Datei erzeugen.

Eigenständige exe Dateien im Game Maker zu erzeugen ist sehr einfach. Im File Menü wählst du den Menüpunkt Create Executable. Du wirst nach dem Namen der exe, die das Spiel enthält, gefragt. Gebe einen Namen an, drücke OK und du hast dein eigenständiges Spiel welches du verbreiten kannst. Da kannst das Icon der exe in den Global Game Settings einstellen.

Wenn du einmal solch eine eigenständige Version deines Spieles erstellt hast, kannst du sie anderen Personen geben oder im Internet vertreiben. Du kannst die mit dem Game Maker erstellten Spiele so vertreiben wie du möchtest. Du kannst sie auch verkaufen. Dies setzt natürlich voraus, dass Bilder und Sounds die du verwendest auch verkauft werden dürfen. Lese die angehängte Lizenzvereinbarung durch, um mehr zu erfahren.

Es ist im Normalfall sehr nützlich, deine exe zu komprimieren und mit extra Informationen zu versehen. In Windows XP kann das direkt im Kontextmenü der Datei gemacht werden, und es gibt auch viele kostenlose Kompressionsprogramme im Web. Alternativ kannst du ein Setup für dein Spiel erzeugen. Auch für diesen Zweck findest du viele kostenlose Programme im Web.

Fortgeschrittene Funktionen

Dieser Teil der Dokumentation gibt dir Informationen über die fortgeschritteneren Funktionen des Game Maker.

Der erweiterte Modus

Bis jetzt betrachteten wir nur die einfachen Features des Game Maker. Aber es gibt viel mehr Möglichkeiten. Um diese zu nutzen, musst du den Game Maker in den erweiterten Modus umschalten. Das geht ganz einfach. Im File Menü klickt auf den Eintrag Advanced mode. (Um den Effekt zu sehen solltest du den Game Maker neu starten oder dein Spiel speichern und es neu laden).

Wenn du Game Maker im erweiterten Modus startest, siehst du folgendes Bild::

/library/manual/images/form_main_advanced.jpg

Es beinhaltet alles, was auch im Anfänger-Modus vorhanden ist, aber es gibt einige zusätzliche Ressourcen, Knöpfe und Menü-Einträge. Wie wir in den nächsten Kapitel sehen werden, haben die verschiedenen Ressourcen zusätzliche Optionen. Wir werden jetzt die zusätzlichen Menü-Einträge betrachten.

File Menü

Im File Menü gibt es folgende zusätzliche Kommandos:

  • Merge Game. Mit diesem Kommando kannst du alle Ressourcen (Sprites, Sounds, Objekte, Räume, etc.) von einem anderem Spiel in das aktuelle Spiel kopieren. Das ist sehr nützlich, wenn ihr einige Teile wiederverwenden wollt (z.B. Menüsysteme). (Bedenkt, dass alle Ressourcen, Instanzen und Tiles eine neue Id bekommen, was manchmal Probleme mit den Scripts verursacht.) Du musst selber dafür sorgen, dass die Ressourcen in den zwei Dateien verschiedene Namen haben, sonst gibt es Probleme.
  • Preferences. Hier kannst du den Game Maker anpassen. Diese Informationen werden für die nächsten Aufrufe des Game Maker gespeichert. Die folgenden Punkte können eingestellt werden.

Einstellungen

Im Menüpunkt Preferences im File Menü kannst du eine Reihe von Einstellungen vornehmen, die für die nächsten Aufrufe des Game Maker gespeichert werden. Die folgenden Punkte können eingestellt werden:
  • Show recently edited games in the file menu. Zeigt die letzten 8 bearbeitenden Spiele unter Recent files im File menu an.
  • Load last opened file on startup. Die letzte Datei wird automatisch beim Start geöffnet.
  • Keep backup copies of files. Das Programm erstellt Backupdateien mit der Dateierweiterung *.gb0-*.gb9. Diese Dateien können mit Game Maker geöffnet werden. Es wird sehr empfohlen mindestens 1 Backup zu haben!
  • Maximal number of backups. Hier kann eingestellt werden, wieviele (1-9) verschiedene Backups das Programm machen soll.
  • Show progress while loading and saving files. Beim Speichern oder Laden einer Datei wird ein Fortschrittsbalken angezeigt.
  • At startup check for, and remove old temporary files. Der Game Maker und dessen Spiele erzeugen temporäre Dateien. Normalerweise werden diese wieder automatisch entfernt, aber manchmal, beispielsweise beim Absturz eines Spieles, bleiben sie zurück. Wenn diese Option aktiviert ist überprüft Game Maker beim Start, ob solche Dateien existieren und entfernt diese.
  • Run games in secure mode. In diesem Modus erlaubt Game Maker es nicht, externe Programme auszuführen; genauso wie das Verändern oder Löschen von Dateien , die woanders liegen, als die des Spieles. (Das ist eine Sicherheitsmassnahme gegenüber Trojanern, obwohl der Erfolg nicht garantiert ist!). Manche Spiele können dadurch nicht korrekt funktionieren. Dieses Einstellung funktioniert nur, wenn der Game Maker läuft. Wenn du also ein Spiel unabhängig vom Game Maker startest, läuft dieses NICHT im Secure mode.
  • Show the origin and bounding box in the sprite image. Zeigt den Bezugspunkt (origin) und den Begrenzungsrahmen (bounding box) eines Sprites an.
  • In object properties, show hints for actions. Zeigt eine Beschreibung der Action im Objektfenster an, wenn die Maus länger darauf verweilt.
  • When closing, remove instances outside the room. Das Programm warnt vor Objekten, die ausserhalb des Raumes liegen und lässt diese löschen.
  • Remember room settings when closing the form. Einige Raum-Einstellungen, wie das Anzeigen des Gitters, das Löschen übereinanderliegender Objekte, etc. kann hier gespeichert werden.
  • Scripts and code and colors. Lese im Kapitel über Skripte nach, um mehr hierüber zu erfahren.
  • Image editor. Normalerweise benutzen Game Maker-User den eingebauten Editor für das Bearbeiten von Bildern. Hier kann man ein anderes Bildbearbeitungsprogramm für das Bearbeiten der Bilder einstellen.
  • External sound editors. Hier kann man einen externen Soundeditor für die verschiedenen Sounddateien einstellen. (Game Maker besitzt keinen eingebauten Soundeditor, deshalb gibt es keine Möglichkeit die Dateien zu bearbeiten, wenn hier nichts eingestellt ist.)

Edit Menü

In diesem Menü findest du folgende zusätzliche Kommandos:
  • Add group. Ressourcen können in Gruppen zusammengefasst werden. Dies ist sehr nützlich, wenn ihr grössere Spiele erstellt, z.B. kannst du alle Sounds eines bestimmten Objektes in einer Gruppe organisieren, oder alle Objekte eines Levels in einer Gruppe zusammenfassen. Dieses Kommando erstellt eine neue Gruppe im aktuell gewählten Ressourcentyp. Du wirst nach einen Namen gefragt. Gruppen können wiederum Gruppen enthalten. Du kannst dann die Ressourcen in die Gruppen verschieben.
  • Find Resource. Mit diesem Kommando gibst du den Namen der Resource ein und dann wird das Eigenschaftsfenster geöffnet.
  • Expand Resource Tree. Klappt den Ressourcenbaum komplett aus, zeigt alle Ressourcen.
  • Collapse Resource Tree. Klaptt den Resssourcenbaum komplett ein, versteckt alle Ressourcen.
  • Show Object Information. Dieses Kommando zeigt einen Überblick über das Objekt an.

Add Menü

In diesem Menü kannst du jetzt auch zusätzliche Ressourcen hinzufügen. Beachte, es gibt für alle auch einen Button in der Toolbar und ein Tastenkürzel.

Scripts Menü

Im Skript Menü gibt es folgende zusätzliche Kommandos:
  • Import Scripts. Importieren von wichtigen Skripts aus Dateien.
  • Export Scripts. Speichern von Skripts in eine Datei, damit es andere nützen können. Wenn du eine Skriptressource auswählst wird nur das eine Skript gespeichert. Wenn du eine Gruppe selektierst, wird die ganze Gruppe gespeichert. Wenn du die root Ressource wählst werden alle Skripts gespeichert. Dieser Menü-Eintrag ist auch verfügbar, wenn du mit der rechten Maustaste auf ein Skript klickst.
  • Show Built-in Variables. Zeigt eine sortierte Liste aller eingebauten Variablen an, lokale und globale.
  • Show Built-in Functions. Zeigt eine sortierte Liste aller eingebauten Funktionen.
  • Show Constants. Zeigt die Liste aller eingebauten und in den Optionen definierte Konstanten.
  • Show Resource Names. Zeigt eine sortierte Liste aller Ressourcen. Klicke darauf, um die betreffende Ressource zu öffnen.
  • Search in Scripts. Du kannst hier nach einer Zeichenkette (string) in allen Skripten suchen. Du kannst darauf klicken , um die betroffene Stelle zum Bearbeiten zu öffnen.
  • Check Resource Names. Prüft alle Ressourcennamen. Wenn diese nicht korrekt sind, werden sie angezeigt, wenn es doppelte gibt oder wenn ein Ressourcenname der Name einer Variablen, Funktion oder Konstante ist. Du kannst darauf klicken, um die betroffene Ressource zu ändern.
  • Check All Scripts. Prüft alle Scripts auf Fehler. Du kannst an die Stelle klicken und der angezeigte Platz wird zum Verändern geöffnet.

Mehr über Sprites

Es gibt eine Reihe erweiterter Möglichkeiten, deine Sprites zu erstellen.

Deine Sprites bearbeiten

Bis jetzt haben wir unsere Sprites nur aus Dateien geladen. Es ist aber auch möglich diese im Game Maker zu erstellen und zu bearbeiten. Um dies zu machen, öffne das Eigenschaftsfenster eines Sprites durch einen Doppelklick auf seinen Eintrag (oder erstelle ein neues Sprite). Nun drücke den Edit Sprite Knopf. Ein neues Fenster erscheint, indem alle zu dem Sprite gehörenden Einzelbildern angezeigt werden.

Das Fenster zum Bearbeiten von Sprites sieht wie folgt aus:

/library/manual/images/form_sprite_editor.jpg

Rechts seht ihr die verschiedenen Bilder des Sprites. Alle Einzelbilder eines Sprites müssen im Game Maker die gleiche Größe haben. Links wird eine Animation des Sprites abgespielt (Wenn diese nicht angezeigt wird, markiere die Box Show Preview). Darunter kann die Geschwindigkeit der Animation und die Hintergrundfarbe geändert werden. So kannst du sehen wie die Animation im Spiel aussehen wird. (Diese Geschwindigkeit ist nur für die Vorschau. Die Geschwindigkeit der Animation im Spiel hängt von der Raumgeschwindigkeit ("room speed") ab).

Der Sprite-Editor beinhaltet viele Befehle für das Erstellen und Verändern von Sprites. Diese werden alle über das Menü gesteuert. (Manche besitzen einen Button in der Symbolleiste). Manche Befehle funktionieren nur bei einzelnen Bildern, daher muss zuerst einen Einzelbild mit der Maus markiert werden.

File Menü

Das File Menü beinhaltet einige Befehle für das Laden und Speichern von Sprites.

  • New. Erstellt ein neues, leeres Sprite. Du musst die Größe des Sprites angeben (alle Bilder eines Sprites müssen die gleiche Größe haben).
  • Create from file. Erzeugt das Sprite aus einer Datei. Viele verschiedene Dateitypen können verwendet werden. Dies erstellt ein Sprite mit einem einzelnen Bild, ausgenommen eine �Animated-GIF-Datei�, welches die Daten in Einzelbilder speichert. Das Pixel links unten wird als Transparenzfarbe genommen und nicht die Transparenzfarbe der GIF-Datei. Du kannst mehrere Bilder auswählen, diese müssen aber die gleiche Größe haben.
  • Add from file. Fügt ein Bild (oder Bilder) aus einer Datei zum aktuellen Sprite hinzu. Wenn das Bild nicht die gleiche Größe hat, kannst du auswählen, wo das Bild platziert wird oder ob es gedehnt wird. Du kannst mehrere Bilder auswählen, diese müssen aber die gleiche Größe haben.
  • Save as GIF. Speichert das Sprite als animierte gif-Datei ab.
  • Save as strip. Speichert das Sprite als Bitmap, die Bilder werden nebeneinander gespeichert.
  • Create from strip. Erstellt ein Sprite aus einem Animationsstreifen. Weiter unten gibt es nähere Informationen.
  • Add from strip. Fügt Bilder aus einem Animationsstreifen hinzu. Weiter unten gibt es nähere Informationen.
  • Close saving changes. Schließt das Fenster und speichert die Änderungen des Sprites. Wenn du die Änderungen nicht speichern willst, klicke auf den Schließen-Button des Fensters.

Edit Menü

Das Edit Menü enthält einige Befehle, die sich mit dem aktuell gewählten Sprite befassen. Du kannst es in die Zwischenablage kopieren, ein Bild von der Zwischenablage einfügen, das aktuelle Sprite löschen, es entfernen und das Sprite nach links oder rechts bewegen. Zuletzt gibt es einen Befehl, um ein einzelnes Bild im eingebauten Bildbearbeitungsprogramm zu bearbeiten (siehe unten).

Transform Menü

Im Transform Menü kannst du einige Veränderungen an den Bildern vornehmen.

  • Mirror horizontal. Spiegelt das Bild waagrecht.
  • Flip vertical. Dreht das Bild senkrecht.
  • Shift. Das Bild waagrecht oder senkrecht verschieben.
  • Rotate. Das Bild 90 Grad,180 Grad, oder einen anderen Wert drehen. Ausserdem kann beim letzten Punkt die Qualität gewählt werden. Experimentiere um den besten Effekt zu erzielen.
  • Resize Canvas. Ändert die Größe der Leinwand. Ausserdem kann angegeben werden, wo das alte Bild in der neuen Leinwand erstellt wird.
  • Stretch. Das Bild zu einer neuen Größe dehnen. Der Veränderungsfaktor und die Qualität kann gewählt werden.
  • Scale. Verändert die Größe des Bildes (aber nicht die der Leinwand). Der Veränderungsfaktor, die Qualität und die Position im aktuellen Bild kann gewählt werden.

Images Menü

Im Images Menü könnt ihr Funktionen für das Bearbeiten von Bildern finden.

  • Cycle left. Verschiebt alle Bilder um einen Platz nach links. Dies startet die Animation von einem anderen Punkt aus.
  • Cycle right. Verschiebt alle Bilder einen Platz nach rechts.
  • Black and white. Wandelt das Sprite in schwarz-weiß (verändert nicht die Transparenzfarbe!)..
  • Colorize. Verändert die Farbe (Farbton) der Bilder. Benutze den Regler, um verschiedene Farben auszuwählen.
  • Colorize Partial. Hier kannst du Teile des Bildes verfärben. Du kannst eine vorhandene Farbe wählen und einen Toleranzbereich. Dies kann beispielsweise genutzt werden, um nur die Farbe des Shirts des Spielers zu ändern.
  • Shift Hue. Ein anderer Weg die Bildfarbe zu ändern. Hier werden alle Farben, je nach Reglerstellung, mehr oder weniger verändert, was interessante Effekte ergibt.
  • Intensity. Verändert die Intensität durch Veränderung der Werte für die Farbsättigung und Helligkeit des Bildes.
  • Invert. Invertiert die Farben des Bildes.
  • Fade. Angabe einer Farbe und der Menge. Die Farbe des Bildes wird jetzt zu dieser Farbe ausgeblendet.
  • Transparency. Angabe des Levels der Transparenz (screen-door transparency). Es wird eine bestimmte Anzahl von Pixeln transparent gemacht.
  • Blur. Verwischt das Bild, die Farben werden vermischt, dadurch wird verschwommener. Je höher der Wert, desto verschwommener wird es.
  • Outline. Erstellt einen Umriss um das Bild. Du wirst nach der Farbe gefragt und ob das vorhandene Bild entfernt werden soll (nur dem Umriss bleibt erhalten) oder ob der Umriss auf das Bild gezeichnet werden soll.
  • Boundary. Dasselbe wie Outline, wird aber nicht um das Bild sondern auf den Bildrand gezeichnet.
  • Crop. Macht das Bild so klein wie möglich. Das ist sehr nützlich, weil grössere Bilder mehr Videospeicher im Game Maker benötigten. Manchmal will man einen kleinen Rand um das Bild lassen, um Transparenzprobleme zu vermeiden.

Du wirst etwas mit diesen Befehlen experimentieren müssen, um das gewünschte Sprite zu erhalten.

Animation Menü

Im Animation Menü werden neue Animationen aus der aktuellen Animation erstellt. Es gibt viele Möglichkeiten und du solltest ein bisschen experimentieren, um den gewünschten Effekt zu erzielen. Vergiss nicht: Du kannst immer eine Animation speichern und später zur aktuellen hinzufügen. Ausserdem kannst du leere Bilder hinzufügen und nicht benötigte löschen. Ich werde kurz die verschiedene Möglichkeiten vorstellen.

  • Set Length. Verändert die Länge einer Animation. Die Animation wird solange wiederholt, bis die angegebene Anzahl der Einzelbilder erreicht wird. (Normalerweise eine Mehrzahl der aktuellen Einzelbilder.)
  • Stretch. Dieser Befehl verändert auch die Länge der Animation. Aber diesmal werden Einzelbilder verdoppelt oder gelöscht, um die richtige Anzahl zu bekommen. Wenn du die Anzahl erhöhst, wird die Animation langsamer, wenn du erniedrigst wird die Animation schneller.
  • Reverse. Dreht die Animation um. Sie wird also rückwärts abgespielt.
  • Add Reverse. Die Umkehrsequenz wird diesmal hinzugefügt, verdoppelt also die Anzahl der Einzelbilder. Das ist nützlich, um Objekte nach links und rechts gehen zu lassen, die Farbe zu ändern und umzudrehen. Manchmal wird man die auftretenden doppelten, ersten und mittleren, Einzelbilder löschen.
  • Translation sequence. Erstellt eine Animation, die Bilder werden langsam mit jedem Schritt in die gewünschte Richtung verändert. Du musst die Anzahl der Einzelbilder und die gesamte Menge der waagerechten und senkrechten Veränderung angeben.
  • Rotation sequence. Erstellt eine Animation, in der sich das Bild dreht. Wähle im Uhrzeigersinn oder gegen den Uhrzeigersinn. Gibt die Anzahl der Einzelbilder und den Winkel in Grad (360 ist eine komplette Drehung). (Möglicherweise musst du die Größe der Leinwand verändern, um sicherzugehen, dass das Bild die ganze Drehung über sichtbar ist.)
  • Colorize. Erstellt eine Animation, in welcher das Bild in eine bestimmte Farbe wechselt.
  • Fade to color. Erstellt eine Animation, in welcher das Bild zu einer bestimmten Farbe ausblendet.
  • Disappear. Das Bild verschwindet langsam.
  • Shrink. Verkleinert das Bild ins Nichts. Die Richtung kann angegeben werden.
  • Grow. Entwickelt das Bild aus dem Nichts.
  • Flatten. Drückt das Bild ins Nichts in der angegebenen Richtung.
  • Raise. Zieht das Bild aus dem Nichts in die gewünschte Richtung.
  • Overlay. Überlagert eine Animation mit einer anderen Animation oder einem Bild aus einer Datei.
  • Morph. Morpht die Animation in eine andere Animation bzw. Bild aus einer Datei. Der beste Erfolg wird erzielt, wenn die zwei Animationen den gleichen Bereich eines Bildes bedecken. Sonst erscheinen teilweise manche Pixel und andere verschwinden.

Besonders mächtig sind die beiden letzten Befehle. Um z.B. ein Objekt aufzublasen(sprengen), nimm eine Anzahl von Kopien und eine Anzahl von leeren Einzelbilder, dann überziehe es mit einer Explosionsanimation (Gehe sicher, dass die Anzahl der Bilder übereinstimmen). Alternativ morphe es in die Explosion. Mit ein bisschen Erfahrung kannst du großartige Sprites erstellen.

Animationsstreifen

Wie oben angegeben, werden Sprites normalerweise als animierte GIF-Datei oder als Animationsstreifen gespeichert. Ein Animationsstreifen ist eine große Bitmap, welche die einzelnen Bilder nebeneinander speichert. Das einzige Problem dabei ist, dass die Grösse der einzelnen Einzelbilder nicht im Bild gespeichert wird. Ausserdem speichern die meisten Strip-Dateien aus dem Internet vielfältige Sprites in einer Datei. Zum Beispiel beinhaltet folgender Teil eines Strips vier verschiedene Animationen:

/library/manual/images/sprites2.gif

Um einzelne Sprites von einer solchen Datei zu wählen, benutze Create from Strip oder Add from Strip vom File Menü. Nach Auswählen eines geeigneten Animationsstreifens von einer Datei, wird das folgende Fenster gezeigt:

/library/manual/images/form_strip.jpg

Rechts siehst du (einen Teil) des Animationsstreifen-Bildes, welches du gewählt hast. Links kannst du einige Parameter sehen, womit die benötigten Einzelbilder ausgewählt werden. Beachte, dass ein oder mehr Rechtecke im Bild, die Bilder die du gewählt hast, anzeigen. Folgende Parameter können eingestellt werden:

  • Number of images. Anzahl der Bilder die vom Animationsstreifen benötigt werden.
  • Images per row. Anzahl der Bilder in einer Reihe. Zum Beispiel, wenn 1 ausgewählt wurde, bekommst du eine senkrechte Sequenz von Bildern.
  • Image width. Breite des einzelnen Bildes.
  • Image height. Höhe des einzelnen Bildes.
  • Horizontal cell offset. Wenn du nicht das linke obere Bild benötigst, kannst du hier einstellen wie viele Bilder waagerecht ausgeschlossen werden.
  • Vertical cell offset. Wieviele Bilder senkrecht übersprungen werden.
  • Horizontal pixel offset. Manchmal gibt es leeren Platz in der oberen Ecke. Hier kannst du die Menge angeben(in Pixeln).
  • Vertical pixel offset. Vertikale Menge des leeren Platzes.
  • Horizontal separation. In manchen Animationsstreifen gibt es leeren Platz zwischen den Bildern. Hier kannst du die waagerechte Menge zwischen den Bildern (in Pixeln) überspringen.
  • Vertical separation. Senkrechter Abstand zwischen den Bildern.

Wenn die korrekte Zahl der Bilder gewählt wurde, drücke OK, um das Sprite zu erstellen. Beachte, dass Sprites von anderen nur mit deren Erlaubnis verwendet werden dürfen oder wenn sie Freeware sind.

Individuelle Einzelbilder bearbeiten

Du kannst auch die Einzelbilder bearbeiten. Selektiere ein Einzelbild und wähle Edit Image vom Image Menü. Dies öffnet das kleine eingebaute Bildbearbeitungsprogramm. Aber bedenke, dies ist ein eingeschränktes Programm für kleine Änderungen von bestehenden Bildern und nicht eines, um neue Bilder zu zeichnen. Dafür werden vollwertige Bildbearbeitungsprogramme empfohlen, lade diese Dateien dann (oder kopiere und füge sie ein) im Game Maker.

/library/manual/images/form_image_editor.jpg

Dieses Fenster zeigt das Bild in der Mitte und einige einfache Zeichenfunktionen links. Hier kannst du hinein- und herauszoomen, Pixel, Linien, Rechtecke, Text etc. zeichnen. Die Farbe hängt davon ab, welche Maustaste benutzt wird. Für manche Zeichenfunktionen kannst du Eigenschaften setzen (wie Linienstärke oder Sichtbarkeit des Randes). Es gibt einen speziellen Button, um alle Pixel einer Farbe in eine andere zu ändern. Dies ist vor allem nützlich, um die Hintergrundfarbe für die Transparenz zu ändern. In der Werkzeugleiste gibt es einige besondere Knöpfe, die alle Pixel eines Bildes in eine bestimmte Richtung bewegen. Ausserdem kann man einstellen, ob ein Gitter/Raster angezeigt wird, wenn das Bild gezoomt wird (arbeitet nur mit einem Zoomfaktor von mindestens 4).

Du kannst Flächen auf die herkömmliche Weise per Klicken und Markieren. Dann platziere die Maus in der Fläche und drücke die Maustaste um sie woanders hin zu verschieben. Die dabei entstehende freie Fläche wird mit der Farbe der linken Maustaste gefüllt. Wenn du die Auswahl mit der <Shift> Taste bewegst bleibt der Originalbereich unangetastet. Mit der <Shift> Taste kannst du auch Kopien eines Bereiches machen. Wenn du statt die linke die rechte Maustaste verwendest wird die Auswahl als transparent betrachtet.

Das Text Tool braucht möglicherweise noch einige Erklärungen. Um Text hinzuzufügen, klicke auf dem Textknopf und dann auf das Bild. Ein Fenster erscheint, in welches du den Text eingeben kannst. Benutze das # Zeichen um eine neue Zeile zu beginnen. Wenn du OK betätigst wird der Text dem Bild hinzugefügt, wobei eine Box darum gezeichnet wird. Du kannst nun den Text mit gedrückter Maustaste verschieben. Mit einem Klick mit der rechten Maustaste kannst du den Text ändern. Mit dem Text Menü kannst du auch die Ausrichtung und die Schriftart ändern.

Rechts im Fenster wird die Farbe gewählt (eine mit der linken Maustaste und eine mit der rechten Maustaste). Es gibt vier Arten, die Farbe zu ändern. Zuerst kannst du mit der Maustaste (links oder rechts) in eine der 16 Basisfarben klicken. Beachte, dass es eine spezielle Farbenbox gibt, welche die Farbe des linken unteren Pixels des Bildes zeigt, die als Transparenzfarbe im Sprite verwendet wird, wenn das Sprite transparent ist. Du kannst diese Farbe verwenden, um Teile des Bildes transparent zu machen. Der zweite Weg ist, in das Bild zu klicken, um die Farbe zu ändern. Hier kannst du viel mehr Farben wählen. Du kannst die Maus halten, um die gewählte Farbe zu sehen. Drittens kannst du mit der linken Maustaste in die Box klicken. Ein Farbdialog öffnet sich, wo du die Farbe ändern kannst. Letzte Möglichkeit, du kannst das Droptool links anklicken, dann auf eine Position im Bild, um die Farbe zu kopieren.

Es gibt hier zwei spezielle Funktionen. Wenn du die <Strg> Taste gedrückt hälst kannst du eine Farbe vom aktuellen Bild wählen. Wenn du die <Shift> Taste gedrückt hälst während du Linien zeichnest bekommst du nur horizontale, vertikale und diagonale Linien. Ähnlich ist es beim Drücken der <Shift> Taste beim Zeichnen von Ellipsen und Rechtecken, es werden dann Quadrate und Kreise gezeichnet.

Im Menü sind die gleichen Veränderungsmöglichkeiten und Bildbearbeitungskommandos, wie im Sprite-Editor. Doch diesmal wirken sie sich nur auf das gewählte Bild aus. (Wenn das Sprite mehrere Bilder hat, sind einige Befehle, z.B. Größe ändern, nicht verfügbar). Die Bilder können als Bitmap-Datei gespeichert werden. Es gibt zwei zusätzliche Befehle im Image Menü:

  • Clear. Füllt das Bild komplett mit der linken Farbe (welche automatisch die transparente Farbe wird).
  • Gradient fill. Füllt ein Bild mit einem Farbverlauf (nicht sehr nützlich für Sprites, aber es sieht gut aus und kann für Hintergründe genutzt werden).

Es fehlen einige schicke Zeichenfunktionen. Dafür solltest du ein professionelles Zeichenprogramm verwenden (oder einfach das Paint Programm von Windows). Der einfachste Weg ist das Kopieren des Bildes in die Zwischenablage. Im Zeichenprogramm drücke dann Einfügen, um das Bild zu erhalten. Ändere es und kopiere es wieder in die Zwischenablage. Jetzt füge das Bild im Game Maker ein.

Erweiterte Sprite Einstellungen

Im erweiterten Modus gibt es im Sprite-Dialogfenster einige zusätzliche Optionen, die wir hier betrachten.

Zuerst gibt es Optionen bezüglich der Kollissionsprüfung. Immer, wenn zwei Instanzen sich treffen, gibt es ein Collission-Event. Kollisionen werden wie folgt ausgeführt. Jedes Sprite hat einen Begrenzungsrahmen. Dieser Rahmen beinhaltet den nicht-transparenten Teil des Einzelbildes. Wenn die Begrenzungsrahmen sich überlappen, wird geprüft ob zwei Pixel im aktuellen Einzelbild der 2 Sprites überlappen. Die zweite Option ist aufwendig und benötigt zusätzlichen Speicherplatz. Wenn du nicht an präziser Kollissionsprüfung eines bestimmte Sprites interessiert bist, solltest du die Box precise collision checking ausschalten. In diesem Falle ist nur der Begrenzungsrahmen maßgebend. Du kannst auch den Begrenzungsrahmen verändern. Dies wird kaum benötigt, doch manchmal willst du den Begrenzungsrahmen kleiner machen, so dass Kollisionen mit erweiterten Teilen des Sprites nicht in Betracht gezogen werden.

Die Ecken eines Sprites können kantig aussehen. Um dies zu vermeiden, kannst du die Box Smooth edges aktivieren. In diesem Fall werden die Pixel am Rand des Sprites (das sind die Pixel neben transparenten Pixeln) teilweise transparent gezeichnet. Dies kann sie um einiges besser aussehen lassen. (Benutze dies nicht, wenn die Sprites Teile eines größeren Gesamtbildes sind. Dadurch würden zwischen den einzelnen Sprite-Teilen störende Linien entstehen.) Der Effekt ist nur im Spiel zu sehen, nicht im Editor!

Während des Spielens werden die Sprites in Texturen umgewandelt. Diese Texturen müssen im Videospeicher sein (in der Grafikkarte), bevor sie genutzt werden können. Wenn du die Box Preload texture aktivierst wird das direkt beim Laden des Spieles durchgeführt, sodass dann später im Spiel keine Verzögerung eintritt. Solltest du viele große Sprites haben, die nicht beim Start benötigt werden, ist es aber sinnvoller die Option auszuschalten. Game Maker wird die Texturen dann zum Videospeicher und zurück bewegen, wenn es notwendig ist.

Schlussendlich kannst du den Bezugspunkt (origin) des Sprites setzen. Das ist der Punkt des Sprites, welcher mit der Position korrespondiert. Wenn du eine Instanz bei einer bestimmte Position setzt, wird der Bezugspunkt hier gesetzt. Die obere linke Ecke des Sprites ist voreingestellt, aber manchmal ist es besser die Mitte oder irgendeinen anderen Punkt auszuwählen. Du kannst auch einen Punkt ausserhalb des Sprites verwenden. Du kannst den Punkt auch durch Klicken in den Sprite setzen (wenn der Bezugspunkt im Sprite-Bild angezeigt wird).

Mehr über Sound und Musik

Im erweiterten Modus hast du viel mehr Kontrolle über die Sounds und Musikstücke, die du deinem Spiel hinzufügst. Wenn du eine Sound-Ressource hinzufügst siehst du folgenden Dialog:

/library/manual/images/form_sound_advanced.jpg

Neben den Knöpfen zum Laden, Speichern und Abspielen gibt es noch eine Reihe von Einstellungen, die nun hier besprochen werden.

Zuerst kannst du die Art des Sounds angeben. Es gibt vier Möglichkeiten. Normal Sound wird für Soundeffekte in Wav Dateien genutzt (obwohl sie auch genauso gut für Midis genutzt werden könnten). Es können mehrere normale Sounds gleichzeitig abgespielt werden. Du kannst auch simultan den selben Sound mehrmals gleichzeitig abspielen. Hintergrundmusik ist dem ähnlich, es kann aber nur eine abgespielt werden. Wenn du also eine neue Hintergrundmusik startest wird die alte gestoppt. Midi Dateien sind standardmäßig Hintergrundmusik. 3D Sounds sind Sounds, die mit speziellen DirectX 3D Funktionen abgespielt werden. Diese werden nur für fortgeschrittene Soundeffekte benötigt.

Sounds werden normalerweise über DirectX abgespielt. Dies ergibt viele Möglichkeiten, ist aber nur auf Midi und Wav Dateien beschränkt. Wenn du andere Dateien, wie z.B. mp3 Dateien, abspielen möchtest musst du die Option mit dem Media Player aktivieren. Diese ist leider sehr eingeschränkt. Es kann nicht die Lautstärke verändert werden, Effekte sind nicht möglich und es kann nur ein Sound parallel abgespielt werden. Beachte, dass Midi Dateien im Media Player abgespielt anders klingen können, als als normal oder Hintergrundmusiken. Der Grund dafür liegt darin, dass der Media Player den Hardware Synthesizer benutzt (welcher auf jedem PC anders ist) während ansonsten die Softwareversion genutzt wird (die auf allen PCs gleich klingt). Benutze besser keine mp3 Dateien in deinem Spiel. Diese müssen dekomprimiert werden, was dein Spiel verlangsamen kann. Der Fakt das die Dateigröße kleiner ist bedeutet nicht automatisch, dass weniger Speicher benötigt werden würde. Auch unterstützen nicht alle Computer diese. Dadurch könnte dein Spiel nicht auf jedem laufen.

Zweitens kannst du Effekte bestimmten, wie Chorus oder Echo (nur in der registrierten Version von Game Maker!) Du kannst beliebige Kombinationen wählen. Das sofortige Anhören des Ergebnisses ist möglich. (Wenn du GML nutzt kannst du sogar die Parameter dieser Effekte bestimmen.)

Ebenso ist es möglich, die Standardlautstärke und -balance des Sounds zu bestimmen.

Für alle Sounds kannst du bestimmen, ob sie vorgeladen (preload) werden sollen oder nicht. Wenn ein Sound abgespielt werden soll, muss er in den Speicher geladen werden. Wenn du ihn vorlädst wird das beim Beginn des Spieles erledigt, wodurch er sofort zur Wiedergabe bereitsteht. Falls nicht wird er beim ersten Abspielen geladen. Dies spart zwar Speicher, führt jedoch zu einer kurzen Verzögerung beim ersten Abspielen.

Game Maker besitzt keinen eingebauten Sound-Editor. Aber in den Einstellungen kannst du einen externen Editor festlegen, mit dem Sounds bearbeitet werden. Hast du dort etwas eingetragen kannst du nun den Edit Sound Knopf benutzen, um den aktuellen Sound zu bearbeiten. (Das Game Maker Fenster wird währenddessen minimiert.)

Mehr über Hintergründe

Neben dem Laden aus Dateien, kannst du auch eigene Hintergrundbilder erstellen. Um das zu tun, drücke auf den Edit Background Knopf. Ein kleines eingebautes Malprogramm wird geöffnet, in dem du deinen Hintergrund erstellen/bearbeiten kannst. Beachte bitte, dass dies kein voll ausgewachsenes Malprogramm ist. Für fortgeschrittene Bearbeitungsaufgaben, verwende bitte ein eigenständiges Malprogramm. Da ist eine Option, die sehr nützlich ist. Im Image Menü findest du einen Befehl Gradient Fill. Dieser kann verwendet werden, um einen schönen Farbverlauf-Hintergrund zu kreieren.

Im erweiterten Modus gibt es hier noch eine Anzahl von Zusatzoptionen.

Die Ränder der Hintergründe, speziell wenn diese transparent sind, können kantig aussehen. Um dies zu beheben aktiviere die Box Smooth edges. In diesem Fall werden die Ränder des Hintergrundes (das sind die Pixel neben transparenten Pixeln) teilweise transparent gezeichnet. Dies kann sie besser aussehen lassen. (Benutze dies nicht, wenn mehrere Hintergründe einen Gesamthintegrund formen sollen, in diesem Fall würden Linien zwischen den Teilen auftreten.) Der Effekt ist nur im Spiel sichtbar, nicht im Editor!

Während des Spielens werden die Hintergründe in Texturen umgewandelt. Texturen müssen in den Videospeicher (auf der Grafikkarte) verschoben werden, bevor sie genutzt werden können. Wenn die Box Preload texture aktiviert ist passiert das direkt beim Laden, sodass später keine Verzögerungen auftreten. Wenn du aber viele große Hintergründe hast, die nicht gleich beim Start gebraucht werden, deaktivierst du die Box besser. Game Maker wird die Texturen dann zum Videospeicher und zurück bewegen, wenn es notwendig ist.

Manchmal willst du einen Hintergrund als Tile benutzen, das ist eine Sammlung kleiner Bilder in einem großen. Wenn du einen Raum erstellst kannst du diese Einzelbilder an verschiedenen Stellen einfügen. Dies ist sehr nützlich um schöne Räume zu erzeugen. Um einen Hintergrund als Tileset zu benutzen, markiere die Box Use as tile set. Der Dialog sieht nun wie folgt aus:

/library/manual/images/form_background_advanced.jpg

Du kannst für das Tileset eine Reihe von Einstellungen vornehmen. Genauer gesagt kannst die die Breite und Höhe der Tiles bestimmen. (Es kann nur eine Größe angegeben werden, deshalb sollten alle Tiles dieselbe Größe haben. Wenn du verschiedene Größen benutzen möchtest, erstelle zwei oder mehr Tilesets.) Du kannst auch einen Bezugspunkt angeben, bei dem das linke oberste Tile anfängt. Als letztes kannst du den Abstand zwischen den Tiles angeben (normalerweise 0 oder 1). Wenn du mehr über das Benutzen von Tiles lernen möchtest, schaue in das Kapitel über das Erstellen von Räumen.

Ein Wort der Warnung ist hier angebracht. Wenn du Abstandsränder zwischen die Tiles setzt und Interpolation zwischen den Pixeln nutzt (siehe Globale Spieleinstellungen) kann dies zu Brüchen zwischen den Tiles führen. Stelle deshalb sicher, das die Pixel um ein Tile mit denen im Tile übereinstimmen.

Mehr über Objekte

Wenn du ein Objekt im erweiterten Modus erschaffst, kannst du mehr Parameter bestimmen.

Depth

Zuerst einmal, kannst du die Zeichenebene (Depth) der Instanzen eines Objektes bestimmen. Wenn Instanzen auf dem Bildschirm gezeichnet werden, geschieht dies in der Reihenfolge der Zeichenebenen. Instanzen mit dem höchsten Depth-Wert, werden zuerst gezeichnet (auf einem Stapel ganz unten, wenn man draufschaut). Instanzen mit dem kleinsten Wert werden zuletzt (obendrauf) gezeichnet. Wenn zwei Instanzen die gleichen Depth-Werte aufweisen, werden sie gezeichnet, wenn sie erschaffen (created) werden. Wenn du sichergehen willst, dass ein Objekt vor allen anderen liegt, gib ihm einen negativen Wert für Depth. Wenn es dahinter liegen soll, gib ihm einen möglichst hohen positiven Wert. Du kannst die Zeichenebene sogar während des Spiels ändern, indem du die Variable depth verwendest.

Persistent objects

Zweitens, kannst du bleibende Objekte erschaffen. Ein bleibendes Objekt übersteht den Wechsel von Raum zu Raum. Es verschwindet nur, wenn es explizit vernichtet wird. Du brauchst also nur eine Instanz des Objekts in den ersten Raum setzen und sie ist dann in allen darauffolgenden Räumen verfügbar. Dies ist nützlich z.B. für eine Hauptfigur, welche sich von Raum zu Raum durchspielt. Der Gebrauch von "persistent objects" ist eine mächtige Funktion, welche leicht zu Fehlern führt.

Parents

Oft sollen Objekte sich gleich verhalten und nur ein paar winzige Unterschiede besitzen. Beispielsweise soll sich ein Monster nach oben und unten bewegen und ein anderes nach links und rechts. Ansonsten Verhalten sie sich völlig gleich. In diesem Fall sollen alle Aktionen, bis auf 1 oder 2, gleich sein. Nun können wir wieder ein Objekt als Parent des anderen eintragen. Aber in diesem Fall bestimmen wir auch Ereignisse für die Kinder-Objekte. Diese Ereignisse "überschreiben" die Eltern-Ereignisse. Das bedeutet, das immer wenn ein Kind-Objekt ein Event besitzt, diese anstelle des Events des Eltern-Objektes ausgeführt wird. Wenn du auch das Eltern-Ereignis ausführen möchtest kannst du den "inherited" Event mit der entsprechenden Aktion benutzen.

Es ist in solchen Fällen üblich, zuerst ein Basisobjekt zu erschaffen. Dieses Objekt enthält die Eigenschaften aber wird nie im Spiel benutzt. Alle aktuellen Objekte, haben dieses Basisobjekt als "parent-object". "Parent-objects" könnten selbst wiederum "parent-objects" haben und so weiter (Schleifen sind nicht erlaubt). Auf diese Weise kannst du eine Hierarchie aufbauen. Es ist höchst nützlich, dein Spiel strukturiert zu halten und ich kann dir nur wärmstens empfehlen, dir diesen Mechanismus zu eigen zu machen.

Da gibt es noch eine zweite Möglichkeit "parent-objects" zu gebrauchen. Sie beinhaltet auch das Kollissionsverhalten für andere Objekte. Lass es mich an einem Beispiel erläutern. Angenommen, du hast 4 verschiedene Bodenobjekte. Wenn ein Ball den Boden berührt, soll er seine Bewegungsrichtung ändern. Dieses muss im "collision-event" vom Ball (Kollision Ball mit Boden) festgelegt werden. Weil da aber vier verschiedene Bodenobjekte sind, müsstest du vier verschiedene "collision-events" für ball festlegen. Wenn du jetzt aber ein Bodenobjekt zum "parent-object" der anderen Bodenobjekte machst, brauchst du nur einmal ein "collision-event" mit diesem "parent-object" machen - die anderen "erben" es ja. Diese anderen Kollisionen lösen ja das gleiche Ereignis aus. Hier sparst du eine Menge an Kopierarbeit.

Wie aufgezeigt, wann immer du ein Objekt benutzt, beziehst du immer dessen Nachkommen mit ein. Das geschieht, wenn du in einer "action" festlegst, dass Anweisung für Instanzen eines bestimmten Objektes gelten. Es passiert auch, wenn du das with()-Statement im GML-Code (Script,GML-Segment) verwendest (siehe unten). Und es greift, wenn du Funktionen wie instance_position aufrufst. Schliesslich arbeitet dieses Prinzip auch, wenn du auf Variablen in anderen Objekten verweist. Um beim obigen Beispiel zu bleiben: Wenn du ball1.speed auf 10 setzt, gilt das auch für ball2, ball3 und ball4.

Masks

Wenn zwei Instanzen sich berühren wird ein "collision event" (Kollisionsereignis) ausgelöst. Um zu bestimmen, ob zwei Instanzen sich berühren, nimmt man die zugehörigen Sprites als Entscheidungsgrundlage. In den meisten Fällen ist das auch gut so, manchmal aber soll die Abfrage einen anderen Umriss als Grundlage nehmen. Zum Beispiel, wenn du ein isometrisches Spiel machst, haben Objekte typischerweise eine Höhe (um einen 3D-Effekt zu erzielen). Für die Kollisionserkennung willst du aber nur den "Bodenteil" des Sprites benutzen. Dies kannst du machen, indem du ein 2. Sprite erstellst (mit den benötigten Dimensionen) und es als Maske für die Kollisionserkennung einsetzt.

Information

Der Knopf Object information zeigt beim Betätigen eine Überblicksansicht des Objektes, die auch ausgedruckt werden kann. Das ist besonders nützlich, wenn man mal den Überblick über die ganzen "events" und "actions" verloren hat.

Mehr Aktionen

Im erweiterten Modus gibt es noch eine Menge mehr Aktionen, welche hier beschrieben werden.

Mehr Move-Aktionen

Einige Bewegungsaktionen gibt es nur im erweiterten Modus. Folgende sind es:

path Set a path for the instance
Mit dieser Aktion kann man ein Objekt dazu bringen, einem gegebenem Pfad zu folgen. Man stellt den Pfad ein und danach die Geschwindigkeit (in Pixel pro Schritt). Falls die Geschwindigkeit positiv ist startet das Objekt am Anfang, anderenfalls am Ende des Pfades. Als nächstes Stellt man ein, was passieren soll, wenn das Ende des Pfades erreicht ist. Man kann die Bewegung anhalten, von vorne anfangen, von der aktuellen Position aus neu anfangen (was bei einem geschlossenen Pfad das gleiche ist) oder die Bewegung umdrehen. Zum Schluss muss man einstellen, ob der Pfad absolut, - das bedeutet, dass seine Position genauso ist, wie eingestellt (dies ist nützlich, wenn man den Pfad für eine bestimmte Position im Raum erstellt hat) - oder relativ � dann wird der Startpunkt (oder Endpunkt, wenn die Geschwindigkeit negativ ist) des Pfades an der aktuellen Position des Objektes platziert. Weitere Informationen findet man im Kapitel Pfade.

pathend End the path for the instance
Mit dieser Aktion beendet man den Pfad für die Instanz..

pathposition Set the position on the path
Mit dieser Aktion kann die aktuelle Position der Instanz auf dem Pfad verändert werden. Der Wert muss zwischen 0 und 1 liegen (0 = Anfang, 1 = Ende).

pathspeed Set the speed for the path
Hiermit ändert man die Geschwindigkeit der Instanz auf dem Pfad. Ein negativer Wert veranlasst die Instanz sich rückwärts zu bewegen. Ein Wert von 0 hält die Instanz an.

steplinear Perform a step towards a point
Diese Aktion sollte im Step-Event eines Objektes ausgeführt werden, um es in Richtung eines gewählten Punktes zu bewegen. Falls die Instanz den gewählten Punkt erreicht hat, wird sie anhalten. Man stellt die Zielposition und die Geschwindigkeit (die Größe des Schrittes in Pixel) ein. Außerdem kann man bestimmen, ob die Bewegung angehalten werden soll, wenn eine solide oder eine beliebige Instanz berührt wird.

steppotential Step towards a point avoiding objects
Diese Bewegungsaktion ist sehr praktisch. Man sollte sie im Step-Event eine Objektes platzieren. Genauso wie die obige Aktion veranlasst sie die Instanz einen Schritt in Richtung eines bestimmten Punktes zu machen, allerdings wird sie nun versuchen, Hindernissen auszuweichen. Wenn sich die Instanz in ein solides Objekt (oder optional in irgendeines) bewegen würde, ändert sie die Richtung, um zu versuchen, sich um das Objekt herumzubewegen. Man kann nicht garantieren, dass die Methode funktioniert, aber in den meisten einfachen Fällen wird sie die Instanz effizient zum Zielpunkt bewegen. Für kompliziertere Fälle gibt es die Bewegungsplanungs-Funktionen (motion planning) (siehe das Kapitel über Bewegungsplanung). Man stellt die Zielposition, die Geschwindigkeit (die Größe des Schrittes in Pixel) und, ob die Bewegung nur soliden oder allen Objekten ausweichen soll, ein.

Mehr Main-Aktionen

Einige erweiterte Main-Aktionen gibt es nur im erweiterten Modus. Die folgenden Funktionen sind dazugekommen:

timeline Set a time line
Mit dieser Aktion kannst du eine bestimmte Zeitleiste für eine Instanz eines Objektes setzen. Du gibst die Zeitleiste und die Startposition in der Zeitleiste (0 ist der Anfang) an. Du kannst diese Aktion auch verwenden, um eine Zeitleiste zu beenden, in diesem Fall wähle No Time Line als Wert.

timelineset Set the time line position
Mit dieser Aktion kannst du die Position in der aktuellen Zeitleiste ändern (entweder absolut oder relativ). Dies kann benutzt werden um bestimmte Teile einer Zeitleiste zu überspringen oder gewisse Teile zu wiederholen. Beispielsweise wenn du eine Zeitleiste in einer Schleife laufen lassen willst, musst du im letzten Moment diese Aktion einfügen um die Position auf 0 zurückzusetzen. Du kannst sie auch einsetzen um auf etwas zu warten. Füge einfach eine Testaktion ein und wenn nicht "wahr" setze die Zeitleisten-Position relativ auf - 1.

video Show a video
Mit dieser Aktion kannst du eine Video-/Filmdatei abspielen. Du musst den Dateinamen angeben und wählen ob es in einem Fenster oder als Vollbild gezeigt werden soll. Stelle sicher das die Datei existiert. Du solltest es entweder mit dem Spiel ausliefern oder als Datafile exportieren.

resourcesprite Replace a sprite from a file
Diese Aktion kann genutzt werden, um ein Sprite mit dem Inhalt einer Datei zu ersetzen. Du gibst das zu ersetzende Sprite an, den Dateinamen (.bmp, .jpg, oder .gif) und die Zahl der Subimages wenn du ein .bmp oder .jpg lädst. Bei einem .gif Bild wird die Anzahl der Subimages automatisch festgestellt. Andere Sprite-Einstellungen, z.B. ob das Sprite transparent ist, werden nicht verändert. Du kannst dies nutzen um das Speichern aller Sprites im Spiel selbst zu umgehen. Am Start eines Levels kannst du die Sprites mit z.B. dem aktuellen Charaktersprite nach Wahl ersetzen. Ersetze kein Sprite DAS SICHTBAR IST! Dies kann Probleme bei Kollisionen erzeugen. Diese Aktion ist nur in der registrierten Version verfügbar.

resourcesound Replace a sound from a file
Mit dieser Aktion kannst du Sound mit dem Inhalt einer Datei (.wav, .mid, oder .mp3). Du gibst den Sound und den Dateinamen an. Du kannst dies nutzen, um das Speichern aller Sounds im Spiel selbst zu umgehen. Z.B., kannst du verschiedene Stücke Hintergrundmusik mit denen ersetzen, die du abspielen möchtest. Ersetze keinen Sound DER GERADE ABGESPIELT WIRD! Diese Aktion ist nur in der registrierten Version verfügbar.

resourcebackground Replace a background from a file
Mit dieser Aktion kannst du den Hintergrund mit dem Inhalt einer Datei ersetzen (.bmp, oder .jpg). Du kannst den Hintergrund und den Dateinamen angeben. Du kannst dies nutzen um das speichern aller Hintergründe im Spiel selbst zu umgehen. Ersetze keinen Hintergrund DER SICHTBAR IST! Diese Aktion ist nur in der registrierten Version verfügbar.

Mehr Control-Aktionen

Einige erweiterte Control-Aktionen gibt es nur im erweiterten Modus. Die folgenden Funktionen sind hinzugekommen:

script Execute a script
Mit dieser Aktion kannst du einen Skript ausführen, dass du deinem Spiel hinzugefügt hast. Du gibst den Skript und maximal 5 Argumente an. Siehe im entsprechenden Kapitel für nähere Informationen über Skripte nach.

inherited Call the inherited event
Diese Aktion ist nur nützlich wenn das Objekt ein Elternobjekt besitzt. Es ruft den entsprechen Event im Elternobjekt auf.

Mehr Draw-Aktionen

Die folgenden erweiterten Zeichenaktionen gibt es nur im erweiterten Modus:

font Set a font for drawing text
Du kannst die Schriftart des Textes setzen, diese wird ab diesen Moment verwendet. Es muss eine der Font-Ressourcen, die du definiert hast, sein. Wenn du "No Font" wählst wird Arial Größe 12 benutzt.

Partikel-Aktionen

Ein Set von Aktionen für Partikel gibt es im Extra Registerreiter. Diese Aktionen sind nur in der registrierten Version des Game Maker verfügbar..

Partikelsysteme sind dazu gedacht Spezialeffekte zu erzeugen. Partikel sind kleine Elemente (dargestellt durch einen Pixel oder eine andere Form). Solche Partikel bewegen sich nach festgelegten Regeln umher und können während der Bewegung die Farbe ändern. Viele solcher Partikel zusammen können z.B. Feuerwerk, Flammen, Regen, Schnee, Weltraum usw. erzeugen.

/library/manual/images/particles.jpg

Game Maker beinhaltet ein umfangreiches Partikelsystem, das durch Funktionen genutzt werden kann. Ein eingeschränktes Partikelsystem kann durch die unten beschriebenen Aktionen benutzt werden.

Ein Partikelsystem kann mit verschiedenen Partikeltypen umgehen. Nachdem das Partikelsystem erstellt wurde, muss als erstes der Partikeltyp festgelegt werden. Mit unten genannten Funktionen kann aus 16 Typen gewählt werden. Jeder Typ hat eine feste Form, Grösse, Startfarbe und Endfarbe. Die Farbe wechselt langsam von der Startfarbe zur Endfarbe. Partikel haben eine begrenzte Lebenszeit. Mit dem Typ kannst du die minimale und die maximale Lebenszeit angeben. Partikel haben auch Geschwindigkeit und Richtung. Schliesslich können Gravitation und Fliehkraft auf Partikel wirken.

Nachdem du die Partikeltypen festgelegt hast, musst du sie an bestimmten Stellen im Raum erzeugen. Du kannst entweder eine bestimmte Anzahl von Partikeln von einer Stelle wegfeuern oder einen konstanten Strom. Partikel erscheinen bei Emitern. Ein Partikelsystem kann bis zu 8 Emitter haben die zur selben Zeit arbeiten. Somit musst du, nachdem du die Partikeltypen festgelegt hast, Emiter erstellen und ihnen sagen ob die Partikel abfeuern oder kontinuierlich ausschütten sollen.

Hier ist das komplette Aktionsset. Experimentiere am Besten etwas herum um den gewünschten Effekt zu bekommen.

partsystcreate Create the particle system
Diese Aktion erstellt das Partikelsystem. Es muss erstellt werden bevor andere Aktionen ausgeführt werden. Du musst es nur einmal erstellen. Du kannst die Tiefe der Partikel angeben. Bei großen positiven Werten erscheinen die Partikel hinter der Szene. Wenn du eine negative Tiefe angibst erscheinen sie vor der Szene.

partsystdestroy Destroy the particle system
Diese Aktion zerstört das Partikelsystem, gibt dessen Speicher frei. Vergesse nicht dies zu tun (z.B. wenn in einen anderen Raum gewechselt wird) weil Partikelsysteme viel Speicher beanspruchen.

partsystclear Clear all particles in the system
Diese Aktion entfernt alle sichtbaren Partikel. Es stoppt nicht die Emitter, deshalb können neue Partikel ausgeschüttet werden (siehe unten).

parttypecreate Create a type of particle
Mit dieser Aktion kannst du einen Partikeltyp erstellen. Du kannst aus den 16 möglichen auswählen. Für den Partikeltyp kannst du die Form, die minimale und maximale Größe (wenn die Partikel erschienen werden Zufallswerte dazwischen verwendet) oder das verwendete Sprite. Gibst du ein Sprite an, wird die verwendet, ansonsten die Form. Für diese gibt es noch die Farbe für den Partikelstart und die Farbe auf die sich die aktuelle Farbe hin verändert. Beachte das nur ein Partikeltyp erstellt wird und kein Partikel. Für dies werden Emitter benötigt (siehe unten).

parttypecolor Set the color for a particle type
Ein Partikel kann eine Farbe haben (standardmäßig weiß). Mit dieser Aktion kannst du die Farbe für einen bestimmten Partikeltyp einstellen. Du musst den gewünschten Partikeltyp für den die Farbe genutzt werden soll angeben. Danach legst du fest, wie die Farbe angewandt werden soll. Entweder eine zufällige Farbe zwischen zwei Farben oder ein kontinierlicher Übergang von einer Farbe in die andere ist möglich. Beide Farben müssen angegeben werden. Zum Schluss gibst du die Alphatransparenz an. Du gibst die Werte an, die der Partikel am Anfang und am Ende haben soll. Die Transparenz geht langsam von einem Wert zum Anderen über. Normalerweise sieht es gut aus wenn der Alphawert langsam abnimmt.

parttypelife Set the life time for a particle type
Ein Partikel lebt nur für eine begrenzte Anzahl von Schritten. Danach verschwindet er. Mit dieser Aktion kannst du die Lebenszeit festlegen. Du gibst minimal und maximal an, der Wert liegt mit Zufall dazwischen.

parttypespeed Set the motion for a particle type
Mit dieser Aktion kannst du Richtung und Geschwindigkeit der Bewegung eines Partikeltyps festlegen. Wieder kannst du maximal und minimal angeben, per Zufall dazwischen gewählt. Z.B. um einen Partikel zufällig zu bewegen, gebe 0 und 360 als Grenzen für die Richtung an. Du kannst auch die Gravitation festlegen. Dieser Wert wird in jedem Step von der Geschwindigkeit abgezogen bis sie 0 ist. (Du kannst ihn mit negativen Werten beschleunigen.)

parttypegravity Set the gravity of a particle type
Mit dieser Aktion kannst du die Gravitation für einen bestimmten Partikeltyp festlegen. 270 ist abwärts.

parttypesecondary Create secondary particles
Dies ist etwas komplizierter. Partikel können andere Partikel in ihrer Lebenszeit und beim Zerstören erzeugen. Mit dieser Aktion kannst du das festlegen. Du kannst den Typ und die Anzahl der Partikel die jeden Step in der Lebenszeit erzeugt werden und dasselbe beim Zerstören eines Partikels. Sei hier sehr behutsam. Du kannst sehr leicht große Mengen Partikel auf diese Weise erstellen, welche das System stark verlangsamen können. Für die Zahlen kannst du auch negative Werte verwenden. Ein negativer Wert x bedeutet das z.B. in jedem Step ein Partikel mit der Wahrscheinlichkeit -1/x erzeugt wird. Wenn du z.B. jeden 4. Step ein sekundäres Partikel erstellen willst, so gebe -4 an. Sekundäre Partikel sind großartig um z.B. Partikel um Partikel oder explodierende Partikel darzustellen.

partemitcreate Create a particle emitter
Diese Aktion erzeugt einen Emitter. Partikel werden von Emittern generiert. Du kannst bis zu acht Emitter einsetzen. Wähle den Emitter, seine Form und seine Position und Ausdehnung im Raum (In der Form einer "Randbox").

partemitdestroy Destroy an emitter
Diese Aktion zerstört den angegeben Emitter. Beachte das bereits existierende Partikel von diesem Emitter nicht zerstört werden.

partemitburst Burst a number of particles from an emitter
Selbst wenn du Partikeltyp und Emitter definiert hast musst du immer noch dem Emitter sagen, dass er Partikel erzeugen soll. Mit dieser Aktion kannst du einem bestimmten Emitter sagen, dass er eine bestimmte Menge eines bestimmten Partikeltyps wegschleudern soll. Alle Partikel werden auf einmal erstellt. Du kannst für die Zahl auch einen negativen Wert einsetzen. Ein negativer Wert x bedeutet, das ein Partikel mit der Wahrscheinlichkeit von -1/x erzeugt wird. So z.B., wenn du einen Partikel mit 25%iger Wahrscheinlichkeit erstellen möchtest, nutze den Wert -4.

partemitstream Stream particles from an emitter
Mit dieser Aktion kannst du einen Emitter dazu bringen, bestimmte Partikel auszuschütten. In jedem Step wird diese Anzahl Partikel ausgeschüttet, was in einem kontinuierlichen Partikelstrom mündet. Der Emitter schüttet Partikel aus bis, er zerstört wird oder du ihm mitteilst 0 Partikel auszuschütten. Für die Anzahl kannst du auch negative Werte verwenden. So z.B., wenn du einen Partikel mit 25%iger Wahrscheinlichkeit erstellen möchtest, nutze den Wert -4.

Extra-Aktionen

Im Extra Registerreiter befinden sich auch einige Funktionen zum Abspielen von CDs. Diese Aktionen sind nur in der registrierten Version des Game Maker verfügbar..

cdplay Play a CD
Mit dieser Aktion kannst du einen Track vom Standardlaufwerk des Systems abspielen. Du gibst den Start- und den Endtrack an.

cdstop Stop the CD
Stoppt die CD-Wiedergabe.

cdpause Pause the CD
Pausiert die CD-Wiedergabe.

cdresume Resume the CD
Spielt eine pausierte CD weiter.

ifcd If a CD exists in the drive
Wenn eine CD im Laufwerk ist, wird die nächste Aktion ausgeführt.

ifcdplay If the CD is playing
Wenn die CD abgespielt wird, wird die nächste Aktion ausgeführt.

Schließlich befinden sich hier noch 2 Aktionen, die in manchen Spielen nützlich sein können:

mouse Set the mouse cursor
Du kannst dies nutzen, um den Windows Mauszeiger mit einem Sprite zu ersetzen. Du legst das Sprite fest und ob der Windows Mauszeiger noch gezeigt werden soll. Das Sprite kann eine Animation sein. Beachte das das Sprite nur im Raum und nicht ausserhalb gezeigt wird.

webpage Open a webpage in a browser Du kannst in dieser Aktion eine Internetadresse angeben. Diese Webseite wird im Standardbrowser des PCs geöffnet werden. (Die Aktion kann auch genutzt werden um andere Dokumente zu öffnen.) Die Aktion funktioniert nicht im sicheren Modus.

Mehr über Räume

Räume im Game Maker habe viele Einstellungsmöglichkeiten. In den vorherigen Kapiteln betrachteten wir nur die wichtigsten. In diesem Kapitel beschreiben wir die anderen Optionen. Wenn du einen Raum im erweiterten Modus öffnest sieht er folgendermaßen aus:

/library/manual/images/form_room_advanced.jpg

Wie du siehst wurden, der Toolbar einige neue Buttons hinzugefügt. Diese sortieren die Instanzen horizontal oder vertikal. Dies wird nützlich wenn sich Instanzen überschneiden. (Wenn du Tiles hinzufügst ordnen die Funktionen Tiles anstatt Objekte.) Auch sind dort Buttons um alle Instanzen zu verankern oder zu lösen. Verankerte Instanzen können weder verschoben noch gelöscht werden. Dies bewahrt vor versehentlichem Löschen einer Instanz. Im Kontextmenü (drücke <strg> und klicke mit rechts auf die Instanz) kannst du Instanzen individuell verankern oder lösen.

Schliesslich kannst du angeben ob du ein isometrisches Raster haben möchtest. Dies erleichtert das Erstellen von isometrischen Spielen. Erstens laufen dann die Rasterlinien diagonal. Zweitens ist das Einrasten anders. (Es funktioniert am besten wenn der Befestigungspunkt links oben ist, wie vorgegeben.)

Auch gibt es zwei neue Register, die wir weiter unten besprechen.

Erweiterte Einstellungen

Es gibt zwei weitere Dinge im Register settings, welche wir noch nicht besprochen haben. Zuerst gibt es eine Auswahlbox Persistent. Normalerweise wird beim Verlassen eines Raumes und späterer Rückkehr der Raum auf seine Anfangseinstellungen zurückgesetzt. Das ist gut so, wenn du einige Levels in dem Spiel hast, aber es wird nicht gewünscht, z.B. in Rollenspielen. Hier soll der Raum so bleiben, wie beim letzten Besuch. Aktivieren der Box Persistent macht genau das. Der Raumstatus wird gespeichert und wenn der Raum wieder besucht wird, ist er genauso wie vorher. Nur wenn das Spiel neu gestartet wird, wird der Raum zurückgesetzt. Es gibt aber eine Ausnahme. Wenn du bei bestimmten Objekten Persistent gewählt hast, bleiben die Instanzen der Objekte nicht im Raum, sondern gehen zum nächsten Raum mit.

Zweitens gibt es einen Button Creation code. Hier kannst du jede Art von Code in GML (Erklärung später) eingeben, der beim Start des Raumes ausgeführt wird. Das ist nützlich für z.B. bestimmte Variablen für den Raum, Erstellen bestimmter Instanzen, usw. Es ist wichtig zu verstehen, was passiert, wenn man einen bestimmten Raum im Spiel betritt.

  • Im aktuellen Raum bekommen alle Instanzen ein "room-end Event". Danach werden die nicht persistenten Instanzen entfernt (kein destroy Event wird erstellt!).
  • Danach werden im neuen Raum die persistenten Instanzen vom vorherigen Raum hinzugefügt.
  • Alle neuen Instanzen werden erzeugt und deren "creation Events" werden ausgeführt (wenn der Raum nicht persistent ist oder vorher nie besucht wurde).
  • Wenn es der erste Raum ist, wird für alle Instanzen das "game-start Event" erstellt.
  • Nun wird das room-create Event ausgeführt.
  • Zuletzt bekommen alle Instanzen ein room-start Event.

So kann z.B. das room start-event Variablen benutzten, welche im Erzeugungscode des Raumes gesetzt wurden und im Erzeugungscode kannst du dich auf die Instanzen (beide; neue und dauernde(persistente))im Raum beziehen.

Es gibt noch eine weitere Option. Im Kontextmenü, das erscheint wenn du mit rechts auf eine Instanz klickst und die <Strg> Taste drückst kannst du einen creation code für die spezifische Instanz angeben. Dieser Code wird beim Start des Raumes ausgeführt, gerade vor dem creation event der Instanz. Das ist nützlich, z.B. um bestimmte Eigenschaften, die typisch für die Instanz sind, einzugeben.

Tiles Hinzufügen

Du kannst auch sogenannte getiledte Hintergründe erstellen. Der Idee dahinter ist folgende. In vielen Spielen willst du einen schönen Hintergrund haben, z.B. sollen in einem Labyrinthspiel die Wände des Labyrinth zusammenpassen und in Plattformspielen willst du viele schön gezeichnete Plattformen, Bäume, usw. sehen. Du kannst im Game Maker viele verschiedene Objekte definieren und den Raum mit diesen Objekten erstellen. Das Problem ist aber die viele Arbeit, große Menge an Ressourcen und das Spiel wird langsamer aufgrund der vielen Objekte. Z.B, für schöne Wände in einem Labyrinthspiel werden 15 verschieden gestaltete Wandobjekte benötigt.

Der Standardweg ist, wie in vielen Spielen, die Wände und andere statische Objekte werden im Hintergrund gezeichnet. Aber wie weiß das Spiel ob ein Objekt gegen eine Wand stösst, wenn es nur im Hintergrund gezeichnet wird? Der Trick ist folgender: Du erstellst ein Wandobjekt für das Spiel. Es muss die richtige Größe haben, aber es muss nicht gut aussehen. Wenn der Raum erstellt wird, platziere das Objekt dorthin, wo die Wand ist. Und jetzt der Trick: Mach' das Objekt unsichtbar. Du siehst nur den schönen Hintergrund. Aber die festen Wandobjekte sind noch immer dort und das Objekt im Spiel wird darauf reagieren.

Du kannst diese Technik für jedes Objekt benutzen, welches nicht seine Form oder Position ändert (Du kannst es auch nicht benutzen wenn, das Objekt animiert wird). Für Plattformspiele benötigst du nur einen Boden und ein Wandobjekt, aber du kannst schöne Hintergründe machen, als ob der Spieler auf Gras oder Baumzweigen geht.

Um Tiles hinzuzufügen musst du zuerst einen Hintergrund als Tileset definieren. Wenn die Tiles teilweise transparent sein sollen, Stelle sicher das der Hintergrund transparent ist. Wenn du eine Hintergrund-Ressource hinzufügst, gebe an das sie als Tileset dienen soll. Dann gebe die Größe der Tiles und evtl. den Raum dazwischen an, wie im Kapitel über Hintergrund-Ressourcen beschrieben.

Wenn du nun den Raum definierst gehe in den Reiter tiles. Das folgende Fenster wird angezeigt (hier sind schon Tiles in den Raum eingefügt).

/library/manual/images/form_room_tiles.jpg

Links oben wird das aktuelle Tile angezeigt. Um das Set auszuwählen, klicke auf den Menüknopf darunter und wähle das gewünschte Hintergrundbild.

Nun kannst du Tiles setzen, indem du links oben das gewünschte Tile auswählst und danach auf die gewünschte Stelle im Raum klickst. Dies funktioniert so, wie das Hinzufügen von Instanzen. Darunterliegende Tiles werden entfernt , sofern du die Box Delete underlying nicht abschaltest. Mit der rechten Maustaste kannst du Tiles löschen. Halte die <Shift> Taste gedrückt um mehrere Tiles hinzuzufügen. Halte die <Strg> Taste gedrückt, um ein Tile an eine neue Position zu verschieben. Die <Alt> Taste verhindert das einrasten am Gitter. Es gibt auch wieder ein Pop-Up Menü, das erscheint, wenn du die <Strg> Taste gedrückt hälst und mit der rechten Maustaste auf ein Tile klickst. Die Knöpfe in der Toolbar oben löschen alle Tiles, verschieben alle Tiles, sortieren die Tiles oder sperren/entsperren sie. (Genauer gesagt arbeiten diese nur auf einer Ebene; siehe unten.)

In manchen Situationen möchtest du eine Grafik in den Raum setzen, die nicht der Tilegröße entspricht oder aus mehreren Tiles besteht. Dies kann wie folgt erledigt werden. Im Auswahlfenster links oben kannst du mit der linken Maustaste, während du die <Alt> Taste gedrückt hälst, eine Auswahl treffen. Diese kannst du nun im Raum auf dieselbe Weise wie die Tiles verwenden. Um mehrere Tiles auszuwählen, halte die <Shift> Taste gedrückt. Beachte das das nur korrekt funktioniert, wenn zwischen den Tiles kein Leerraum ist. Wenn du einen Bereich mehrfacher Größe des Raumgitters markieren willst, drücke die <Strg> Taste anstelle der <Shift> Taste. (Beachte das du während des Bewegens die Tasten wechseln kannst. Dies kann manchmal nützlich sein.)

Tiles können auf verschiedenen Ebenen (Layern) mit verschiedener Tiefe liegen. Unten kannst du die aktuelle Tiefe sehen. Standardmäßig ist diese 1000000, was normalerweise hinter allen Instanzen ist, sodass diese sich vor den Tiles bewegen. Du kannst den Add Knopf benutzen um neue Ebenen hinzuzufügen, jede mit einer anderen Tiefe. Negative Tiefen können verwendet werden, um Tiles vor den Objekten anzuzeigen. Wenn du den Objekten eine andere Tiefe gibst, kannst du sie zwischen verschiedenen Ebenen anzeigen lassen. Wenn du Delete drückst wird eine Ebene mit allen sich darin befindlichen Tiles gelöscht. (Es muss immer mindestens eine Ebene geben.) Wenn du Change drückst kannst du die Tiefe einer Ebene ändern. Wenn du ihr dieselbe Tiefe wie einer anderen gibst werden sie vereint.

Tiles zu benutzen ist eine mächtige Möglichkeit, sie sollte so oft wie möglich genutzt werden. Sie sind viel schneller als Objekte und das Bild wir nur einmal abgespeichert. So kannst du sehr große Räume erstellen, die trotzdem nur wenig Speicher verbrauchen.

Views

Zuletzt gibt es ein Register views. Dies gibt dir einen Mechanismus in die Hand, um bestimmte Teile deines Raumes an verschieden Plätzen, am Bildschirm zu zeichnen. Es gibt viele Anwendungen für Views. Zuallererst willst du in einigen Spielen nur einen Teil des Raumes immer zeigen, z.B. im den meisten Plattformspielen, folgt der Sichtbereich  dem Hauptcharakter. In Zwei-Spieler-Spielen willst du des öfteren einen geteilten Bildschirm. Drittens wird in manchen Spielen ein Teil des Bildschirms gescrollt, während der andere Teil stehen bleibt (z. B. eine Statusanzeige). Das kann im Game Maker sehr einfach gemacht werden.

Wenn du das Register views anklickst, werden folgende Informationen gezeigt:

/library/manual/images/form_room_views.jpg

Oben gibt es die Auswahlbox Enable the use of Views. Wenn Views gewünscht werden, muss das angekreuzt werden. Darunter siehst du eine Liste mit 8 Views. Darunter kannst du Informationen über das aktuelle View sehen. Zuerst muss du angegeben, ob das View sichtbar ist, wenn der Raum gestartet wird. Gehe sicher das einer sichtbar ist! Sichtbare Views werden fett gedruckt angezeigt.

Ein View wird durch einen rechteckigen Bereich im Raum definiert, welcher der Bereich ist, der im View angezeigt wird. Du kannst die Position der linken oberen Ecke, die Breite und die Höhe dieses Bereiches festlegen. Danach musst du festlegen, wo der Bereich im Fenster auf dem Bildschirm angezeigt werden soll. Dieser Bereich wird (View)port bezeichnet. Wiederum gibst du die Position der linken oberen Ecke und die Größe an. Wenn du nur ein View hast ist dies normalerweise (0,0). Beachte das die Größe auf dem Bildschirm anders sein kann, als die des Views. In diesem Fall wird der View skaliert um zu passen. (Mit Code ist auch das Rotieren möglich.) Die Ports können sich überlappen. In diesem Fall werden sie nach ihrer Reihenfolge aufeinander gezeichnet.

Wie oben erwähnt, willst du häufig ein bestimmtes Objekt verfolgen. Ganz unten kannst du das Objekt angeben. Wenn mehrere Instanzen dieses Objektes vorhanden sind, wird nur das erste im View verfolgt. (Im Code kannst du diese bestimmte Instanz, der gefolgt werden soll, angeben). Normalerweise soll der Charakter fähig sein zu gehen, ohne dass der View geändert wird. Nur wenn der Charakter nahe am Rand ist, soll der View ändern. Du kannst die Größe des Randes angeben, welcher um das Objekt sein sichtbar soll. Zuletzt kannst du die Geschwindigkeit des Views angeben. Das bedeutet, dass sich die Spielfigur ausserhalb des Bildschirmes bewegen kann, aber es gibt ein geschmeidigeres Spiel. Benutze �1, wenn du den View sofort ändern willst.

Schriftarten

Wenn du in deinem Spiel Text zeichnen möchtest wird dieser in Arial 12 gezeichnet. Um aussergewöhnlicher aussehende Texte zu schaffen kannst du aber die Schriftart ändern. Um andere Schriftarten zu nutzen musst du von diesen Font Ressourcen erstellen. In jeder Font Ressource legst du die Schriftart fest, die später mit der Aktion zum Zeichnen von Text verwendet werden kann.

Um deinem Spiel eine Schriftart hinzuzufügen, benutze den Add Font Knopf im Add Menü oder den passenden Knopf in der Toolbar. Folgendes Fenster erscheint.

/library/manual/images/form_font.jpg

Wie immer solltest du auch einer Font Ressource einen Namen geben. Als nächstes wählst du eine Schriftart aus. Du kannst auch die Größe, und ob sie fett und/oder kursiv sein soll, auswählen. Beachte, das große Schriftarten viel Speicherplatz benötigen. Deshalb empfehle ich keine Schriftarten größer als, sagen wir 32. (Es ist möglich die Schriftarten während des Spieles zu skalieren.) Ein Beispiel in der angegebenen Schriftart wird unten angezeigt.

Eine Schriftart besteht für gewöhnlich aus 256 Zeichen, von 0 bis 255 durchnummeriert. Aber normalerweise nutzt du nur einen Bruchteil davon. Deshalb werden standardmäßig nur die Buchstaben 32 bis 127 gespeichert. Je mehr Zeichen du verwendest, umso mehr Speicher wird benötigt. Du kannst die zu Verwendende Zahl an Buchstaben ändern. Den Index eines Zeichens kannst du mit der Zeichentabelle im Windows Startmenü unter Zubehör/Systemprogramme herausfinden. Einige Standardabschnitte können per Knopfdruck bestimmt werden: Der Normal Abschnitt von 32 bis 127, der All Abschnitt von 0 bis 255, der Digits Abschnitt der nur die 10 Ziffern enthält und der Letters Abschnitt der alle großen und kleinen Buchstaben enthält. Andere Abschnitte können durch Start- und Endposition bestimmt werden. Wenn ein Zeichen nicht im Abschnitt liegt wird es durch ein Leerzeichen ersetzt.

Normalerweise hast du schon eine gute Zahl von Schriftarten auf deinem PC installiert, und es gibt Webseiten mit vielen Hundert mehr. Das Problem ist, dass wenn du eine Schriftart in deinem Spiel verwendest, und das Spiel dann an jemand anderes weitergibst, die Wahrscheinlichkeit hoch ist, das er oder sie die Schriftart nicht auf dem PC hat. Um dies zu umgehen integriert Game Maker alle Schriftarten, die du benutzen willst, im Spiel, aber nur in der Exe. Deswegen musst du beim Weitergeben des Spieles nicht auf die Schriftarten achten. Aber wenn du jemandem die editierbare Version gibst und du aussergewöhnliche Schriftarten benutzt, gebe der Person diese auch gleich mit.

Pfade

In fortgeschrittenen Spielen soll öfters eine Instanz einen bestimmten Pfad folgen. Obwohl so etwas mit Timer oder Code möglich wäre, ist das ziemlich kompliziert. Pfade sind dafür besser geeignet. Die Idee ist einfach. Du bestimmst einen Pfad durch Zeichnen. Nun kannst du eine Aktion erstellen, z. B. im create event. Du befiehlst dem Objekt, einem bestimmten Pfad zu folgen. Dieses Kapitel beschreibt diesen Vorgang im Detail.

Pfade definieren

Um einen Pfad deinem Spiel hinzuzufügen, wähle Add Path vom Add Menü. Das folgende Dialogfenster wird geöffnet (in dem Beispiel haben wir bereits einen kleinen Pfad hinzugefügt).

/library/manual/images/form_path.jpg

Oben links im Fenster kannst du den Namen des Pfades setzen. Darunter findest du die Punkte, die den Pfad bestimmen. Jeder Punkt hat eine Position und eine Geschwindigkeit (speed, kurz sp.). Je nachdem, wie du den Pfad nutzt, ist die Position entweder absolut, d.h. die Instanz, für die du später den Pfad nutzt, wird ihm genau an dieser Stelle folgen, oder relativ, d.h. die Instanz startet immer mit der ersten Position des Pfades und folgt dem Pfad von da an. Die Geschwindigkeit soll wie folgt verstanden werden: Ein Wert von 100 ist die originale Geschwindigkeit der Instanz für den Pfad. Eine niedrigerer Wert verringert die Geschwindigkeit, ein höherer Wert erhöht sie (er zeigt also den Prozentsatz der aktuellen Geschwindigkeit). Die Geschwindigkeit wird zwischen den Punkten interpoliert, sie kann also etwas abweichen.

Um einen Punkt hinzuzufügen drücke den Add Knopf. Eine Kopie des aktuell gewählten Punktes wird gemacht. Du kannst jetzt die aktuelle Position und Geschwindigkeit ändern, indem du Werte überschreibst. Immer wenn du einen Punkt in der Liste wählst, kannst du auch dessen Werte ändern. Drücke Insert um einen neuen Punkt vor dem aktuellen einzufügen, und Delete um den aktuellen Punkt zu löschen.

Rechts im Dialogfenster siehst du den aktuellen Pfad. Der rote Punkt zeigt den aktuell gewählten Kontrollpunkt. Die blauen Punkte sind die anderen Kontrollpunkte. Das grüne Quadrat zeigt die Position, an der Pfad startet. Du kannst den Pfad auch mit der Maus ändern. Klick irgendwo in das Bild, um einen Punkt hinzuzufügen. Klicke auf einen existierenden Punkt und ziehe in, um die Position zu ändern. Wenn du die <shift> Taste während des Klickens auf einen Punkt hältst, fügst du einen Punkt ein. Schließlich kannst du die rechte Maustaste verwenden, um Punkte zu entfernen. (Auf diese Art kannst du aber nicht die Geschwindigkeit ändern.) Normalerweise rasten die Punkte im Gitter ein. Die Gitter-Definitionen kannst du an der oberen Werkzeug-Leiste ändern. Hier kannst du auch bestimmen, ob das Gitter sichtbar sein soll oder nicht. Wenn du einen Punkt exakt positionieren willst, halte die <alt>-Taste beim Hinzufügen oder Bewegen gedrückt.

Du kannst die Form eines Pfades auf zwei Weisen beeinflussen. Erstens durch die Art der Verbindung. Du kannst entweder direkte Verbindungen oder sanfte Kurven nehmen. Zweitens kannst du angeben, ob der Pfad geschlossen sein soll oder nicht.

Auf der Toolbar gibt es einige wichtige Knöpfe. Von links nach rechts haben sie die folgenden Bedeutungen. Der erste schließt das Fenster und speichert den Pfad, wenn du fertig bist. (Wenn du die Änderungen nicht speichern möchtest, klicke auf das X im Fenstertitel.) Als nächstes gibt es den Knopf, der Änderungen Rückgängig macht.

Die daraufhin folgenden Knöpfe erlauben dir den Pfad zu leeren, die Reihenfolge der Punkte umzudrehen, ihn zu verschieben, ihn horizontal zu spiegeln, ihn vertikal zu drehen, ihn zu rotieren und ih zu skalieren. Die nächsten Knöpfe sind für das Bewegen der Ansicht (nicht des Pfades selbst; Der aktuelle Ansichtsbereich wird oben in der Toolbar angezeigt) und um die Ansicht zu zentrieren.

Als nächstes kannst du die Gittergröße bestimmen und festlegen, ob im Gitter eingerastet werden soll. Schließlich gibt es einen Knopf um einen bestimmten Raum als Hintergrund anzuzeigen. Damit kannst du den Pfad einfach im Raum ausrichten, z.B. für eine Rennstrecke, sodass die Instanzen später der korrekten Strecke folgen. (Dies ergibt nur Sinn, wenn du absolute Pfade verwendest; siehe unten.)

Pfade Objekten zuweisen

Um einen Pfad der Instanz eines Objektes zuzuweisen, kannst du die Pfad-Aktion in einem Ereignis platzieren, wie z.B. im create event. Für diese Aktion musst du einen Pfad aus dem herunterklappenden Menü auswählen. Es gibt auch weitere Werte, die du festlegen kannst.

Du musst den Pfad, dem gefolgt werden soll, sowie die Geschwindigkeit in Bildpunkten pro Schritt festlegen. Wenn die Geschwindigkeit positiv ist, startet die Instanz am Anfang des Pfades. Wenn sie negativ ist, startet sie am Ende. Bedenke, dass wenn du den Pfad festgelegt hast, du die aktuelle Geschwindigkeit relativ zu dieser festgelegten Geschwindigkeit festlegst. Es gibt auch eine Aktion, mit der du die Geschwindigkeit ändern kannst, in der der Pfad ausgeführt wird. Du kannst davon Gebrauch machen um z.B. die Instanz langsamer oder schneller werden zu lassen während sie dem Pfad folgt. Beachte, dass die normale Geschwindigkeit ignoriert wird (eigentlich wird sie auf 0 gesetzt), wenn ein Pfad ausgeführt wird. Weiterhin haben Dinge wie Gravitation und Reibung keinen Einfluss auf die Bewegung auf dem Pfad.

Als nächstes legst du das Schluss-Verhalten (end behavior) fest, das bestimmt, welches passieren soll, wenn das Ende des Pfades erreicht ist. Du kannst die Bewegung stoppen und den Pfad damit Beenden. Du kannst den Pfad auch von vorne beginnen lassen, die Instanz springt dann zurück zu dem Punkt an dem der Pfad gestartet wurde, und führt den Pfad erneut aus. Eine dritte Option erlaubt es dir, den Pfad von der derzeitigen Position aus neuzustarten, die Instanz folgt dann wieder dem Pfad, aber nun von seiner jetzigen Position aus (Das ist dasselbe, wie wenn der Pfad in sich geschlossen ist). Als Letztes kannst du wählen, dass die Bewegung rückwärts abläuft, und die Instanz damit auf dem Pfad zurückbewegt wird. Beachte, dass am Ende des Pfades zusätzlich das end of path event (Ende des Pfades-Ereignis) ausgeführt wird; siehe unten.

Schließlich kannst du einstellen ob der Pfad absolut oder relativ sein soll. Ein absoluter Pfad wird an der Stelle ausgeführt, an der er festgelegt wurde. Die Instanz wird an die Startposition gesetzt und von dort aus bewegt (bzw. von der Endposition aus wenn die Geschwindigkeit negativ ist). Das ist nützlich wenn du z.B. eine Rennstrecke und einen Pfad dafür angelegt hast. Wenn du relative auswählst fängt die Instanz dem Pfad von ihrer derzeitigen Position aus zu folgen. Das ist nützlich wenn die Instanz eine Bewegung an Ort und Stelle ausführen soll. Zum Beispiel Raumschiffe in einem "Space Invaders"-Spiel können einen bestimmten Zug von ihrer Position aus machen.

Wenn du die Instanz auf eine andere Position auf dem Pfad platzieren willst, kannst du die Aktion set the path position (Setze die Pfad-Position) benutzen. Eine Pfad-Position liegt immer zwischen 0 und 1, wobei 0 für die Startposition und 1 für die Endposition des Pfades steht. Beachte, dass während jedem Schritt die Richtungs-Variable (direction) automatisch in korrekte Richtung eingestellt wird. So kannst du diese Variable benutzten um z.B. das passende Einzelbild zu wählen.

Wenn du Skripte oder pieces of code benutzt hast du mehr Kontrolle über die Möglichkeiten der Ausführung des Pfades. Es gibt eine Funktion um einen Pfad für eine Instanz zu starten. Die Variable path_position bestimmt die derzeitige Position auf dem Pfad (zwischen 0 und 1, wie oben bereits beschrieben). Die Variable path_speed bestimmt die Geschwindigkeit auf dem Pfad. Eine Variable path_scale kann benutzt werden um den Pfad zu skalieren. Ein Wert von 1 ist die normale Größe. Ein größerer Wert macht den Pfad größer; Ein kleinerer Wert macht ihn kleiner. Die Variable path_orientation bestimmt die Ausrichtung in der der Pfad ausgeführt wird (in Grad gegen den Uhrzeigersinn). Dies erlaubt dir den Pfad in einer anderen Ausrichtung (z.B. von oben nach unten statt von links nach rechts). Weiterhin gibt es eine Variable um das Endverhalten (end behavior) zu bestimmen. Schließlich gibt es noch eine Menge Funktionen um die Eigenschaften von Pfaden zu erfragen (z.B. die x- und y-Koordinate an bestimmten Positionen), sowie Funktionen um Pfade zu erstellen. Es gibt sogar Funktionen, die kollisionsfreie Pfade erstellen, um ein bestimmtest Ziel zu erreichen. Schaue in spätere Kapitel über GML für Details.

Du fragst dich vielleicht, was passiert, wenn die Instanz mit einer anderen Instanz kollidiert, während sie einem Pfad folgt. Grob gesagt passiert das gleiche wie wenn die Instanz sich mit einer Geschwindigkeit bewegt. Wenn dort eine feste (solid) Instanz ist, wird die Instanz auf ihre voherige Position zurückgesetzt. Wenn beide Instanzen fest (solid) sind werden sie auf ihre neuen Positionen gesetzt . Als nächstes werden die Kollision(s)-Ereignis(se) durchgeführt und es wird kontrolliert ob die Kollision sich aufgelöst hat. Falls nicht und die andere Instanz ist fest (solid), stoppt die Instanz, sowie sie sollte (angenommen ein Kollisions-Ereignis wurde definiert). Zusätzlich, wird die Variable path_position nicht erhöht. Wenn die blockierende Instanz verschwindet wird die Instanz weiter ihrem Pfad folgen. Um die Kollisionen selbst zu handhaben kann die Variable path_positionprevious nützlich sein. Sie beinhaltet die vorherige Position für den Pfad und du kannst die Pfad-Position gleich dieser Variable setzen, um Vorwärtskommen auf dem Pfad zu vermeiden.

The path event

Wie oben bereits beschrieben, kannst du festlegen was passieren soll wenn die Instanz das Ende des Pfades erreicht. An diesem Punkt tritt das End of path Event ein. Du findest es unter den other. Hier kannst du dann Aktionen plazieren. Vielleicht möchtest du die Instanz dann zerstören, oder sie einem neuen (anderen) Pfad folgen lassen.

Zeitleisten

In vielen Spielen müssen bestimmte Dinge zu einem gewissen Zeitpunkt geschehen. Du kannst dies auch mit Alarm-Events machen, aber wenn es zu kompliziert wird, funktioniert das nicht mehr. Eine Zeitleisten Ressource ist dafür gedacht. In einer Zeitleiste gibst du an, welche Aktion zu einem bestimmten Zeitpunkt geschehen soll. Du kannst alle Aktionen, die für die verschiedenen Ereignisse vorhanden sind, benutzen. Wenn eine Zeitleiste erstellt ist, kannst du sie mit einer Instanz eines Objekte verbinden. Diese Instanz führt die Aktion zum angegebenen Zeitpunkt aus. Lass' mich ein Beispiel zeigen. Vorausgesetzt du willst eine Wache erstellen. Diese Wache sollte 20 Zeitschritte lang nach links, 10 nach oben, 20 nach rechts, 10 nach unten gehen und dann stehen bleiben. Dafür musst du eine Zeitleiste erstellen, beim Start setzt du die Bewegung nach links. Beim Zeitpunkt 20 setzt du die Bewegung nach oben, beim Zeitpunkt 30 die Bewegung nach rechts, beim Zeitpunkt 50 eine Bewegung nach unten und beim Zeitpunkt 60 hälst du die Bewegung an. Nun kannst du die Zeitleiste mit der Wache verbinden und die Wache wird genau das Geplante machen. Du kannst auch eine Zeitleiste benutzen, um die Steuerung des Spieles globaler zu halten. Erstelle ein unsichtbares Kontrollerobjekt, erstelle eine Zeitleiste, welche an bestimmten Zeitpunkten Feinde erstellt, und weise es dem Kontrollerobjekt zu. Wenn du anfängst, damit zu arbeiten, wirst du feststellen, dass dies ein sehr wirkungsvolles Konzept ist.

Um eine Zeitleiste zu erstellen wähle Add Time Line vom Add Menü. Das folgende Fenster wird geöffnet.

/library/manual/images/form_timeline.jpg

Es sieht so ähnlich wie das Objekteigenschaftsfenster aus. Links kannst du den Namen sehen und es sind Buttons zum Hinzufügen und Verändern von Zeitleisten vorhanden. Daneben ist eine Liste von Zeitpunkten. Diese Liste gibt die Zeitpunkte in Zeitschritten an, wenn die zugeteilte Aktion stattfinden soll. Daneben werden die Aktionen des gewählten Zeitpunktes aufgelistet und ganz rechts ist das ganze Set von den Aktionen verfügbar.

Um einen Zeitpunkt hinzuzufügen drücke den Add Knopf. Gib den Zeitpunkt an(das ist die Anzahl der Schritte seit die Zeitleiste gestartet wurde). Nun kannst du die Aktion eintragen in die Liste genauso wie im Event der Objekte. Es gibt auch Buttons um den gewählten Zeitpunkt zu löschen, den Zeitpunkt zu ändern und zum Löschen der Zeitleiste.

Zuletzt gibt es zwei spezielle Schaltflächen. Mit dem Merge Knopf kannst du alle Zeitpunkte eines Zeitraumes in einen Zeitpunkt vermischen. Mit dem Shift Knopf kannst du alle Zeitpunkte in einem Zeitraum durch Angabe eines Wertes nach vorne oder hinten verschieben. Gehe sicher, keine negativen Zeitmomente zu erschaffen. Diese werden nie ausgeführt.

Es gibt zwei Aktion die sich auf Zeitleisten beziehen.

timeline Set a time line
Mit dieser Aktion setzt du die bestimme Zeitleiste für eine Instanz eines Objektes. Du gibst die Zeitleiste und die Startposition in der Zeitleiste (0 zum Beginnen) an. Du kannst diese Aktion auch für das Ende einer Zeitleiste benützen, einfach "No Time Line" als Wert wählen.

timelineset Set the time line position
Mit dieser Aktion kannst du die Position in der aktuellen Zeitleiste (beide absolut oder relativ) bestimmen. Das kann benutzt werden, um bestimmte Teile der Zeitleiste zu überspringen oder bestimmte Teile zu wiederholen. Wenn du also eine Zeitleiste in einer Schleife laufen lassen willst, füge diese Aktion im letzten Moment ein und setze als Position 0. Du kannst dies genauso benutzen um auf irgendetwas wartest. Füge die Test-Aktion hinzu, und wenn nicht diese nicht "wahr" (true) ist, setzte die Zeitleistenposition relativ zu �1.

Scripts

Game Maker hat eine eingebaute Programmiersprache. Wenn du einmal mit dem Game Maker vertraut bist, und den vollen Umfang ausreizen willst, ist es vorteilhaft, das Verwenden der Sprache zu erlernen. Für eine komplette Beschreibung schaue mal in die GML Kapitel. Es gibt zwei Wege die Sprache zu nutzen. Zuerst kannst du Skripte erstellen. Das sind Teile eines Codes, denen du einen Namen gibst. Diese werden im Ressourcenbaum gezeigt und können in einer Datei gespeichert oder von einer Datei geladen werden. Sie können zum Erstellen von Bibliotheken verwendet werden, welche die Möglichkeiten vom Game Maker stark erweitern. Du kannst auch eine Code Aktion in manchen Events einfügen und ein Stück Code dort eingeben. Code Aktionen haben keinen Namen und können keine Argumente verwenden. Auch haben sie das bekannte Auswahlfeld um zu bestimmen für welches Objekt die Aktion ausgeführt wird. Dann gibst du den Code auf dieselbe Weise wie bei Skripten ein. Wir konzentrieren uns jetzt aber auf Skripte in diesem Kapitel.

Wie vorher beschrieben, ist ein Skript ein Stück Code in der eingebauten Programmiersprache, dass einen bestimmten Task(Aufgabe) ausführt. Ein Skript kann einige Argumente beinhalten. Um ein Skript von irgendeinem Event aus auszuführen, kannst du die Skript Aktion benutzen. In dieser Aktion gibt du den auszuführenden Skript an, gemeinsam mit höchstens 5 Argumenten. (Du kannst auch eine Skript im piece of code ausführen genauso wie du Funktionen ausführst, dann kannst du bis zu 16 Argumente angeben). Wenn das Skript einen Wert zurückgibt, kannst du es als Funktion nutzen um Werte in anderen Aktionen nutzbar zu machen.

Um Skripte in dein Spiel hinzuzufügen, wähle Add Script vom Add Menü. Das folgende Fenster wird geöffnet (im folgende Beispiel haben wir bereits ein kleines Skript erstellt, welcher das Produkt der zwei Argumente zurückgibt).

/library/manual/images/form_script.jpg

(Das ist der eingebaute Skripteditor. In den Einstellungen kannst du auch einen externen Editor angeben). Rechts oben kannst du den Namen des Skriptes eingeben. Im kleinen Editor kannst du das Skript eingeben. Beachte das unten eine Liste aller Funktionen, eingebauter Variablen und Konstanten angezeigt wird. Dies hilft dir die zu finden die du brauchst. Per Doppelklick (oder per <Strg>-P) kann man sie hinzufügen. Diese Liste kann in den Optionen abgeschaltet werden.. Der Editor hat einige nützliche Eigenschaften, die meisten sind mit Schaltflächen erreichbar. (drücke die rechte Maustaste für zusätzliche Befehle):

  • Mehrfaches Rückgängig machen und Wiederholen einer Eingabe entweder pro Tastendruck oder in Gruppen (kann in den Einstellungen geändert werden)
  • Automatisches intelligentes Einrücken von Zeilen, dass sich nach der vorherigen Zeile richtet (kann in den Einstellungen gesetzt werden)
  • Intelligenter Tabulator, der bis zum ersten nicht freien Platz in der vorherigen Zeile springt (kann in den Einstellungen gesetzt werden)
  • Benutze <Strg> um gewählte Linien einzurücken und <Shift><Strg> um gewählte Linien nicht einzurücken
  • Ausschneiden und Einfügen
  • Suchen und Ersetzen
  • Benutze <Strg> und oben, unten, Bild auf oder Bild ab zum Scrollen ohne die Cursorposition zu ändern
  • Drücke F4 um einen Skript oder Ressource, deren Name auf der Cursorposition ist, zu öffnen (funktioniert nicht in der Code Aktion; nur in Skripts)
  • Speichern und Laden des Skriptes als Textdatei

Es gibt auch eine Schaltfläche zum Testen ob das Skript korrekt ist. Nicht alle Aspekte können zu diesem Zeitpunkt getestet werden, aber der Syntax deines Skriptes wird getestet, zusammen mit der Existenz der benutzten Variablen.

Wie du wahrscheinlich bemerkt hast, sind Teile des Skripttextes farbig. Der Editor kennt die existierenden Objekte, eingebauten Variablen und Funktionen, usw. Farb-Coding ist sehr hilfreich um Fehler zu vermeiden. Du siehst sofort ob du einen Namen falsch geschrieben hast oder ein Schlüsselwort als Variable verwendet hast. Farb-Coding ist ein bisschen langsam. In den Einstellungen im File Menü kannst du Farb-Codung ein- und ausschalten. Hier kannst du auch die Farbe der verschiedenen Komponenten des Programms einstellen. (Wenn manchmal etwas beim Farb-Coding schief geht, drücke zweimal <f12>, um es aus- und wieder einzuschalten). Du kannst auch die Schriftart für Skripte und Code umstellen.

Skripte sind sehr nützlich um die Fähigkeiten des Game Maker zu erweitern. Das bedeutet dass du das Design der Skripte sorgfältig erledigen musst. Skripte können in Bibliothek gespeichert werden und deinem Spiel hinzugefügt werden. Um eine Bibliothek zu importieren, benutze Import scripts vom File Menü. Um Skripte im Form von Bibliotheken zu speichern benutze Export scripts. Skript Bibliotheken sind einfache Textdateien (obwohl sie die Dateierweiterung .gml besitzen). Am besten bearbeite sie nicht direkt, da sie eine spezielle Struktur haben. Manche Bibliotheken mit nützlichen Skripten sind beigefügt. (Um unnötige Arbeit beim Laden des Spieles zu vermeiden, lösche nach dem Importieren der Bibliothek die Skripte die du nicht benötigst).

Wenn du ein Skript erstellst kannst du leicht Fehler machen. Teste deine Skripts immer über den dazu zu verwendenden Knopf. Wenn während des Ausführens eines Skriptes ein Fehler auftritt, wird dies mit dem Typ des Fehlers und der Stelle gemeldet. Selten wirst du ein Pop-Up mit dem Text "Unexpected error occurred during the game" sehen. Dieser Fehler ist auf Windows oder auf die Hardware zurückzuführen. Oft wird dies durch unendlich Rekursion, ungenügend Speicher oder schlechte Hardware, Treiber oder Firmware zurückführbar sein. Generell liegen diese Probleme ausserhalb des GM-Bereiches. Wenn du einige Dinge noch genauer prüfen willst, benutzt du am besten den Debug Modus. Nun erscheint ein Fenster, in dem du viele Informationen deines Spieles überwachen kannst.

/library/manual/images/form_debug.jpg

Im Run Menü kannst du das Spiel anhalten, es Schritt für Schritt ablaufen lassen und es sogar neu starten. Im Watch Menü kannst du dir die Werte einiger Ausdrücke anschauen. Benutze Add um den Ausdruck anzugeben, dessen Wert bei jedem Step angezeigt werden soll. Auf diese Weise kannst du herausfinden, ob dein Spiel korrekt läuft. Du kannst viele Ausdrücke überwachen. Du kannst sie für spätere Benutzung speichern (z.B. nachdem du eine Korrektur am Spiel gemacht hast.). Im Tools Menü findest du Einträge um noch mehr Informationen anzuzeigen. Du kannst eine Liste aller Instanzen im Spiel sehen, alle globalen Variablen beobachten (nunja, zumindest die wichtigsten) und die lokalen Variablen einer Instanz (entweder über den Objektnamen oder über die ID der Instanz). Du kannst auch die Nachrichten sehen, die du über den Code show_debug_message(str) senden kannst. Schließlich kannst du dem Spiel auch Kommandos geben und die Geschwindigkeit verändern. Wenn du komplexe Spiele machen möchtest, solltest du lernen mit der Debug Funktion umzugehen.

Der letzte Schliff für dein Spiel

Sobald du dein Spiel weiterverteilen möchtest, vergewisserst du dich besser, dass es alle Bestandteile besitzt, die es zu einem guten Spiel machen. Neben dem Spiel selbst bedeutet es, dass du eine Beschreibung des Spiel bereitstellst, die korrekten globalen Spieleinstellungen setzt und auf die Ausführungsgeschwindigkeit kümmerst. Dieser Abschnitt versorgt dich mit Informationen über diese Aspekte.

Spielbeschreibung

Ein gutes Spiel versorgt den Spieler mit einigen Informationen wie man das Spiel spielt. Diese Informationen werden angezeigt, wenn der Spieler während des Spiels die <F1> Taste drückst. Um die Spielbeschreibung zu erstellen, klicke doppelt auf Game Information im Ressourcen-Baum (Spielkomponenten)auf der linken Bildschirmseite. Ein kleiner integrierter Editor wird geöffnet, in dem du die Spielbeschreibung bearbeiten kannst. Du kannst verschiedene Farben, unterschiedliche Schriftarten und Schriftstile verwenden. Zudem kannst du die Hintergrundfarbe setzen.

Im File Menü kannst du eine Anzahl von Options bestimmen. Hier kannst du die Titelleiste der Spielbeschreibung im Spiel festlegen. Außerdem kannst du die Position (verwende -1 für zentriert) und die Größe des Spielbeschreibungsfensters festlegen und ob es einem Rahmen haben soll und vom Spieler in der Größe verändert werden kann. Du kannst erzwingen, dass das Informationsfenster immer oben liegt und du kannst angeben, ob das Spiel weiterläuft während die Spielbeschreibung eingeblendet wird.

Eine interessante Funktion ist das Nachahmen des Spielfensters. Sobald du diese Option aktivierst, wird das Spielbeschreibungsfenster exakt dem Spielfenster angepasst in punkto Position und Größe. Das Ergebnis sieht dann so aus, als ob der Text im Spielfenster erscheint. Die Wahl der richtigen Hintergrundfarbe ergibt einen netten visuellen Effekt. (Möglicherweise willst du am Ende der Hilfe-Datei den Spieler darauf aufmerksam machen, dass er durch drücken der Escape-Taste, das Spiel fortsetzen kann.)

Ein guter Rat: Halte die Spielbeschreibung kurz aber präzise. Natürlich solltest du deinen Namen erwähnen, weil du ja das Spiel erstellt hast. Alle Beispiele, die mitinstalliert wurden, enthalten eine Info-Datei über das Spiel und wie es entstand.

Falls du eine schickere/noblere Hilfe erstellen willst, verwende ein Programm, wie Word. Wähle dann den Teil aus, den du verwenden willst und transferiere ihn mittels kopieren und einfügen in den "game information editor". Für professionellere Spiele wirst du diesen Mechanismus wahrscheinlich nicht verwenden, sondern spezielle Räume (rooms) erstellen, um die Hilfe zum Spiel anzuzeigen.

Globale Spieleinstellungen

Es gibt eine Anzahl von Einstellungen, die du für dein Spiel verändern kannst. Diese verändern die Form des Hauptfensters, setzen einige Grafikoptionen, befassen sich mit Interaktionseinstellungen, bis hin zum Ladebild , Konstanten und Informationen über den Erstellers des Spiels. Zudem kannst du hier angeben, welche Dateien zu einem "stand-alone game" dazugehören und wie Fehler behandelt werden sollen.

Die Einstellungen können durch Doppelklicken auf Global Game Settings im Ressourcen-Baum auf der linken Seite des Bildschirms verändert werden. Sie sind unterteilt in eine Anzahl von Registerkarten. (Manche Optionen sind nur im "advanced mode" (Fortgeschrittenenmodus) zugänglich.)

Graphics options (Grafik- und Fensteroptionen)

Auf dieser Registerkarte kannst du eine Anzahl von Optionen setzen, die auf das grafische Erscheinungsbild deines Spiels bezogen sind. Es ist normalerweise nützlich diese Effekte auszuprobieren, da sie einen entscheidenden Einfluß auf das Aussehen des Spiels haben. Vewgiß nicht, daß verschiedene Benutzer unterschiedliche Rechner besitzen. Vergewissere dich, daß die Einstellungen auch auf den Rechnern anderer funktionieren.

Start in fullscreen mode (Starte im Vollbildmodus)
Falls markiert läuft das Spiel im Vollbildmodus, ansonsten in einem Fenster.

Scaling (Skalierung)
Hier kannst du angeben, was passiert, wenn das Fenster größer als der "room" ist oder falls das Spiel im Vollbildmodus läuft. Es gibt drei Wahlmöglichkeiten. Du kannst eine feste Skalierung angeben. Der "room" wird dann skaliert, mit dem angegebenen Betrag, in der der Mitte des Fensters oder des Bildschirms gezeichnet. 100 bedeutet keine Skalierung. Typischerweise verwendet man feste Skalierungen, wenn die "sprites" und "rooms" sehr klein sind. Die zweite Möglichkeit ist die Skalierung des "room" in der Art, daß er den Bildschirm/ das Fenster ausfüllt unter Beibehaltung des Seitenverhältnisses (das Verhältnis zwischen Breite und Höhe). Die dritte Möglichkeit ist die Skalierung auf maximale Ausdehnung (der Bilschirm/das Fenster ist komplett gefüllt). Dies kann zu Bildverzerrungen führen (besonders im Fenstermodus, wo der Benutzer das Fenster in der Größe verändern kann).

Interpolate colors between pixels (Interpolieren von Farben zwischen Pixeln)
Falls markiert, werden die Farben von Pixeln (von "sprites", Hintergründen und Kacheln ("tiles")), die nicht auf den Pixeln des Bildschirms liegen interpoliert. Dies ist insbesondere der Fall, wenn sie skaliert, rotiert oder auf nicht-ganzzahlige Positionen gesetzt werden. Interpolation macht die Bewegung flüssiger, kann aber auch einen "verwaschenen" Effekt erzeugen. (Bei "tiles" (Kacheln) kann es zu Lücken/Rissen führen, sofern sie nicht sorgfältig erstellt wurden.)

Color outside the room region (Rahmenfarbe festlegen)
Falls der "room" den Bildschirm/ das Fenster nicht komplett ausfüllt, entstehen unbenutzte Flächen. Hier kannst du die Einfärbung dieser Flächen festlegen.

Allow the player to resize the game window (Zulassen von Größenänderungen des Spielfensters durch den Spieler)
Falls markiert, kann der Spieler durch klicken und ziehen mit der Maus auf eine Ecke des Spielfensters, dessen Größe änder (nur im Fenstermodus möglich).

Let the game window always stay on top (Spielfenster liegt immer obenauf)
Falls markiert, liegt das Spielfenster immer über allen anderen Fenstern.

Don't draw a border in windowed mode (Zeichne keinen Rahmen im Fenstermodus)
Falls markiert, hat das Spiel im Fenstermodus keinen Rahmen und keine Titelleiste.

Don't show the buttons in the window caption (Unterdrücke die Schaltknöpfe in der Titelleiste)
Falls markiert, werden die Schaltknöpfe zum Schließen/Minimieren/Maximieren in der Titelleiste nicht angezeigt.

Display the cursor (Stelle den Mauszeiger dar)
Gibt an, ob der Mauszeiger sichtbar oder unsichtbar ist. Abgeschaltet ist es gewöhnlich schneller und hübscher. (Du kannst sehr einfach dein eigenes Mauszeigerobjekt im Game Maker machen.)

Freeze the game when the form looses focus (Einfrieren des Spiels bei Fokusverlust)
Falls markiert, friert das Spiel ein, wenn der Spieler ein anderes Fenster aktiviert (z. B. wenn ein anderes Programm gestartet wird) - solange, bis das Spielfenster wieder aktiviert wird.

Resolution (Bildschirmauflösung)

Auf dieser Registerkarte kannst du festlegen, in welcher Auflösung dein Spiel laufen soll. Voreingestellt wird die Auflösung nicht verändert. Aber manchmal möchtest du, dass das Spiel in einer niedrigeren Auflösung läuft oder du möchtest die Monitorfrequenz einstellen, um sicherzugehen, dass das Timing (Synchronisierung) richtig stimmt. Falls du die Auflösung ändern willst, musst du zuerst das Kästchen aktivieren, welches mit Set the resolution of the screen bezeichnet ist.

Drei Dinge kannst du dort einstellen. Zuerst die Farbtiefe. Dies gibt die Anzahl von Bits an, die für die Farbinformationen eines Pixels verwendet werden. Die meisten Rechner unterstützen 16-bit (High Color) oder 32-bit (Full Color) aber ältere Rechner erlauben auch 8-bit und manchmal 24-bit color. Game Maker arbeitet nur im 16-bit und 32-bit Farbmodus korrekt. 32-bit Farbmodus erzeugt hübschere Grafiken, verbraucht aber auch mehr Arbeitsspeicher und Prozessorleistung. Falls du möchtest, dass dein Spiel auch auf älteren Rechnern läuft, setzte die Farbtiefe auf 16-bit. Ansonsten verwende 32-bit oder lass es, wie es ist.

Zweitens gibt es die Bildschirmauflösung, die Anzahl der Pixel (horizontal und vertikal)auf dem Bildschirm. Ein Verändern der Auflösung ist nützlich, wenn z. B. die "rooms" ziemlich klein sind. In diesem Falle hilft es möglicherweise die Bildschirmauflösung zu reduzieren. Mach' dir aber klar, dass dieses auch andere Programme, die grad laufen, beeinflusst. Dies führt manchmal zu Problemen mit niedrigen Auflösungen. Somit ist es besser, dies nur im Vollbildmodus zu machen. Game Maker setzt automatisch wieder die alten Einstellungen, sobald das Spiel beendet wird.

Schließlich kannst du noch die "refresh frequency" (Bildwiederholfrequenz) ändern. Diese gibt an, wie oft in der Sekunde das Bild auf dem Monitor neu gezeichnet wird. Falls deine "room speed" größer als diese Frequenz ist, sind nicht alle "steps" sichtbar. Es funktioniert am besten, wenn die Frequenz ein Vielfaches der "room speed" ist. (Wenn du eine Frequenz festlegst die zu hoch oder nicht verfügbar ist, wird sie nicht verändert.)

Es gibt eine weitere Einstellung, um Abreißen zu vermeiden: Use synchronization to avoid tearing. Dies erfordert einige Erklärungen. Eine Anzeige wird mehrere Male in der Sekunde wiederholt, abhängig von der Bildwiederholfrequenz. Falls nun ein "room" zur Hälfte in so einer Auffrischphase gezeichnet wird, erscheint in in der oberen Hälfte des Bildschirms das alte Bild, während in der unteren schon das Neue angezeigt wird. Diesen Effekt nennt man "tearing" (to tear = durchreißen,losreißen). Um ihn zu vermeiden, aktiviere diese Option. In diesem Fall wird das neue Bild erst angezeigt, wenn die Auffrischung abgeschlossen ist. Die nächste Auffrischung zeigt dann das Neue Bild. Somit synchronisieren wir die Bilddarstellung mit der Bildwiederholfrequenz. Ein Nachteil ist, dass man auf das Ende des Auffrischens warten muss. Auch bricht die Framerate auf die Hälfte ein, wenn das Bild nicht schnell genug berechnet werden konnte. Um Konflikten zwischen internen Timings und dem Monitor aus dem Weg zu gehen setze die Raumgeschwindigkeit auf 30 oder 60.

Verschiedene andere Optionen

Hier kannst du eine Anzahl von zusätzlichen Optionen einstellen. Zunächst kannst du einige Tastenvoreinstellungen setzen:

Lass' <Esc> das Spiel beenden
Falls markiert, beendet das Drücken der Esc-Taste das Spiel. Weiter entwickelte Spiele unterdrücken dieses gewöhnlich, weil sie vor beenden des Spiels noch einige Sachen (z.B. Speichern) erledigen wollen. In diesem Falle entferne den Haken aus der Auswahlbox und halte eine eigene Aktion für die ESC-Taste bereit. (Das Drücken des Kreuzchens oben rechts im Fenster generiert auch ein ESC-key-event.)

Taste <F1> zeigt die Spielinformation an
Falls markiert, wird durch Drücken der F1-Taste, die Spielinformation angezeigt.

Laß' <F4> zwischen den Bildschirmmodi wechseln
Falls markiert wechselt die F4-Taste zwischen Vollbild und Fenster-Ansicht.

Verwende <F5> and <F6> zum Laden und Speichern des Spiels
Falls markiert, kann der Spieler <F5> verwenden, um das aktuelle Spiel zu speichern und <F6> um das zuletzt gespeicherte wieder zu laden. (Beachte, das nur die Grundlegenden Spieleigenschaften abgespeichert werden, erweiterte Funktionen wie Partikel und Datenstrukturen bleiben aussen vor. Dafür musst du die selbst ein System ausdenken.)

Weiterhin kannst du die Priorität des Spiel-Prozesses einstellen. Diese Priorität gibt an, wieviel Prozessorzeit dem Spiel zugeteilt wird. Im "normal mode" versucht das Betriebssystem jedem Prozess ausreichend Rechenzeit zu geben. Je höher du die Priorität einstellst, desto mehr Rechenzeit wird dem Spiel zugewiesen, wodurch es flüssiger läuft. Aber andere Prozesse bekommen weniger Zeit (auch Windowsprozesse, somit kann es passieren, dass die Maus nicht mehr vernünftig reagiert). Verwende es mit Vorsicht.

Ladeoptionen

Hier kannst du angeben, was passieren soll, wenn ein Spiel geladen wird. Zuallererst kannst du ein eigenes Lade-Bild festlegen. Zweitens kannst du angeben, ob ein Fortschrittsbalken an der Unterkante des Bildes dargestellt werden soll. Du hast drei Möglichkeiten hier. Entweder soll kein Ladebalken angezeigt werden oder der voreingestellte. Du kannst aber auch zwei Bilder angeben: Das Hintergrundbild des Ladebalkens und das Vordergrundbild des Ladebalkens. Du kannst einstellen, ob der Vordergrund-Ladebalken skaliert (das ist voreingestellt) oder gekürzt werden soll, während er wächst. Im zweiten Fall vergewissere dich, dass das Bild ausreichend groß ist, um den Ladebalken auszufüllen. (Beachte, dass beide Bilder in diesem Fall angegeben werden müssen - nicht nur eines.)

Es ist Möglich anzugeben, dass das Lade-Bild transparent sein soll. In diesem Fall gibt das linke untere Pixel des Hintergrundbildes die Transparenzfarbe vor. Weiterhin kann die Lichtdurchlässigkeit (alpha translucency) angegeben werden. Ein Wert von 0 bedeutet völlig durchlässig. Ein Wert von 255 bedeutet völlig undurchlässig. (Beides funktioniert nur unter Windows 2000, XP, oder später.)

Als zweites kannst du hier angeben, welches Icon für ein "stand-alone game" verwendet werden soll. Du kannst nur 32x32 Icons benutzen. Falls du eine andere Art von Icon zu benutzen versuchst, bekommst du eine Warnung.

Schliesslich kannst du noch die einzigartige "game id" ändern. Diese id wird verwendet beim Speichern der Highscoreliste und beim Speichern von Spielständen. Falls du eine neuere Version deines Spiels herausgibst und nicht die alte Highscoreliste übernehmen willst, solltest du diese Nummer ändern.

Konstanten

Unter dieser Registerkarte kannst du globale Konstanten definieren, die innerhalb von allen Skripten und Codeschnipseln oder als Werte für Aktionen verwendet werden können. Jede Konstante hat einen Namen und einen Wert. Bei der Benennung sollten die gleichen Regeln beachtet werden, wie bei den Variablen, diese sind, sie müssen mit einem Buchstaben oder dem Unterstrich anfangen und dürfen weiterhin nur aus Buchstaben, Ziffern oder dem Unterstrich bestehen. Es ist äußerst empfehlenswert, dass du deine Konstanten einfach unterscheidbar gestaltest. Eine übliche Vereinbarung ist, sie nur mit Großbuchstaben und dem Unterstrich zu bilden.

Ein Wert einer Konstanten sollte aus einem konstanten Ausdruck bestehen. Das heißt, es ist entweder eine konstante Zahl oder eine Zeichenkette (eingegrenzt von Anführungszeichen) oder ein Ausdruck. Der Ausdruck wird bestimmt, bevor irgendwas anderes in dem Spiel geschieht. Somit kann er sich beispielsweise nicht auf den aktuellen Raum, eine Instanz oder ein Skript beziehen. Aber er kann die eingebauten Konstanten enthalten oder die namen von Ressourcen.

Du kannst eine Konstante hinzufügen mittels des Add Knopfes und löschen mit dem Delete Knopf. Du kannst den Namen oder Wert einer Konstante ändern, indem du darauf klickst. Ferner gibt es noch Knöpfe, um alle Konstanten zu löschen oder sie zu sortieren (nach Namen).

Einbinden von Dateien in "Stand-alone" Spiele

Wie schon vorher bemerkt, kannst du "stand-alone"(eigenständige) Versionen deines Spiels erstellen. Manchmal benötigt dein Spiel zusätzliche Dateien. Beispielsweise möchtest du Video-Dateien oder Text-Dateien einbeziehen, die in dem Spiel verwendet werden. In manchen Fällen möchtest du DLLs oder Bilder und Sounds hinzufügen, die während des Spielverlaufs geladen werden. Du kannst diese zusammen mit der ausführbaren "stand-alone"-Datei bereitstellen aber manchmal ist es einfacher, sie in Datei einzubinden. Auf diese Weise braucht nur eine Datei weitergegeben werden.

Du kannst die Dateien, welche du in die exe-Datei einfügen möchtest, hier angeben. Oben in dem Formular befindet sich eine Liste der einzubindenden Dateien. Verwende Add um Dateien zu selektieren und der Liste hinzuzufügen (du kannst mehrere Dateien auswählen). Verwende Delete oder Clear um Dateien von der Liste zu entfernen. (Mache dir klar, dass diese Dateien nicht in die .gm6-Datei integriert werden - nur ihre Namen. Falls du also jemandem die editierbare .gm6-Datei zusenden möchtest, solltest du auch die Dateien mitsenden, die eingebunden werden sollen.)

Die Dateien in der Liste werden in die exe-Datei eingepackt, die erstellt wird. Wenn das Spiel gestartet wird, werden diese ausgepackt und können aus dem Spiel heraus angesprochen werden. Es ist wichtig, sich klar zu machen, wo dies geschieht. Es gibt zwei Möglichkeiten, die du auswählen kannst. In der voreingestellten Situation werden die Dateien in den Ordner entpackt, indem sich auch das "stand-alone" Spiel befindet. Dies ist gleichzeitig auch das Arbeitsverzeichnis des Spiels. Somit kann das Spiel einfach die Dateinamen verwenden, um auf die Dateien zuzugreifen (es werden keine Pfadangaben benötigt). Dies funktioniert gut, wenn die exe-Datei beispielsweise auf einer Festplatte gespeichert wird, versagt aber, wenn sie auf einem "Nur-Lesen"-Medium gespeichert wird - zum Beispiel auf einer CD.

Die zweite Möglichkeit ist anzugeben, dass die Dateien in einem temporären Verzeichnis entpackt werden sollen, welches zur Laufzeit des Spiels erstellt wird. Falls du diese Option wählst, musst du die Pfadangabe zu diesem Verzeichnis bereitstellen, wenn du die Datei während des Spiels verwenden willst. Dieser Pfad kann erhalten werden durch verwenden der internen Variable temp_directory. Vergiss nicht in diesem Fall den Backslash (zurückgelehnter Schrägstrich) hinzuzufügen. Um zum Beispiel eine Videodatei abzuspielen verwende folgendes Code-Beispiel:

{
show_video(temp_directory+'\movie.avi',true,true);
}
Beachte, dass dieses temporäre Verzeichnis gelöscht wird, wenn das Spiel beendet wird. Somit kannst du beispielsweise keine Spielstände oder besondere Informationen darin speichern. Wähle diese Option nur, wenn du das Spiel von einer CD starten willst oder wenn du keinerlei Dateien aus dem Spiel heraus schreiben willst.

Falls eine Datei, die entpackt wird, schon existiert, wird sie normalerweise nicht geschrieben. Du kannst dieses Verhalten ändern, indem du Overwrite existing files markierst. Ferner werden die Dateien nicht entfernt, wenn das Spiel beendet wird (solange sie sich nicht im temporären Verzeichnis befinden, welches komplett entfernt wird). Du kannst da ändern, indem du Remove at game end markierst.

Ein Wort der Warnung an dieser Stelle. Wenn du dein Spiel testest, ist das Arbeitsverzeichnis des Spiels das Verzeichnis, wo die .gm6-Datei gespeichert ist. Wenn deine "include files" auch hier gespeichert sind und du auswählst sie beim Spielende zu entfernen, ist es möglich, dass du alle zusammen verlierst! Somit ist es ratsam, sie nicht zusammen mit der .gm6-Datei zu speichern!

Fehlerbehandlung

Hier kannst du eine Anzahl von Optionen einstellen, die sich auf die Meldung von Fehlern beziehen.

Anzeigen von Fehlermeldungen
Falls markiert, werden Fehlermeldungen dem Spieler angezeigt. In der endgültigen Version des Spiels möchtest du diese Option möglicherweise abstellen.

Schreibe Fehlermeldungen in die Datei game_errors.log
Falls markiert, werden alle Fehlermeldungen in eine Datei namens game_errors.log geschrieben, welche sich im Spielverzeichnis befindet.

Abbruch bei allen Fehlermeldungen
Normalerweise sind bestimmte Fehler gravierend, während andere ignoriert werden können. Falls diese Option markiert ist, werden alle Fehler als gravierend eingestuft und führen zu einem Spielabbruch In der endgültige Version des Spieles, die du verteilen willst, möchtest du möglicherweise diese Option aktivieren.

Behandle nicht initialisierte Variablen als 0
Ein häufiger Fehler ist es eine Variable zu verwenden, bevor ihr ein Wert zugewiesen wurde. Manchmal ist es schwierig, dies zu vermeiden. Falls diese Option markiert ist, werden nicht initialisierte Variablen nicht länger als Fehler gemeldet, sondern ihnen wird der Wert 0 zugewiesen. Sei trotzdem achtsam. Es kann auch dazu führen, dass du Tippfehler nicht mehr erkennen kannst.

Informationen über das Spiel

Hier kannst du den Autor des Spiels angeben, die Version des Spiels und einige Information über das Spiel. Zudem wird das letzte Bearbeitungsdatum vermerkt. Dies ist nützlich, falls mehrere Leute an einem Spiel arbeiten oder wenn neuere Version erstellt werden. Diese Informationen sind nicht zugänglich, wenn das Spiel läuft.

Gedanken zur Ausführungsgeschwindigkeit

Wenn du kompliziertere Spiele entwirfst, möchtest du wahrscheinlich, dass sie so schnell wie möglich laufen. Obwohl Game Maker sein Bestes gibt, damit die Spiele schnell laufen, hängt eine Menge davon ab, wie du dein Spiel gestaltest. Andererseits ist es ziemlich einfach, Spiele zu erstellen, die ein Menge Speicher verbrauchen. In diesem Kapitel gebe ich dir ein paar Hinweise, wie du dein Spiel schneller und kleiner machen kannst.

Zuerst betrachte deine verwendeten Sprites und Hintergründe kritisch. Animierte Sprites benötigen viel Speicher und das Zeichnen dieser Sprites kostet viel Zeit. Mach' deine Sprites daher so klein wie möglich. Entferne jedes unsichtbare Gebiet drumherum (das Kommando crop im Editor erledigt dies automatisch). Das gleiche gilt für Hintergrundbilder. Falls du ein bildschirmfüllendes Hintergrundbild verwendest, vergewissere dich, dass du die Hintergrundfarbe abschaltest.

Falls du den Vollbild-Modus verwendest, vergewissere dich, dass die Dimension des Raumes (oder Fensters) niemals größer als die des Bildschirmes ist. Die meistens Grafikkarten sind gut im größer Skalieren von Bildern aber schlecht im kleiner Skalieren! Wennimmer möglich, schalte den Mauszeiger (cursor) ab - es verlangsamt die Grafik.

Sei auch vorsichtig beim Verwenden von vielen Views. Für jeden View wird der Raum neu gezeichnet.

Neben der Grafik gibt es noch andere Aspekte, die die Geschwindigkeit beeinflussen. Vergewissere dich, dass du so wenig Instanzen wie möglich hast. Achte insbesondere darauf, Instanzen, die nicht mehr benötigt werden, zu zerstören (z.B. wenn sie den Raum verlassen). Vermeide viel Arbeit im step event oder drawing event der Instanzen. Oft ist es nicht notwendig, dass Dinge jeden step überprüft werden. Interpretation von code ist halbwegs schnell - aber es ist interpretiert. Auch kosten manche Funktionen und Aktionen viel Zeit; insbesondere diejenigen, welche alle Instanzen überprüfen (beispielsweise die "bounce action").

Bedenke die Behandlung der collision events. Normalerweise bieten sich zwei Optionen. Objekte die keinerlei "collision events" besitzen, werden viel schneller bearbeitet, behandle Kollisionen in den Objekten, von denen nur ein paar Instanzen existieren.

Sei behutsam mit der Verwendung großer Sound-Dateien. Sie verbrauchen viel Speicher und lassen sich schlecht komprimieren. Vielleicht prüfst du, ob du nicht deine mit einer niedrigeren Sample-Rate verwenden kannst.

Abschließend: Falls du ein Spiel erstellen willst, was viele Leute spielen können - teste es auf älteren Rechnern.

Game Maker Language (GML)

Der Game Maker besitzt eine eingebaute Programmiersprache. Diese Programmiersprache geben die viel mehr Flexibilität und Kontrolle als die Standard-Aktionen. Wir diese Sprache wird GML bezeichnet (Game Maker Language). In diesem Abschnitt wird die Programmiersprache GML beschrieben und ein kleiner Überblick über alle (fast 1000) Funktionen und Variablen, um dein Spiel zu steuern, geben.

GML im Überblick

Der Game Maker besitzt eine eingebaute Programmiersprache. Diese Programmiersprache geben die viel mehr Flexibilität und Kontrolle als die Standard-Aktionen. Wir diese Sprache wird GML bezeichnet (Game Maker Language). Es gibt verschiedene Stellen an denen du Code ablegen kannst. Erstens, wenn du ein Skript definierst. Ein Skript ist ein Programm in GML. Zweitens, wenn du einem Event die Code-Aktion hinzufügst. In einer Code-Aktion musst du wiederum GML Code eingeben. Drittens, im Room Creation Code. Und schließlich, wo auch immer du einen Wert in einer Aktion festlegst, kannst du einen GML Ausdruck angeben. Ein Ausdruck ist, wie wir später sehen werden, kein ganzes Programm, aber ein Stück Code welches eine Wert zurückgibt.

In diesem Kapitel werden wir die grundlegenden Strukturen von GML Programmen durchleuchten. Wenn du Programme in GML benutzen möchtest, musst du auf einige Dinge achten. Zuerst müssen alle deine Ressourcennamen (Sprites, Objekte, Sounds, usw.) mit einem Buchstaben beginnen und nur aus Buchstaben Zahlen und dem Unterstrich '_' Symbol bestehen. Ansonsten kannst du sie nicht aus dem Programm ansprechen. Stelle sicher, das alle Ressourcen einmalige Namen besitzen. Achte auch darauf eine Ressource nicht self, other, global, oder all zu benennen, weil diese in GML eine besondere Bedeutung haben. Verwende auch keine der Schlüsselwörter, wie unten angegeben.

Informationen über die GML Programmiersprache können auf den folgenden Seiten gefunden werden:

Ein Programm
Variablen
Zuweisungen
Ausdrücke
Extra Variablen
Adressierung von Variablen in anderen Instanzen
Arrays
If Statement
Repeat Statement
While Statement
Do Statement
For Statement
Switch Statement
Break Statement
Continue Statement
Exit Statement
Funktionen
Skripte
With Konstruktion
Kommentar
Funktionen und Variablen in GML

Ein Programm

Ein Programm besteht aus einer Anzahl von Instruktionen, Statements genannt. Ein Programm muss mit dem Symbol '{' starten und mit dem Symbol '}' aufhören. Zwischen diesen befinden sich die Statements. Statements müssen mit ';' getrennt werden. Deshalb sieht die allgemeine Struktur eines Programms so aus:

{
<Statement>;
<Statement>;
...
}

Es gibt eine Zahl von verschiedenen Typen von Statements, welche unten besprochen werden.

Variablen

Wie jede Programmiersprache beinhaltet auch GML Variablen. Variablen sind Speicherorte, in denen Informationen festgehalten werden können. Sie haben einen Namen, sodass du dich auf sie beziehen kannst. Eine Variable in GML kann entweder eine reelle Zahl oder eine Zeichenkette speichern. Wie auch in vielen anderen Sprachen müssen auch in GML Variablen nicht deklariert werden. Es gibt eine große Zahl eingebauter Variablen. Einige globale, wie mouse_x und mouse_y, welche die aktuelle Mausposition wiedergeben, während sich die anderen auf die lokale Instanz beziehen, für die das Programm läuft. , wie x und y, die die aktuelle Position der Instanz wiedergeben. Eine Variable hat einen Namen, welcher mit einem Buchstaben anfangen muss und nur Buchstaben, Zahlen und das Unterstrich-Symbol '_' enthalten darf. (Die maximale Länge ist 64 Zeichen.) Wenn du eine neue Variable verwendest, wird sie lokal der aktuellen Instanz zugewiesen und ist für Programme in andere Instanzen nicht bekannt (auch für welche desselben Objektes). Du kannst dennoch diese Variablen ansprechen; siehe unten.

Assignments

Ein Assignment weist der Variable einen Wert zu. Es muss in dieser Form sein:

<Variable> = <Ausdruck>;

Ein Ausdruck kann eine normale Zahl (z.B. 5.8 !Achtung ihr dürft kein "," Komma als Dezimaltrennzeichen benutzen. Game Maker ist ein englisches Programm, deshalb müsst ihr einen "." Punkt verwenden!) aber auch komplizierter sein. Ihr könnt z.B. einen Wert zu dem derzeitigen Wert der Variable dazuzählen, indem ihr "+=" benutzt. Ferner könnt ihr subtrahieren durch "-=", multiplizieren durch "*=" und dividieren durch "/=". Auch ist die Benutzung der Operatoren zulässig, die zwei Ausdrücke bitweise bearbeiten (|=, &\, or ^=).

Ausdrücke

Ausdrücke können Zahlen (z.B. 3.4), hexadezimale Zahlen mit einem $ Zeichen (z.B. $00FFAA), Zeichenketten zwischen Anführungsstrichen (entweder die einzelnen ' oder die doppelten " ) (z.B. 'Hallo' oder "Hallo") oder kompliziertere Ausdrücke sein. Für Ausdrücke gibt es die folgenden Operatoren:
  • && || ^^: kombiniert boolesche Variablen (Variablen die entweder true oder false sein können (für alle die vom RPG Maker kommen: es handelt sich hierbei um Switches, die ja entweder ON (true) oder OFF (false) sein können)) (&& = und, || =oder , ^^ = xor)
  • <(kleiner als) <=(kleiner oder gleich) ==(gleich) !=(ungleich) >= (grösser oder gleich) > (grösser als) werden dazu benutzt um zu vergleichen (Ergebnis entweder true(1) oder false(0)).
  • | & ^: bitweise Operatoren (| = bitweise or, & = bitweise and, ^ = bitweise xor)
  • <<  >>: bitweise Operatoren (<< = Verschiebe den ganzen Ausdruck nach links, > > = Verschiebe nach rechts)
  • + - Addition, Subtraktion
  • * / div mod sind: Multiplikation, Division, Ganzzahldivision, Modulo(der Rest einer Interger(=Ganzzahl)division)

Beachte das ein Wert von x div y dasselbe wie x/y gerundet zur nächsten Ganzzahl ist. Der mod Operator zieht den Restwert multipliziert mit dem Teiler vom Anfangswert ab. In anderen Worten, x mod y = x - (x div y) * y. Außerdem existieren die folgenden Operatoren, die nur einen Parameter übernehmen:

  • !: not, Verändert "true" in "false" und umgekehrt
  • -: negativiert den nächsten Wert
  • ~: negativiert den nächsten Wert bitweise
Als Werte könnt ihr Zahlen, Variablen oder Funktionen, die einen Wert zurückgeben, benutzen. Unter-Ausdrücke können in Klammern gesetzt werden. Alle Operatoren funktionieren mit Zahlen, Vergleiche funktionieren auch für Zeichenketten und + fügt Zeichenketten zusammen.(z.B. wird aus "Hallo" + "...und Tschüss!" wird "Hallo... und Tschüss!") ( Bitte beachte, dass, im Gegensatz zu manchen Hochsprachen, immer beide Argumente eines Booleschen Operators berechnet werden, auch wenn das Ergebnis nach dem Ersten bereits feststeht.)

Beispiele

Hier sind einige Beispiele mit Zuweisungen:

{
x = 23; // x wird dem Wert 23 zugeordnet
str = 'hello world'; // str wird der Zeichenkette �hello world� zugeordnet
y += 5; // der Wert von y wird 5 addiert.
x *= y; // x wird mit y multipliziert
x = 23*((2+4) / sin(y)); // x bekommt den Wert, den 23*((2+4) / sin(y)) zurückgibt.
str = 'hello' + " world"; // str bekommt den Zusammenschnitt von 'hello' + " world"
b = (x < 5) && !(x==2 || x==4); // b ist eine boolesche Variable, d.h. sie kann
nur true oder false sein. Wenn dieser Ausdruck (x < 5) && !(x==2 ||
x==4) stimmt, dann bekommt es den Wert true, sonst false.
}

Variablen

Du kannst Variablen erstellen, indem du ihnen einfach einen Wert zuweist. Wenn du einfach einen Variablennamen benutzt, wird die Variable lokal erstellt, du wirst sie also in anderen Objekten nicht finden. Wenn du auf Variablen eines anderen Objektes zugreifen willst, schreibe einfach den Namen des Objektes, getrennt durch einen Punkt, gefolgt vom Variablennamen.

Um globale Variablen zu erstellen, die für alle Objekte sichtbar sind, schreibe vor ihren Namen das Word global und einen Punkt. Beispielsweise könnte man folgendes schreiben:

{
  if (global.doit)
  {
    // mach etwas
    global.doit = false;
  }
}

Manchmal braucht man Variablen nur in einem Stück Code oder in einem Skript. Dazu müssen die Variablen am Anfang des Codes mit dem Schlüsselwort var deklariert werden. Auf diese Weise wird kein Speicher verschwendet, Namenskonflikte werden umgangen und es ist schneller als globale Variablen. Die Deklaration sieht wie folgt aus:

var <varname1>,<varname2>,<varname3>, ...

Z. B. kann man schreiben:

{
  var xx,yy;
  xx = x+10;
  yy = y+10;
  instance_create(xx,yy,ball);
}

Auf Variablen anderer Instanzen zugreifen

Wie früher beschrieben, kann man Variablen der derzeitigen Instanz verändern, indem man Statements wie folgendes benutzt:
x = 3;

Aber in manche Fällen will man auf Variablen anderer Instanzen zugreifen. Beispielsweise könntest du die Bewegung aller Bälle stoppen, den Haupt Charakter auf eine bestimmte Position bringen oder, im Falle einer Kollision, das Sprite der anderen Instanz ändern. Das kann dadurch erreicht werden, indem man vor den Variablennamen den Namen des Objektes und einen Punkt schreibt. Also kann man z.B. schreiben:

ball.speed = 0;

Das würde die Geschwindigkeit aller Bälle ändern. Es gibt einige Spezial-"Objekte".

  • self: Die derzeitige Instanz, für die alle Actions ausgeführt werden
  • other: Die andere, in einer Kollision verwickelte Instanz
  • all: Alle Instanzen
  • noone: Keine Instanz (klingt vielleicht seltsam, aber später wird es gebraucht)
  • global: Keine Wirkliche Instanz, aber ein Container, der Variablen hält
Folgende Beispiele zeigen Statements nach obigem Schema:
other.sprite_index = sprite5;
all.speed = 0;
global.message = 'Ein gutes Ergebnis';
global.x = ball.x;

Jetzt könntest du dich fragen, was bei der letzten Zuweisung passiert, wenn es mehrere Bälle gibt. Es wird einfach der erste genommen und dessen x-Wert wird der globalen Variable zugewiesen.

Aber was ist, wenn man die Geschwindigkeit eines bestimmten Balls, anstatt aller Bälle verändern will? Das ist etwas komplizierter. Jede Instanz hat ihre eigene Id. Wenn du im Room-Editor Instanzen platzierst, wird die Id der Instanz, über der sich der Mauszeiger befindet, angezeigt. Die IDs sind Zahlen, die größer oder gleich 100000 sind. So eine Nummer kann links des Punktes verwendet werden, aber Vorsicht der Punkt wird als Dezimalpunkt interpretiert werden, deshalb musst du Klammern um die Id setzen. Beispielsweise könnte die Id eines Balles 100032 sein, dann könntest du folgendes schreiben:

(100032).speed = 0;

Wenn du während der Laufzeit Instanz erstellst, dann gibt die Funktion die Id des Objektes zurück, deshalb kann man schreiben:

{
nnn = instance_create(100,100,ball);
nnn.speed = 8;
}

Das erschafft einen Ball und setzt seine Geschwindigkeit. Beachte, dass wir die Id einer Variablen zugewiesen haben und diese dann links des Punktes geschrieben haben. Das ist erlaubt und funktioniert. Auch das folgende Programm ist richtig:

{
obj[0] = ball;
obj[1] = schlaeger;
obj[0].alarm[4] = 12;
obj[1].id.x = 12;
}

Das letzte Statement sollte wie folgt gelesen werden. Wir nehmen die Id des ersten Schlägers und weisen dessen x Variable den Wert 12 zu.

Objektnamen, die speziellen Objekte und Ids können außerdem in einigen Funktionen benutzt werden. Sie werden wie Konstanten behandelt.

Arrays

In GML kann man 1- und 2-Dimensionale Arrays benutzen. Schreibe den Index einfach zwischen zwei eckige Klammern und die zwei Indizes für 2 Dimensionale Arrays durch ein Komma getrennt. Sobald ein Index benutzt wird, wird der Array im Hauptspeicher reserviert. Jeder Array beginnt beim Index 0. Sei deshalb Vorsichtig große Werte als Indizes zu benutzen, weil der ganze Array sofort im Hauptspeicher reserviert wird. Benutze nie negative Indizes. Das System begrenzt die Indizes auf 32000 und den gesamten Array auf 1000000. Folglich kann man schreiben:
{
a[0] = 1;
i = 1;
while (i < 10) { a[i] = 2*a[i-1]; i += 1;}
b[4,6] = 32;
}

If-Statement

Ein if-Statement hat die Form
if (<Ausdruck>) <Statement>

oder

if (<Ausdruck>) <Statement> else <Statement>

Das Statement kann auch ein Block sein. Wenn euer Ausdruck wahr ist (true oder gerundet 1), dann wird das erste Statement ausgeführt, wenn euer Ausdruck falsch (false oder gerundet 0) ist, dann wird euer Statement ausgeführt, was nach dem else-tag kommt. Um das if-Statement besser zu verstehen, sollte man es einmal ganz ins Deutsche übersetzt ansehen: Es besagt nämlich nichts anderes als: Wenn (Ausdruck erfüllt ist) <Tue dieses Statement> sonst <Tue dieses Statement>.

Es macht den Code leserlicher, immer klare klammern um die einzelnen Statements zu schreiben. Dadurch hat ein if-Statement die Form:

if (<Ausdruck>)
{
<Statement>
}
else
{
<Statement>
}

Beispiel
Das folgende Programm bewegt das Objekt zur Mitte des Bildschirms:

{
if (x<200) {x += 4} else {x -= 4};
}

Repeat Statement

Ein repeat-Statement hat die Form:
repeat (<Ausdruck>) <Statement>

Das Statement wird so oft wiederholt, wie der gerundete Wert des Ausdrucks angibt.

Beispiel
Das folgende Programm erschafft 5 Bälle an zufälligen Orten.

{
repeat (5) instance_create(random(400),random(400),ball);
}

While-Statement

Ein while-Statement hat die Form:
while (<Ausdruck>) <Statement>

Das Statement wird solange ausgeführt, solange der Wert des Ausdrucks "true" ist.
Wenn wir das while-Statements wieder wörtlich ins Deutsche übersetzten, dann wird man diese Art der Schleife vielleicht besser verstehen:
Solange (Ausdruck wahr ist) <Tue dieses Statement>
Bei While-Schleifen ist Vorsicht geboten, weil man sie leicht in eine Endlosschleife verwandeln kann. In diesem Fall würde das Programm stehen bleiben und nicht mehr auf Benutzereingaben reagieren.

Beispiel
Das folgende Programm versucht das Objekt an einen freien Ort zu setzen (Das ist genau das selbe wie die Action "Move an object to a random position").

{
while (!place_free(x,y))
{
x = random(room_width);
y = random(room_height);
}
}

Do-Statement

Ein do-Statement hat die Form:
do <Statement> until(<Ausdruck>)

Das Statement wird solange ausgeführt bis der Ausdruck "true" ist, dabei wird das Statement mindestens einmal ausgeführt.
Zu einer besseren Veranschaulichung, sollte man das do-Statement mal ganz ins Deutsche übersetzten:
Tue <Das Statement> solange, bis (Ausdruck erfüllt ist)

Bei Do-Schleifen ist Vorsicht geboten, weil man sie leicht in eine Endlosschleife verwandeln kann. In diesem Fall würde das Programm stehen bleiben und nicht mehr auf Benutzereingaben reagieren.

Beispiel
Das folgende Programm versucht das Objekt an einen freien Ort zu setzen (Das ist genau das selbe wie die Action "Move an object to a random position"). Der einzige Unterschied zu dem obigem Programm besteht darin, dass hier das Objekt mindestens einmal versetzt wird, was oben nicht der Fall ist.

{
do
{
x = random(room_width);
y = random(room_height);
}
until (place_free(x,y))
}

For-Statement

Ein for-Statement hat die Form:
for (<Statement1> ; <Ausdruck> ;<Statement2>) <Statement3>
Das funktioniert wie folgt:
Am Anfang der for-Schleife wird Statement1 ausgeführt, dann wird der Ausdruck bewertet. Wenn er "true" (wahr) ist wird Statement3 ausgeführt. Statement2 ist das Statement, was am Ende der for-Schleife ausgelöst wird. Schliesslich wird der Ausdruck nochmals bewertet, dann wird wieder Statement3 ausgeführt und... das ganze geht solange, bis der Ausdruck "false" (falsch) ist.
Das klingt kompliziert, ist aber eigentlich ganz einfach:
Das erste Statement (Statement1) aktiviert die for-Schleife, dabei wird sie aber nur einmal ausgeführt und das ist zum Zeitpunkt, wo die Schleife aktiviert wird.
Der Ausdruck überprüft, ob die Schleife beendet werden muss.
Statement2 ist ein "Schritt-Statement", das zur nächsten Berechnung der Schleife führt. Meistens wird es dazu benutzt um durch einen bestimmten Bereich von Zahlen Befehle auszuführen.

Beispiel
Das folgende Programm initialisiert einen Array mit den zehn
Werten 1-10.

{
for (i=0; i<=9; i+=1) list[i] = i+1;
}

Switch-Statement

In einigen Situationen muss das Spiel auf bestimmte Werte reagieren. Das ist mit vielen if-Statements möglich, aber es ist einfacher mit einem switch-Statement. Ein switch-Statement hat die Form:
switch (<Ausdruck>)
{
case <Ausdruck1>: <Statement1>; ... ; break;
case <Ausdruck2>: <Statement2>; ... ; break;
...
default: <Statement>; ...
}

Das geht so: Zuerst wird der Wert des Ausdrucks errechnet, der dann mit den anderen Ausdrücken (die hinter den case-Statements stehen) verglichen wird. Die Ausführung des Scripts wird da fortgesetzt, wo der erste, zu dem Wert passende, Ausdruck steht und dort beendet, wo ein break-Statement steht. Wenn kein Ausdruck den richtigen Wert hat, wird die Ausführung beim default-Statement fortgesetzt (es ist kein default-Statement notwendig, es kann auch unter Umständen entfallen) Es sei angemerkt, dass mehrere case-Statements für ein und dasselbe Statement gesetzt werden können. Das break-Statement ist ebenfalls nicht notwendig. Wenn kein break-Statement vorhanden ist, wird die Ausführung bei dem nächsten case-Statement fortgesetzt.

Beispiel
Das folgende Programm reagiert auf bestimmte Tasten, die gedrückt sind/werden.

switch (keyboard_key)
{
case vk_left:
case vk_numpad4:
x -= 4; break;
case vk_right:
case vk_numpad6:
x += 4; break;
}

Break-Statement

Das break-Statement hat die Form:
break

Wenn es innerhalb einer for-Schleife, while-Schleife, repeat-Schleife, einem switch-Statement oder einem with-Statement (Erklärung zu diesem folgt später) vorkommt, beendet es die Ausführung dieser Schleife oder des Statements. Ausserhalb dieser Statements beendet es die Ausführung des Skripts (nicht die des Spiels).

Continue-Statement

Das continue-Statement hat die Form:
continue

Wenn es innerhalb einer for-Schleife, while-Schleife, repeat-Schleife, einem switch-Statement oder einem with-Statement vorkommt, fährt es mit dem nächsten Wert der Schleife oder des Statements fort.

Exit-Statement

Das exit-Statement hat die Form:
exit

Es beendet einfach die Ausführung des Scripts oder des "piece of code". (Es beendet nicht die Ausführung des Spiels! Dafür wird die Funktion game_end() benötigt.)

Funktionen

Eine Funktion hat die Form: Funktionsname, gefolgt von keinem oder mehreren Argumenten in Klammern, getrennt durch Kommata.
<funktion>(<arg1>,<arg2>,...)
Es gibt zwei Arten von Funktionen. Erstens gibt es sehr viele eingebaute Funktionen und zweitens kann jedes Skript, das in eurem Spiel eingebaut ist, auch als Funktion verwendet werden.
Achtung! Auch bei Funktionen ohne Argumente müssen die Klammern gesetzt werden! Einige Funktionen geben Werte zurück und können als Ausdruck benutzt werden, andere führen einfach Befehle aus. Es ist nicht möglich Funktionen auf die linke Seite eines Assignments zu schreiben.

Scripts

Wenn ein Skript erstellt wird, willst du häufig auf Argumente zugreifen, die ihm weitergegeben wurden (Entweder wenn du das Skript ausführst oder wenn du es in einem Programm, oder von einem anderem Skript aus oder sogar gleich im selben Skript aufrufst).
Diese Argumente sind in den Variablen argument0, argument1, ..., argument15. Man kann also maximal nur 16 Argumente benutzten. (Merke, dass, wenn du dein Script von einer "Action" aus aufrufst, du nur die ersten 5 Argumente deklarieren kannst.) Du kannst auch argument[0] etc. benutzten.

Skripte können auch einen Wert zurückgeben, sodass sie in Ausdrücken verwendet werden können.
Für das ausgeben eines Wertes wird das return Statement benutzt:

return <Ausdruck>

Die Ausführung des Skripts wird nach dem return Statement beendet!

Beispiel
Hier ist die Definition für ein Script, dass das Quadrat des ersten Argumentes errechnet:

{
return (argument0*argument0);
}

Um ein Skript aus einem Stück Code heraus aufzurufen, muss man genauso verfahren wie bei einer "normalen" Funktion, d.h. den Skriptnamen und die Argumente in Klammern dahinter schreiben.

With Konstruktion

Wie oben angegeben ist es möglich, die Variablen anderer Instanzen zu verarbeiten. Aber es kann vorkommen, das du noch mehr mit den anderen Instanzen tun möchtest. Z.B. alle Bälle um 8 Pixel nach unten Bewegen. Du denkst wohl, das dies mit folgendem Code gemacht werden kann

ball.y = ball.y + 8;

Das ist aber nicht richtig. Dieser Code nimmt die y Koordinate des ersten Balls und fügt 8 hinzu. Dann wird dieser neue Wert als y-Koordinate aller Bälle gesetzt. Das Ergebnis wäre, dass alle Bälle an der selben y-Koordinate sind. Das Statement

ball.y += 8;

hat den selben Effekt, es ist nur eine Variante unseres oberen Beispiels. Wie erreichen wir dies also? Dafür gibt es das with Statement. Die allgemeine Form ist

with (<expression>) <statement>

<expression> gibt eine oder mehrere Instanzen an. Du kannst eine Instanz-ID, den Objektnamen (um alle Instanzen zu adressieren) oder eines der speziellen Objekte (all, self, other, none) angeben. <statement> wird dann für jede Instanz ausgeführt, als wäre diese die aktuelle (self) Instanz. Um also alle Bälle 8 Pixel nach unten zu bewegen, kannst du folgendes eingeben.

with (ball) y += 8;

Wenn du mehrere Aufgaben durchführen möchtest, mache geschweifte Klammern drumherum. Um z.B. alle Bälle an eine zufällige Position zu bewegen, benutze

with (ball)
{
x = random(room_width);
y = random(room_height);
}

Beachte das in den Statements die angegebene Instanz die self-Instanz wird. Die ursprüngliche self-Instanz wurde zur other-Instanz. Um z.B. alle Bälle auf die Position der Instanz zu setzen, nutze

with (ball)
{
x = other.x;
y = other.y;
}

Das with Statement ist sehr leistungsfähig. Ich geb dir ein paar mehr Beispiele. Um alle Bälle zu zerstören, nutze

with (ball) instance_destroy();

Wenn eine Bombe explodiert und du alle Instanzen in der Nähe zerstören möchtest, nutze

with (all)
{
if (distance_to_object(other) < 50) instance_destroy();
}

Kommentare

Du kannst Kommentare zu deinen Programmen hinzufügen. Wenn // in einer Zeile steht, wird alles dahinter ignoriert. Mehrzeilige Kommentare sind dadurch möglich, dass du alles zwischen/* und */ schreibst. (Die Farbcodierung könnte dabei nicht richtig funktionieren! Drücke 2x F12 um den Text neu einfärben zu lassen.)

Funktionen und Variablen in GML

GML enthält eine große Zahl eingebauter Funktionen und Variablen. Mit diesen kannst du dein Spiel vollständig kontrollieren. Für alle Aktionen existieren auch Funktionen, sodass du keine Aktionen verwenden musst, wenn du Code bevorzugst. Es gibt auch noch viel mehr Funktionen und Variablen die Teile des Spieles kontrollieren und nicht mit Aktionen verwendet werden können. Wenn du also fortgeschrittene Spiele machen möchtest, wird dir ans Herz gelegt, weiterzulesen um alle Möglichkeiten zu kennen. Diese Funktionen und Variablen können auch genutzt werden, wenn einer Aktion ein Wert übergeben werden muss. Deshalb profitierst du von den Informationen hier auch, wenn du keinen Code benutzen möchtest.

Die folgenden Konventionen werden ab jetzt genutzt. Variablen mit einen * sind nur lesbar, d.h. ihr Wert kann nicht geändert werden. Variablen mit [0..n] nach dem Namen sind Arrays. Die maximale Anzahl ist angegeben.

Berechnungen

Der Game Maker beinhaltet eine große Anzahl von Funktionen, um gewisse Berechnungen durchzuführen. Es folgt eine vollständige Auflistung.

Konstanten

Die folgenden mathematischen Konstanten existieren:

true (wahr) entspricht 1.
false (unwahr) entspricht 0.
pi (Kreiszahl Pi) entpricht 3.1415...

Funktionen mit reellen Zahlen

Die folgenden Funktionen existieren, die mit reellen Zahlen arbeiten.

random(x) Gibt eine zufällige Zahl zwischen 0 und x wieder. Die Zahl ist immer kleiner als x.
choose(val1, val2, val3, ...) Gibt zufällig eine der angegeben Zahlen aus. Die Funktion kann bis zu 16 Argumente haben.
abs(x) Gibt den absoluten Wert von x wieder (Betrag).
sign(x) Gibt das Vorzeichen von x wieder (-1, 0 oder 1).
round(x) Gibt x gerundet auf den nächsten Integer wieder.
floor(x) Gibt x abgerundet auf den nächsten Integer wieder.
ceil(x) Gibt x aufgerundet auf den nächsten Integer wieder.
frac(x) Gibt den Bruchteil von x wieder, das ist der Teil hinter dem Dezimalzeichen.
sqrt(x) Gibt die Quadratwurzel von x wieder. x darf nicht negativ sein.
sqr(x) Gibt x*x wieder.
power(x, n) Gibt x hoch n wieder.
exp(x) Gibt e der Potenz von x wieder.
ln(x) Gibt den natürlichen Logarhitmus von x wieder.
log2(x) Gibt den Logarithmus von x zur Basis von 2 wieder.
log10(x) Gibt den Logarithmus von x zur Basis von 10 wieder.
logn(n, x) Gibt den Logarithmus von x zu Basis von n wieder.
sin(x) Gibt den Sinus von x wieder (x in Radiant (Bogenmaß)).
cos(x) Gibt den Kosinus von x wieder (x in Radiant (Bogenmaß)).
tan(x) Gibt den Tangens von x wieder (x in Radiant (Bogenmaß)).
arcsin(x) Gibt den Arcus-Sinus von x zurück.
arccos(x) Gibt den Arcus-Kosinus von x zurück.
arctan(x) Gibt den Arcus-Tangens von x zurück.
arctan2(y, x) Berechnet den Arcus-Tangens(Y/X), und gibt einen Winkel im korrekten Viertelkreis wieder.
degtorad(x) Konvertiert Grad zu Radiant (Gradmaß zu Bogenmaß).
radtodeg(x) Konvertiert Radiant zu Grad (Bogenmaß zu Gradmaß).
min(val1, val2, val3, ...) Gibt das Minimum der Werte wieder. Die Funktion kann bis zu 16 Argumente umfassen. Sie müssen entweder alle Strings oder reelle Zahlen sein.
max(val1, val2, val3, ...) Gibt das Maximum der Werte wieder. Die Funktion kann bis zu 16 Argumente umfassen. Sie müssen entweder alle Strings oder reelle Zahlen sein.
mean(val1, val2, val3, ...) Gibt den Durchschnitt der Werte wieder. Die Funktion kann bis zu 16 Argumente umfassen. Sie müssen entweder alle Strings oder reelle Zahlen sein.
median(val1, val2, val3, ...) Gibt den Mittelwert der Argumente zurück. (Wenn er ungerade ist wird der kleinste der beiden zurückgegeben.) Die Funktion kann bis zu 16 Argumente haben. Sie müssen alle Real Werte sein.
point_distance(x1, y1, x2, y2) Gibt die Distanz zwischen dem Punkt (x1,y1) und dem Punkt (x2,y2) wieder.
point_direction(x1, y1, x2, y2) Gibt die Direction (Richtung) von dem Punkt (x1,y1) zu dem Punkt (x2,y2) in Grad wieder.
lengthdir_x(len, dir) Gibt die horizontale x-Komponente von dem Vektor bestimmt durch die gegebene Länge und Richtung wieder.
lengthdir_y(len, dir) Gibt die vertikale y-Komponente von dem Vektor bestimmt durch die gegebene Länge und Richtung wieder.
is_real(x) Gibt wieder, ob x eine reelle Zahl ist (im Gegensatz zu einem String).
is_string(x) Gibt wieder, ob x ein String ist (im Gegensatz zu einer reellen Zahl).

Funktionen zum Umgang mit Strings

Die folgenden Funktionen arbeiten mit Zeichen und Strings (Zeichenketten).

chr(val) Gibt das Zeichen mit dem Asci-Code von val in einem String wieder.
ord(str) Gibt den Asci-Code des ersten Zeichens in str wieder.
real(str) Konvertiert str in eine reelle Zahl, wobei str ein Minuszeichen, einen Punkt zur Dezimalstellenabtrennung (Kein Komma!) und sogar einen exponentiellen Teil enthalten kann.
string(val) Konvertiert die reelle Zahl in einen String in einem Standard-Format (keine Dezimalstellen, wenn es sich um einen Integer handelt, sonst zwei Dezimalstellen).
string_format(val, tot, dec) Konvertiert val in einen String in einem eigenen Format: tot beschreibt die Gesamtanzahl der Stellen und dec beschreibt die Anzahl von Dezimalstellen.
string_length(str) Gibt die Anzahl von Zeichen in dem String wieder.
string_pos(substr, str) Gibt die Position von substr in str wieder(0=kein Vorkommen).
string_copy(str, index, count) Gibt einen Substring (Teilstring) von str wieder, beginnend ab Position index mit der Länge count.
string_char_at(str, index) Gibt das Zeichen in str an der Position index wieder.
string_delete(str, index, count) Gibt eine Kopie von str ohne den Teil beginnend ab Position index mit der Länge count wieder.
string_insert(substr, str, index) Gibt eine Kopie von str mit substr hinzugefügt an Position index wieder.
string_replace(str, substr, newstr) Gibt eine Kopie von str mit dem ersten Vorkommnis von substr ersetzt durch newstr wieder.
string_replace_all(str, substr, newstr) Gibt eine Kopie von str mit allen Vorkommnissen von substr ersetzt durch newstr wieder.
string_count(substr, str) Gibt die Anzahl der Vorkommnisse von substr in str wieder.
string_lower(str) Gibt eine klein geschriebende Kopie von str wieder.
string_upper(str) Gibt eine groß geschriebene Kopie von str wieder.
string_repeat(str, count) Gibt einen String bestehend aus einer Anzahl von count Kopien von str.
string_letters(str) Gibt einen String wieder, der nur die Buchstaben aus str enthält.
string_digits(str) Gibt einen String wieder, der nur die Ziffern aus str enthält.
string_lettersdigits(str) Gibt einen String wieder, der die Buchstaben und Ziffer aus str enthält.

Die folgenden Funktionen arbeiten mit Textspeicherung in der Zwischenablage.

clipboard_has_text() Gibt wieder, ob sich Text in der Zwischenablage befindet.
clipboard_get_text() Gibt den aktuellen Text in der Zwischenablage wieder.
clipboard_set_text(str) Setzt den String str in die Zwischenablage.

Umgang mit Datumsangaben und Uhrzeiten

Im Game Maker ist eine große Anzahl von Funktionen verfügbar, um mit Datumsangaben und Uhrzeiten zu arbeiten. Eine Datum-Uhrzeit-Kombination wird in einer reellen Zahl abgespeichert. Der ganzzahlige Teil eines Datum-Uhrzeit-Wertes entspricht der Anzahl von Tagen, die seit dem 30.12.1899 vertrichen sind. Der Bruchteil eines Datum-Uhrzeit-Wertes ist der Bruch des 24 Stunden-Tages, der vertrichen ist. Die folgenden Funktionen sind vorhanden:

date_current_datetime() Gibt den Datum-Uhrzeit-Wert wieder, der dem derzeitigem Moment entspricht.
date_current_date() Gibt den Datum-Uhrzeit-Wert wieder, der nur dem derzeitigem Datum entspricht (ignoriert die Uhrzeit).
date_current_time() Gibt den Datum-Uhrzeit-Wert wieder, der nur dem derzeitigem Datum entspricht (ignoriert das Datum).
date_create_datetime(year, month, day, hour, minute, second) Generiert einen Datum-Uhrzeit-Wert dem angegebenen Datum und der angegebenen Uhrzeit entsprechend.
date_create_date(year, month, day) Generiert einen Datum-Uhrzeit-Wert dem angegebenen Datum entsprechend.
date_create_time(hour, minute, second) Generiert einen Datum-Uhrzeit-Wert der angegebenen Uhrzeit entsprechend.
date_valid_datetime(year, month, day, hour, minute, second) Gibt wieder, ob das angegebene Datum und die angegebene Uhrzeit gültig sind.
date_valid_date(year, month, day) Gibt wieder, ob das angegebene Datum gültig ist.
date_valid_time(hour, minute, second) Gibt wieder, ob die angegebene Zeit gültig ist.
date_inc_year(date, amount) Gibt ein neues Datum wieder, welches amount Jahre nach dem angegebenen Datum ist. amount muss ein Integer-Wert sein.
date_inc_month(date, amount) Gibt ein neues Datum wieder, welches amount Monate nach dem angegebenen Datum ist. amount muss ein Integer-Wert sein.
date_inc_week(date, amount) Gibt ein neues Datum wieder, welches amount Wochen nach dem angegebenen Datum ist. amount muss ein Integer-Wert sein.
date_inc_day(date, amount) Gibt ein neues Datum wieder, welches amount Tage nach dem angegebenen Datum ist. amount muss ein Integer-Wert sein.
date_inc_hour(date, amount) Gibt ein neues Datum wieder, welches amount Stunden nach dem angegebenen Datum ist. amount must be an integer number.
date_inc_minute(date, amount) Gibt ein neues Datum wieder, welches amount Minuten nach dem angegebenen Datum ist. amount muss ein Integer-Wert sein.
date_inc_second(date, amount) Gibt ein neues Datum wieder, welches amount Sekunden nach dem angegebenen Datum ist. amount muss ein Integer-Wert sein.
date_get_year(date) Gibt das Jahr von date entsprechend wieder.
date_get_month(date) Gibt den Monat von date entsprechend wieder.
date_get_week(date) Gibt die Woche des Jahres von date entsprechend wieder.
date_get_day(date) Gibt den Tag des Monats von date entsprechend wieder.
date_get_hour(date) Gibt die Stunde von date entsprechend wieder.
date_get_minute(date) Gibt die Minute von date entsprechend wieder.
date_get_second(date) Gibt die Sekunde von date entsprechend wieder.
date_get_weekday(date) Gibt den Tag der Woche von date entsprechend wieder.
date_get_day_of_year(date) Gibt den Tag des Jahres von date entsprechend wieder.
date_get_hour_of_year(date) Gibt die Stunde des Jahres von date entsprechend wieder.
date_get_minute_of_year(date) Gibt die Minute des Jahres von date entsprechend wieder.
date_get_second_of_year(date) Gibt die Sekunde des Jahres von date entsprechend wieder.
date_year_span(date1, date2) Gibt die Anzahl von Jahren zwischen den zwei Daten wieder. Über unvollendete Jahre wird in einem Bruch berichtet.
date_month_span(date1, date2) Gibt die Anzahl von Monaten zwischen den zwei Daten wieder. Über unvollendete Monate wird in einem Bruch berichtet.
date_week_span(date1, date2) Gibt die Anzahl von Wochen zwischen den zwei Daten wieder. Über unvollendete Wochen wird in einem Bruch berichtet.
date_day_span(date1, date2) Gibt die Anzahl von Tagen zwischen den zwei Daten wieder. Über unvollendete Tage wird in einem Bruch berichtet.
date_hour_span(date1, date2) Gibt die Anzahl von Stunden zwischen den zwei Daten wieder. Über unvollendete Stunden wird in einem Bruch berichtet.
date_minute_span(date1, date2) Gibt die Anzahl von Minuten zwischen den zwei Daten wieder. Über unvollendete Minuten wird in einem Bruch berichtet.
date_second_span(date1, date2) Gibt die Anzahl von Sekunden zwischen den zwei Daten wieder. Über unvollendete Sekunden wird in einem Bruch berichtet.
date_compare_datetime(date1, date2) Vergleicht die zwei Datum-Uhrzeit-Werte. Gibt -1, 0, oder 1 wieder, abhängig davon, ob der erste Wert kleiner, gleich oder größer ist als der zweite Wert.
date_compare_date(date1, date2) Vergleicht die zwei Datum-Uhrzeit-Werte only taking the date part into account. Gibt -1, 0, oder 1 wieder, abhängig davon, ob der erste Wert kleiner, gleich oder größer ist als der zweite Wert.
date_compare_time(date1, date2) Vergleicht die zwei Datum-Uhrzeit-Werte only taking the time part into account. Gibt -1, 0, oder 1 wieder, abhängig davon, ob der erste Wert kleiner, gleich oder größer ist als der zweite Wert.
date_date_of(date) Gibt den Datum-Anteil des angebenen Datum-Uhrzeit-Wert wieder, indem der Uhrzeit-Anteil auf 0 gesetzt wird.
date_time_of(date) Gibt den Uhrzeit-Anteil des angebenen Datum-Uhrzeit-Wert wieder, indem der Datum-Anteil auf 0 gesetzt wird.
date_datetime_string(date) Gibt einen String wieder, der das gegebene Datum und die gegebene Uhrzeit im Standardformat für das System anzeigt.
date_date_string(date) Gibt einen String wieder, der das gegebene Datum im Standardformat für das System anzeigt.
date_time_string(date) Gibt einen String wieder, der die gegebene Zeit im Standardformat für das System anzeigt.
date_days_in_month(date) Gibt die Anzahl von Tagen im Monat wieder, angegeben durch den Datum-Uhrzeit-Wert.
date_days_in_year(date) Gibt die Anzahl von Tagen im Jahr wieder, angegeben durch den Datum-Uhrzeit-Wert.
date_leap_year(date) Gibt wieder, ob das durch den Datum-Uhrzeit-Wert angegebene Jahr ein Schaltjahr ist.
date_is_today(date) Gibt wieder, ob der angegebene Datum-Uhrzeit-Wert heute ist.

Game play

Es gibt viele Funktionen um das Game Play zu definieren. Diese beeinflussen die Erstellung und Bewegung der Instanzen, das Timing, den Raum und die Verarbeitung von Events.

Informationen über das Game Play können auf folgenden Seiten gefunden werden:

Umherbewegen
Pfade
Bewegungsplanung
Kollisionserkennung
Instanzen
Instanzen deaktivieren
Timing
Räume
Punkte
Events generieren
Andere Variablen und Funktionen

Umherbewegen

Offensichtlich ist es ein wichtiger Aspekt bei Spielen, die Objektinstanzen auch zu bewegen. Jede Instanz besitzt zwei eingebaute Variablen x und y, welche die Position der Instanz markieren. (Um präzise zu sein: Sie geben den Bezugs-/Ursprungspunkt des "sprites" an.) Position (0,0) ist die linke obere Ecke des Raumes.
Du kannst die Position der Instanz ändern, indem du seine x und y Variablen veränderst. Wenn dein Objekt komplizierte Bewegungen vollführen soll, ist das hier der richtige Weg. Typischerweise wird dieser Programmcode ins "step event" (Schrittereignis) des Objektes gesetzt.

Wenn das Objekt mit konstanter Geschwindigkeit und gleichbleibender Richtung bewegt werden soll, gibt es einen einfacheren Weg: Jedes Objekt besitzt eine horizontale Geschwindigkeitskomponente (hspeed) und eine vertikale Geschwindigkeitskomponente (vspeed). Beide werden in "pixels per step" (Bildpunkte pro Programmschritt) angegeben. Eine positive horizontale Geschwindigkeitskomponente bedeutet eine Bewegung nach rechts, eine negative nach links. Positive vertikale Geschwindigkeit bewegt nach unten, negative nach oben. Somit musst du nur einmal diese Variablen setzen (beispielsweise im "creating event"), um der Objektinstanz eine konstante Bewegung zu geben.

Es gibt noch eine andere Art, Bewegung zu spezifizieren - Richtungsangabe (0° bis 359°) und Geschwindigkeit (sollte nicht negativ sein). Du kannst diese Variablen setzen und auslesen, um eine beliebige Bewegung zu spezifizieren. (innerhalb des Game Makers werden diese Werte in "hspeed" und "vspeed" umgewandelt.) Ferner gibt es noch die Reibung (friction) und die Anziehungskraft (gravity) samt Richtung (gravity direction). Abschliessend sei noch die Funktion: motion_add(dir,speed) erwähnt, welche eine Bewegung zur vorhandenen addiert.
Um vollständig zu sein, hat jede Instanz folgende Variablen und Funktionen, welche sich mit Position und Bewegung befassen:

x x-position der Instanz.
y y-position der Instanz.
xprevious vorherige x-position.
yprevious vorherige y-position.
xstart Anfangs-x-position im Raum.
ystart Anfangs-y-position im Raum.
hspeed Horizontale Komponente der Geschwindigkeit (speed).
vspeed Vertikale Komponente der Geschwindigkeit (speed).
direction Momentane Richtung (direction) {0°-360°, gegen den Uhrzeigersinn, 0 = nach rechts}.
speed Momentane Geschwindigkeit (in "pixels per step" [pps]).
friction Momentane Reibung (friction) (in "pixels per step").
gravity Momentaner Wert der Anziehungskraft (gravity) (in "pixels per step").
gravity_direction Richtung der Anziehungskraft (270 ist nach unten).
motion_set(dir, speed)Setzt die Bewegung mit angegebener Richtung(dir) und Geschwindigkeit(speed).
motion_add(dir, speed)Addiert die Bewegung zur vorhandenen (Vektoraddition).

Es gibt ein Menge an Funktionen, welche dir bei Bewegungsdefinitionen helfen:

place_free(x, y) Gibt an, ob die Instanz an angegebener Position(x,y) eine Kollision auslöst. Sie wird verwendet als Prüfroutine bevor man sich auf die neue Stelle bewegt.
place_empty(x, y) Gibt an, ob die Instanz an angegebener Position(x,y) auf nichts trifft. (Diese Funktion beachtet auch "non-solid" Instanzen.)
place_meeting(x, y, obj) Gibt an, ob die Instanz an angegebener Position(x,y) das Objekt obj trifft. obj kann ein Objekt sein - in so einem Fall gibt die Funktion den Wert "true" zurück, wenn es auf eine Instanz des Objekts trifft. Es kann aber auch eine "instance id" sein, das besondere Wort "all" (bedeutet irgendeine Instanz irgendeines Objektes), oder das besondere Wort "other".
place_snapped(hsnap, vsnap) Gibt an, ob die Instanz am Raster ausgerichtet ist(hsnap,vsnap).
move_random(hsnap, vsnap) Bewegt die Instanz zu einer freien, zufälligen und am Raster ausgerichteten Position.
move_snap(hsnap, vsnap) Richtet die Instanz am Raster aus.
move_wrap(hor, vert, margin) Wenn die Instanz außerhalb des Raumes ist, wird sie Auf die andere Seite des Raumes gesetzt, von wo aus sie sich wieder in den Raum bewegen kann. hor gibt an die Instanz zu versetzen, wenn sie sich horizontal aus dem Raum bewegt hat.vert macht das selbe vertikal. margin gibt an wie weit die Instanz  aus dem Raum heraus sein muss, um versetzt zu werden.
move_towards_point(x, y, sp) Bewegt die Instanz mit der Geschwindigkeit (sp) zum Punkt(x,y).
move_bounce_solid(adv) Abprallen von "solid" Instanzen. adv gibt an, ob genauer berechnet wird (schräge Wände).
move_bounce_all(adv) Abprallen von allen Instanzen - nicht nur "solide".
move_contact_solid(dir, maxdist) Bewegt die Instanz solange in die angegebene Richtung, bis ein Kontakt mit einer anderen "solid" Instanz erreicht wird. Wenn an der aktuellen Position keine Kollision vorliegt, wird die Instanz kurz vor der Kollision platziert. Wenn schon eine Kollision vorliegt, wird die Instanz nicht bewegt. Du kannst die maximale Bewegungsweite(maxdist) angeben (negative Werte bedeuten beliebig lange).
move_contact_all(dir, maxdist) Wie oben, nur diesmal stoppt die Instanz bei jedem Kontakt mit einem anderen Objekt - nicht nur "solid" Objekte.
move_outside_solid(dir, maxdist) Bewegt die Instanz solange in die angegebene Richtung, bis sie sich nicht mehr innerhalb eines "solid" Objekts befindet. Wenn an der angegebenen Stelle keine Kollision auftritt, wird die Instanz auch nicht bewegt. Auch hier kannst Du die maximale Bewegungsweite angeben (maxdist negativ = beliebig weit).
move_outside_all(dir, maxdist) Wie oben, nur diesmal alle Objekte nicht nur "solid objects".
distance_to_point(x, y) Gibt die Distanz der Umrissbox (bounding box) der Instanz zum Punkt (x,y) wieder.
distance_to_object(obj) Gibt die Distanz der Instanz zur nächstgelegenen Instanz des angegebenen Objektes (obj) an.
position_empty(x, y) Gibt an, ob sich nichts an Position (x,y) befindet.
position_meeting(x, y, obj)Gibt an, ob an Position (x,y) eine Instanz von Objekt (obj) vorhanden ist. obj kann ein Objekt sein, ein "instance id" oder eins der Schlüsselwörter: "self"(selbst), "other"(andere), oder "all"(alle).

Pfade

Im Game Maker kannst du Pfade definieren und Instanzen beauftragen, solchen Pfaden zu folgen. Obwohl du dafür die Aktionen (actions) verwenden kannst, gibt es Funktionen und Variablen dafür, welche mehr Flexibilität bieten:
path_start(path, speed, endaction, absolute) Startet einen Pfad für die aktuelle Instanz. Der "path" ist der Name des Pfades, der beschritten werden soll. Die "speed" ist die Gewschwindigkeit, mit der der Pfad abgeschritten werden soll. Eine negative Geschwindigkeitsangabe bedeutet, dass der Pfad rückwärts von der Instanz beschritten werden soll. Die "endaction" gibt an, was geschehen soll, wenn das Ende des Pfades erreicht worden ist. Folgende Werte können eingesetzt werden:

0 : stoppt den Pfad
1: setzt den Pfad an der Startposition fort (wenn der Pfad nicht geschlossen ist, wird zur Anfangsposition gesprungen)
2: setzt den Pfad an der aktuellen Position fort
3: verfolgt den Pfad zurück, das heißt Vorzeichenänderung der Geschwindigkeit (speed)
Das Argument "absolute" sollte wahr (true) oder falsch (false) sein. Wenn es wahr ist, werden absolute Koordinaten des Pfades verwendet. Wenn es falsch ist, werden die Koordinaten relativ zur aktuellen Position der Instanz verwendet. Um es genauer zu sagen: Wenn die Geschwindigkeit positiv ist, wird der Startpunkt des Pfades auf die aktuelle Position der Instanz gesetzt und der Pfad wird von dort aus abgeschritten. Wenn die Geschwindigkeit negativ ist, wird der Endpunkt des Pfades an die aktuelle Position der Instanz gesetzt und der Pfad wird rückwärts abgeschritten.
path_end() Beendet das Abschreiten eines Pfades für die aktuelle Instanz.
path_index* Index des aktuellen Pfades, dem die Instanz folgt. Du kannst das nicht direkt ändern, sondern musst obenstehende Funktion verwenden.
path_position Position im aktuellen Pfad. 0 entspricht dem Anfang des Pfades. 1 entspricht dem Ende des Pfades. Der Wert muß zwischen 0 und 1 liegen.
path_positionprevious Vorherige Position im aktuellen Pfad. Dies kann beispielsweise in Kollisionsereignissen verwendet werden, um die Position im Pfad auf die vorherige Stelle zu setzen.
path_speed Geschwindigkeit (in pixel pro step) mit der der Pfad abgeschritten wird. Verwende einen negativen Wert, für die Rückwärtsbewegung.
path_orientation Orientierung (gegen den Uhrzeigersinn "counter-clockwise") in welcher der Pfad ausgeführt wird. 0 ist die normale Orientierung des Pfades.
path_scaleSkalierung des Pfades. Vergrößern, um den Pfad aufzublähen. 1 ist der voreingestellte Wert.
path_endaction Die Aktion, die am Ende des Pfades ausgeführt werden soll. Du kannst die oben genannten Werte verwenden.

Motion planning (Bewegungsplanung)

Bewegungsplanung hilft dir bestimmte Instanzen von einer gegebenen Stelle zu einer anderen Stelle zu bewegen, wobei Kollisionen mit bestimmten anderen vermieden werden (Wände zum Beispiel). Bewegungsplanung ist ein schwieriges Problem. Es ist unmöglich allgemeine Funktionen bereitzustellen, die in allen Situationen zufriedenstellend arbeiten. Auch sind die Berechnungen für kollisionsfreie Bewegungen recht zeitaufwändig. Deshalb sei sorgsam wie und wann Du es einsetzt. Bitte behalte diese Anmerkungen immer im Hinterkopf, wenn du irgendeine folgender Funktionen verwendest.

Verschiedene Arten der Bewegungsplanung werden vom Game Maker bereitgestellt. Die einfachste Art lässt eine Instanz einen Schritt in Richtung Zielposition machen, direkt und gradlinig, wenn möglich - aber auch in anderer Richtung, falls erforderlich. Diese Funktionen sollten im "step event" einer Instanz verwendet werden. Sie korrespondieren mit den Bewegungsplanungsaktionen ("motion planning actions"), die auch verfügbar sind:

mp_linear_step(x, y, stepsize, checkall) Diese Funktion lässt die Instanz einen Schritt in Richtung der angegebene Stelle (x,y) ausführen. Die Schrittweite des Schrittes wird durch "stepsize" angezeigt. Wenn die Instanz sich schon an der Stelle befindet, wird sie sich nicht weiter bewegen. Wenn "checkall" wahr ("true") ist stoppt die Instanz, sobald sie auf eine Instanz irgendeinenes Objektes trifft. Wenn es nicht wahr ("false") ist, stoppt sie nur, wenn eine "solid" Instanz getroffen wird. Beachte, dass diese Funktion nicht versucht Umwege zu machen, wenn sie auf Hindernisse stößt. Sie schlägt einfach fehl in diesem Fall. Die Funktion gibt wieder, ob die Zielposition erreicht wurde.
mp_linear_step_object(x, y, stepsize, obj) Dasselbe wie die obige Funktion, diesmal wird aber nur obj als Hindernis gesehen. obj kann ein Objekt oder eine Instanz sein.
mp_potential_step(x, y, stepsize, checkall) Wie voranstehende Funktion, lässt auch diese Funktion die Instanz einen Schritt auf eine bestimmte Position hin machen. Aber diesmal versucht sie Hindernisse zu umgehen. Wenn die Instanz mit "solid" Instanz (oder irgendeiner, wenn "checkall" "true (wahr) ist) zusammen zu stoßen droht, wird sie die Richtung ändern, um die Instanz zu meiden und es umgehen. Diese Näherung unterliegt keiner garantiert funktionierenden Arbeitsweise aber in den meisten einfachen Fällen bewegt es die Instanz effektiv auf die Zielposition. Die Funktion gibt an, ob das Ziel erreicht wurde.
mp_potential_step_object(x, y, stepsize, obj) Dasselbe wie die obige Funktion, diesmal wird aber nur obj als Hindernis gesehen. obj kann ein Objekt oder eine Instanz sein.
mp_potential_settings(maxrot, rotstep, ahead, onspot) Die vorherige Funktion verrichtet ihre Arbeit, indem sie eine Anzahl von Parametern verwendet, welche mit dieser Funktion verändert werden können. Prinzipiell funktioniert diese Methode wie folgt. Zuerst wird versucht, das Ziel auf direktem Weg zu erreichen. Es wird eine Anzahl von Schritten vorausgeschaut, was mit dem Parameter "ahead" (voreingestellt auf 3) festgelegt werden kann. Vermindern dieses Wertes führt dazu, dass die Instanz die Richtungsänderung später beginnt. Erhöhen bedeutet eine frühere Richtungsänderung. Falls diese Prüfung zu einer Kollision führt, schaut sie nach anderen Richtungen, die mehr links oder rechts, von der bestmöglichen Richtung liegen. Dies macht sie in Schritten der Größe "rotstep" (voreingestellt 10). Vermindern dieses Wertes ermöglicht der Instanz mehr Bewegungsmöglichkeit, ist aber langsamer. Der Parameter "maxrot" ist ein wenig schwierig zu erklären. Die Instanz besitzt eine aktuelle Bewegungsrichtung ("direction"). maxrot (voreingestellt 30) gibt die Abweichung zur aktuellen Bewegungsrichtung an, die maximal in einem Schritt geändert werden darf. Auch wenn sie sich beispielsweise direkt zum Ziel bewegen könnte, macht sie es nur so, dass die maximale Abweichung der Bewegungsrichtung nicht überschritten wird. Falls Du "maxrot" hoch ansetzt, kann die Instanz die Bewegungsrichtung mehr ändern in einem Schritt. Dies macht es einfacher einen kurzen Weg zu finden aber der Weg wird hässlicher sein. Falls Du aber den Wert kleiner machst, wird der Weg geschmeidiger aber möglicherweise mit längeren Umwegen (manchmal wird das Ziel auch garnicht erreicht). Falls kein Schritt gemacht werden kann, hängt das Verhalten vom Wert des Parameters "onspot" ab. Wenn "onspot" wahr (true) ist (der voreingestellte Wert), wird die Instanz auf dem Fleck um den Betrag, der durch "maxrot" vorgegeben ist, rotieren. Falls der Wert unwahr (false) ist, findet keine Bewegung statt. Den Wert auf "false zu setzen ist beispielsweise nützlich für Autos, setzt aber die Wegfindungschancen herab.

Beachte bitte, dass die Potenzial_Näherung nur lokale Informationen verwendet. Somit wird nur eine Lösung gefunden, wenn diese lokalen Informationen hinreichend sind, die richtige Richtung der Bewegung zu bestimmen. Es wird beispielsweise scheitern, einen Weg aus einem Labyrinth zu finden (fast immer).

Die zweite Art von Funktionen berechnet einen kollisionsfreien Weg für die Instanz. Sobald der Weg kalkuliert worden ist, kannst Du ihn der Instanz zuweisen, damit sie aufs Ziel zubewegt wird. Die Berechnung des Pfads nimmt einige Zeit in Anspruch aber dafür wird danach die Abschreitung des Pfads zügig sein. Dies gilt selbstverständlich nur, wenn sich die Situation nicht in der Zwischenzeit verändert. Zum Beispiel, wenn Hindernisse sich verändern, musst du den Weg wahrscheinlich neu berechnen. Beachte auch hier, dass diese Funktionen fehlschlagen können. Diese Funktionen sind nur in der registrierten Funktion vom Game Maker verfügbar.

The Die ersten beiden Funktionen verwenden lineare-Bewegung- und Potential-Feld-Näherung, die auch für die "step"-Funktionen verwendet werden.

mp_linear_path(path, xg, yg, stepsize, checkall) Diese Funktion berechnet einen geradlinigen Weg für die Instanz von der aktuellen Position zur Position (xg,yg), wobei die angegebene "stepsize" verwendet wird. Sie gebraucht Schritte (steps) wie in der Funktion mp_linear_step(). Der angegebene Pfad (path) muss schon existieren und wird durch einen neuen Pfad überschrieben. (In einem späteren Kapitel wird das Erstellen und Vernichten von Pfaden erläutert.) Die Funktion gibt an, ob ein Pfad gefunden wurde. Die Funktion stoppt und berichtet das Fehlschlagen, wenn kein direkter Pfad zwischen Start und Ziel existiert. Wenn sie fehlschlägt wird trotzdem ein Pfad definiert, der bis zu der Stelle verläuft, an der die Instanz blockiert wurde.
mp_linear_path_object(path, xg, yg, stepsize, obj) Dasselbe wie die obige Funktion, diesmal wird aber nur obj als Hindernis gesehen. obj kann ein Objekt oder eine Instanz sein.
mp_potential_path(path, xg, yg, stepsize, checkall, factor)  Diese Funktion berechnet einen Pfad für die Instanz von der aktuellen Position und mit der momentanen Orientierung zur Position (xg,yg), wobei die angegebene Schrittweite (stepsize) verwendet wird und versucht wird Kollisionen mit Hindernissen zu vermeiden. Sie verwendet Potential-Feld-Schritte, wie in der Funktion mp_potential_step() und zusätzlich die Parameter die mit der Funktion mp_potential_settings() eingestellt werden können. Der angegebenen Pfad muss schon vorhanden sein und wird durch einen neuen Pfad überschrieben. (In einem späteren Kapitel wird das Erstellen und Vernichten von Pfaden erläutert.) Die Funktion gibt an, ob ein Pfad gefunden wurde. Um zu vermeiden, dass die Funktion endlos weiterrechnet, musst Du einen Längenfaktor (length factor) größer 1 bereitstellen. Die Funktion stoppt und berichtet das Fehlschlagen, wenn sie keinen kürzeren Pfad, zwischen Start und Ziel, kleiner als dieser faktorabhängigen Distanz findet. Ein Faktor von 4 ist normalerweise ausreichend aber wenn Du lange Umwege erwartest, kannst Du ihn möglicherweise verlängern. Wenn sie fehlschlägt, wird trotzdem ein Pfad erstellt, der in Richtung des Zielpunktes weist, ihn aber nicht erreicht. mp_potential_path_object(path, xg, yg, stepsize, factor, obj) Dasselbe wie die obige Funktion, diesmal wird aber nur obj als Hindernis gesehen. obj kann ein Objekt oder eine Instanz sein.

Die anderen Funktionen verwenden einen wesentlich komplexeren Mechanismus, wobei eine Gitter-basierte Näherung genutzt wird (manchmal A* Algorithmus genannt). Es ist erfolgreicher in der Wegfindung (obwohl es auch manchmal fehlschlagen kann) und findet kürzere Pfade aber es erfordert mehr Aufwand von deiner Seite. Die Grundlegende Idee ist folgende. Zuerst legen wir ein Gitter über den (relevanten Teil des) Raum. Du kannst wählen zwischen einem feinmaschigen Gitter (was langsamer sein wird) oder einem groben Gitter. Als nächstes bestimmen wir für alle relevanten Objekte die Gitterzellen, die sie überlappen (sowohl "bounding boxes" alsauch präzise Prüfung können verwendet werden) und markieren diese Zellen als verboten. Somit wird eine Zelle als verboten markiert, sogar wenn sie nur teilweise von einem Hindernis überdeckt wird. Schließlich spezifizieren wir eine Start- und eine Zielposition (welche innerhalb der freien Zellen liegen müssen) und die Funktion berechnet den kürzesten Pfad (eigentlich dicht am kürzesten) zwischen diesen. Der Pfad wird durch die Zentren der freien Zellen verlaufen. Wenn also die Zellen groß genug sind, so dass die im Zentrum platzierte Instanz vollständig innerhalb liegt, wird es erfolgreich sein. Diesen Pfad kannst du nun einer Instanz übergeben, damit sie ihm folgt. Die Gitter-basierte Näherung ist sehr mächtig (und wird in vielen professionellen Spielen angewandt) aber es erfordert sorgsames Bedenken von dir. Du musst bestimmen, welche Gebiete und Zellgrößen ausreichend sind, um das Spiel zu lösen. Auch musst du festlegen, welche Objekte gemieden werden müssen und ob präzise Kollisionsprüfung wichtig ist. All diese Parameter beeinflussen stark die Effizienz dieser Näherung.

Insbesondere die Größe der Zellen ist entscheidend. Erinnere dich daran, dass die Zellen groß genug sein müssen, um das sich bewegende Objekt, was mit seinem Bezugspunkt (origin) im Zentrum der Zelle liegt, ganz zu umfassen. (Sei sorgsam mit der Position des Bezugspunkts des Objektes. Realisiere auch, dass du den Pfad verschieben kannst, wenn der Bezugspunkt des Objektes nicht in dessen Zentrum liegt!) Andererseits bestehen mehr mögliche Pfade, je kleiner die Zellen sind. Wenn du die Zellen zu groß machst, werden Öffnungen/Durchgänge zwischen den Hindernissen möglicherweise verschlossen, weil alle Zellen ein Objekt schneiden.

<>Die Funktionen für die Gitter-basierte Näherung sind folgende:
mp_grid_create(left, top, hcells, vcells, cellwidth, cellheight) Diese Funktion erstellt das Gitter. Sie gibt einen Index zurück, der bei allen anderen Aufrufen verwendet werden muss. Du kannst mehrfache Gitter-Strukturen zur selben Zeit erstellen und verwalten. "left" und "top" geben die Position der linken oberen Ecke des Gitters an. "hcells" und "vcells" geben die Anzahl der horizontalen und vertikalen Zellen an. Schließlich geben "cellwidth" und "cellheight" die Größe der Zellen an.
mp_grid_destroy(id) Zerstört das angegebene Gitter und gibt belegten Speicher frei. Vergiss nicht dies aufzurufen, sobald Du das Gitter nicht mehr benötigst.
mp_grid_clear_all(id) Markiert alle Zellen des Gitters als frei.
mp_grid_clear_cell(id, h, v) Markiert die angegebene Zelle . Zelle 0,0 ist die linke obere Zelle als frei.
mp_grid_clear_rectangle(id, left, top, right, bottom) Markiert alle Zellen die das angegebene Rechteck schneiden (in Raumkoordinaten) als frei.
mp_grid_add_cell(id, h, v) Markiert die angegebene Zelle als verboten. Zelle 0,0 ist die linke obere Zelle.
mp_grid_add_rectangle(id, left, top, right, bottom) Markiert alle Zellen die das angegebene Rechteck schneiden als verboten.
mp_grid_add_instances(id, obj, prec) Markiert alle Zellen die eine Instanz des angegebenen Objektes schneiden als verboten. Du kannst auch eine individuelle Instanz verwenden, indem du "obj" die id der Instanz zuweist. Ferner kannst du das Schlüsselwort "all" angeben, um alle Instanzen aller Objekte anzugeben. "prec" gibt an, ob präzise Kollisionsprüfung verwendet werden soll (funktioniert nur, wenn präzise Prüfung für das von der Instanz verwendete sprite aktiviert ist).
mp_grid_path(id, path, xstart, ystart, xgoal, ygoal, allowdiag) Berechnet einen Pfad durch das Gitter. "path" muss einen existierenden Pfad angeben, der durch den Computerpfad ersetzt wird. "xstart" und "ystart" geben den Start und "xgoal" und "ygoal" das Ziel an. "allowdiag" gibt an, ob diagonale Bewegung zulässig ist statt nur horizontaler oder vertikaler. Die Funktion gibt wieder, ob sie erfolgreich einen Pfad gefunden hat. (Beachte, dass der Pfad unabhängig von der aktuellen Instanz ist; es ist ein Pfad durch das Gitter, nicht ein Pfad für eine besondere Instanz.)
mp_grid_draw(id) Diese Funktion zeichnet das Gitter, wobei freie Zellen grün eingefärbt sind und verbotene werden rot gezeichnet. Diese Funktion ist sehr langsam und steht nur zur Fehlersuche zur Verfügung.

Kollisionsprüfung

Wenn Bewegungen geplant werden oder aufgrund bestimmter Aktionen entschieden wird, ist es oftmals wichtig zu wissen, ob Kollisionen mit anderen Objekten an bestimmten Stellen/Positionen bestehen. Folgende Funktionen können dafür verwendet werden. All diese haben drei Argumente gemeinsam:
Das Argument obj kann ein Objekt sein, das Schlüsselwort all, oder die id einer Instanz.
Das Argument prec gibt an, die Prüfung präzise sein soll oder nur auf der "bounding-box" der Instanz basiert. Präzise Prüfung wird nur ausgeführt, wenn das sprite der Instanz es aktiviert hat.
Das Argument notme kann auf wahr (true) gesetzt werden, um anzugeben, dass die aufrufende Instanz nicht geprüft wird.
Alle diese Funktionen geben entweder die id von einer der beiden kollidierenden Instanzen zurück oder sie melden einen negativen Wert, wenn keine Kollision vorliegt.
collision_point(x, y, obj, prec, notme) Diese Funktion prüft, ob an Punkt (x,y) eine Kollision mit Instanzen des Objektes obj vorliegt.
collision_rectangle(x1, y1, x2, y2, obj, prec, notme) Diese Funktion prüft, ob eine Kollision zwischen dem (gefüllten) Rechteck mit den angegebenen gegenüberliegenden Ecken und Instanzen des Objektes obj vorliegt. Beispielsweise kannst du sie verwenden, um zu prüfen, ob ein Gebiet frei von Hindernissen ist.
collision_circle(xc, yc, radius, obj, prec, notme)Diese Funktion prüft, ob eine Kollision zwischen dem (gefüllten) Kreis mit Kreismittelpunkt an Position (xc,yc) mit gegebenem Radius und Instanzen des Objektes obj vorliegt. Beispielsweise kannst du damit überprüfen, ob ein Objekt dicht an einer bestimmten Stelle liegt.
collision_ellipse(x1, y1, x2, y2, obj, prec, notme) Diese Funktion prüft, ob eine Kollision zwischen der (gefüllten) Ellipse mit den angegebenen gegenüberliegenden Ecken und Instanzen des Objektes obj besteht.
collision_line(x1, y1, x2, y2, obj, prec, notme) Diese Funktion prüft, ob eine Kollision zwischen dem Liniensegment von (x1,y1) zu (x2,y2) und Instanzen des Objektes obj vorliegt. Dies ist eine mächtige Funktion. Du kannst sie beispielsweise benutzen, um zu prüfen, ob eine Instanz eine andere Instanz "sehen" kann, indem Du prüfst, ob das Liniensegment zwischen den beiden eine Wand schneidet.

Instanzen

Im Spiel sind die grundlegenden Einheiten die Instanzen der verschiedenen Objekte. Während des Spielverlaufs kannst du einige Aspekte dieser Instanzen verändern. Du kannst auch neue Instanzen erschaffen und/oder vernichten. Neben den oben besprochenen Bewegungsvariablen und den unten aufgeführten zeichnenbezogenen Variablen besitzt jede Instanz noch folgende Variablen:
object_index* Index des Objektes wovon dies hier eine Instanz ist. Diese Variable kann nicht verändert werden.
id* Der einzigartige Bezeichner für diese Instanz (>= 100000). (Beachte: Beim Erstellen von Räumen, wird die id immer angezeigt, wenn der Mauszeiger über einem Objekt ist.)
mask_index Index des "sprites", welches als Maske bei Kollisionen verwendet wird. Verwende einen Wert von -1, damit es das gleiche wie der "sprite_index" benutzt.
solid Gibt an, ob die Instanz "solid" ist. Kann im Spiel verändert werden.
persistent Gibt an, ob die Instanz "persistent" (beständig) ist und nach einem Raumwechsel wieder erscheint. Oftmals willst du das in gewissen Momenten abstellen (Beispielsweise wenn du zum ersten Raum zurück willst).

Es gibt nur ein Problem, wenn man sich mit Instanzen befasst. Es ist nicht gerade leicht einzelne Instanzen zu identifizieren. Sie haben keinen Namen. Wenn nur eine Instanz eines bestimmten Objektes vorhanden ist, kannst du den Namen des Objektes verwenden - Wenn jedoch mehrere Instanzen vorhanden sind, musst du
die id ermitteln. Dies ist eine einzigartige Identifizierung der Instanz. Du kannst sie bei "with statements" und als Objektbezeichner verwenden. Glücklicherweise gibt es eine Anzahl von Funktionen und Variablen, die dir helfen, die id zu ermitteln.

instance_count* Anzahl der Instanzen, welche momentan im Raum sind.
instance_id[0..n-1]* Die id der bestimmten Instanz. Wobei n die Nummer der Instanz ist. Beachte, dass die Position einer Instanz im Array sich bei jedem Schritt verändert, benutze deswegen nicht die Werte vorheriger Schritte.

Lass mich ein Beispiel geben. Angenommen jede Einheit in deinem Spiel hat ein bestimmte Stärke (power) und du willst die stärkste ermitteln - verwende folgenden Programmcode:

{
maxid = -1;
maxpower = 0;
for (i=0; i<instance_count; i+=1)
{
iii = instance_id[i];
if (iii.object_index == unit)
{
if (iii.power > maxpower)
{maxid = iii; maxpower = iii.power;}
}
}
}

Nach der Schleife enthält maxid die id der Instanz mit der höchsten "power" (Stärke). (Vernichte keine Instanzen während eines solchen Schleifendurchlaufs, weil sie automatisch aus dem Array genommen werden und als Folge wirst du Instanzen überspringen).

instance_find(obj, n) Gibt die id der (n+1)ten Instanz des Objektes obj an. obj kann ein Objekt oder das Schlüsselwort "all" sein. Wenn es nicht existiert, wird das besondere Objekt "noone" zurückgegeben. Beachte, dass sich die Zuordnung wieder bei jedem Schritt verändert, deswegen benutze nicht die Werte vorheriger Schritte.
instance_exists(obj) Gibt an, ob eine Instanz des Objektes obj existiert. obj kann ein Objekt, eine Instanz-ID oder das Schlüsselwort "all" sein.
instance_number(obj) Gibt die Anzahl der Instanzen von Objekt obj an. obj kann ein Objekt oder das Schlüsselwort "all" sein.
instance_position(x, y, obj) Gibt die ID der Instanz des Objektes obj an Position (x,y) an. Falls mehrere Instanzen an dieser Stelle sind, wird nur die erste gemeldet. obj kann ein Objekt oder das Schlüsselwort "all" sein. Wenn es nicht existiert, wird das spezielle Objekt "noone" zurückgegeben.
instance_nearest(x, y, obj) Gibt die ID der Instanz von Objekt obj zurück, welche am nächsten am Punkt (x,y) ist. obj kann ein Objekt oder das Schlüsselwort "all" sein.
instance_furthest(x, y, obj)Gibt die ID der Instanz von Objekt obj zurück, welche am weitesten vom Punkt (x,y) entfernt ist. obj kann ein Objekt oder das Schlüsselwort "all" sein.
instance_place(x, y, obj) Gibt die ID der Instanz von Objekt obj an, welche getroffen wird, wenn die aktuelle Instanz an der Position (x.,y) gesetzt wird. obj kann ein Objekt oder das Schlüsselwort "all" sein. Wenn es nicht existiert, wird das besondere Objekt "noone" zurückgegeben.

Folgende Funktionen können verwendet werden, um Instanzen zu erschaffen und zu vernichten:

instance_create(x, y, obj) Erschafft eine Instanz des Objektes obj an der angegebenen Position (x,y). Die Funktion liefert die ID der neuen Instanz zurück.
instance_copy(performevent) Erschafft eine Kopie der momentanen Instanz. Das Argument gibt an, ob das "creation event" ausgeführt wird für die Kopie. Die Funktion liefert die ID der neuen Kopie der Instanz.
instance_destroy() Vernichtet die momentane Instanz.
instance_change(obj, perf) Wechselt die Instanz nach obj. Ob ein "creation/destroy event" ausgelöst wird, gibt perf an.
position_destroy(x, y) Vernichtet alle Instanzen deren "sprites" Position (x,y) abdecken.
position_change(x, y, obj, perf) Wechselt alle Instanzen an Position (x,y) in obj. "perf" gibt an, ob das "create-/destroy event" ausgelöst wird.

Instanzen deaktivieren

Wenn du einen großen Raum erstellst, zum Beispiel bei Plattformspielen, kombiniert mit einem kleinen View, liegen viele Instanzen ausserhalb des sichtbaren Bereiches. Diese Instanzen sind aber trotzdem aktiv und führen ihre "events" durch. Auch bei Kollisionsprüfungen werden diese berücksichtigt. Dies kann viel CPU Leistung verbrauchen, was oft nicht erwünscht ist. (Es ist beispielsweise unwichtig ob sich Instanzen ausserhalb des Views bewegen.) Um dieses Problem zu lösen enthält Game Maker Funktionen zum Deaktivieren und Aktivieren von Instanzen. Bevor du sie benutzt musst du verstehen wie sie funktionieren.

Wenn du Instanzen deaktivierst sind sie in gewissem Sinne nicht existent für das Spiel. Sie sind nicht mehr sichtbar und ihre Events werden nicht ausgeführt.
Somit existieren sie für alle Aktionen und Funktionen nicht mehr. Dies spart Rechnerleistung aber sei vorsichtig. Wenn du z.B. alle Instanzen eines Objektes deaktivierst kannst du sie nicht löschen (Weil sie nicht existieren.). So kann ein vom Spieler gefundener Schlüssel keine deaktivierte Tür öffnen.

Der schlimmste Fehler, den du machen kannst, ist die Instanz zu deaktivieren welche für das Aktivieren zuständig ist. Um dies zu verhindern haben einige Funktionen hier die Möglichkeit sich nicht selbst zu deaktivieren.

Dies sind die möglichen Funktionen:

instance_deactivate_all(notme) Deaktiviert alle Instanzen im Raum. Wenn notme true ist wird die ausführende Instanz nicht deaktiviert (Was normalerweise das ist was du willst.).
instance_deactivate_object(obj)  Deaktiviert alle Instanzen im Raum für das gegebene Objekt. Du kannst auch "all" für alle Instanzen oder die ID einer bestimmten Instanz angeben.
instance_deactivate_region(left, top, width, height, inside, notme) Deaktiviert alle Instanzen in der angegebenen Region (dessen Umrisse im Bereich liegen). Wenn inside false ist werden alle Instanzen ausserhalb der Region deaktiviert.Wenn notme true ist wird die ausführende Instanz nicht deaktiviert (Was normalerweise das ist was du willst.).
instance_activate_all()  Aktiviert alle Instanzen im Raum.
instance_activate_object(obj) Aktiviert alle Instanzen im Raum für das gegebene Objekt. Du kannst auch "all" für alle Instanzen oder die ID einer bestimmten Instanz angeben.
instance_activate_region(left, top, width, height, inside) Aktiviert alle Instanzen in der angegebenen Region. Wenn inside false ist werden alle Instanzen ausserhalb der Region deaktiviert.

Zum Beispiel, um alle Instanzen ausserhalb des Views zu deaktivieren kannst du den folgenden Code im Step Event des bewegenden Objekts angeben:

{
instance_activate_all();
instance_deactivate_region(view_left[0],view_top[0],
view_width[0],view_height[0],false,true);
}

In der Praxis wirst du wahrscheinlich eine Region nutzen die etwas grösser ist als der View.

Timing (Abstimmung)

In guten Spielen sind die Dinge, welche im Spiel geschehen, gut aufeinander abgestimmt. Glücklicherweise erledigt der Game Maker die meisten Abstimmungsangelegenheiten für Dich. Er achtet darauf, das gewisse Dinge mit einer konstanten Rate abgearbeitet werden. Diese Rate wird beim Erstellen eines Raumes festgelegt Aber du kannst sie ändern, indem du die globale Variable "room_speed" verwendest. So kannst du beispielsweise die Spielgeschwindigkeit langsam erhöhen und dadurch das Spiel schwieriger werden lassen, indem du die "room_speed" bei jedem Schritt (step) um einen kleinen Wert erhöhst (z.B.: 0.001). Wenn dein Rechner langsam ist, wird die Spielgeschwindigkeit evtl. nicht erreicht werden können. Dies kann durch die Variable fps, welche kontinuierlich die Bilder pro Sekunde angibt, geprüft werden. Schliesslich gibt es noch für fortgeschrittenere "Timing-Fälle" die Variable "current_time", welche die Anzahl der verstrichenen Millisekunden seit Rechnerstart angibt. Hier ist eine Aufstellung der verfügbaren Variablen (nur die erste kann verändert werden).
room_speed Geschwindigkeit des Spiels im aktuellen Raum ("steps" pro Sekunde).
fps* Anzahl der gezeichneten Bilder pro Sekunde.
current_time* Anzahl der vergangenen Millisekunden seit Systemstart.
current_year* Das aktuelle Jahr.
current_month* Der aktuelle Monat.
current_day* Der aktuelle Tag.
current_weekday* aktueller Wochentag (1=Sonntag,...,7=Samstag).
current_hour* aktuelle Stunde.
current_minute* aktuelle Minute.
current_second* aktuelle Sekunde.

Manchmal willst du das Spiel für eine gewisse Zeit anhalten. Benutze dafür die "sleep"-Funktion.

sleep(numb) schläft numb Millisekunden lang.

Wie du wissen solltest, besitzt jede Instanz 12 verschiedene Alarmuhren (alarm clocks), welche du stellen kannst. Um die Werte, der diversen Uhren, zu verändern (oder, um sie in Erfahrung zu bringen) verwende folgende Variable:

alarm[0..11] Wert der angezeigten Alarmuhr (alarm clock). (Achtung: Alarmuhren werden nur aktualisiert, wenn das "alarm event" des entsprechenden Objektes auch "actions" enthält!)

Wir haben schon erfahren, das du für komplizierte Timing-Aufgaben die "time line" (Zeitlinie) Komponente verwenden kannst. Jede Instanz kann mit einer "time line" verknüpft werden. Folgende Variablen befassen sich damit:

timeline_index Index der "time line", welche mit der Instanz verknüpft ist. Du kannst hier die "time line" angeben, die verwendet werden soll.
Setze es auf -1, um ein Verwenden der "time line" zu unterbinden.
timeline_position Aktuelle Position innerhalb der "time line". Du kannst dies ändern, um Teile auszulassen oder zu wiederholen.
timeline_speed Normalerweise wird bei jedem Schritt (step) die Positionsmarke der "time line" um 1 erhöht. Du kannst diesen Betrag ändern, indem du der Variablen einen anderen Wert zuweist. Du kannst reelle Zahlen verwenden, z. B. 0.5(auf den Punkt achten!). Wenn der Wert grösser als eins ist, können mehrere Momente in einem (im selben) Schritt (step) abgearbeitet werden. Sie werden der Reihe nach ausgeführt, so dass keine "action" ausgelassen wird.

Rooms (Räume)

Spiele finden in Räumen (rooms) statt. Jeder Raum besitzt einen Index, welcher durch den Raumnamen angegeben wird. Der aktuelle Raum ist in der Variablen "room" gespeichert. Du kannst nicht davon ausgehen, das Räume fortlaufend nummeriert sind. Addiere oder subtrahiere niemals einen Wert zu/von der "room"-Variablen. Verwende besser die unten angeführten Funktionen und Variablen. Ein typisches Stück Programmcode würde in etwa so aussehen:

{
if (room != room_last)
{
room_goto_next();
}
else { game_end(); } }

Folgende Funktionen und Variablen befassen sich mit Räumen:

room Index des aktuellen Raumes; kann verändert werden, um zu einem anderen Raum zu gelangen - verwende lieber nachstehende Routinen dafür.
room_first* Index des ersten Raums des Spiels.
room_last* Index des letzten Raums des Spiels.
room_goto(numb) Springe zum Raum mit dem Index "numb".
room_goto_previous() Springe zum vorherigen Raum.
room_goto_next() Springe zum nächsten Raum.
room_restart() Starte den aktuellen Raum erneut.
room_previous(numb) Gibt den Index des Raumes vor dem Raum "numb" an (-1 = keiner) aber wechselt nicht dorthin.
room_next(numb) Gibt den Index des Raumes nach "numb" an (-1 = keiner).
game_end() Beendet das Spiel.
game_restart() Startet das Spiel neu.

Wenn man eine der obigen Funktionen zum Raumverändern oder dem Spiel beenden/neustarten aufruft musst du beachten, das dies nicht sofort geschieht. Es geschieht erst nachdem die aktuelle Aktion vollständig durchgeführt wurde. Also wird erst der Rest des Skriptes ausgeführt, was auch für aufrufende Skripte gilt..

Räume haben einige zusätzliche Eigenschaften:

room_width* Breite des Raumes gemessen in Pixel.
room_height* Höhe des Raumes gemessen in Pixel.
room_caption Zeichenkette, die in der Titelleiste des Fensters vom Raum angezeigt wird.
room_persistent Gibt an, ob der aktuelle Raum persistent (dauerhaft/beständig) ist.

Viele Spiele bieten dem Spieler die Möglichkeit ein Spiel zu speichern und einen gespeicherten Spielstand zu laden. Im Game Maker geschieht dies automatisch, wenn der Spieler <F5> für das Speichern und <F6> für das Laden drückt. Du kannst auch Spiele Laden/Speichern, indem du GML-Programmcode verwendest (beachte, dass der Ladevorgang nur zum Ende des aktuellen Schrittes (step) stattfindet).

game_save(string) Speichert das Spiel unter dem Namen "string" ab.
game_load(string) Lädt einen Spielstand aus der Datei "string".

Bitte bedenke bitte, dass nur grundlegene Daten gespeichert werden. Wenn du z.B. eine bestimmte Hintergrundmusik im Spiel hast, wird die genaue Position nicht abgespeichert. Außerdem werden geänderte Ressourcen, Inhalte von Stacks, Partikel und Multiplayer-Einstellungen nicht gespeichert.

Punkte

Ein anderer wichtiger Aspekt bei Spielen ist der Punktestand, die Gesundheit (der Spielfigur) und die Anzahl, der "Leben". Game Maker führt über den Punktestand in globalen Variable score, und über die Anzahl der "Leben" in der globalen Variable lives Buch. Du kannst den Punktestand ändern, indem du einfach die Variable score veränderst. Das gleiche gilt bei health(Gesundheit) und lives(Leben). Wenn die Variable lives grösser als 0 ist und kleiner oder gleich Null wird, wird das "no-more-lives event" für alle Instanzen ausgeführt. Wenn du nicht willst, dass score und lives in der Titelleiste des Fensters angegeben werden, setze die Variable show_score, etc., auf "false". Auch kannst du die Titelleiste verändern. Bei anspruchsvolleren Spielen ist es besser eine eigene Anzeige zu machen.

score Der aktuelle Punktestand.
lives Die aktuelle Anzahl der Leben.
health Die aktuelle "health" (0-100).
show_score Gibt an, ob der Punktestand in der Titelleiste des Fensters angezeigt werden soll.
show_lives Gibt an, ob die Anzahl der "Leben" in der Titelleiste des Fensters angezeigt werden soll.
show_health Gibt an, ob die Gesundheit in der Titelleiste des Fensters angezeigt werden soll.
caption_score Text der beim Punktestand angezeigt wird.
caption_lives Text der bei den "Leben" angezeigt wird.
caption_health Text der bei "health" angezeigt wird.

Generating events

Wie du weißt, ist der Game Maker komplett event-gesteuert. Sämtliche Aktionen geschehen als Resultat von events. Es gibt viele unterschiedliche events. Creation und destroy events werden ausgelöst wenn eine Instanz erschaffen oder vernichtet wird. In jedem Schritt (step), bearbeitet das System zuerst die alarm events. Danach werden Tastatur- und Mausereignisse verarbeitet und anschließend das step event. Dann werden die Instanzen an ihre neuen Positionen gesetzt und das collision event ausgewertet. Schliesslich wird das draw event verwendet, um die Instanzen zu zeichnen (beachte, dass wenn mehrere Views eingesetzt werden, das draw event mehrmals pro step aufgerufen wird). Du kannst auch ein Ereignis mittels GML-Programmcode einer Instanz zuweisen. Folgende Funktionen gibt es:

event_perform(type, numb) Löst das event numb mit angegebenen type für die aktuelle Instanz aus.

ev_create
ev_destroy
ev_step
ev_alarm
ev_keyboard
ev_mouse
ev_collision
ev_other
ev_draw
ev_keypress
ev_keyrelease
Wenn mehrere Ereignisse desselben Typen vorhanden sind, kann numb verwendet werden, das genaue Ereignis zu bestimmen. Für das alarm event liegt "numb" im Bereich 0 bis 11. Fürs Tastaturereignis verwende den Tastencode der Taste. Für Mausereignisse kannst du folgende Konstanten verwenden:

ev_left_button
ev_right_button
ev_middle_button
ev_no_button
ev_left_press
ev_right_press
ev_middle_press
ev_left_release
ev_right_release
ev_middle_release
ev_mouse_enter
ev_mouse_leave
ev_mouse_wheel_up
ev_mouse_wheel_down
ev_global_left_button
ev_global_right_button
ev_global_middle_button
ev_global_left_press
ev_global_right_press
ev_global_middle_press
ev_global_left_release
ev_global_right_release
ev_global_middle_release
ev_global_press
ev_global_release
ev_joystick1_left
ev_joystick1_right
ev_joystick1_up
ev_joystick1_down
ev_joystick1_button1
ev_joystick1_button2
ev_joystick1_button3
ev_joystick1_button4
ev_joystick1_button5
ev_joystick1_button6
ev_joystick1_button7
ev_joystick1_button8
ev_joystick2_left
ev_joystick2_right
ev_joystick2_up
ev_joystick2_down
ev_joystick2_button1
ev_joystick2_button2
ev_joystick2_button3
ev_joystick2_button4
ev_joystick2_button5
ev_joystick2_button6
ev_joystick2_button7
ev_joystick2_button8
Für das collision event gib den Index des anderen Objektes an. Schließlich kannst du für die übrigen Ereignisse folgende Konstanten nutzen:

ev_outside
ev_boundary
ev_game_start
ev_game_end
ev_room_start
ev_room_end
ev_no_more_lives
ev_no_more_health
ev_animation_end
ev_end_of_path
ev_user0
ev_user1
ev_user2
ev_user3
ev_user4
ev_user5
ev_user6
ev_user7
ev_user8
ev_user9
ev_user10
ev_user11
ev_user12
ev_user13
ev_user14
ev_user15
Beim step event kannst du folgende Konstanten benutzen:

ev_step_normal
ev_step_begin
ev_step_end
event_perform_object(obj, type, numb) Diese Funktion arbeitet genau wie voranstehende, mit der Ausnahme, dass du events in anderen Objekten auslösen kannst. Beachte, dass die Aktionen in diesen Ereignissen für die aktuelle Instanz gilt, nicht für das der Instanz zugeordnete Objekt.
event_user(numb) Beim Menüpunkt "other events" kannst du 16 benutzerdefinierte events erstellen. Diese werden nur ausgelöst, wenn du diese Funktion aufrufst. numb liegt im Bereich 0-15.
event_inherited() Führt das ererbte Ereignis aus. Funktioniert nur, wenn die Instanz ein Elternobjekt hat.

Du kannst Informationen über das momentan ausgeführte event bekommen, indem du folgende Variablen verwendest:

event_type* Type des momentan ausgeführten events.
event_number* Nummer des momentan ausgeführten events.
event_object* Der Objektindex, für den das aktuelle event ausgeführt wird.
event_action* Der Index der Aktion die gerade ausgeführt wird (0 ist die erste innerhalb des Ereignisses, etc.).

Andere Variablen und Funktionen<

Hier sind einige Variablen und Funktionen die sich mit Fehlern befassen.

error_occurred Gibt an, ob ein Fehler aufgetreten ist
error_last Zeichenkette, die die letzte Fehlermeldung angibt
show_debug_message(str) Zeigt die Zeichenkette im "debug mode" (Entwanzugsmodus/Fehlersuchmodus)

Die folgenden Funktionen gibt es, um zu prüfen, ob bestimmte Variablen definiert sind und mit ihnen kannst du auch Variablen setzen und ihre Werte auslesen. Bei allen Funktionen wird der Variablenname als "string" (Zeichenkette) übergeben!

variable_global_exists(name) Gibt an, ob eine globale Variable mit der Bezeichnung "name" existiert.
variable_local_exists(name) Gibt an, ob eine lokale Variable mit Bezeichnung "name" für die aktuelle Instanz existiert.
variable_global_get(name) Gibt den Wert der globalen Varaiblen wieder.
variable_global_array_get(name, ind) Gibt den Wert des Index ind des globalen Arrays name an (ein String).
variable_global_array2_get(name, ind1, ind2) Gibt den Wert der Indexa ind1,ind2 des globalen 2-dimensionalen Arrays mit dem Namen name an (ein string).
variable_local_get(name) Liefert den Wert der lokalen Variablen.
variable_local_array_get(name, ind) Gibt den Wert des Index ind des globalen Arrays name an (ein String).
variable_local_array2_get(name, ind1, ind2) Gibt den Wert der Indexa ind1,ind2 des globalen 2-dimensionalen Arrays mit dem Namen name an (ein string).
variable_global_set(name, value) Setzt den Wert(value) für die globale Variable.
variable_global_array_set(name, ind, value) Setzt den Wert value des Index ind des globalen Arrays name (ein String) fest.
variable_global_array2_set(name, ind1, ind2, value) Setzt den Wert value der Indexa ind1,ind2 des globalen 2-dimensionalen Arrays mit dem Namen name (ein string) fest.
variable_local_set(name, value) dasselbe - nur für die lokale Variable.
variable_local_array_set(name, ind, value) Setzt den Wert des Index ind des lokalen Arrays name (ein String) fest.
variable_local_array2_set(name, ind1, ind2, value) Setzt den Wert der Indexa ind1,ind2 des lokalen 2-dimensionalen Arrays mit dem Namen name (ein string) fest.

Beispielsweise kannst du schreiben:

{
  if variable_global_exists('ammunition')
    global.ammunition += 1
  else
    global.ammunition = 0
}

Du kannst diese Funktionen auch verwenden, um Variablen an Skripte zu übergeben - indem du ihre Bezeichnungen als Zeichenkette (string) übergibst und obige Funktionen verwendest, um sie zu verändern.

Du kannst die Priorität mit den folgenden Funktionen verändern:

set_program_priority(priority) Setzt die Priorität für das Programm fest. Du kannst Werte zwischen -3 und +3 wählen. Bei -3 läuft das Spiel nur wenn kein anderes Programm Prozessorleistung beansprucht oder im Leerlauf sind. Die Werte -2 und -1 sind unter Normal, deshalb werden andere Prozesse mehr Priorität bekommen.0 ist der Normalwert. +1 und +2 geben eine höhere Priorität, woraus eine höhere Spielgeschwindigkeit und ein flüssigerer Ablauf sichergestellt werden. Aber andere Prozesse bekommen weniger Prozessorleistung. +3 ist der Echtzeitmodus. Im Echtzeitmodus wird die gesamte Prozessorleistung dem Spiel zugeteilt. Dies kann zu ernsthaften Problemen mit anderen Programmen führen. Auch Tastenanschläge und das drücken des "X" in der rechten oberen Ecke können von Windows nicht mehr wahrgenommen werden. Teste es vorsichtig bevor du es festsetzt.

Benutzerinteraktion

Es gibt kein Spiel ohne Interaktion des Benutzers. Der Standardweg dies im Game Maker zu tun, ist es "actions" in "mouse- " oder "keyboard events" zu setzen. Aber manchmal brauchst du mehr Kontrolle. Aus einem Stück Programmcode heraus kannst du prüfen, ob bestimmte Tasten auf der Tastatur gedrückt sind und du kannst prüfen an welcher Position die Maus sich befindet und ob ihre Tasten betätigt werden. Gewöhnlich prüfst du diese Aspekte im "step event" eines Kontrollobjektes und wählst entsprechende Aktionen aus.

Die Tastatur

Für Tastaturinteraktionen existieren folgende Variablen und Funktionen:

keyboard_lastkey Keycode der zuletzt betätigten Taste. Siehe unten für keycode-Konstanten. Du kannst es ändern, zum Beispiel auf 0 setzen, wenn du es bearbeitet hast.
keyboard_key Keycode der momentan betätigten Taste (siehe unten; 0 falls keine).
keyboard_lastchar Zuletzt gedrücktes Zeichen (als string).
keyboard_string String, der die maximal 1024 zuletzt getippten Zeichen enthält. Diese Zeichenkette beinhaltet nur druckbare Zeichen. Ferner reagiert er korrekt auf das Drücken der "Backspace" - Taste, indem das letze Zeichen gelöscht wird.

Manchmal ist es praktisch eine Taste auf einer anderen abzubilden. Zum Beispiel wenn du dem Spieler gestatten willst, sowohl die Pfeiltasten, alsauch den Ziffernblock zu verwenden. Anstatt die "actions" zu duplizieren, kannst du die Tasten des Ziffernblocks auf den Pfeiltasten abbilden. Vielleicht möchtest du ja auch einen Mechanismus einbauen, wo der Spieler sich seine Tasten selber aussuchen kann. Dafür stehen folgende Funktionen zu Verfügung:

keyboard_set_map(key1, key2) Bildet die Taste mit keycode key 1 auf key 2 ab.
keyboard_get_map(key) Gibt die momentane Verknüpfung/Abbildung der Taste wieder.
keyboard_unset_map() Setzt alle Tastenzuweisungen zurück.

Um zu prüfen, ob eine bestimmte (Maus-)Taste gedrückt ist, verwende nachfolgende Funktionen. Dies ist besonders nützlich, wenn mehrere Tasten gleichzeitig gedrückt sind.

keyboard_check(key) Gibt an, ob die Taste mit dem angegebenen keycode momentan gedrückt ist.
keyboard_check_pressed(key) Gibt an, ob die Taste mit dem angegebenen keycode seit dem letzten step gedrückt wurde.
keyboard_check_released(key) Gibt an, ob die Taste mit dem angegebenen keycode seit dem letzten step losgelassen wurde.
keyboard_check_direct(key) Gibt an, ob die Taste mit dem angegebenen keycode gedrückt ist, indem die Hardware direkt geprüft wird. Das Ergebnis ist unabhängig davon, welche Anwendung grade aktiv ist. Es ermöglicht zusätzliche Überprüfungen. Insbesondere kannst du die keycodes vk_lshift, vk_lcontrol, vk_lalt, vk_rshift, vk_rcontrol und vk_ralt to prüfen, um zu erfahren, ob die linke/rechte Shift-Taste, die Control oder die Alt-Taste gedrückt ist.

Die folgenden Routinen können verwendet werden, um den Tastaturstatus zu ändern:

keyboard_get_numlock() gibt an, ob "numlock" gesetzt ist.
keyboard_set_numlock(on) Setzt (true) oder deaktiviert (false) den "numlock".
keyboard_key_press(key) Simuliert den Tastendruck der angegebenen Taste.
keyboard_key_release(key) Simuliert das Loslassen der angegebenen Taste.

Folgende Konstanten für virtuelle keycodes existieren:

vk_nokey keycode gibt an, dass keine Taste gedrückt ist
vk_anykey keycode gibt an, dass irgendeine Taste gedrückt ist
vk_left keycode für die linke Pfeiltaste
vk_right keycode für die rechte Pfeiltaste
vk_up keycode für die aufwärts Pfeiltaste
vk_down keycode für die abwärts Pfeiltaste
vk_enter enter Taste
vk_escape escape Taste
vk_space space Taset
vk_shift shift Taste
vk_control control Taste
vk_alt alt Taste
vk_backspace backspace Taste
vk_tab tab Taste
vk_home home Taste
vk_end end Taste
vk_delete delete Taste
vk_insert insert Taste
vk_pageup pageup Taste
vk_pagedown pagedown Taste
vk_pause pause/break Taste
vk_printscreen printscreen/sysrq Taste
vk_f1 ... vk_f12 keycodes für die Funktionstasten F1 bis F12
vk_numpad0 ... vk_numpad9 Zifferntasten auf dem Ziffernblock
vk_multiply Multiplikations-Taste auf dem Ziffernblock
vk_divide Divisions-Taste auf dem Ziffernblock
vk_add Additions-Taste auf dem Ziffernblock
vk_subtract Subtraktions-Taste auf dem Ziffernblock
vk_decimal Dezimalpunkt-Taste auf dem Ziffernblock

Für die Buchstabentasten verwende zum Beispiel ord('A'). (Für Großbuchstaben) Für die Zahlentasten verwende zum Beispiel ord('5') , für die <5> Taste. Folgende Konstanten können nur verwendet werden mit keyboard_check_direct:

vk_lshift linke Shift-Taste
vk_lcontrol linke control-Taste
vk_lalt linke Alt-Taste
vk_rshift rechte Shift-Taste
vk_rcontrol rechte control-Taste
vk_ralt rechte Alt-Taste

Zum Beispiel: Angenommen, du hast ein Objekt, welches der Spieler mittels der Pfeiltasten steuert. Dann kannst du folgenden code in das Step-Event des Objektes setzen:

{
if (keyboard_check(vk_left)) x -= 4;
if (keyboard_check(vk_right)) x += 4;
if (keyboard_check(vk_up)) y -= 4;
if (keyboard_check(vk_down)) y += 4;
}

Natürlich ist es viel unkomplizierter, dies einfach in die keyboard-events zu setzen.

Es gibt noch weitere Funktionen, die sich auf Tastaurinteraktionen beziehen.

keyboard_clear(key) Löscht den Status der Taste. Dies bedeutet, es werden keine Tastaturereignisse mehr erzeugt, bis die Wiederholfunktion einsetzt.
io_clear() Löscht Tastatur- und Mausstatus.
io_handle() Bearbeitet Nutzereingaben, frischt Tastatur- und Mausstatus auf.
keyboard_wait() Wartet, bis der Nutzer irgendeine Taste auf der Tastatur betätigt.

Die Maus

Für Mausinteraktionen existieren folgende Variablen und Funktionen:

mouse_x* X-Koordinate der Maus im "room" (Raum). Kann nicht geändert werden.
mouse_y* Y-Koordinate der Maus im "room" (Raum). Kann nicht geändert werden.
mouse_button Momentan gedrückter Mausknopf. als Wert verwende mb_none, mb_any, mb_left, mb_middle, or mb_right.
mouse_lastbutton Zuletzt gedrückter Mausknopf.

Um zu prüfen, ob ein bestimmter Mausknopf gedrückt ist, verwende folgende Funktionen. Dies ist besonders nützlich, wenn mehrere Tasten gleichzeitig gedrückt sind.

mouse_check_button(numb) Gibt an, ob der Mausknopf momentan gedrückt ist (verwende als Werte mb_none, mb_left, mb_middle, oder mb_right).
mouse_check_button_pressed(numb) Gibt an, ob der Mausknopf seit dem letzten step gedrückt wurde.
mouse_check_button_released(numb) Gibt an, ob der Mausknopf seit dem letzten step losgelassen wurde.

Es gibt zusätzliche Funktionen, die sich auf Mausinteraktionen beziehen.

mouse_clear(button) Löscht den Status des Mausknopfes. Das heißt, es werden solange keine Mausereignisse erzeugt, bis der Spieler den Knopf loslässt und erneut drückt.
io_clear() Löscht sowohl Tastatur-, als auch Mausstatus.
io_handle() Bearbeitet Nutzereingabe, auffrischen von Maus- und Tastaturstatus.
mouse_wait() Wartet, bis der Nutzer eine Maustaste drückt.
.

Der Joystick

Es gibt einige Funktionen, die mit Joysticks verknüpft sind. Um aber volle Kontrolle über die Steuerknüppel zu haben, gibt es einen ganzen Satz an Funktionen, die sich mit ihnen befassen. Game Maker unterstützt bis zu zwei Joysticks. Demnach verwenden alle Funktionen eine joystick id als Argument.

joystick_exists(id) Gibt an, ob joystick id (1 oder 2) existiert.
joystick_name(id) Gibt den Namen des Joysticks wieder
joystick_axes(id) Gibt die Anzahl der Achsen des Joysticks wieder.
joystick_buttons(id) Gibt die Anzahl der Knöpfe des Joysticks wieder.
joystick_has_pov(id) Gibt an, ob der Joystick "point-of-view" Fähigkeiten besitzt.
joystick_direction(id) Gibt den keycode (vk_numpad1 bis vk_numpad9) entsprechend der Richtung von joystick id (1 oder 2).
joystick_check_button(id, numb) Gibt an, ob ein Joystick-Knopf gedrückt ist (numb im Bereich von 1-32).
joystick_xpos(id) Gibt die Position der X-Achse von joystick id an (-1 bis 1).
joystick_ypos(id) Gibt die Position der Y-Achse wieder.
joystick_zpos(id) Gibt die Position der Z-Achse wieder (sofern vorhanden).
joystick_rpos(id) Gibt die Ruderposition an (oder 4.Achse).
joystick_upos(id) Gibt die u-Position (oder 5.Achse) an.
joystick_vpos(id) Gibt die v-Position an (oder 6.Achse).
joystick_pov(id) Gibt die "point-of view" Position des joysticks an. Dies ist ein Winkel von 0 bis 360 Grad. 0 ist vorwärts, 90 ist nach rechts, 180 ist rückwärts und 270 nach linkst. Falls keine "point-of-view" Richtung vom Nutzer betätigt ist, wird -1 zurückgegeben.

Spiele-Grafiken

Ein wichter Teil eines Spieles sind seine Grafiken. Game Maker kümmert sich normalerweise selbst um fast alles und bei einfachen Spielen ist das auch gut so. Aber manchmal möchtest du eben doch mehr Kontrolle. Für manche Dinge gibt es Aktionen, doch per Funktionen ist viel mehr möglich. Diese Kapitel gibt dir alle Informationen darüber was in deinem Spiel in diesem Bereich vor sich gehen kann.

Sprites und images

Jedes Objekt kann mit einem "sprite" verbunden werden. Es kann ein Einzelbild oder eine Bildfolge sein. Für jede Instanz des Objektes zeichnet das Programm das korrespondierende Bild auf den Bildschirm, wobei der Bezugspunkt (origin) (wie in den "sprite properties" definiert) auf die X,Y-Position der Instanz gelegt wird.Wenn eine Bildfolge vorhanden ist, werden alle Animationsschritte der Reihe nach gezeichnet, um einen Animationseffekt zu erhalten. Es gibt eine Vielzahl von Variablen, welche die Darstellung der Bilder beeinflussen. Sie können verwendet werden, um unterschiedliche Effekte zu erzielen. Jede Instanz besitzt folgende Variablen:

visible Wenn visible (sichtbar) auf 1 (true/wahr) gesetzt wird, wird das Bild dargestellt, sonst nicht. Unsichtbare Instanzen sind trotzdem aktiv und verursachen collision events; Du siehst sie nur nicht! Die Sichtbarkeit auf Null zu setzen ist zum Beispiel für "controller objects" (Steuerungsobjekte) (mach sie nonsolid (nicht massiv) um collision events zu vermeiden) oder versteckte Schalter sehr nützlich.
sprite_index Dies ist der Index (lat. Anzeiger) des momentanen sprites der Instanz. Du kannst ihn ändern, um der Instanz ein anderes sprite zuzuweisen. Als Wert kannst du die Bezeichnungen/Namen der verschiedenen sprites verwenden, welche du schon erstellt hast. Das Wechseln des sprites ändert nicht den Index des angezeigten "sub-image" (Bild einer Bildfolge).
sprite_width* Gibt die Breite des sprites an. (Dieser Wert ist unveränderbar aber möglicherweise willst du ihn trotzdem benutzen).
sprite_height* Gibt die Höhe des sprites an. (Auch dieser Wert ist unveränderbar.)
sprite_xoffset* Gibt den horizontalen Versatz (offset) des sprites an, wie in den "sprite properties" festgelegt. (Auch unveränderbar.)
sprite_yoffset* Vertikaler Versatz. (unveränderbar.)
image_number* Bildnummer eines Bildes einer Bildfolge der Instanz (unveränderbar).
image_index Wenn ein sprite aus einer Bildfolge besteht, wird diese zyklisch wiederholt. Diese Variable zeigt das momentan dargestellte Bild der Bildfolge an (Nummerierung beginnt bei 0). Du kannst das momentan angezeigte Bild ändern, indem du den Wert dieser Variablen änderst. Das Programm setzt, beginnend mit dem angegebenem Bild, die zyklische Wiederholung fort.
image_speed Die Zyklusgeschwindigkeit. Ein Wert von 1 bedeutet pro "step" ein Bild weiter. Kleinere Werte bedeuten eine langsamere Zyklusgeschwindigkeit, wobei jedes Bild der Bildfolge mehrfach gezeichnet wird. Grössere Werte bedeuten, dass einzelne Bilder der Bildfolge übersprungen werden, um die Bewegung schneller zu gestalten. Manchmal willst du nur ein spezielles Bild einer Bildfolge darstellen und nicht immer den ganzen Zyklus. Das kannst du erreichen, indem du diese Variable auf 0 und die Variable image_index auf den Index des Bildes setzt, welches dargestellt werden soll (Das erste Bild der Bildfolge hat den Index 0). Dies ist nützlich, wenn ein Objekt unterschiedliche Erscheinungsbilder hat.
Angenommen du hast ein Objekt, welches sich drehen kann und du hast eine Bildfolge worin alle Bilder, je nach Ausrichtung, enthalten sind (entgegen dem Uhrzeigersinn). Dann kannst du im "step event" des Objekts folgendes setzen:
{
image_index = direction * image_number/360;
image_speed = 0;
}
depth Normalerweise werden Bilder dargestellt in der Reihenfolge, wie die Instanzen erstellt werden. Du kannst dies ändern, indem du eine "image depth" (Zeichenebene) festlegst. Voreingestellt ist 0, sofern du keinen anderen Wert in den "object properties" angegeben hast. Je höher der Wert, desto weiter ist die Instanz "entfernt". (Du kannst auch negative Werte einsetzen.) Instanzen mit höherer "depth" werden hinter Instanzen mit niedrigerer "depth" dargestellt. Durch festlegen der "depth" wird sichergestellt, dass die Instanzen in der von dir gewünschten Anordnung dargestellt werden (z.B. Ein Flugzeug vor den Wolken). Hintergrundinstanzen sollten eine hohe (positive) "depth" haben und Vordergrundinstanzen eine niedrige (negative) "depth"
image_xscale Ein Skalierungsfaktor, um die Bilder grösser oder kleiner darzustellen. Ein Wert von 1 gibt die Normalgrösse an. Ein Ändern der Skalierung beeinflusst auch die Bildbreite und die "collision events", wie du vermutlich schon erwartet hast. Ändern der Skalierung kann verwendet werden, um 3D-Effekte zu simulieren. Benutze -1 um das Sprite horizontal zu spiegeln.
image_yscale Dasselbe nur für die Höhe.
image_angle Der Winkel, um den das Sprite rotiert ist. Er wird in Grad (°) gegen den Uhrzeigersinn angegeben. Ein Wert von 0 Grad gibt an, dass das Sprite nicht gedreht werden soll. Diese Variable kann nur in der Registrierten Version des Game Makers verändert werden!
image_alpha Transparenzwert(alpha) der bei der Darstellung verwendet wird. 1 ist der normale Wert; ein Wert von 0 ist total transparent.
image_blend Überblendungsfarbe des Sprites. Ein Wert von c_white ist der Standard. Wenn du eine andere Farbe angibst wird das Sprite entsprechend eingefärbt. Damit kann man die Spritefarbe on the fly zu ändern. Diese Variable kann nur in der Registrierten Version des Game Makers verändert werden!
bbox_left* Linke Seite des Begrenzungsrahmens (bounding box) vom Bild der Instanz (Skalierung berücksichtigt).
bbox_right* Rechte Seite des Begrenzungsrahmens.
bbox_top* Oberkante des Begrenzungsrahmens.
bbox_bottom* Unterkante des Begrenzungsrahmens.

Backgrounds (Hintergrundbilder)

Jeder Raum kann bis zu acht Hintergründe haben und eine Hintergrundfarbe. Alle diese Aspekte von Hintergründen kannst du mit einem Codeschnipsel (piece of code) und mittels folgender Variablen ändern (Manche sind Arrays mit Wertebereich 0-7, die den Hintergrund angeben):
background_color Hintergrundfarbe des Raumes.
background_showcolor Gibt an, das Fenster in der Hintergrundfarbe zu füllen.
background_visible[0..7] Gibt an, ob dieses Hintergrundbild sichtbar ist.
background_foreground[0..7] Gibt an, ob das Hintergrundbild im Vordergrund ist.
background_index[0..7] Hintergrundbildindex für den Hintergrund.
background_x[0..7] X Position des Hintergrundbildes.
background_y[0...7] Y Position des Hintergrundbildes.
background_width[0...7]* Breite des Hintergrundbildes.
background_height[0...7]* Höhe des Hintergrundbildes.
background_htiled[0..7] Gibt an, ob das Hintergrundbild horizontal gekachelt(tiled) ist.
background_vtiled[0..7] Gibt an, ob das Hintergrundbild vertikal gekachelt(tiled) ist.
background_xscale[0..7] Horizontaler Skalierungsfaktor für den Hintergrund.
background_yscale[0..7] Vertikaler Skalierungsfaktor für den Hintergrund.
background_hspeed[0..7] Horizontaler "scrolling speed" (Verschiebung) des Hintergrundes (pixels pro step).
background_vspeed[0..7] Vertikaler "scrolling speed" (Verschiebung) des Hintergrundes (pixels pro step).
background_blend[0..7] Farbe, mitder das Hintergrundbild eingefärbt wird. c_white ist Standard. Nur in der Registrierten Version verfügbar!
background_alpha[0..7] Transparenzwert (alpha) der zum Zeichnen des Hintergrundes benutzt wird. Ein Wert von 1 entspricht den normalen Einstellungen; ein Wert von 0 bedeutet totale Transparenz.

Sprites und Hintergründe zeichnen

Normalerweise sind allen Objekten Sprites zugeordnet, die gezeichnet werden, aber du kannst das Draw-Event benutzen um andere Sachen zu zeichnen. Dieses und einige folgende Kapitel geben die Informationen darüber, was alles möglich ist. Zuerst gibt es die Funktionen, die Sprites und Hintergründe auf verschiedenste Arten und Weisen zu zeichnen. Diese geben dir mehr Kontrolle über die Erscheinung des Sprites. Du kannst auch (Teile von) Hintergründe zeichnen.
draw_sprite(sprite, subimg, x, y) Zeichnet das Bild subimg(-1 entspricht dem aktuellen) der Bildfolge(sprite) mit Index sprite , mit dem Bezugspunkt (x,y). (Ohne Color- und Alpha-blending)
draw_sprite_stretched(sprite, subimg, x, y, w, h) Zeichnet das Bild so, dass es den Bereich mit w Breite und h Höhe und der Linken-oberen Ecke bei (x,y) ausfüllt.
draw_sprite_tiled(sprite, subimg, x, y) Zeichnet das "sprite" gekachelt, so dass es den ganzen Raum ausfüllt. (x,y) ist die Stelle an der ein "sprite" gezeichnet wird.
draw_sprite_part(sprite, subimg, left, top, right, bottom, x, y)Zeichnet den Teil des Subimages subimg (-1=aktuelles) des Sprites sprite mit der linken oberen Ecke an Position x,y

draw_background(back, x, y) Stellt den Hintergrund mit Index back an Position x,y dar.
draw_background_stretched(back, x, y, w, h) Zeichnet den Hintergrund gestreckt im angegebenen Bereich.
draw_background_tiled(back, x, y) Kachelt den Hintergrund, damit er den ganzen Raum ausfüllt.
draw_background_part(back, left, top, right, bottom, x, y) Zeichnet den Teil des Hintergrundes mit der linken oberen Ecke an Position x,y.

Die folgenden Funktionen sind erweiterte Version der oben genannten. Sie sind nur in der Registrierten Version verfügbar!

draw_sprite_ext(sprite, subimg, x, y, xscale, yscale, rot, color, alpha) Zeichnet das Sprite skaliert, um rot Grad gegen den Uhrzeigersinn gedreht, mit den Faktoren x,y. color gibt die Farbe an, mitder das Sprite geblendet wird (benutze c_white um nicht zu blenden). alpha gibt die Durchsichtigkeit des Sprites an. Ein Wert von 0 macht es komplett transparent. Ein Wert von 1 komplett undurchsichtig.
draw_sprite_stretched_ext(sprite, subimg, x, y, w, h, color, alpha) Zeichnet das "sprite" gestreckt, so dass es den angegeben Bereich ausfüllt (x,y = linke obere Ecke; w= "width" (Breite) und h= Höhe). color legt das Blending und alpha die Transparenz fest.
draw_sprite_tiled_ext(sprite, subimg, x, y, xscale, yscale, color, alpha) Kachelt das Sprite, damit es den ganzen Raum ausfüllt aber mit Skalierung, Color-Blending und Transparenz.
draw_sprite_part_ext(sprite, subimg, left, top, right, bottom, x, y, xscale, yscale, color, alpha) Zeichnet das "sprite" gekachelt, so dass es den ganzen Raum ausfüllt aber nun mit Skalierung, Color-Blending und Transparenz
draw_sprite_general(sprite, subimg, left, top, right, bottom, x, y, xscale, yscale, rot, c1, c2, c3, c4, alpha) Die mächtigste Funktion. Zeichnet den angegebenen Teil des subimg (-1 ist das Aktuelle) des Sprites mit seinem Ursprung bei (x, y) nun aber mit Skalierung, Rotation, Color-Blending für alle vier Ecken (c1 = oben-links, c2 = oben-rechts, c3 = unten-rechts, c4 = unten-links) und Transparenz

draw_background_ext(back, x, y, xscale, yscale, rot, color, alpha) Zeichnet den Hintergrund skaliert, um rot Grad gedreht, mit color geblendet und mit alpha (0-1).
draw_background_stretched_ext(back, x, y, w, h, color, alpha) Zeichnet den Hintergrund gestreckt im angegebenen Bereich. color gibt die das Color-Belding und alpha die Transparenz an.
draw_background_tiled_ext(back, x, y, xscale, yscale, color, alpha) Kachelt den Hintergrund, damit er den ganzen Raum ausfüllt aber mit Skalierung, Color-Blending und Transparenz.
draw_background_part_ext(back, left, top, right, bottom, x, y, xscale, yscale, color, alpha) Zeichnet den Teil des Hintergrundes an Position x,y aber mit Skalierung, Color-Blending und Transparenz.
draw_background_general(back, left, top, right, bottom, x, y, xscale, yscale, rot, c1, c2, c3, c4, alpha) Die mächtigste Funktion. Zeichnet den angegebenen Teil des Hintergrundes bei (x, y) nun aber mit Skalierung, Rotation, Color-Blending für alle vier Ecken (c1 = oben-links, c2 = oben-rechts, c3 = unten-rechts, c4 = unten-links) und Transparenz

Formen zeichnen

Es gibt eine große Sammlung von Funktionen, die verschiedene Formen zeichnen. Außerdem gibt es Funktionen um Text zu zeichnen (siehe Nächstes Kapitel) Diese Funktionen werden im Draw-Event benutzt, weil sie hauptsächlich dort Sinn ergeben. Bedenke, dass Kollisionen zwischen Objekten mit ihren Sprites/Masks berechnet werden, nicht mit dem, was du Zeichnest. Die folgenden Funktionen zeichnen einfache Formen.
draw_clear(col) Säubert den ganzen Raum in der angegebenen Farbe (kein Alpha-Blending)
draw_clear_alpha(col, alpha) Säubert den ganzen Raum in der angegebenen Farbe und mit dem angegeben Alphawert (nützlich für Oberflächen).
draw_point(x, y) Zeichnet einen Punkt bei den Koordinaten (x, y) in der aktuellen Farbe.
draw_line(x1, y1, x2, y2) Zeichnet eine Linie von (x1, y1) bis (x2, y2).
draw_rectangle(x1, y1, x2, y2, outline) Zeichnet ein Rechteck. outline gibt an, ob nur die Außenlinie gezeichnet werden soll(true) oder es gefüllt sein soll(false).
draw_roundrect(x1, y1, x2, y2, outline) Zeichnet ein abgerundetes Rechteck. outline gibt an, ob nur die Außenlinie gezeichnet werden soll(true) oder es gefüllt sein soll(false).
draw_triangle(x1, y1, x2, y2, x3, y3, outline) Zeichnet ein Dreieck. outline gibt an, ob nur die Außenlinie gezeichnet werden soll(true) oder es gefüllt sein soll(false).
draw_circle(x, y, r, outline) Zeichnet einen Kreis mit Radius r. outline gibt an, ob nur die Außenlinie gezeichnet werden soll(true) oder er gefüllt sein soll(false).
draw_ellipse(x1, y1, x2, y2, outline) Zeichnet eine Ellipse. outline gibt an, ob nur die Außenlinie gezeichnet werden soll(true) oder sie gefüllt sein soll(false).
draw_arrow(x1, y1, x2, y2, size) Zeichnet einen Pfeil von (x1,y1) nach (x2,y2). size gibt die Größe des Pfeils in Pixeln an.
draw_button(x1, y1, x2, y2, up) Zeichent einen Button. up gibt an, ob er nach oben (true) oder nach unten sein soll (false).
draw_path(path, x, y, absolute) Mit dieser Funktion wird der Pfad im Raum mit seiner Startposition bei (x, y) gezeichnet. Wenn absolute wahr ("true") ist, wird der Pfad dort gezeichnet, wo er definiert wurde und die x- und y-Werte werden ignoriert.
draw_healthbar(x1, y1, x2, y2, amount, backcol, mincol, maxcol, direction, showback, showborder) Mit dieser Funktion kannst du eine Lebensanzeige (oder irgendeine andere Anzeige, die einen Wert angibt. z.B. den Schaden) zeichnen. Die Argumente x1, y1, x2 und y2 geben den gesamten Bereich der Anzeige an. amount gibt an, wieviel die Anzeige anzeigen soll (mus zwischen 0 und 100 liegen). backcol ist die Hintergrundfarbe der Anzeige. mincol und maxcol geben die Farben an, in denen die Anzeige gezeichnet wird, wenn amount 0 bzw. 100 ist. Wenn amount zwischen 0 und 100 ist werden die Farben ihren Anteilen entsprechend gemischt, folglich kann man sehr leicht eine Anzeige machen, die ihre Farbe von Grün nach Rot verändert. direction gibt an, in welche Richtung die Anzeige steigt (0 = von Links nach Rechts, 1 = von Rechts nach links, 2 = von Oben nach Unten, 3 = von Unten nach Oben). Schließlich gibt showback an ob der Hintergrund angezeigt werden soll und showborder, ob die Anzeige einen Schwarzen Rand haben sollen.

Die meisten der obigen Funktionen nutzen die Farb- und Alpha- Einstellungen, die du mit folgenden Funktionen verändern kannst.

draw_set_color(col) Setzt die Farbe, die von nun an zum Zeichnen verwendet wird.
draw_set_alpha(alpha) Setzt den Transparenzwert, der von nun an verwendet wird (Sollte zwischen 0 und 1 liegen. 0 ist ganz transparent, 1 ganz sichtbar)
draw_get_color() Gibt die aktuelle Farbe zurück.
draw_get_alpha() Gibt den aktuellen Alphawert zurück.

Es existieren viele vordefinierte Farben:

c_aqua
c_black
c_blue
c_dkgray
c_fuchsia
c_gray
c_green
c_lime
c_ltgray
c_maroon
c_navy
c_olive
c_purple
c_red
c_silver
c_teal
c_white
c_yellow

Die folgenden Funktionen helfen dir genau die Farben zu erstellen, die du willst.

make_color_rgb(red, green, blue) Gibt eine Farbe zurück, die die angegeben Rot, Grün und Blau Werte hat. red, green und blue müssen zwischen 0 und 255 liegen.
make_color_hsv(hue, saturation, value) Gibt eine Farbe zurück, die die angegebenen Farb-, Sättigungs- und Helligkeitswerte hat. (Jeder zwischen 0 und 255)
color_get_red(col) Gibt den Rot-Wert der Farbe zurück.
color_get_green(col) Gibt den Grün-Wert der Farbe zurück.
color_get_blue(col) Gibt den Blau-Wert der Farbe zurück.
color_get_hue(col) Gibt den Farb-Wert der Farbe zurück.
color_get_saturation(col) Gibt den Sättigungs-Wert der Farbe zurück.
color_get_value(col) Gibt den Helligkeits-Wert der Farbe zurück.
merge_color(col1, col2, amount) Gibt ein gemischte Farbe der beiden zurück. Die Stärken der beiden wird durch amount angegeben, bei einem Wert von 0 wird col1 zurückgegeben, bei 1 col1.

Die folgenden diversen Funktionen existieren:

draw_getpixel(x, y) Gibe die Farbe zurück, die an der Position (x, y) im Raum vorhanden ist. Diese Funktion ist nicht sehr schnell, sei als vorsichtig.
screen_save(fname) Speichert ein Bild des Bildschirms als Bmp in den angegebenen Dateinamen ab. Diese Funktion ist nützlich um Screenshot zu erstellen.
screen_save_part(fname, x, y, w, h) Speicher den angegebene Teil des Bildschirms ab.

Text

Manchmal muss man in Spielen Text anzeigen und dafür musst du eine Schrift auswählen. Schriften werden durch Font Ressourcen definiert (du kannst diese entweder im Game Maker oder mit den Funktionen um Ressourcen zu erstellen, erzeugen). Es gibt verschiedene Funktionen, um Text auf verschiedene Arten zu zeichnen, aber in jeder gibst du die Position an, an der der Text auf dem Bildschirm erscheinen soll. Es gibt zwei Funktionen, die die horizontale und vertikale Ausrichtung des Textes zu dieser Position verändern:
draw_set_font(font) Setzt die Schrift, die benutzt wird, wenn text gezeichnet wird. Benutze -1 um sie auf die Standard Schrift (Arial 12) zu setzen.
draw_set_halign(halign) Setzt die horizontale Ausrichtung für Text. Benutze eine der folgenden Konstanten:
fa_left links
fa_center zentriert
fa_right rechts

draw_set_valign(valign) Setzt die vertikale Ausrichtung für Text. Benutze eine der folgenden Konstanten:

fa_top oben
fa_middle mittig
fa_bottom unten

draw_text(x, y, string) Zeichnet den "string" (Zeichenkette) an Position x,y mit der eingestellten Farbe und Alpha. Ein # Symbol oder "carriage return" chr(13) oder "linefeed" chr(10) werden als Zeilenende gewertet; so kannst du mehrzeilige Texte zeichnen. (Verwende \# um das # Symbol darzustellen.)
draw_text_ext(x, y, string, sep, w) Genauso wie obige Funktion, aber man kann zwei Argumente mehr angeben. sep gibt an, wie groß der Zeilenabstand in mehrzeiligem Text ist. Wenn du -1 benutzt, wird der normale Zeilenabstand benutzt.  w gibt die Breite des Textes in Pixeln an. Zeilen die breiter als diese Breite sind, werden an Leerzeichen und Bindestrichen (-) umgebrochen. Benutze -1 um die Zeilen nicht umbrechen zu lassen.
string_width(string) Breite des Strings wie er in der eingestellten Schriftart  mit der draw_text() Funktion gezeichnet werden würde. Das kann dazu benutzt werden um Grafiken präzise zu platzieren.
string_height(string) Höhe des Strings wie er in der eingestellten Schriftart  mit der draw_text() Funktion gezeichnet werden würde.
string_width_ext(string, sep, w) Breite des Strings wie er in der eingestellten Schriftart  mit der draw_text_ext() Funktion gezeichnet werden würde. Das kann dazu benutzt werden um Grafiken präzise zu platzieren.
string_height_ext(string, sep, w) Höhe des Strings wie er in der eingestellten Schriftart  mit der draw_text_ext() Funktion gezeichnet werden würde.

Die folgenden Funktionen ermöglichen es skalierten und rotierten Text und sogar Farbverläufe auf Texten zu zeichnen. Diese Funktionen sind nur in der registrierten Version des Game Makers verfügbar!

draw_text_transformed(x, y, string, xscale, yscale, angle) Zeichnet den String an der angegebenen Position genau wie oben, aber horizontal und vertikal mit den angegebenen Werten skaliert und um den Winkel angle Grad gegen den Uhrzeigersinn gedreht.
draw_text_ext_transformed(x,y,string,sep,w,xscale,yscale,angle)
Kombiniert die Funktionen draw_text_ext und draw_text_transformed. Erlaubt es mehrzeiligen Text skalert und rotiert zu zeichnen.
draw_text_color(x, y, string, c1, c2, c3, c4, alpha) Zeichnet den String an der angegebenen Position genau wie oben. Die vier Farben geben die Farben der vier Ecken (links-oben, rechts-oben, rechts-unten, links-unten) an. alpha ist der Transparenzwert, der benutzt werden soll (0-1).
draw_text_ext_color(x, y, string, sep, w, c1, c2, c3, c4, alpha) Genau wie draw_text_ext() nur mit eingefärbten Ecken.
draw_text_transformed_color(x, y, string, xscale, yscale, angle, c1, c2, c3, c4, alpha) Genau wie draw_text_transformed()nur mit eingefärbten Ecken.
draw_text_ext_transformed_color(x, y, string, sep, w, xscale, yscale, angle, c1, c2, c3, c4, alpha) Genau wie draw_text_ext_transformed() nur mit eingefärbten Ecken.

Fortgeschrittene Zeichnungs-Funktionen

Diese Funktionalität ist nur in der registrierten Version des Game Makers verfügbar.

Weiter oben wurde eine Anzahl von einfachen Zeichnungs-Funktionen beschrieben. Hier findest du eine Anzahl von zusätzlichen Funktionen, die dir viel mehr Möglichkeiten bieten. Zuallererst gibt es Funktionen, um Formen mit Farbverläufen zu zeichnen. Dann gibt es Funktionen, um mehr gewöhnliche Polygone zu zeichnen, und schließlich gibt es die Möglichkeit, texturierte Polygone zu zeichnen.

Die folgenden, erweiterten Versionen der einfachen Zeichnungs-Funktionen Funktionen existieren. Jede von ihnen erhält extra Farbparameter, die benutzt werden, um die Farbe an den verschiedenen Eckpunkten zu bestimmen. Die standard Zeichnungs-Farbe wird in diesen Funktionen nicht verwendet.

draw_point_color(x, y, col1) Zeichnet einen Punkt bei (x|y) in der angegebenen Farbe.
draw_line_color(x1, y1, x2, y2, col1, col2) Zeichnet eine Linie von (x1|y1) nach (x2|y2), durch Interpolation der Farbe zwischen col1 und col2.
draw_rectangle_color(x1, y1, x2, y2, col1, col2, col3, col4, outline) Zeichnet ein Rechteck. Die vier Farben geben die Farben bei dem oben-linken, dem oben-rechten, dem unten-rechten, und dem unten-linken Eckpunkt an. outline gibt an, ob nur die Kontur gezeichnet werden muss (true) oder ob es ausgefüllt sein soll (false).
draw_roundrect_color(x1, y1, x2, y2, col1, col2, outline) Zeichnet ein abgerundetes Rechteck. col1 ist die Farbe in der Mitte und col2 die Farbe an der Grenze. outline gibt an, ob nur die Kontur gezeichnet werden muss (true) oder ob es ausgefüllt sein soll (false).
draw_triangle_color(x1, y1, x2, y2, x3, y3, col1, col2, col3, outline) Zeichnet ein Dreieck. Die drei Farben sind die Farben der drei Eckpunkte, welche über das Dreieck interpoliert werden. outline gibt an, ob nur die Kontur gezeichnet werden muss (true) oder ob es ausgefüllt sein soll (false).
draw_circle_color(x, y, r, col1, col2, outline) Zeichnet einen Kreis bei (x,y) mit dem Radius r. col1 ist die Farbe in der Mitte und col2 die Farbe an der Grenze. outline gibt an, ob nur die Kontur gezeichnet werden muss (true) oder ob es ausgefüllt sein soll (false).
draw_ellipse_color(x1, y1, x2, y2, col1, col2, outline) Zeichnet eine Ellipse. col1 ist die Farbe in der Mitte und col2 die Farbe bei der Grenze. outline gibt an, ob nur die Kontur gezeichnet werden muss (true) oder ob es ausgefüllt sein soll (false).

Du kannst auch größerer Primitives zeichnen. Dies funktioniert leicht anders. Du fängst an zu spezifzieren, welches Primitive du zeichnen möchtest. Als nächstes spezifizierst du die Eckpunkte für es, und schließlich beendest du das Primitive, bei welchem Moment es gezeichnet wird. Es gibt sechs Arten von Primitives:

pr_pointlist Die Eckpunkte sind ein Satz von Punkten.
pr_linelist Die Eckpunkte sind ein Satz von Linien-Segmenten. Jedes Paar von Eckpunkten bildet ein Linien-Segment. Also muss es einen geraden Satz von Eckpunkten geben.
pr_linestrip Die Eckpunkte bilden eine Polylinie, wobei der erste mit dem zweiten, der zweite mit dem dritten etc. verbunden ist. Der letzte ist nicht mit dem ersten verbunden. Du musst eine extra Kopie des ersten Eckpunktes hierfür spezifizieren.
pr_trianglelist Die Eckpunkte sind ein Satz von Dreiecken. Jede Dreiergruppe von Eckpunkten bildet ein Dreieck. Also muss die Anzahl von Eckpunkten ein Vielfaches von 3 sein.
pr_trianglestrip Die Eckpunkte bilden wieder Dreiecke, aber diesmal funktioniert es leicht anders. Die ersten drei bilden das erste Dreieck. Die letzten zwei von diesen Eckpunkten, zusammen mit dem nächsten Eckpunkt, bilden das zweite Dreieck, etc. Also jeder neue Eckpunkt spezifiziert ein neues Dreieck, welches mit dem letzten verbunden ist.
pr_trianglefan Einer Dreiecksliste (triangle list) ähnlich, aber diesmal ist der Erste Eckpunkt Teil von allen Dreiecken. Wiederum spezifiziert jeder neue Eckpunkt ein neues Dreieck, welches mit dem vorherigen Eckpunkt und dem ersten verbunden ist.

Die folgenden Funktionen existieren für das Zeichnen von Primitives

draw_primitive_begin(kind) Beginne ein Primitive des angegebenen Typs.
draw_vertex(x, y) Füge den Eckpunkt (x|y) dem Primitive hinzu, benutzt die zuvor gesetzte Farbe und den alpha Wert.
draw_vertex_color(x, y, col, alpha) Füge den Eckpunkt (x|y) dem Primitive hinzu, mit seiner eigenen Farbe und seinem eigenem Alpha- Wert. Dies erlaubt dir Primitives mit sich sauber ändernden Farben und Alpha-Werten zu erstellen.
draw_primitive_end() Beendet die Beschreibung des Primitives. Diese Funktion zeichnet es eigentlich.

Letzendlich ist es möglich, Primitives unter Verwendung von Sprites oder Hintergründen als Texturen zu zeichnen. Wenn eine Textur benutzt wird wird das Bild auf dem Primitive platziert, wobei es neugeformt wird um auf das Primitive zu passen. Texturen werden benutzt, um Details zu Primitives hinzuzufügen, wie z.B. eine Backsteinwand. Um Texturen zu benutzen, musst du zuerst die Id der Textur, die du benutzen möchtest, erhalten. Hierfür existieren die folgenden Funktionen:

sprite_get_texture(spr, subimg) Gibt die Id der Textur dem Einzelbild subimg des angegebenen Sprites entsprechend wieder.
background_get_texture(back) Gibt die Id der Textur dem angegebenen Hintergrund entsprechend wieder.

Eine ausgewählte Textur muss sich noch nicht im in Videospeicher befinden. Das System wird sie dorthin legen, sobald du sie einmal brauchst, aber manchmal möchtest du dies selbst entscheiden. Für dies existieren die folgenden zwei Funktionen:

texture_preload(texid) Legt die Textur sofort in den Videospeicher.
texture_set_priority(texid, prio) Wenn es zu wenig Videospeicher gibt, wird etwas vorübergehend entfernt werden, um Platz für andere zu schaffen, die gebraucht werden. Die mit der niedrigeren Priorität werden zuerst entfernt. Normalerweise haben alle die Priorität 0, aber du kannst die Priorität hier ändern. (Benutze positive Werte!)

Um Texturen zu Primitives hinzuzufügen, musst du spezifizieren, welche Teile der Texturen wo auf dem Primitive platziert werden müssen. Positionen in den Texturen werden mit Werten zwischen 0 und 1 angegeben, allerdings gibt es ein Problem hier. Größen von Texturen müssen Potenzen von 2 sein (also z.B. 32x32 oder 64x64). Wenn du Sprites oder Backgrounds als Texturen benutzen möchtest, gehst du besser sicher, dass sie eine solche Größe haben. Um herauszufinden welcher Teil der Textur tatsächlich benutzt wird kannst du die folgenden zwei Funktionen benutzen. Sie geben einen Wert zwischen 0 und 1 wieder, der die benutzte Breite/Höhe der Textur angibt. Das Spezifizieren dieses Wertes als Textur-Koordinate wird die rechte oder untere Seite der Textur angeben.

texture_get_width(texid) Gibt die Breite der Textur mit der angegeben Id wieder. Die Breite liegt in dem Bereich von 0-1.
texture_get_height(texid) Gibt die Höhe der Textur mit der angegeben Id wieder. Die Breite liegt in dem Bereich von 0-1.

Um texturierte Primitives zu zeichnen, kannst du die folgenden Funktionen benutzen:

draw_primitive_begin_texture(kind, texid) Starte ein Primitive der angegebenen Art und der gegebenen Textur.
draw_vertex_texture(x, y, xtex, ytex) Füge den Eckpunkt (x|y) dem Primitive mit der Position (xtex|ytex) in der Textur hinzu, überblendet mit dem zuvor festgelegten Farben- und dem Alpha-Wert. xtex und ytex sollten normalerweise zwischen 0 und 1 liegen aber auch größere Werte können benutzt werden, die zu einer Wiederholung der Textur führen (siehe unten).
draw_vertex_texture_color(x, y, xtex, ytex, col, alpha) Füge den Eckpunkt (x|y) dem Primitive mit der Position (xtex|ytex) in der Textur hinzu, überblendet mit seinem eigenen Farben- und Alpha-Wert.
draw_primitive_end() Beendet die Beschreibung des Primitives. Diese Funktion zeichnet es eigentlich.

Es gibt drei Funktionen, die beeinflussen, wie Texturen gezeichnet werden:

texture_set_interpolation(linear) Gibt an, ob lineare Interpolation (true) benutzt oder ob der nächste Pixel genommen werden soll (false). Lineare Interpolation gibt sauberere Texturen, kann aber auch ein bisschen verwischen und kostet manchmal zusätzliche Zeit. Diese Einstellung beeinflusst auch das Zeichnen von Sprites und dem Hintergrund. Standard ist false. (Dies kann auch in den globalen Spiel Einstellungen geändert werden.)
texture_set_blending(blend) Gibt an, ob Überblenden mit Farb- und Alpha-Werten benutzt werden soll. Dies auszuschalten mag auf alter Hardware schneller sein. Diese Einstellung beeinflusst auch das Zeichnen von Sprites und dem Hintergrund. Standard ist true.
texture_set_repeat(repeat) Gibt an, ob die Textur wiederholt werden soll. Dies funktioniert wie folgt. Wie oben angegeben liegen Textur-Koordinaten im Bereich von 0-1. Wenn du einen Wert größer als 1 spezifizierst, wird der Rest standardmäßig nicht gezeichnet. Durch das Setzen von repeat auf true wird die Textur wiederholt. Beachte, dass Sprites und Hintergründe immer ohne Wiederholung gezeichnet werden. Also wenn du einmal einen Sprite oder Hintergrund zeichnest, wird dieser Wert auf false zurückgesetzt. Standard ist false.

Es gibt zwei weitere Funktionen, die nicht nur nützlich zum Zeichnen von Texturen sind. Normalerweise werden Primitives mit dem Hintergrund überblendet durch Benutzung des Alpha-Wertes. Du kannst tatsächlich angeben, wie dies passieren muss. Neben dem normalen Modus ist es möglich, dass die neue Farbe von der existierenden Farbe addiert oder subtraiert werden muss. Dies kann benutzt werden um z.B. Spot- Lichter oder Schatten zu kreieren. Weiterhin ist es möglich, sozusagen das Maximum der neuen und der existierenden Farbe zu nehmen. Dies kann bestimmte Saturations-Effekte verhindern, die durch Addieren erhalten kannst. Beachte, dass beide, Subtraieren und Maximum, den Alpha-Wert nicht vollständig in Betracht ziehen. (DirectX erlaubt dies nicht.) Also gehst du besser sicher, dass das äußere Areal schwarz ist. Es gibt zwei Funktionen. Die erste gibt dir nur die vier oben beschriebenen Optionen. Die zweite Funktion gibt dir eine Menge mehr Möglichkeiten. Du solltest ein bisschen mit den Einstellungen expirimentieren. Wenn sie effektiv genutzt werden, können sie benutzt werden, um z.B. interessante Explosionen or Halo-Effekte zu kreieren.

draw_set_blend_mode(mode) Gibt an, welcher Überblendungsmodus zu benutzen ist. Die folgenden Werte sind möglich: bm_normal, bm_add, bm_subtract, and bm_max. Vergiss nicht, den Modus nach Benutzung auf normal wieder zurückzusetzen, weil sonst auch andere Sprites und sogar Hintergründe mit dem neuen Überbledungsmodus gezeichnet werden.
draw_set_blend_mode_ext(src, dest) Gibt an, welcher Überblendungsmodus für beide, die Quell- und die Ziel-Farbe zu benutzen ist. Die neue Farbe ist ein Faktor times mal die Quelle und ein anderer Faktor mal das Ziel. Diese Faktoren werden mit dieser Funktion festgelegt. Um dies zu verstehen, haben die Quelle und das Ziel beide als Rot, Grün, Blau und Alpha Komponente(???). Die Quelle ist also (Rs, Gs, Bs, As) und das Ziel ist (Rd, Gd, Bd, Ad). Alle werden in Betracht gezogen, zwischen 0 und 1 zu liegen. Die Überblendungs- faktoren, die du für Quelle und Ziel auswählen kannst, sind:
  • bm_zero: Überblendungsfaktor ist (0, 0, 0, 0).
  • bm_one: Überblendungsfaktor its (1, 1, 1, 1).
  • bm_src_color: Überblendungsfaktor ist (Rs, Gs, Bs, As).
  • bm_inv_src_color: Überblendungsfaktor ist (1�Rs, 1�Gs, 1�Bs, 1�As).
  • bm_src_alpha: Überblendungsfaktor is (As, As, As, As).
  • bm_inv_src_alpha: Überblendungsfaktor ist (1�As, 1�As, 1�As, 1�As).
  • bm_dest_alpha: Überblendungsfaktor ist (Ad, Ad, Ad, Ad).
  • bm_inv_dest_alpha: Überblendungsfaktor is (1�Ad, 1�Ad, 1�Ad, 1�Ad).
  • bm_dest_color: Überblendungsfaktor ist (Rd, Gd, Bd, Ad).
  • bm_inv_dest_color: Überblendungsfaktor ist (1�Rd, 1�Gd, 1�Bd, 1�Ad).
  • bm_src_alpha_sat: Überblendungsfaktor ist (f, f, f, 1); f = min(As, 1�Ad).
Zum Beispiel legt der normale Überblendungsmodus die Quell-Blende auf bm_src_alpha und die Ziel-Blende auf bm_inv_src_alpha fest. Vergiss nicht, den Modus nach Benutzung auf normal wieder zurückzusetzen, weil sonst auch andere Sprites und sogar Hintergründe mit dem neuen Überbledungsmodus gezeichnet werden.

Das Zeichnen von texturierten Primitives ist ein bisschen Arbeit, kann aber zu großartigen Ergebnisen führen. Du kannst es sogar benutzen um vorgetäuschte 3D-Spiele zu machen.

Oberflächen zeichnen

Diese Funktionen sind nur in der registrierten Version des Game Makers verfügbar.

In manchen Situationen möchtest du eventuell nicht direkt auf den Bildschirm, sondern auf eine Leinwand,  zeichnen, die später dazu benutzt werden kann Dinge auf den Bildschirm zu zeichnen. Diese Leinwände heissen Oberflächen (Surfaces). Wenn du z.B. den Spieler etwas zeichnen lassen willst, willst du nicht, dass es direkt auf den Bildschirm gezeichnet wird (weil es in nächsten Step bereits verschwunden wäre), sondern auf eine Oberfläche, die in jedem Step auf den Bildschirm gezeichnet wird. Oder du willst eine Textur verwenden, die sich mit der Zeit verändert.

Alles das ermöglichen Oberflächen. Sie sind zudem noch vergleichsweise einfach zu benutzen: Zuerst erstellst du eine Oberfläche, danach gibst du an, dass alles weitere Zeichnen auf der Oberfläche stattfinden soll. Von diesem Moment an arbeiten alle Zeichenfunktionen auf dieser Oberfläche. Sobald du fertig bist, setzt du das Zeichen-Ziel zurück und alles weitere wird wieder  auf den Bildschirm gezeichnet. Du kannst eine Oberfläche auf viele verschiedene Weisen auf den Bildschirm zeichnen, oder sie als Textur benutzen. Es gibt einige Dinge auf die du achten musst, beachte dazu die Hinweise weiter unten.

Die folgenden Funktionen existieren um mit Oberflächen (Surfaces) zu arbeiten:

surface_create(w, h) Erstellt eine Oberfläche mit der angegebenen Höhe und Breite. Gibt die Id der Oberfläche zurück, die in den weitern Funktionsaufrufen benutzt werden muss. Beachte, dass die Oberfläche nicht gelöscht (leer gemacht) werden wird, dafür bist du verantwortlich. (Setze sie als Ziel fest und rufe die entsprechende Säuberungsfunktion auf.)
surface_free(id) Löscht die Oberfläche aus dem Speicher.
surface_exists(id) Gibt zurück, ob die Oberfläche mit der angegebenen Id existiert.

surface_get_width(id) Gibt die Breite der Oberfläche zurück.
surface_get_height(id) Gibt die Höhe der Oberfläche zurück.
surface_get_texture(id) Gibt die Textur, die der Oberfläche entspricht zurück. Diese kann genutzt werden um texturierte Objekte mit dem Inhalt der Oberfläche zu zeichnen.

surface_set_target(id) Setzt die angegebene Oberfläche als Ziel aller Zeichenfunktionen fest, die dann darauf arbeiten. Die Projektion wird so eingestellt, dass die Oberfläche einfach bedeckt wird.
surface_reset_target() Setzt das Zeichen-Ziel auf den normalen Bildschirm zurück.

surface_getpixel(id, x, y) Gibt die Farbe des Pixels an der Position (x, y) in der Oberfläche zurück. Diese Funktion ist nicht sehr schnell, setzte sie also vorsichtig ein.
surface_save(id, fname) Speichert ein Bmp der Oberfläche an den angegebenen Dateinamen. Nützlich um Screenshots zu machen.
surface_save_part(id, fname, x, y, w, h) Speichert den angegebenen Teil der Oberfläche in ein Bmp mit dem angegebenen Dateinamen.

draw_surface(id, x, y) Zeichnet die Oberfläche an die Position (x, y). (Ohne Farb- und Alpha-Blending)
draw_surface_stretched(id, x, y, w, h) Zeichnet die Oberfläche gestreckt auf die angegebene Region.
draw_surface_tiled(id, x, y) Zeichnet die Oberfläche Wiederholt, so dass sie den ganze Raum ausfüllt.
draw_surface_part(id, left, top, width, height, x, y) Zeichnet den angegebenen Teil der Oberfläche mit ihrem Ursprung bei (x,y).
draw_surface_ext(id, x, y, xscale, yscale, rot, color, alpha) Zeichnet die Oberfläche gesteckt, gedreht und mit Farb- und Alpha-Blending. (Benutze c_white für keine Farbveränderung und alpha im Bereich von 0-1.)
draw_surface_stretched_ext(id, x, y, w, h, color, alpha) Zeichnet die Oberfläche auf die angegeben Region gestreckt. color gibt die Farb- und alpha die Alpha-Blending-Werte an.
draw_surface_tiled_ext(id, x, y, xscale, yscale, color, alpha) Zeichnet die Oberfläche weiderholt, so dass sie den ganzen Raum ausfüllt, aber mit Skalierung und Farb- und Alpha-Blending.
draw_surface_part_ext(id, left, top, width, height, x, y, xscale, yscale, color, alpha) Zeichnet den angegebenen Teil der Oberfläche mit ihrem Ursprung bei (x,y) aber mit Skalierung und Farb- und Alpha-Blending.
draw_surface_general(id, left, top, width, height, x, y, xscale, yscale, rot, c1, c2, c3, c4, alpha) Die allgemeinste Funktion. Sie zeichnet den angegebenen Teil der Oberfläche mit ihrem Ursprung bei (x,y) aber mit Saklierung, Rotation, einer Farbe für jeden Eckpunkt (In der Reihenfolge oben-links, oben-rechts, unten-rechts und unten-links) und einer Trasparenzeinstellung.

surface_copy(destination, x, y, source) Kopiert die Quell-Oberfläche (source) an der Position (x,y) in die Ziel-Oberfläche (destination). (Ohne jeglich Form des Blendings)
surface_copy_part(destination, x, y, source, xs, ys, ws, hs) Kopiert den angegebenen Teil der Quell-Oberfläche (source) mit ihrem Ursprung bei (x,y) in die Ziel-Oberfläche (destination). (Ohne jegliche Form des Blendings)

Beachte, dass es keine Funktion gibt, die einen Teil des Bildschirms auf die Oberfläche kopiert. (Das ist nicht möglich, weil zwischen dem Bildschirm und der Oberfläche verschiedene Formate benutzt werden könnten.) Falls das trozdem von Nöten sein sollte, setze einfach eine Oberfläche als Zeichen-Ziel und zeichne dann den Raum. Schließlich kannst du dann die Funktionen benutzen um einen bestimmten Ausschnitt zu bekommen.

Du kannst von Oberflächen auch Sprites und Hintergründe erzeugen, beachte dazu den Abschnitt, der vom Verändern von Ressourcen handelt.

Beachte folgendes, wenn du die obenstehenden Funktionen nutzt:

  • Du solltest das Zeichen-Ziel nie ändern, sobald du bereits zeichest, d.h. nicht in einem Draw-Event. Dies hätte schwerwiegende Probleme mit der Projektionsmatrix und der Anzeige zur Folge.
  • Oberflächen funtkionieren im 3D-Modus nicht richtig. Du kannst sie benutzen, während der 3D-Modus deaktiviert ist (indem du d3d_end() aufrufst, bevor du sie benutzt), aber sobald der 3D-Modus aktiviert wird, gehen die Oberflächen verloren.
  • Wegen der Geschwindigkeit werden Oberflächen nur im Video-RAM gespeichert. Aus diesem Grund kann es passieren, dass sie verloren gehen, wenn z.B. die Auflösung geändert wird oder der Bildschirmschoner gestartet wird.
  • Oberflächen werden nicht mit gespeichert, wenn das Spiel gespeichert wird.

Tiles

Wie du wissen solltest kannst du Tiles zu einen Raum hinzufügen. Ein Tile ist ein Teil eines Hintergrundbildes. Tiles sind NUR sichtbare Bilder. Sie reagieren nicht auf Events und sie generieren keine Collisionen. Das Resultat: Tiles werden viel schneller behandelt als Objekte. Alles was kein Event oder Collision hat, sollte am besten als Tile genommen werden. Auch ist man oft besser damit bedient, ein Tile zu benutzen und ein einfaches Objekt für die Kollisionen zu erstellen.

Du hast mehr Kontrolle über Tiles als du glaubst. Du kannst sie hinzufügen wenn du den Raum designst, aber du kannst sie auch während des Spiels hinzufügen. Du kannst ihre Position ändern, und kannst sie skalieren oder du kannst sie auch teilweise Transparent machen. Ein Tile hat die folgenden Einstellungen:

  • background. Das Hintergrundbild von dem das Tile genommen ist.
  • left, top, width, height. Der Teil vom genutzten Background.
  • x, y. Die Position der linken oberen Ecke des Tiles im Raum.
  • depth. Die Tiefe des Tile. Du kannst jede Tiefe nehmen die du willst, um das Tile zwischen Objekten sichtbar zu machen.
  • visible. Ob das Tile sichtbar ist.
  • xscale, yscale. Jedes Tile kann skaliert gezeichnet werden (Voreinstellung ist 1).
  • blend. Eine Überblendungsfarbe welche benutzt wird wenn das Tile gezeichnet wird.
  • alpha. Ein Alphawert zeigt die Transparenz des Tiles an. 1 = nicht transparent, 0 = voll transparent.
Zum wechseln der Einstellung von einem einzelnen Tile musst du seine ID wissen. Wenn du Tiles beim Raumerstellen hinzufügst wird die ID in der unteren Informationsleiste angezeigt. Es gibt aber auch eine Funktion mit der du die ID eines Tiles, das an einer bestimmten Stelle platziert ist herausfindest.

Die folgenden Funktionen existieren um mit Tiles zu handeln:

tile_add(background, left, top, width, height, x, y, depth) Fügt ein neues Tile dem Raum hinzu mit den angezeigten Werten (siehe oben für ihre Bedeutung). Die Funktion gibt die ID des Tiles zurück um sie später zu verwenden.
tile_delete(id) Löscht das Tile mit der angegebenen ID.
tile_exists(id) Gibt zurück ob das Tile mit der angegebenen ID existiert.

tile_get_x(id) Gibt die X-Position des Tiles mit der angegebenen ID zurück.
tile_get_y(id) Gibt die Y-Position des Tiles mit der angegebenen ID zurück.
tile_get_left(id) Gibt den linken Wert des Tiles mit der angegebenen ID zurück.
tile_get_top(id) Gibt den oberen Wert des Tiles mit der angegebenen ID zurück.
tile_get_width(id) Gibt die Breite des Tiles mit der angegebenen ID zurück.
tile_get_height(id) Gibt die Höhe des Tiles mit der angegebenen ID zurück.
tile_get_depth(id) Gibt die Tiefe des Tiles mit der angegebenen ID zurück.
tile_get_visible(id) Gibt zurück ob das Tile mit der angegebenen ID sichtbar ist.
tile_get_xscale(id) Gibt den xscale des Tiles mit der angegebenen ID zurück.
tile_get_yscale(id) Gibt den yscale des Tiles mit der angegebenen ID zurück.
tile_get_background(id) Gibt den Background des Tiles mit der angegebenen ID zurück.
tile_get_blend(id) Gibt die Überblendungsfarbe des Tiles mit der angegebenen ID zurück.
tile_get_alpha(id) Gibt den Alphawert des Tiles mit der angegebenen ID zurück.

tile_set_position(id, x, y) Setzt die Position des Tiles mit der angegebenen ID.
tile_set_region(id, left, right, width, height) Setzt die Region des Tiles mit der angegebenen ID in sein Background.
tile_set_background(id, background) Setzt den Background für das Tile mit der angegebenen ID.
tile_set_visible(id, visible) Setzt die Sichtbarkeit des Tiles mit der angegebenen ID.
tile_set_depth(id, depth) Setzt die Tiefe des Tiles mit der angegebenen ID.
tile_set_scale(id, xscale, yscale) Setzt die Skalierung des Tiles mit der angegebenen ID.
tile_set_blend(id, color) Setzt die Überblendfarbe des Tiles mit der angegebenen ID zurück. Nur in der registrierten Version verfügbar!
tile_set_alpha(id, alpha) Setzt den Alphawert des Tiles mit der angegebenen ID.

Die folgenden Funktionen handeln mit den Layern von Tiles, das sind Sammlungen von Tiles mit der selben Tiefe.

tile_layer_hide(depth) Versteckt alle Tiles des angezeigten Tiefen Layer.
tile_layer_show(depth) Zeigt alle Tiles des angezeigten Tiefen Layer.
tile_layer_delete(depth) Zerstört alle Tiles des angezeigten Tiefen Layer.
tile_layer_shift(depth, x, y) Schiebt alle Tiles des angezeigten Tiefen Layer über den Vektor x,y. Kann benutzt werden um scrollende Layer von Tiles zu erstellen.
tile_layer_find(depth, x, y) Gibt die ID des Tiles mit der gegebenen Tiefe an der Position (x,y) zurück. Wenn kein Tile an der Position existiert wir -1 zurückgegeben. Wenn mehrere Tiles mit der gegebenen Tiefe an der Position existieren wird der erste zurückgegeben.
tile_layer_delete_at(depth, x, y) Löscht den Tile mit der gegebenen Tiefe bei der Position (x,y). Wenn mehrere Tiles mit der gegebenen Tiefe an der Position existieren werden alle gelöscht.
tile_layer_depth(depth, newdepth) Ändert die Tiefe von allen Tiles mit der angezeigten Tiefe zur neuen Tiefe. Mit der Funktion kannst du ganze Tile Layer mit der neuen Tiefe versehen.

Die Anzeige

Die Anzeige repräsentiert das gesamte Areal auf dem Monitor. Sie hat eine Größe (typischerweise 1024x768 oder 1280x1024), eine Farbentiefe, das ist die Anzahl der Bits, die benutzt werden, um einen einzelnen Pixel zu repräsentieren (typischerweise 16 = Hohe Farbe oder 32 = Volle Farbe), und eine Bildwiederholungsrate, das ist die Anzahl der Male pro Sekunde die Anzeige neu aufgebaut wird (typischerweise zwischen 60 und 120). Diese Einstellungen können zwar normalerweise durch die Anzeige-Eigenschaften geändert werden, aber für Spiele obgleich, im Besonderen wenn sie im Vollbildmodus laufen, ist es wichtig, diese Einstellungen ändern zu können. All diese Einstellungen können für das Spiel in den Spiel Einstellungen initialisiert werden. Für die Benutzung während des Spielgeschehens existieren die folgenden Funktionen. Beachte dennoch, dass das Verändern der Einstellungen während des Spielgeschehens in einer zeitlichen Verzögerung resultieren wird, so wie Dinge wiederhergestellt werden müssen. Die Funktionen um den Modus festzulegen sind nur in der registrierten Version verfügbar.

display_get_width() Gibt die Breite der Anzeige in Pixeln wieder.
display_get_height() Gibt die Breite der Anzeige in Pixeln wieder.
display_get_colordepth() Gibt die Farbentiefe in Bits wieder.
display_get_frequency() Gibt die Bildwiederholungsrate der Anzeige wieder.
display_set_size(w, h) Legt die Breite und Höhe der Anzeige in Pixeln fest. Gibt wieder, ob dies erfolgreich war. (Beachte, dass nur bestimmte Kombinationen erlaubt sind.)
display_set_colordepth(coldepth) Legt die Farbentiefe fest. Im Allgemeinen sind nur 16 und 32 erlaubte Werte. Gibt wieder, ob sie erfolgreich war.
display_set_frequency(frequency) Legt die Bildwiederholungsrate für den Bildschirm fest. Nur wenige Bildwiederholungsraten sind erlaubt. Typischerweise könntest du dies auf 60 mit einem identischem Room Speed festlegen um saubere Bewegung mit 60 Bildern pro Sekunde zu erhalten. Gibt wieder, ob sie erfolgreich war.
display_set_all(w, h, frequency, coldepth) Legt alles auf einmal fest. Benutze -1 für Werte, die du nicht ändern willst. Gibt wieder, ob sie erfolgreich war.
display_test_all(w, h, frequency, coldepth) Testet, ob die angegebenen Einstellungen erlaubt sind. Sie ändert nicht die Einstellungen. Benutze -1 für Werte, die du nicht ändern willst. Gibt wieder, ob die Einstellungen erlaubt sind.
display_reset() Setzt die Anzeige-Einstellungen auf diejenigen, als das Programm gestartet wurde, zurück.

Manchmal ist es nützlich, Information über die Position der Maus auf der Anzeige zu erhalten oder diese Position zu ändern. Für dies existieren die folgenen Funktionen:

display_mouse_get_x() Gibt die x-Koordinate der Maus auf der Anzeige wieder.
display_mouse_get_y() Gibt die y-Koordinate der Maus auf der Anzeige wieder.
display_mouse_set(x, y) Legt die Position der Maus auf der Anzeige auf die angegebenen Werte fest.

Das Fenster

Das aktuelle Spiel findet in einem Fenster statt. Dieses Fenster hat eine Anzahl von Eigenschaften, wie z.B. ob es einen Rahmen hat, ob es im Vollbildmodus ist, etc. Normalerweise werden diese in den Spiel Einstellungen festgelegt. Aber du kannst sie während des Spiels ändern. Die folgenden Funktionen existieren für dies:

window_set_visible(visible) Legt fest, ob das Spielfenster sichtbar ist. Zweifellos möchtest du normalerweise, dass das Fenster während des gesamten Spiels sichtbar bleibt.
window_get_visible() Gibt wieder, ob das Spielfenster sichtbar ist.
window_set_fullscreen(full) Legt fest, ob das Fenster im Vollbildmodus angezeigt wird.
window_get_fullscreen() Gibt wieder, ob das Fenster im Vollbildmodus angezeigt wird.
window_set_showborder(show) Legt fest, ob der Rahmen um das Fenster angezeigt wird. (Im Vollbildmodus wird er nie angezeigt.)
window_get_showborder() Gibt wieder, ob der Rahmen um das Fenster im Fenstermodus angezeigt werden.
window_set_showicons(show) Legt fest, ob die Rahmensymbole (Minimieren, Maximieren, Schließen) angezeigt werden. (Im Vollbildmodus werden diese nie angezeigt.)
window_get_showicons() Gibt wieder, ob die Rahmensymbole im Fenstermodus angezeigt werden.
window_set_stayontop(stay) Legt fest, ob das Fenster immer über den anderen Fenster steht.
window_get_stayontop() Gibt wieder, ob das Fenster immer über anderen Fenstern steht.
window_set_sizeable(sizeable) Legt fest, ob die Fenstergröße vom Spieler verändert werden kann. (Der Spieler kann sie nur verändern wenn der Rahmen angezeigt wird und das Fenster sich nicht im Vollbildmodus befindet.)
window_get_sizeable() Gibt wieder, ob die Fenstergröße vom Spieler verändert werden kann.
window_set_caption(caption) Legt den Kopfzeilen-String für das Fenster fest. Normalerweise spezifizierst du dies wenn du den Raum definierst und er kann durch das Benutzen der Variable room_caption verändert werden. Diese Funktion ist normalerweise als nicht sinnvoll, es sei denn, du zeichnest den Raum selber anstatt es den Game Maker machen zu lassen. Die Kopfzeile ist nur sichtbar, wenn das Fenster einen Rahmen hat und wenn sich das fenster nicht im Vollbildmodus befindet.
window_get_caption() Gibt die Fensterkopfzeile wieder.
window_set_cursor(curs) Legt den Mauszeiger, der im Fenster benutzt wird, fest. Du kannst die folgenden Konstanten benutzen:

cr_default
cr_none
cr_arrow
cr_cross
cr_beam
cr_size_nesw
cr_size_ns
cr_size_nwse
cr_size_we
cr_uparrow
cr_hourglass
cr_drag
cr_nodrop
cr_hsplit
cr_vsplit
cr_multidrag
cr_sqlwait
cr_no
cr_appstart
cr_help
cr_handpoint
cr_size_all

Im Besonderen Fall, um den Mauszeiger zu verstecken, benutze cr_none als Wert.
window_get_cursor() Gibt den Zeiger, der im Fenster benutzt wird, wieder.
window_set_color(color) Legt die Farbe des Teiles des Fensters fest, der nicht für das Anzeigen des Raumes benutzt wird.
window_get_color() Gibt die Fensterfarbe wieder.
window_set_region_scale(scale, adaptwindow) Wenn das Fenster größer als der aktuelle Raum ist, wird der Raum normalerweise in einer Region zentriert im Fenster angezeigt. Es ist dennoch möglich anzugeben, dass es skaliert um das gesamte oder einen Teil des Fensters auszufüllen. Ein Wert von 1 ist keine Skalierung. Wenn du einen Wert von 0 benutzt wird die Region skaliert um das ganze Fenster auszufüllen. Wenn du es auf einen negativen Wert setzt, wird es auf die maximale Größe innerhalb des Fensters unter Beibehaltung des Verhältnisaspekts skaliert (das ist oft das, was du möchtest). adaptwindow gibt an, ob die Fenstergröße angepasst werden muss wenn der skalierte Raum nicht reinpasst. Das Anpassen des Fensters ist nur effektiv wenn der Skalierungsfaktor positiv ist.
window_get_region_scale() Gibt den Skalierungsfaktor für die Zeichnungs-Region wieder.

Das Fenster hat eine Position auf dem Bildschirm und eine Größe. (Wenn wir über Position und Größe reden, meinen wir immer den Klienten-Teil des Fensters ohne den Rahmen.) Du kannst diese, auch wenn du es wohl kaum je von innerhalb deines Spiels tuen wirst, verändern. Normalerweise werden sie automatisch oder durch den Spieler bestimmt. Die folgenden Funktionen können benutzt werden, um die Fensterposition und -größe zu verändern. Beachte, dass diese Funktionen mit dem Fenstermodus handeln. Wenn das Fenster sich im Vollbildmodus befindet können sie immer noch benutzt werden, aber werden nur einen Effekt haben, wenn der Vollbildmodus ausgeschaltet wird.

window_set_position(x, y) Setzt die Position des (Klienten-Teil des) Fensters auf die angegebenen Position fest.
window_set_size(w, h) Legt die Größe des (Klienten-Teil des) Fensters auf die angegebende Größe fest. Beachte, dass wenn die angegebende Größe zu klein ist, um in die Zeichnungsregion hineinzupassen, sie groß genug gehalten wird für die Region um reinzupassen.
window_set_rectangle(x, y, w, h) Legt die Position und Größe des Fenster-Rechtecks fest. (Führt beide vorherigen Routinen in einem Schritt durch.)
window_center() Zentriert das Fenster auf dem Bildschirm.
window_default()
Gibt dem Fenster die normale Größe und Position (zentriert) auf dem Bildschirm.
window_get_x() Gibt die aktuelle x-Koordinate des Fensters wieder.
window_get_y() Gibt die aktuelle y-Koordinate des Fensters wieder.
window_get_width() Gibt die aktuelle Breite des Fensters wieder.
window_get_height() Gibt die aktuelle Höhe des Fensters wieder.

Wiedereinmal möchtest du wahrscheinlich nie irgendeine der Fensterpositionierungs-Funktionen benutzen, da Game Maker sich automatisch um sie kümmert.

In seltenen Fällen möchtest du die Position der Maus in Bezug auf das Fenster. (Normalerweise benutzt du die Mausposition immer in Bezug auf den Raumes oder einer Ansicht.) Die folgenden Funktionen existieren für dies.

window_mouse_get_x() Gibt die x-Koordinate der Maus im Fenster wieder.
window_mouse_get_y() Gibt die y-Koordinate der Maus im Fenster wieder.
window_mouse_set(x, y) Setzt die Position der Maus im Fenster auf die angegeben Werte.

Views

Wie du wissen solltest, kannst du bis zu acht verschiedene Views definieren, wenn du Räume entwirfst. Ein View ist durch sein Ansichts-Areal und seines Ansichts-Ports auf dem Bildschirm im Raum definiert (oder um genau zu sein, in der Zeichnungs-Region innerhalb des Fensters). Durch das Benutzen von Views kannst du verschiedene Teile vom Raum an verschiedenen Stellen auf dem Bildschirm zeigen. Weiterhin kannst du sicher gehen, dass ein bestimmtes Objekt immer sichtbar bleibt.

Du kannst die Views innerhalb des Codes kontrollieren. Du kannst Views sichtbar und unsichtbar machen und den Platz oder die Größe vom View in der Zeichnungs-Region oder die Position und Größe des Views im Raum (was insbesondere nützlich ist, wenn du kein Objekt zum Sichtbar-Sein angibst) ändern. Du kannst die Größe von der horizontalen und vertikalen Grenze um das sichtbare Objekt ändern, und du kannst angeben welches Objekt in den Views sichtbar bleiben muss. Letzteres ist sehr wichtig wenn die bedeutenden Objekte während des Spieles wechseln. Zum Beispiel willst du vielleicht das Hauptcharakter-Objekt seinem derzeitigen Status entsprechend ändern. Unglücklicherweise bedeutet dies, dass es nicht länger das Objekt ist, das sichtbar bleiben muss. Dem kann durch eine Zeile von Code im Erstellungs-Ereignis von all den möglichen Hauptcharakter-Objekten abgeholfen werden (angenommen, dass dies in der ersten Ansicht passieren muss):

{
view_object[0] = object_index;
}

Die folgenden Variablen existieren, die die Ansicht beeinflussen. Alle, bis auf die ersten zwei, sind Arrays von 0 (die erste Ansicht) bis 7 (die letzte Ansicht) reichend.

view_enabled Ob Views aktiviert sind oder nicht.
view_current* Der derzeitig gezeichnete View (0-7). Benutze dies nur im Draw Event. Du kannst zum Beispiel diese Variable überprüfen um bestimmte Dinge nur in einem View zu zeichnen. Die Variable kann nicht verändert werden.
view_visible[0..7] Ob der einzelne View auf dem Bildschirm sichtbar ist.

view_xview[0..7] X-Position des Views im Raum.
view_yview[0..7] Y-Position des Views im Raum.
view_wview[0..7] Breite des Views im Raum.
view_hview[0..7] Höhe des Views im Raum.
view_xport[0..7] X-Position des View-Ports in der Zeichnungs-Region.
view_yport[0..7] Y-Position des View-Ports in der Zeichnungs-Region.
view_wport[0..7] Breite des View-Ports in der Zeichnungs-Region.
view_hport[0..7] Höhe des View-Ports in der Zeichnungs-Region.
view_angle[0..7] Drehungs-Winkel, der für den View im Raum benutzt wird (gegen den Uhrzeigersinn in Grad).
view_hborder[0..7] Größe der horizontalen Begrenzung um das sichtbare Objekt herum (in Pixeln).
view_vborder[0..7] Größe der vertikalen Begrenzung um das sichtbare Objekt herum (in pixels).
view_hspeed[0..7] Maximale horizontale Geschwindigkeit des Views.
view_vspeed[0..7] Maximale vertikale Geschwindigkeit des Views.
view_object[0..7] Objekte deren Instanzen im View sichtbar bleiben müssen. Wenn es mehrere Instanzen von diesem Objekt gibt wird nur der ersten gefolgt. Du kannst auch eine Instanz-Id dieser Variable zuweisen. In diesem Fall wird der einzelnen Instanz gefolgt.

Beachte, dass die Größe des Bildes auf dem Bildschirm auf Basis der sichtbaren Views beim starten des Raumes berechnet wird. Wenn du Views während des Spiels änderst, passen sie vielleicht nicht mehr auf dem Bildschirm. Die Bildschirm-Größe jedoch wird nicht automatisch angepasst. Also wenn du dies brauchst musst du es selber durch das Benutzen der folgenden Funktionen machen:

window_set_region_size(w, h, adaptwindow) Setzt die Breite und Höhe der Zeichnungs-Region im Fenster. adaptwindow gibt an, ob die Fenster-Größe angepasst werden muss falls die Region nicht hineinpasst.
window_get_region_width() Gibt die derzeitige Breite der Zeichungs-Region wieder.
window_get_region_height() Gibt die derzeitige Höhe der Zeichnungs-Region wieder.

In einem Spiel brauchst du oft die Position des Mauszeigers. Normalerweise benutzt du für dies die Variablen mouse_x und mouse_y. Wenn es mehrere Views gibt, geben diese Variablen die Maus-Position bezüglich des Views, in der die Maus ist, an. Manchmal jedoch, brauchst du die Mausposition unter Berücksichtigung eines bestimmten Views, auch wenn sie außerhalb dieses Views ist. Für dies existieren die folgenden Funktionen.

window_view_mouse_get_x(id) Gibt die X-Koordinate der Maus bezüglich des Views mit dem Index id wieder.
window_view_mouse_get_y(id) Gibt die Y-Koordinate der Maus bezüglich des Views mit dem Index id wieder.
window_view_mouse_set(id, x, y) Setzt die Position der Maus bezüglich des Views mit dem Index id wieder.
window_views_mouse_get_x() Gibt die X-Koordinate der Maus bezüglich des Views, in dem sie sich befindet, wieder. (genau wie mouse_x).
window_views_mouse_get_y() Gibt die Y-Koordinate der Maus bezüglich des Views, in dem sie sich befindet, wieder. (genau wie mouse_y).
window_views_mouse_set(x, y) Setzt die Position der Maus bezüglich des ersten Views, der sichtbar ist.

Übergänge

Wie du weißt, kannst du, wenn du dich von einem zu einem anderen Raum bewegst, einen Übergang auswählen. Du kannst auch den Übergang für das nächste Einzelbild festlegen ohne dich in einen anderen Raum zu bewegen durch Verwendung der Variable namens transition_kind. Wenn du ihr einen Wert zwischen 1 und 13 zuweist, wird der entsprechende Übergang benutzt (dies sind die selben Übergänge, die du für die Räume auswählen kannst). Ein Wert von 0 gibt keinen Übergang an. Sie beeinflusst nur das nächste Mal, wenn ein Einzelbild gezeichnet wird.

transition_kind Gibt den nächsten Einzelbild-Übergang an. Du kannst die folgenden Werte benutzen

0 = kein Effekt
1 = Erstellen von links
2 = Erstellen von rechts
3 = Erstellen von oben
4 = Erstellen von unten
5 = Erstellen von der Mitte
6 = Schieben von links
7 = Schieben von rechts
8 = Schieben von oben
9 = Schieben von unten
10 = Einflechten von links
11 = Einflechten von rechts
12 = Einflechten von oben
13 = Einflechten von unten

Beachte, dass es wirklich einfach ist deine eigenen Übergänge durch Verwendung der verschiedenen Zeichnungs-Funktionen zu machen. Zum Beispiel, um eine Abblende zu machen kannst du ein großes Rechteck, welches den Raum ausfüllt, mit einem ansteigendem Alpha-Wert zeichnen. Oder du kannst die Position und Größe der Ansicht ändern, um den Raum aus dem Blickfeld verschwinden zu lassen.

Neuzeichnen des Bildschirms

Normalerweise wird am Ende jedes Schrittes der Raum auf dem Bildschirm neugezeichnet. Aber unter seltenen Umständen musst du den Raum in anderen Momenten neuzeichnen. Dies kommt vor, wenn dein Programm die Kontrolle übernimmt. Zum Beispiel bevor eine lange Zeit geschlafen wird mag eine Neuzeichnung erforderlich sein. Auch wenn dein Code eine Meldung anzeigt und auf den Spieler warten möchte, eine Taste zu drücken, brauchst du eine Neuzeichnung dazwischen. Es gibt zwei verschiedene Routinen, um dies zu tun.

screen_redraw() Zeichnet den Raum durch Aufrufung aller Zeichnungs-Ereignisse neu.
screen_refresh() Erneuert den Bildschirm durch Benutzung des derzeitigen Raumbildes (ohne die Zeichnungs-Ereignisse auszuführen).

Um die zweite Funktion zu verstehen, musst du völlig verstehen,wie das Zeichnen intern funktioniert. Es gibt intern ein Bild, auf dem alles Zeichnen stattfindet. Dieses Bild ist auf dem Bildschirm nicht sichtbar. Nur am Ende jedes Schrittes, nachdem alles Zeichnen stattgefunden hat, wird das Bildschirm-Bild durch das interne Bild ersetzt. (Dies wird Doppel-Bufferung genannt.) Die erste Funktion zeichnet das interne Bild neu und erneuert dann das Bildschirm-Bild. Die zweite Funktion erneuert nur das Bild auf dem Bildschirm.

Nun solltest du erkennen, warum du keine Zeichnungs-Aktionen oder -Funktionen in anderen Ereignissen als dem Zeichnungs-Ereignissen benutzen kannst. Sie werden Dinge auf dem internen Bild zeichnen, aber diese werden auf dem Bildschirm nicht sichtbar sein. Und wenn die Zeichnungs-Ereignisse ausgeführt werden, wird zuerst der Raum- Hintergrund gezeichnet, wodurch alles, was du auf das interne Bild gezeichnet hast, gelöscht wird. Aber wenn du screen_refresh() nach deiner Zeichnung benutzt, wird das aktualisierte Bild auf dem Bildschirm sichtbar werden. Also ein Skript kann z.B. etwas Text auf den Bildschirm zeichnen, die Erneuerungs- Funktion aufrufen, und dann auf den Spieler warten, eine Taste zu drücken, wie in dem folgenden Teilstück-Code.

{
  draw_text(screen_width/2,100,'Drücke eine Taste, um Fortzufahren.');
  screen_refresh();
  keyboard_wait();
}

Bitte beachte dies, wenn du in einem anderen Ereignis als dem Zeichnungs-Ereignis zeichnest: Du zeichnest lediglich auf dem Bild, nicht in der Ansicht! Also benutzt du die selben Koordinaten wie wenn es keine Ansichten gäbe. Sei vorsichtig, wenn du diese Technik benutzt. Stelle sicher, dass du sie zuerst verstehst und beachtest, dass das Erneuern des Bildschirms etwas Zeit benötigt.

Wenn du den Raum selber zeichnest kann es nützlich sein, ihn überhaupt NICHT automatisch zeichnen zu lassen. Zum Beispiel möchtest du den Raum vielleicht nur alle fünf Schritte zeichnen. Du kannst die folgenden Funktionen für dies benutzen:

set_automatic_draw(value) Gibt an, ob der Raum automatisch neugezeichnet wird (true, standard) oder nicht (false).

Abschließend gibt es eine Funktion mit der du festlegen kannst, ob das Gezeichnete mit der Bildwiederholungsrate des Monitors angeglichen wird:

set_synchronization(value) Gibt an, ob das Gezeichnete mit der Bildwiederholungsrate des Monitors angeglichen wird.

You can also force a wait for the next vertical synchronization using the following function:

screen_wait_vsync() Wartet auf die nächste vertikale Synchronisation des Monitors.

Soundeffekte und Musik

Sounds spielen eine grundlegende Rolle in Computerspielen. Sie werden deinem Spiel in Form von Ressourcen hinzugefügt. Stelle sicher, das die Namen gültige Variablennamen sind. Wie du siehst kann man 4 verschiedene Typen hinzufügen: normale Sounds, Hintergrundmusik, 3D Sounds und Sounds die mit dem Media Player gespielt werden.

Normale Sounds werden für Soundeffekte genutzt. Normalerweise nimmt man hierfür WAV Dateien. Viele können zur selben Zeit gespielt werden (auch mehrfaches Abspielen des selben normalen Sounds). Du kannst ihnen alle möglichen Effekte zuordnen.

Hintergrundmusik ist normalerweise eine Midi Datei, manchmal auch eine WAV Datei. Soundeffekte können hinzugefügt werden. Der einzige Unterschied zu normalen Sounds ist, das nur einer gespielt werden kann. Wenn du einen neuen startest hört der jetzige auf.

3D Sounds ermöglichen 3D Soundeffekte welche weiter unten beschrieben sind. Sie sind mono Sounds (WAV oder Midi).

Wenn du aber einen anderen Typen abspielen willst, beispielsweise MP3, können diese nicht über DirectX abgespielt werden. Dafür muss der normaler Media Player herhalten. Das ist aber sehr beschränkt. Es kann nur ein Sound gleichzeitig abgespielt werden. Keine Effekte können genutzt werden (nicht mal Lautstärkeveränderungen) und das Timing zum Wiederholen ist armselig. Es kann auch eine Verzögerung eintreten. Es wird dir sehr empfohlen dieses auf keinen Fall zu benutzen. (Einige Computer unterstützen dies auch nicht)

Informationen über Sound und Musik können auf den folgenden Seiten gefunden werden:

Grundlegende Soundfunktionen
Spezialeffekte
3D Musik
CD Musik

Grundlegende Soundfunktionen

Es gibt fünf grundlegende Funktionen für Geräusche: Zwei, um eine WAV-Datei abzuspielen, eine zum Prüfen, ob ein SFX abgespielt wird und zwei um sie anzuhalten. Die meisten nehmen den Index als Argument. Der Name des SFX stellt diesen Zeiger dar. Du kannst aber auch den "index" in einer Variablen speichern und damit arbeiten.

sound_play(index) Spielt den SFX(index entspricht Name)einmal. Falls es eine Hintergrundmusik ist wird die aktuelle gestoppt.
sound_loop(index) Spielt den SFX(index entspricht Name)als Endlosschleife. Falls es eine Hintergrundmusik ist wird die aktuelle gestoppt.
sound_stop(index) Stoppt den SFX(index entspricht Name),wenn mehrere gespielt werden,werden alle angehalten.
sound_stop_all() Stoppt die gesamten SFX.
sound_isplaying(index) Gibt an,ob der angegebene (index)SFX gespielt wird. Nachdem du die Funktion zum abspielen eines Sounds aufgerufen hast kommt der Sound aber nicht direkt an den Lautsprechern an, deswegen kann die Funktion vielleicht fälschlicherweise false zurückgeben. Dasselbe ist, wenn du einen Sound anhälst und der noch eine Weile spielt (z.B. wegen eines Echos) gibt die Funktion true zurück.

Es ist möglich, weitere Soundeffekte zu benutzen. Du kannst die Lautstärke und das Panorama verändern, d.h. ob es links oder rechts ertönt. In all diesen Fällen kann die Lautstärke nur reduziert werden. Diese Funktionen funktionieren nicht mit dem Media Player (wie mp3 Dateien).

sound_volume(index, value) Ändert die Lautstärke von index (0 =leise,1 = laut).
sound_global_volume(value) Ändert die Lautstärke für alle Sounds (0 = leise, 1 = laut).
sound_fade(index, value, time) Ändert die bisherige Lautstärke in eine neue (0 = leise, 1 = laut) während der angegebenen Zeit (in Millisekunden). Dies kann zum Ein- oder Ausblenden von Musik genutzt werden.
sound_pan(index, value) Ändert das Panorama von index (-1 = links, 0 = mitte, 1 = rechts).
sound_background_tempo(factor) Ändert das Tempo der Hintergrundmusik (wenn es eine Midi Datei ist). factor gibt den Multiplikationsfaktor an. Ein Wert von 1 entspricht dem normalen Tempo. Größere Werte bedeuten schnelleres Tempo, kleinere Werte ein langsameres Tempo. Muss zwischen 0.01 und 100 liegen.

Neben WAV und Midi Dateien (und mp3 Dateien) gibt es einen vierten Dateityp, der abgespielt werden kann: Direct Music Dateien. Diese haben die Erweiterung .sgt. Solche Dateien referrieren oft auf andere Dateien und Infos wie z.B. Band oder Stil. Um die Dateien zu finden, muss das Soundsystem wissen, wo sie sich befinden. Um das zu erreichen kannst du die folgende Funktionen zum suchen nach Dateien benutzen. Beachte, das du die Datei selbst hinzufügen musst. Game Maker macht dies nicht automatisch.

sound_set_search_directory(dir) Gibt das Verzeichnis an, in dem Direct Music Dateien gespeichert sind. Der dir string darf nicht das finale Backslash enthalten.

Soundeffekte

Diese Funktionen sind nur in der registrierten Game Maker Version verfügbar.

Soundeffekte werden dazu genutzt, die Sounds und Hintergrundmusiken anders klingen zu lassen. Beachte jedoch, das Soundeffekte nur auf Wav und Midi Dateien angewandt werden können, nicht auf mp3 Dateien. Dieser Abschnitt beschreibt die Funktionen zur Benutzung dieser Soundeffekte. Beachte aber, das du zur Nutzung der Funktionen eine gute Kenntnis der Soundtechnologie und von Synthesizern haben solltest. Es gibt hier keine Erklärung der einzelnen Parameter. Suche im Web oder in Büchern nach weiteren Informationen.

Um einen Soundeffekt einem bestimmten Sound zuzuordnen kannst du folgenden Funktionen nutzen

sound_effect_set(snd, effect) Setzt eine (Kombination von) Soundeffekt(en) für den angegebenen Sound. effect kann jeder der folgenden Werte sein:
se_none
se_chorus
se_echo
se_flanger
se_gargle
se_reverb
se_compressor
se_equalizer
Du kannst die Effekte durch addieren kombinieren. So kannst du z.B.

sound_effect_set(snd,se_echo+se_reverb);

benutzen um Echo und Reverb Effekte zu bekommen.

Alle Effekte haben Standardeinstellungen. Du kannst diese auch ändern wenn der Effekt einem Sound zugeordnet wurde. Die Reihenfolge dabei ist wichtig! Du musst den Effekt erst einem Sound zuordnen und dann die Parameter ändern. Wenn du den Effekt neu zuordnest sind die Einstellungen aber weg. Achte darauf, dass alle Parameter in einem bestimmten Rahmen liegen müssen, welcher unten angegeben wird. Die folgenden Funktionen gibt es um die Parameter zu modifizieren:

sound_effect_chorus(snd, wetdry, depth, feedback, frequency, wave, delay, phase) Setzt die Parameter für den Chorus Effekt für den angegebenen Sound. Die folgenden Parameter können gesetzt werden:
wetdry Anteil des wet (bearbeitet) Signal zum dry (unbearbeitet) Signal. (Rahme: 0 bis 100, Standard 50)
depth Prozentsatz mit dem die Verzögerungszeit vom Niederfrequenz-Oscillator moduliert wird, in Hundertsteln eines Prozentpunktes. (Rahmen: 0 bis 100, Standard 25)
feedback Prozentsatz des Ausgabesignals der wieder im Eingabesignal landet. (Rahmen: -99 bis 99, Standard 0)
frequency Frequenz des LFO. (Rahmen: 0 bis 10, Standard 0)
wave Wellenform des LFO. (0 = dreieckig, 1 = Welle, Standard 1)
delay Anzahl der Millisekunden um die die Ausgabe verzögert wird. (Rahmen: 0 bis 20, Standard 0)
phase Phasendifferential zwischen linken und rechten LFOs. (Rahmen: 0 bis 4, Standard 2)
sound_effect_echo(snd, wetdry, feedback, leftdelay, rightdelay, pandelay) Setzt die Parameter für den Echo Effekt. Die folgenden Parameter können beeinflusst werden:
wetdry Anteil des wet (bearbeitet) Signal zum dry (unbearbeitet) Signal. (Rahme: 0 bis 100, Standard 50)
feedback Prozentsatz der Eingangsrückschleifung (Rahmen: 0 bis 100, Standard 0)
leftdelay Verzögerung des linken Kanals, in Millisekunden. (Rahmen: 1 bis 2000, Standard 333)
rightdelay Verzögerung des rechten Kanals, in Millisekunden. (Rahmen: 1 bis 2000, Standard 333)
pandelay Ob die Kanäle mit sukzessivem Echo getauscht werden sollen. (0 = nicht tauschen, 1 = tauschen, Standard 0)
sound_effect_flanger(snd, wetdry, depth, feedback, frequency, wave, delay, phase) Setzt die Parameter des Flanger Effekts für den angegebenen Sound. Die folgenden Parameter können gesetzt werden:
wetdry Anteil des wet (bearbeitet) Signal zum dry (unbearbeitet) Signal. (Rahme: 0 bis 100, Standard 50)
depth Prozentsatz mit dem die Verzögerungszeit vom Niederfrequenz-Oscillator moduliert wird, in Hundertsteln eines Prozentpunktes. (Rahmen: 0 bis 100, Standard 25)
feedback Prozentsatz des Ausgabesignals der wieder im Eingabesignal landet. (Rahmen: -99 bis 99, Standard 0)
frequency Frequenz des LFO. (Rahmen: 0 bis 10, Standard 0)
wave Wellenform des LFO. (0 = dreieckig, 1 = Welle, Standard 1)
delay Anzahl der Millisekunden um die die Ausgabe verzögert wird. (Rahmen: 0 bis 20, Standard 0)
phase Phasendifferential zwischen linken und rechten LFOs. (Rahmen: 0 bis 4, Standard 2)
sound_effect_gargle(snd, rate, wave) Setzt die Parameter des Gargle Effekts für den angegebenen Sound. Die folgenden Parameter können gesetzt werden:
rate Die Rate der Modulation in Hertz. (Rahmen: 1 to 1000, Standard 1)
wave Wellenform der Modulationswelle. (0 = dreieckig, 1 = Welle, Standard 1)
sound_effect_reverb(snd, gain, mix, time, ratio) Setzt die Parameter des Reverb Effekts für den angegebenen Sound. Die folgenden Parameter können gesetzt werden:
gain Inputlevel des Signals, in Dezibel (dB). (Rahmen: -96 to 0, Standard 0)
mix Reverb Mix, in dB. (Rahmen: -96 bis 0, Standard 0)
time Reverb Zeit, in Millisekunden. (Rahmen: 0.001 bis 3000, Standard 1000)
ratio Frequenzmultiplikation. (Rahmen: 0.001 bis 0.999, Standard 0.001)
sound_effect_compressor(snd, gain, attack, release, threshold, ratio, delay) Setzt die Parameter des Kompressor Effekts für den angegebenen Sound. Die folgenden Parameter können gesetzt werden:
gain Ausgabelevel nach der Kompression. (Rahmen: -60 to 60, Standard 0)
attack Zeit, bevor die Kompression die volle Stärke erreicht. (Rahmen: 0.01 bis 500, Standard 0.01)
release Geschwindigkeit der Zurückfahrung des Kompressors nachdem das Eingangslevel unterschritten wurde. (Rahmen: 50 bis 3000, Standard 50)
threshold Punkt an welchem die Kompression beginnt, in Dezibel. (Rahmen: -60 bis 0, Standard -10)
ratio Kompressionsfaktor. (Rahmen: 1 bis 100, Standard 10)
delay Zeit die verstreicht, nachdem der Level erreicht wurde und bevor die Attack-Phase startet, in Millisekunden. (Rahmen: 0 bis 4, Standard 0)
sound_effect_equalizer(snd, center, bandwidth, gain) Setzt die Parameter des Equalizer Effekts für den angegebenen Sound. Die folgenden Parameter können gesetzt werden:
center Center-Frequenz, in Hertz. (Rahmen: 80 bis 16000)
bandwidth Bandbreite, in Halbtönen.(Rahmen: 1 bis 36)
gain Gain. (Rahmen: -15 bis 15)

3D sound

Diese Funktionen sind nur in der registrierten Game Maker Version verfügbar.

3D Sounds sind Sounds die eine Position (und Ausbreitungsgeschwindigkeit) haben, unter Berücksichtigung des Hörers. Auch wenn er meist nur in 3D Spielen eingesetzt wird kannst du ihn auch effektiv 2D Spielen nutzen. Die Idee ist, das der Sound eine Position im Raum hat. In allen Funktionen wird davon ausgegangen, dass der Hörer an Position (0,0,0) sitzt. Das System berechnet wie der Zuhörer den Sound hören würde und gibt ihn aus. Der Effekt ist gut wenn er auf guten Lautsprechern zu hören ist, funktioniert aber auch auf kleinen Brüllwürfeln zufriedenstellend.

Neben der Position kann der Sound auch eine Ausbreitungsgeschwindigkeit haben. Das führt zu den gut bekannten Dopplereffekten die korrekt modelliert sind. Schließlich kann ein Sound auch eine Ausrichtungen haben , und wieder wird der Sound entsprechend angepasst.

Game Maker unterstützt 3D Sound über die Funktionen hier unten. Diese funktionieren nur bei Ressourcen, deren Typ 3D ist. (Der Nachteil ist, das 3D Sounds Mono und nicht Stereo sind, was aber mit dem Prinzip zusammenhängt.)

sound_3d_set_sound_position(snd, x, y, z) Setzt die Position des Sounds im Raum unter Berücksichtigung der Position des Zuhörers. Werte der x-Achse nehme von links nach rechts zu, die der y-Achse von unten nach oben, und die der z-Achse von nah nach fern. Die Werte sind in Metern anzugeben. Die Lautstärke mit welcher der Sound spielt verhält sich so wie in der realen Welt.
sound_3d_set_sound_velocity(snd, x, y, z) Setzt die Vektorgeschwindigkeit des angegebenen Sounds. Beachte, das dadurch nicht die Position geändert wird. Vektorgeschwindigkeit wird nur zur Berechnung von Dopplereffekten benötigt. Wenn du also die Position des Sounds verändern möchtest, musst du das selber tun.
sound_3d_set_sound_distance(snd, mindist, maxdist) Setzt das Minimum bei dem der Sound nicht mehr lauter wird und das Maximum bei den er nicht mehr gehört wird. Wenn der Abstand zwischen 0 und dem Minimum liegt ist der Sound am lautesten. Zwischen Minimum und Maximum wird er immer leiser bis er nicht mehr gehört werden kann. Standardmäßig ist das Minimum 1 Meter und die maximale Distanz 1 Milliarde Meter.
sound_3d_set_sound_cone(snd, x, y, z, anglein, angleout, voloutside) Normalerweise hat ein Sound in alle Richtungen dieselbe Amplitude. Du kannst den Soundkegel aber ändern und ihn diagonal klingen lassen. x,y,z geben die Richtung des Soundkegels an. anglein gibt den inneren Winkel an. Wenn der Zuhörer im inneren Winkel ist hört er den Sound bei normaler Lautstärke. angleout gibt den äusseren Winkel an. Wenn der Zuhörer im äusseren Winkel ist wird die Lautstärke mit voloutside moduliert. Um genau zu sein, voloutside ist eine negative Zahl die die hundertstel Dezibel angibt, die vom inneren Winkel abgezogen werden müssen. Zwischen innerem und äußeren Winkel wird die Lautstärke moduliert.

CD Musik

Diese Funktionen sind nur in der registrierten Game Maker Version verfügbar.

Es gibt auch eine Anzahl von Funktionen die sich mit der Wiedergabe von CDs beschäftigen.

cd_init() Muss vor den anderen Funktionen aufgerufen werden. Sollte auch bei CD-Wechsel aufgerufen werden (oder einfach von Zeit zu Zeit).
cd_present() Gibt an, ob im Standard-CD-Laufwerk eine CD vorhanden ist.
cd_number() Gibt die Zahl der Stücke auf CD zurück.
cd_playing() Gibt zurück, ob die CD abgespielt wird.
cd_paused() Gibt zurück ob die CD pausiert oder anhält.
cd_track() Gibt das aktuelle Stück zurück (1=das erste).
cd_length() Gibt die Gesamtlänge der CD in Millisekunden wieder.
cd_track_length(n) Gibt die Länge von Stück n der CD in Millisekunden wieder.
cd_position() Gibt die aktuelle Position auf der CD in Millisekunden zurück.
cd_track_position() Gibt die aktuelle Position im Stück in Millisekunden zurück.
cd_play(first, last) Lässt die CD vom Stück first bis zum Stück last spielen. Wenn du die ganze CD abspielen willst gebe 1 und 1000 als Argumente.
cd_stop() Hält die CD an.
cd_pause() Pausiert die CD.
cd_resume() Spielt weiter ab.
cd_set_position(pos) Setzt die Position auf der CD in Millisekunden.
cd_set_track_position(pos) Setzt die Position im aktuellen Stück in Millisekunden.
cd_open_door() Öffnet den CD-Tray.
cd_close_door() Schließt den CD-Tray.

Es gibt eine sehr allgemeine Möglichkeit die Multimediafunktionen von Windows zu benutzen.

MCI_command(str) Diese Funktion sendet str an das Media Control Interface (MCI). Es gibt den zurückgegebenen String zurück. Du kannst das nutzen um alle Mediengeräte anzusprechen. Schau in der Windows Dokumentation nach wie man dieses Kommando benutzen kann. Zum Beispiel spielt MCI_command('play cdaudio from 1') eine CD (nachdem du mit den anderen Kommandos korrekt initialisiert hast). Diese Funktion ist nur für den fortgeschrittenen Nutzer!

Splash Screens, highscores, und andere Pop-Ups

In diesem Abschnitt werden wir eine Anzahl von Funktionen beschreiben, die verwendet werden können, um Splash-Screens mit Videos, Bildern, etc. anzuzeigen; um Nachrichten und Fragen an den Spieler zu richten und um die Highscoretabelle zu zeigen.

Splash screens

Viele Spiele benutzen sogenannte Splash Screens. Diese screens zeigen ein Video, ein Bild, oder etwas Text. Oft werden sie zu Beginn eines Spieles verwendet (als ein Intro), am Anfang eines Levels oder am Ende des Spiels (beispielsweise die Credits). Im Game Maker können solche Splash Screens mit Text, Bildern oder Videos zu jedem Zeitpunkt innerhalb des Spiels angezeigt werden. Das Spiel wird solange wie der Screen angezeigt wird pausiert. Dies sind die Funktionen, die verwendet werden:

show_text(fname, full, backcol, delay) Zeigt einen Text Splash Screen. fname ist der Name der Textdatei (.txt oder .rtf). Du musst diese Datei selber in das Spielverzeichnis stellen. Auch wenn du eine stand-alone Version deines Spiels erstellst, darfst du nicht vergessen, diese Datei dort hinzuzufügen. full gibt an, ob es im Vollbildmodus angezeigt wird. backcol ist die Farbe des Hintergrundes, und delay ist die Verzögerung, bevor es wieder zurück zum Spiel geht. (Der Spieler kann immer mittels Mausklick in den screen zum Spiel zurückkehren.)
show_image(fname, full, delay) Zeigt einen Bild Splash Screen. fname ist der Name der Bilddatei (nur .bmp, .jpg und .wmf files). Du musst diese Datei selber in den Spielordner stellen. full gibt an, ob es im Vollbildmodus angezeigt wird. delay ist die Verzögerung, bevor es wieder zurück zum Spiel geht.
show_video(fname, full, loop) Zeigt einen Video Splash Screen. fname ist der Name der Video-Datei (.avi,.mpg). Du musst diese Datei selber in das Spielverzeichnis stellen. full gibt an, ob es im Vollbildmodus angezeigt wird. loop gibt an, ob es wiederholt werden soll.
show_info() Zeigt das game information Fenster.
load_info(fname) Lädt die Spielinformation aus einer Datei namens fname. Dies sollte eine rtf-Datei sein. Dies macht es möglich, zu verschiedenen Zeitpunkten entsprechende Hilfen anzuzeigen.

Pop-up Nachrichten und Fragen

Es existiert ein Anzahl von anderen Funktionen, um Nachrichten, Fragen, eine Menüauswahl oder einen Dialog, wo der Spieler eine Zahl, eine Zeichenkette, eine Farbwahl oder einen Dateinamen eingibt, einzublenden:

show_message(str) Zeigt eine Dialogbox mit der Zeichenkette (str) als Nachricht.
show_message_ext(str, but1, but2, but3) Zeigt eine Dialogbox mit der Zeichenkette (str) als Nachricht und bis zu drei Knöpfen an. But1, but2 und but3 beinhalten den Text der Knöpfe. Eine leere Zeichenkette bedeutet, dass der Knopf nicht angezeigt wird. Innerhalb dieses Textes kannst du das & Symbol verwenden, um anzugeben, dass das nächste Zeichen als Tastaturkürzel (keyboard shortcut) für diesen button gilt. Die Funktion gibt die Zahl des gedrückten Buttons wieder (0 falls der User die Esc-Taste gedrückt hat).
show_question(str) Zeigt eine Frage; liefert "true" (wahr) falls der User "yes" ausgewählt hat und ansonsten "false" (falsch) als Rückgabewert.
get_integer(str, def) Fragt den Spieler in einer Dialogbox nach einer Zahl. str ist die Nachricht. def ist die voreingestellte Zahl, die angezeigt wird.
get_string(str, def) Fragt den Spieler in einer Dialogbox nach einer Zeichenkette. str ist die Nachricht. def ist der voreingestellte Wert, der angezeigt wird.
message_background(back) Setzt das Hintergrundbild für die Pop-Up Box für jede der obigen Funktionen. back muss einer der fürs Spiel festgelegten Hintergründe sein. Falls back teilweise transparent ist, ist es die Nachricht auch (nur für Windows 2000 oder später).
message_alpha(alpha) Setzt die alpha Transparenz für die Pop-Up Box für jede der oben erwähnten Funktionen. alpha muss zwischen 0 (komplett durchsichtig) und 1 (nicht durchsichtig)liegen (nur ab Windows 2000 oder später).
message_button(spr) Setzt die sprites für die Knöpfe, die in der Pop-Up Box verwendet werden. spr muss ein sprite sein, dass aus drei Einzelbildern besteht, das Erste stellt den nicht gedrückten Knopf dar und der Mauszeiger ist weit weg, das Zweite stellt den Knopf dar, wenn der Mauszeiger sich über diesem befindet aber er noch nicht gedrückt wurde und das Dritte stellt den gedrückten Knopf dar.
message_text_font(name, size, color, style) Setzt die Schriftart für den Text in der Pop-Up Box. (Dies ist eine normale Windows-Schriftart, nicht eine der Schriftarten aus den Spiel-Font-Ressourcen!). style gibt den Schriftstil an (0=normal, 1=fett, 2=kursiv, and 3=fett-kursiv).
message_button_font(name, size, color, style) Setzt die Schriftart für die Buttons in der Pop-Up Box. style gibt den Schriftstil an (0=normal, 1=fett, 2=kursiv, und 3=fett-kursiv).
message_input_font(name, size, color, style) Setzt die Schriftart für das Eingabefeld in der Pop-Up Box. style gibt den Schriftstil an (0=normal, 1=fett, 2=kursiv, und 3=fett-kursiv).
message_mouse_color(col) Setzt die Farbe der Schrift für die Buttons in der Pop-Up Box, wenn der Mauszeiger darüber ist.
message_input_color(col) Setzt die Farbe für den Hintergrund im Eingabefeld der Pop-Up Box.
message_caption(show, str) Setzt die Titelzeile der Pop-Up Box. show gibt an, ob ein Rand angezeigt wird (1) oder nicht (0) und str gibt den Titeltext an, wenn der Rand gezeigt wird.
message_position(x, y) Setzt die Position der Pop-Up Box auf dem Bildschirm.
message_size(w, h) Legt die Größe der Pop-Up Box auf dem Bildschirm fest. Wenn du 0 für die width (Breite) wählst , wird die Breite des Bildes verwendet. Wenn du 0 für die height (Höhe) wählst, wird die Höhe basierend auf der Anzahl der Zeilen der Nachricht errechnet.
show_menu(str, def) Zeigt ein popup menu. str gibt den Menü-Text an. Dieser besteht aus den verschiedenen Menü-Einträgen getrennt durch einen senkrechten Strich. Zum Beispiel: str = 'menu0|menu1|menu2'. Wenn der erste Eintrag gewählt wird, wird eine 0 zurückgegeben, usw. Wenn der Spieler keinen Menüeintrag auswählt, wird der voreingestellte Wert def zurückgegeben.
show_menu_pos(x, y, str, def) Zeigt ein Pop-Up Menü wie in der vorhergehenden Funktion nur an der Position x,y auf dem Bildschirm.
get_color(defcol) Fragt den Spieler nach einer Farbe (color). defcol ist die voreingestellte Farbe. Falls der Benutzer "cancel" drückt wird der Wert -1 zurückgegeben.
get_open_filename(filter, fname) Fragt den Spieler nach einem Dateinamen der mit dem angegebenen filter geöffnet werden soll. Der Filter hat die Form 'name1|mask1|name2|mask2|...'. Eine mask (Maske) beinhaltet die verschiedenen Optionen getrennt durch ein Semikolon. * bedeutet eine beliebige Zeichenkette. Zum Beispiel: 'bitmaps|*.bmp;*.wmf'. Wenn der Benutzer "cancel" drückt, wird eine leere Zeichenkette zurückgegeben.
get_save_filename(filter, fname) Fragt nach einem Dateinamen der mit dem angegebenen Filter abgespeichert wird. Wenn der Benutzer "cancel" drückt, wird eine leere Zeichenkette zurückgegeben.
get_directory(dname) Fragt nach einem Verzeichnis. dname ist der voreingestellte Name. Wenn der Benutzer "cancel" drückt wird eine leere Zeichenkette zurückgegeben.
get_directory_alt(capt, root) Eine alternative Möglichkeit nach einem Verzeichnis zu fragen. capt ist die anzuzeigende Titelleiste. root ist die Wurzel des anzuzeigenden Verzeichnisbaumes. Verwende eine leere Zeichenkette, um den vollständigen Baum anzuzeigen Wenn der Benutzer "cancel" drückt, wird eine leere Zeichenkette zurückgegeben.
show_error(str, abort) Zeigt eine Standard-Fehler-Nachricht an (und/oder schreibt sie ins log file). abort gibt an, ob das Spiel abgebrochen werden soll.

Highscore-Tabelle

Ein besonderes Pop-Up ist die Highscore-Tabelle, welche für jedes Spiel aufrechterhalten wird. Die folgenden Funktionen bestehen dafür:

highscore_show(numb) Zeigt die Highscore-Tabelle. numb ist der neue Punktestand. Wenn der Punktestand hoch genug ist, um in die Tabelle aufgenommen zu werden, kann der Spieler einen Namen eingeben. Verwende -1, um die aktuelle Tabelle nur anzuzeigen.
highscore_set_background(back) Setzt das zu verwendende Hintergrundbild. back muss der Index einer der Hintergrundressourcen sein.
highscore_set_border(show) Gibt an, ob die Highscore-Tabelle einen Rahmen haben soll oder nicht.
highscore_set_font(name, size, style) Setzt die Schriftart, die in der Tabelle für den Text verwendet wird. (Dies ist eine gewöhnliche Windows-Schriftart, nicht eine aus den Schriftart-Ressourcen.) Du bestimmst den Namen, Größe und Art (0=normal, 1=fett, 2=kursiv, 3=fett-kursiv).
highscore_set_colors(back, new, other) Setzt die Farbe, die für den Hintergrund (back) der Tabelle verwendet wird , bei Neueinträgen (new) und bei den übrigen (other) Einträgen.
highscore_set_strings(caption, nobody, escape) Ändert die verschiedenen vorgegebenen Zeichenketten, die verwendet werden, wenn die Highscore-Tabelle angezeigt wird. caption ist der Titel des Fensters. nobody ist die Zeichenkette, die verwendet wird, wenn keiner diesen Rang in der Tabelle besetzt. escape ist die Zeichenkette an der Unterkante, welche angibt, die Esc-Taste zu drücken. Du kannst diese verwenden, wenn dein Spiel eine andere Sprache verwenden soll.
highscore_show_ext(numb, back, border, col1, col2, name, size) Zeigt die Highgscore-Tabelle mit einer Anzahl von Optionen (dies kann auch erreicht werden, indem man eine Anzahl der vorstehenden Funktionen verwendet). numb ist der neue Punktestand. Falls der Punktestand hoch genug ist, um in die Tabelle aufgenommen zu werden, kann der Spieler einen Namen eingeben. Verwende -1, um die aktuelle Tabelle einfach nur anzuzeigen. back ist das zu verwendende Hintergrundbild, border gibt an, ob ein Rahmen gezeichnet werden soll oder nicht. col1 ist die Farbe des neuen Eintrags, col2 bestimmt die Farbe der übrigen Einträge. name ist der Name der zu verwendenden Schriftart und size ist die Schriftgröße.
highscore_clear() Löscht die Einträge der Highscore-Tabelle.
highscore_add(str, numb) Fügt einen Spieler mit dem Namen str und dem Punktestand numb zu der Tabelle hinzu.
highscore_add_current() Fügt den aktuellen Punktestand zu der Tabelle. Der Spieler wird nach einem Namen gefragt.
highscore_value(place) Gibt den Punktestand der Person auf dem angegebenen Tabellenplatz wieder (1-10). Dies kann verwendet werden, um deine eigene Highscoretabelle zu zeichnen.
highscore_name(place) Gibt den Namen der Person auf dem angegebenen Tabellenplatz wieder (1-10).
draw_highscore(x1, y1, x2, y2) Zeichnet die Highscore-Tabelle in den "room" innerhalb des angegebenen Rechteckes unter Verwendung der aktuellen Schriftart.

Ressourcen

Im Game Maker kannst du verschiedene Arten von Ressourcen definieren, beispielsweise sprites, sounds, fonts, objects, etc.. In diesem Kapitel wirst du eine Anzahl von Funktionen vorfinden, die Informationen über die Ressourcen liefern. Im nächsten Kapitel findest du Informationen über das Ändern und Erstellen von Ressourcen zur Laufzeit.

Sprites

Nachstehende Funktionen liefern dir Informationen zu einem sprite:

sprite_exists(ind) Gibt wieder, ob ein sprite mit dem angegebenen Index existiert.
sprite_get_name(ind) Gibt den Namen des sprites wieder, dessen Index angegeben ist.
sprite_get_number(ind) Gibt die Anzahl der Einzelbilder des angegebenen sprites wieder.
sprite_get_width(ind) Liefert die Breite des angegebenen sprites zurück.
sprite_get_height(ind) Gibt die Höhe des angegebenen sprites an.
sprite_get_transparent(ind) Gibt an, ob das sprite mit gegebenem Index transparent ist.
sprite_get_smooth(ind) Gibt an, ob das sprite mit dem angegebenen Index geglättete Ränder hat oder nicht.
sprite_get_preload(ind) Gibt wieder, ob das sprite mit dem angegebenen Index im Voraus geladen werden soll.
sprite_get_xoffset(ind) Gibt den x-offset des sprites mit dem angegebenen Index wieder.
sprite_get_yoffset(ind) Gibt den y-offset des sprites mit dem angegebenen Index wieder.
sprite_get_bbox_left(ind) Gibt die linke Kante der "bounding box" des sprites mit dem angegebenen Index wieder.
sprite_get_bbox_right(ind) Gibt die rechte Kante der "bounding box" des sprites mit dem angegebenen Index wieder.
sprite_get_bbox_top(ind) Gibt die obere Kante der "bounding box" des sprites mit dem angegebenen Index wieder.
sprite_get_bbox_bottom(ind) Gibt die untere Kante der "bounding box" des sprites mit dem angegebenen Index wieder.
sprite_get_bbox_mode(ind) Gibt den "bounding box" Modus wieder(0=automatisch, 1=ganzes Bild, 2=manuell) vom sprite mit dem angegebenen Index.
sprite_get_precise(ind) Gibt an, ob das sprite mit dem angegebenen Index "precise collision checking" (exakte Kollisionsprüfung) verwendet.

Sounds

Die folgenden Funktionen werden dir Informationen über einen sound liefern:

sound_exists(ind) Gibt an, ob der sound mit dem angegebenen Index existiert.
sound_get_name(ind) Gibt den Namen des Sounds mit dem angegebenen Index wieder.
sound_get_kind(ind) Gibt die Art des Sounds mit dem angegebenen Index wieder (0=normal, 1=background, 2=3d, 3=mmplayer).
sound_get_preload(ind) Gibt an, ob der sound mit dem angegebenen Index im Voraus geladen wird.

Sounds benötigen viele Ressourcen und viele Systeme können nur eine begrenzte Zahl von ihnen speichern und abspielen. Falls du ein grösseres Spiel erstellst, willst du möglicherweise mehr Kontrolle darüber haben, welche Sounds im Audio-Speicher liegen und zu welcher Zeit. Du kannst das Kästchen der "preload"-Option aktivieren, um sicherzustellen, dass Sounds nur bei Bedarf geladen werden. Dies kann allerdings zu einer kleinen Verzögerung führen, wenn der sound zum ersten Mal verwendet wird. Zudem werden Sounds nicht automatisch wieder aus dem Speicher entfernt, wenn sie nicht mehr gebraucht werden. Für mehr Kontrolle kannst du folgende Funktionen verwenden.

sound_discard(index) Gibt den Speicherplatz des indizierten Sounds wieder frei.
sound_restore(index) Stellt den indizierten sound im Audio-Speicher wieder her, damit er sofort abspielbar ist.

Backgrounds - Hintergrundbilder

Die nachfolgenden Funktionen geben dir Informationen über einen background:

background_exists(ind) Gibt an, ob der background mit dem angegebenen Index existiert.
background_get_name(ind) Gibt den Namen des background mit dem angegebenen Index wieder.
background_get_width(ind) Gibt die Breite des background mit dem angegebenen Index an.
background_get_height(ind) Gibt die Höhe des background mit dem angegebenen Index an.
background_get_transparent(ind) Gibt an, ob der background mit dem angegebenen Index transparent ist.
background_get_smooth(ind) Gibt an, ob der background mit dem angegegebenen Index gelättete Ränder hat.
background_get_preload(ind) Gibt an, ob der background mit dem angegebenen Index im Voraus geladen werden soll.

Fonts - Schriftarten

Die nachstehenden Funktionen geben dir Informationen über eine Schriftart:

font_exists(ind) Gibt zurück, ob die Schriftart mit dem angegebenen Index existiert.
font_get_name(ind) Gibt den Namen der Schriftart mit dem angegeben Index wieder.
font_get_fontname(ind) Gibt den Schriftartnamen der Schriftart mit dem angegebenen Index wieder.
font_get_bold(ind) Gibt an, ob die Schriftart mit dem angegebenen Index "bold" (fettgedruckt) ist.
font_get_italic(ind) Gibt an, ob die Schriftart mit dem angegebenen Index "italic" (kursiv) ist.
font_get_first(ind) Gibt den Index des ersten Zeichens der Schriftart mit dem angegebenen Index wieder.
font_get_last(ind) Gibt den Index des letzten Zeichens der Schriftart mit dem angegebenen Index wieder.

Paths - Pfade

Die folgenden Funktionen geben dir Informationen über einen path:

path_exists(ind) Gibt an, ob der path mit dem angegebenen Index existiert.
path_get_name(ind) Gibt den Namen des path mit dem angegebenen Index wieder.
path_get_length(ind) Gibt die Länge des path mit dem angegebenen Index wieder.
path_get_kind(ind) Gibt die Art der Verbindung des path mit dem angegebenen Index wieder (0="straight" (direkt), 1="smooth" (weich) ).
path_get_closed(ind) Gibt an, ob der Pfad geschlossen oder offen ist.
path_get_precision(ind) Gibt die Genauigkeit an, die für das Glätten eines path verwendet wurde.
path_get_number(ind) Gibt die Anzahl der Definitionspunkte des path wieder.
path_get_point_x(ind, n) Gibt die x-Koordinate des n'ten Definitionspunktes des path wieder. 0 ist der erste Punkt.
path_get_point_y(ind, n) Gibt die y-Koordinate des n'ten Definitionspunktes des path wieder. 0 ist der erste Punkt.
path_get_point_speed(ind, n) Gibt den "speed"-Faktor für den n'ten Definintionspunkt des path wieder. 0 ist der erste Punkt.
path_get_x(ind, pos) Gibt die x-Koordinate an Position pos des path an. pos muss zwischen 0 und 1 liegen.
path_get_y(ind, pos) Gibt die y-Koordinate an Postion pos des path an. pos muss zwischen 0 und 1 liegen.
path_get_speed(ind, pos) Gibt den "speed"-Faktor an Position pos für den path wieder. pos muss zwischen 0 und 1 liegen.

Scripts - Scripte

Die nachstehenden Funktionen werden dir Informationen über ein script geben:

script_exists(ind) Gibt an, ob ein Skript mit dem angegeben Index existiert.
script_get_name(ind) Gibt den Namen des Skriptes mit dem angegebenen Index wieder.
script_get_text(ind) Gibt die Textzeichenkette ("text string") des Skriptes mit dem angegeben Index wieder.

Time lines - Zeitlinien

Die nachstehenden Funktionen geben dir Informationen über eine Zeitlinie:

timeline_exists(ind) Gibt an, ob eine Zeitlinie mit dem angegebenen Index existiert.
timeline_get_name(ind) Gibt den Namen der Zeitlinie mit dem angegeben Index zurück.

Objects - Objekte

Die folgenden Funktionen geben dir Informationen über ein Objekt:

object_exists(ind) Gibt an, ob ein object mit dem angegebenen Index existiert.
object_get_name(ind) Gibt den Namen des Objektes mit dem angegeben Index wieder.
object_get_sprite(ind) Gibt den Index des voreingestellten sprite wieder des objects mit dem angegebenen Index.
object_get_solid(ind) Gibt an, ob das object mit dem angegebenen Index voreingestellt "solid" (massiv) ist.
object_get_visible(ind) Gibt an, ob das object mit dem angegebenen Index voreingestellt "visible" (sichtbar) ist.
object_get_depth(ind) Gibt die depth des Objektes mit dem angegebenen Index an.
object_get_persistent(ind) Gibt an, ob das Objekt mit dem angegebenen Index "persistent" (dauerhaft) ist.
object_get_mask(ind) Gibt den Index der "mask" (Maskierung) des Objektes mit dem angegeben Index wieder (-1 falls keine besondere Maskierung vorhanden).
object_get_parent(ind) Gibt den Index des "parent object" (Elternobjekt)des Objektes mit dem angegebenen Index an (-1 falls es kein parent hat).
object_is_ancestor(ind1, ind2) Gibt an, ob Objekt ind2 ein Vorfahre (ancestor) von Objket ind1 ist.

Rooms - Räume

Die nachfolgenden Funktionen geben dir Informationen über einen Raum:

room_exists(ind) Gibt an, ob ein room mit dem angegebenen Index existiert.
room_get_name(ind) Gibt den Namen des room mit dem angegebenen Index wieder.

Beachte das, weil Räume sich während des Spielen des Raumes verändern, es andere Funktionen gibt, um an Informationen über den Inhalt eines Raumes zu gelangen.

Ressourcen verändern

Diese Funktionen sind nur in der registrierten Version des Game Maker verfügbar!

Es ist möglich neue Ressourcen während des Spieles zu erstellen. Ausserdem kann man bestehende Ressourcen verändern. Dieses Kapitel beschreibt diese Möglichkeiten. Sei gewarnt! Das Verändern von Ressourcen führt leicht zu schweren Fehlern in deinem Spiel!!! Du musst folgende Regeln befolgen:

  • Verändere keine Ressourcen die gerade benutzt werden. Dies führt zu Fehlern! Verändere beispielsweise keine Sprites welche gerade von einer Instanz benutzt werden.
  • Wenn du das Spiel während des Spiels speicherst, werden neue und geänderte Ressourcen NICHT mit diesem Spiel gespeichert. Also, wenn du das gespeicherte Spiel später wieder lädst, sind sie nicht mehr da. Generell, wenn du Ressourcen veränderst, solltest du nicht länger das eingebaute System für das Laden und Speichern von Spielen benutzen.
  • Wenn du das Spiel während des Spielens neu startest, werden die geänderten Ressourcen nicht in ihrer originalen Form wiederhergestellt. Generell, wenn du Ressourcen veränderst, solltest du nicht mehr die Aktion oder Funktion für das Neu Starten (Restart) des Spieles verwenden.
  • Verändern der Ressourcen kann sehr langsam sein. Verändern des Sprites oder Hintergründe ist sehr langsam. Also benutze es nicht während des Spielablaufes.
  • Das Erstellen von Ressourcen während des Spieles (hauptsächlich Sprites und Hintergründe) benötigt einen Menge Speicher. Also gehe sorgfältig damit um. Wenn du z. B. ein 32 Frame 128x128 animiertes Sprite hast und du beschließt 36 drehende Kopien davon zu machen, benutzt du 36x32x128x128x4 = 36 MB des Speichers!
  • Stelle sicher, dass du die Ressourcen löscht, wenn sie nicht mehr gebraucht werden. Sonst geht dem System der Speicher aus.
Generell solltest du keine Ressourcen während des Spielablaufes ändern. Erstelle und verändere Ressourcen am Beginn des Spieles oder vielleicht am Beginn eines Raumes.

Sprites

Die folgenden Routinen sind für das Manipulieren von Sprite-Eigenschaften vorhanden.:

sprite_set_offset(ind, xoff, yoff) Setzt das Offset des Sprites mit dem angegebenen Index.
sprite_set_bbox_mode(ind, mode) Setzt den Begrenzungsrahmen des Sprites (0=automatisch, 1=gesamtes Bild, 2=manuell).
sprite_set_bbox(ind, left, top, right, bottom) Setzt den Begrenzungsrahmen des Sprites mit dem angegebenen Index. Funktioniert nur, wenn dieser als manuell eingestellt wurde.
sprite_set_precise(ind, mode) Soll das Sprite mit dem angegebenen Index präzise Kollisionserkennung benützen (true oder false).

Die folgenden Routinen können für das Erstellen oder Entfernen neuer Sprites verwendet werden.

sprite_duplicate(ind) Erstellt ein Duplikat des Sprites mit dem angegebenen Index. Es gibt den Index des neuen Sprites zurück. Wenn ein Fehler passiert, wird �1 zurückgegeben.
sprite_assign(ind, spr) Verbindet das angegebene Sprite mit dem Sprite ind. Dies macht einfach eine Kopie des aktuellen Sprites. Auf diese Weise kannst du ein existierendes Sprite einem andere zuweisen, z.B. einem neuen Sprite.
sprite_merge(ind1, ind2) Vermischt die Bilder vom Sprite ind2 in den Sprite ind1, fügt ihm am Ende hinzu. Wenn die Größe nicht mit dem Sprite übereinstimmt, wird dieser verändert. Sprite ind2 wird nicht gelöscht!
sprite_add(fname, imgnumb, precise, transparent, smooth, preload, xorig, yorig) Fügt ein Bild aus einer Datei den Sprite-Ressourcen hinzu. Nur bmp, jpg und gif Bilder können geladen werden. Wenn das Bild bmp oder jpg ist kann es als Animationsstreifen mit verschiedenen Subimages nebeneinander geladen werden. imgnumb gibt deren Zahl an (1 für ein einzelnes Bild). Für (animierte) gifs wird dieses Argument ignoriert; die Zahl der Bilder in der gif Datei wird genutzt. precise gibt an, ob präzise Kollisionsüberprüfung genutzt werden soll. transparent gibt an, ob das Bild teiltransparent sein soll. smooth gibt an, ob die Ecken geglättet werden sollen. preload gibt an, ob die Textur in der Speicher vorgeladen werden soll. xorig und yorig geben die Position des Bezugspunktes an. Die Funktion gibt den Index des neuen Sprites zurück um es zu zeichnen oder es über die Variable sprite_index einer Instanz zuzuweusen. Falls ein Fehler auftritt wird -1 zurückgegeben.
sprite_replace(ind, fname, imgnumb, precise, transparent, smooth, preload, xorig, yorig) Dasselbe wie oben, aber das Sprite ind wird damit ersetzt. Es wird zurückgegeben, ob es erfolgreich war.
sprite_create_from_screen(x, y, w, h, precise, transparent, smooth, preload, xorig, yorig) Erstellt ein Sprite von der angegebenen Bildfläche. Dies macht es möglich, ein beliebiges Sprite zu erstellen. Zeichne mit den Zeichenfunktionen ein Bild auf dem Bildschirm und mache dann ein Sprite davon. (Wenn du es nicht im Draw Event machst wird dies sogar nicht auf dem Bildschirm angezeigt.) Die anderen Parameter sind wie oben. Die Funktion gibt den Index des neuen Sprites wider. Vorsicht ist hier geboten. Auch wenn wir hier über den Bildschirm reden, ist es die Zeichenregion die zählt. Das dort möglicherweise ein Fenster ist und dies skaliert wird wird nicht beachtet.
sprite_add_from_screen(ind, x, y, w, h) Fügt ein Feld am Bildschirm als nächstes Einzelbild eine Sprites mit dem index ind.
sprite_create_from_surface(id, x, y, w, h, precise, transparent, smooth, preload, xorig, yorig) Erzeugt ein Sprite von der Oberfläche mit der angegebenen ID. Dies macht es möglich jede Art von Sprite zu erstellen, in dem du das was du willst auf eine Oberfläche zeichnest und daraus ein Sprite machst. Die Funktion gibt den Index des neuen Sprites zurück. Beachte das die Alphawerte im Sprite beibehalten werden.
sprite_add_from_surface(ind, id, x, y, w, h) Fügt einen Bereich der Oberfläche id dem Sprite ind als neues Subimage hinzu.
sprite_delete(ind) Löscht das Sprites aus dem Speicher, gibt den Speicher frei.

Die folgenden Routinen existieren, um das Aussehen eines Sprites zu ändern.

sprite_set_alpha_from_sprite(ind, spr) Ändert die Alpha (Transparenz) Werte des Sprites mit dem Index ind mit den Werten des Sprites spr. Dies kann nicht rückgängig gemacht werden.

Sounds

Die folgenden Routinen erstellen neue Sounds und löschen diese.

sound_add(fname, kind, preload) Fügt die Sound-Ressource dem Spiel hinzu. fname ist der Name der Sounddatei. kind gibt den Typ an (0=normal, 1=background, 2=3d, 3=mmplayer). preload gibt an, ob der Sound sofort in den Puffer geladen werden soll (true oder false). Die Funktion gibt den Index des neuen Sounds wider, welcher genutzt werden kann, um ihm abzuspielen. (-1 falls ein Fehler auftrat, z.B. die Datei existiert nicht).
sound_replace(index, fname, kind, loadonuse) Dasselbe wie oben, diesmal wird aber der sound index ersetzt. Gibt zurück, ob es korrekt ist.
sound_delete(index) Löscht den Sound und gibt dessen Speicher frei. Er kann nicht länger wiederhergestellt werden.

Hintergründe

Die folgenden Routinen sind für das Manipulieren von Hintergründen vorhanden.

background_duplicate(ind) Erstellt eine Duplikat des Hintergrundes mit dem angegebenen Index. Es gibt den Index des neuen Hintergrundes zurück. Wenn ein Fehler passiert, gibt es -1 zurück.
background_assign(ind, back) Verbindet den angegebenen Hintergrund mit dem Hintergrund ind. Dies erstellt eine Kopie des Hintergrundes.
background_add(fname, transparent, smooth, preload) Fügt den Hintergrund aus der Datei fname den Hintergrund-Ressourcen hinzu. Nur bmp und jpg Bilder können verwendet werden. transparent gibt an, ob der Hintergrund teiltransparent sein soll. smooth gibt an, ob die Ecken geglättet werden sollen. preload gibt an, ob die Textur vorgeladen werden soll. Die Funktion gibt den Index des neuen Hintergrundes zurück, um ihn zu zeichnen oder ihn der Variable background_index[0] zu übergeben um ihn im aktuellen Raum anzuzeigen. Wenn ein Fehler auftritt wird -1 zurückzugeben.
background_replace(ind, fname, transparent, smooth, preload) Dasselbe wie oben, ersetzt diesmal aber den Hintergrund. Die Funktion gibt an, ob sie erfolgreich war. Wenn der Hintergrund sichtbar ist, wird er auch ersetzt.
background_create_color(w, h, col, preload) Erstellt einen Hintergrund mit der angegebenen Größe und Farbe und mit den gegebenen Einstellungen. Es gibt den Index des neuen Hintergrunds zurück. Wenn ein Fehler passiert wird -1 zurückgegeben.
background_create_gradient(w, h, col1, col2, kind, preload) Erstellt einen Hintergrund mit der angegebenen Größe und Farbverlauf und mit den gegebenen Einstellungen. col1 und col2 geben die Start- und Endfarbe an. kind ist eine Zahl zwischen 0 und 5 welche die Art des Verlaufs angibt: 0=horizontal 1=vertikal, 2= rechteckig, 3=ellipse, 4=doppelt horizontal, 5=doppelt vertical. Es gibt den Index des neuen Hintergrunds zurück. Wenn ein Fehler passiert wird -1 zurückgegeben.
background_create_from_screen(x, y, w, h, transparent, smooth, preload) Erstellt einen Hintergrund von der angegebenen Bildfläche. Dies macht es möglich, einen beliebigen Hintergrund zu erstellen. Zeichne mit den Zeichenfunktionen ein Bild auf dem Bildschirm und mache dann einen Hintergrund davon. (Wenn du es nicht im Draw Event machst wird dies sogar nicht auf dem Bildschirm angezeigt.) Die anderen Parameter sind wie oben. Die Funktion gibt den Index des neuen Hintergrundes wider. Vorsicht ist hier geboten. Auch wenn wir hier über den Bildschirm reden, ist es die Zeichenregion die zählt. Das dort möglicherweise ein Fenster ist und dies skaliert wird wird nicht beachtet.
background_create_from_surface(id, x, y, w, h, transparent, smooth, preload) Erzeugt einen Hintergrund von der Oberfläche mit der angegebenen ID. Dies macht es möglich jede Art von Hintergrund zu erstellen, in dem du das was du willst auf eine Oberfläche zeichnest und daraus einen Hintergrund machst. Die Funktion gibt den Index des neuen Hintergrundes zurück. Beachte das die Alphawerte im Hintergrund beibehalten werden.
background_delete(ind) Löscht den Hintergrund und gibt seinen Speicher frei.

Die folgenden Routinen existieren, um das Aussehen eines Hintergrundes zu ändern.

background_set_alpha_from_background(ind, back) Ändert die Alpha (Transparenz) Werte des Hintergrundes mit dem Index ind mit den Werten des Hintergrundes spr. Dies kann nicht rückgängig gemacht werden.

Schriftarten

Es ist möglich Schriftarten während des Spieles mit den folgenden Funktionen zu erstellen, ersetzen und zu löschen. (Ersetze nicht die aktuelle Schriftart, oder setze sie danach wenigstens nochmals.)

font_add(name, size, bold, italic, first, last) Fügt eine neue Schriftart hinzu und gibt deren Index zurück, Name, Größe und ob fett oder kursiv, und das erste und letzte Zeichen müssen angegeben werden.
font_add_sprite(spr, first, prop, sep) Fügt eine neue Schriftart hinzu und gibt deren Index zurück. Die Schriftart wird aus einem Sprite gemacht. Das Sprite muss ein Subimage für jedes Zeichen enthalten. first gibt das erste Zeichen in dem Sprite an. Beispielsweise kannst du ord('0') benutzen wenn dein Sprite die Zahlen enthält. prop gibt an, ob die Schriftart proportional ist. In einer proportionalen Schriftart wird für jedes Zeichen die Bounding Box als Breite genommen. Schließlich gibt sep den horizontalen Abstand der Zeichen in Pixeln an. Ein typischer Wert liegt zwischen 2 und 8, ja nach Schriftgröße.
font_replace(ind, name, size, bold, italic, first, last) Ersetzt die Schriftart ind mit einer neuen Schriftart, gebe Namen, Größe, fett oder kursiv, und das erste und letzte Zeichen an.
font_replace_sprite(ind, spr, first, prop, sep) Ersetzt die Schriftart ind mit einer neuen, sprite-basierenden Schriftart.
font_delete(ind) Löscht die angegebene Schriftart und gibt deren Speicher frei.

Pfade

Es ist möglich Pfade zu erstellen und Punkte den Pfaden zuzuordnen. Verändere nie einen Pfad welcher von einer Instanz benutzt wird. Dies kann zu unerwarteten Fehlern führen. Die folgenden Funktionen existieren:

path_set_kind(ind, val) Setzt die Art der Verbindung des Pfades mit dem angegebenen Index (0 = gerade, 1 = sanft).
path_set_closed(ind, closed) Gibt an ob der Pfad geöffnet (false) oder geschlossen sein muss (true).
path_set_precision(ind, prec) Gibt die Präzision an mit der die "Flüssigkeit" des Pfades berechnet werden soll (sollte zwischen 1 und 8 liegen).
path_add() Fügt einen neuen leeren Pfad hinzu. Der Index des Pfades wird zurückgegeben.
path_delete(ind) Löscht den Pfad mit dem angegebenen Index.
path_duplicate(ind) Erstellt eine Kopie des Pfades mit dem gegebenen Index her. Gibt den Index der Kopie wieder.
path_assign(ind, path) Verbindet den angegebenen Pfad mit dem Pfad ind. So erstellt sie eine Kopie von path. Damit kannst du einen existierenden Pfad einen neuen Pfad zuweisen.
path_append(ind, path) Fügt dem angegeben Pfad den Pfad ind an.
path_add_point(ind, x, y, speed) Fügt eine Punkt zu dem Pfad mit dem angegebenen Index in die Position (x, y) mit der angegebenen Geschwindigkeitsfaktor. Denke daran das ein Faktor von 100 die aktuelle Geschwindigkeit darstellt. Niedrigere Werte verlangsamen und höhere beschleunigen.
path_insert_point(ind, n, x, y, speed) Fügt dem gegebenen Pfad einen Punkt vor dem Punkt n an, an der Position (x,y) und mit dem gegebenen Geschwindigkeitsfaktor.
path_change_point(ind, n, x, y, speed) Verändert den Punkt n im Pfad mit dem gegebenen Index zur Position (x,y) und dem gegebenen Geschwindigkeitsfaktor.
path_delete_point(ind, n) Löscht den Punkt n aus dem Pfad ind.
path_clear_points(ind) Löscht alle Punkte im Pfad, wird in einen leeren Pfad umgewandelt.
path_reverse(ind) Dreht den Pfad um.
path_mirror(ind) Spiegelt den Pfad horizontal (an seinem Zentrum).
path_flip(ind) Spiegelt den Pfad vertikal (an seinem Zentrum).
path_rotate(ind, angle) Rotiert den Pfad im Uhrzeigersinn ind angle Grad (um sein Zentrum).
path_scale(ind, xscale, yscale) Skaliert den Pfad mit den gegebenen Faktoren (aus seinem Zentrum).
path_shift(ind, xshift, yshift) Versetzt den Pfad mit den gegebenen Werten.

Skripte

Skripte können nicht während des Ausführung eines Spieles geändert werden. Skripte sind Teil der Spiellogik. Verändern von Skripten würde leicht zu Fehlern führen. Aber es gibt andere Wege dies zu bewerkstelligen. Wenn du wirklich ein Stück Code ausführen willst, welcher noch nicht beim Design des Spieles vorhanden ist (z. b. von einer Datei) kannst du folgende Funktionen benutzen:

execute_string(str) Führt das Stück Code des Strings aus.
execute_file(fname) Führt das Stück Code in der Datei aus.

Manchmal willst du einen Skriptindex in einer Variable speichern und ausführen. Dafür kannst du folgende Funktion verwenden

script_execute(scr, arg0, arg1, ...) Führt das Skript mit dem Index scr und den angegebenen Argumenten aus.

Zeitleisten

Die folgenden Routinen sind für das Erstellen und Verändern von Zeitleisten verfügbar. Verändere keine Zeitleisten die gerade benutzt werden!

timeline_add() Erstellt eine neue Zeitleiste. Es gibt den Index der Zeitleiste zurück.
timeline_delete(ind) Löscht die Zeitleiste mit dem angegebenen Index. Gehe sicher dass keine Instanz dieser Zeitleiste in irgendeinem Raum benutzt.
timeline_moment_add(ind, step, codestr) Fügt eine Code Aktion in die Zeitleiste um angegebenen Zeitpunkt. codestr beinhaltet den Code der Aktion. Wenn der Schritt (step) nicht vorhanden ist, wird er erstellt. Also kannst du mehre Code Aktionen zum gleichen Zeitpunkt hinzufügen.
timeline_moment_clear(ind, step) Diese Funktion löscht die Aktionen zu einem gewissen Zeitpunkt.

Objekte

Auch Objekte können manipuliert werden und während des Spielablaufes erstellt werden. Ändere oder lösche NIE ein Objekt von dem Instanzen vorhanden sind. Das kann zu unerwarteten Effekten führen, da die bestimmten Objekteigenschaften mit der Instanz gespeichert werden, daher hat das Verändern des Objekts nicht den gewünschten Erfolg.

object_set_sprite(ind, spr) Setzt den Sprites des Objektes mit dem angegebenen Index. Benutze -1 um den aktuellen Sprite vom Objekt zu entfernen.
object_set_solid(ind, solid) Sollen die Instanzen die vom Objekt erstellt werden solid sein oder nicht (true oder false).
object_set_visible(ind, vis) Sollen die Instanzen die vom Objekt erstellt werden sichtbar sein oder nicht (true oder false).
object_set_depth(ind, depth) Setzt die voreingestellte Zeichentiefe der Instanzen der erstellten Objektes.
object_set_persistent(ind, pers) Sollen die Instanzen die vom Objekt erstellt werden, dauerhaft sein oder nicht (true oder false).
object_set_mask(ind, spr) Setzt die Sprite Maske des Objektes mit dem angegebenen Index. Benutze -1 um die Maske zu dem Sprites des Objektes zu setzen.
object_set_parent(ind, obj) Setzt das Elternobjekt. Benutze -1 um kein Elternobjekt zu haben. Das Ändern des Elternobjektes ändert das Verhalten der Instanzen des Objektes.

Die folgenden Routinen sind nützlich um neue Objekte on the fly zu erstellen. Wie bei allen anderen Routinen, so sei auch hier vorsichtig, dass du nicht die ganze Zeit neue Objekte erstellst.

object_add() Fügt ein neues Objekt ein. Der Index des Objekte wird zurückgegeben. Du kannst den Index benützen um bestimmte Eigenschaften des Objektes zu setzen und für das Erstellen von Instanzen des Objektes.
object_delete(ind) Löscht das Objekt mit dem angegeben Index. Gehe sicher das keine Instanz des Objektes in irgendeinem Raum existiert.
object_event_add(ind, evtype, evnumb, codestr) Um dem Objekte ein Verhalten zu geben, müssen wir dem Objekt Eigenschaften definieren. Du kannst nur Code-Aktionen für die Events hinzufügen. Du musst das Objekt nennen, den Event Typ. Die Event Nummer (benutze die Konstanten welche für die event_erform() Funktion angeben ist). Zuletzt gib den Code Zeichenkette, welche ausgeführt werden soll, an. Du kannst mehrer Code Aktionen zu jedem Event hinzufügen.
object_event_clear(ind, evtype, evnumb) Du kannst dies nutzen, um alle Aktionen in einem Event zu löschen.

Das Erstellen von Objekten ist teilweise nützlich wenn du ein Skript oder Action Bibliothek erstellst. Ein Initialisierungsskript kann Objekte erstellen, die Texte anzeigen und ein anderes Skript kann solche Objekt mit einem bestimmten Text hinzufügen. In dieser Art hast du einen einfachen Mechanismus um Text anzuzeigen oder Objekte zu erstellen, die das Standardinterface benutzen.

Räume

Das manipulieren von Räumen während des Spielablaufes kann auch gefährlich sein. Du musst bedenken, das sich Räume die ganze Zeit je nach Spielablauf verändern. Dies betrifft im Normal fall nur den aktuellen Raum und es gibt, wie in den vorherigen Abschnitten beschrieben, Routinen zum Manipulieren von Instanzen, Hintergründen und Tiles im aktiven Raum. Aber die Änderungen im Raum bleiben erhalten, wenn der Raum dauerhaft ist. Deshalb solltest du nie irgendwas an einem aktiven oder irgendeinem Raum ändern, der dauerhaft ist und schon zuvor besucht wurde. Solche Änderungen werden normalerweise nicht wahrgenommen, aber sie können zu unerwarteten Fehlern führen. Da Räume in einem komplizierten Verfahren miteinander verknüpft sind, gibt es keine Möglichkeit diese zu löschen.

Die folgenden Routinen gibt es

room_set_width(ind, w) Setzt die Breite des Raumes mit dem angegeben Index.
room_set_height(ind, h) Setzt die Höhe des Raumes mit dem angegeben Index.
room_set_caption(ind, str) Setzt die Überschrift des Raumes mit dem angegeben Index.
room_set_persistent(ind, val) Gibt an ob der Raum mit dem angegeben Index dauerhaft ist oder nicht.
room_set_code(ind, str) Setzt den Initialisierungscode (str) für den Raum mit dem angegeben Index.
room_set_background_color(ind, col, show) Setzt die Farbeigenschaften für einen Raum mit dem angegeben Index. Wenn es keinen Hintergrund hat. col gibt die Farbe an und show gibt an ob die Farbe angezeigt werden soll oder nicht.
room_set_background(ind, bind, vis, fore, back, x, y, htiled, vtiled, hspeed, vspeed, alpha) Setzt den Hintergrund mit Index (0-7) für den Raum mit dem angegebenen Index. vis gibt an ob der Hintergrund sichtbar ist und fore ob es ein Vordergrund ist. back ist der Index der Hintergrund-Datei. x, y geben die Position des Bildes an und htiled und vtiled gibt an ob das Bild geteilt wird. hspeed und vspeed geben die Geschwindigkeit mit welcher der Hintergrund sich bewegt und alpha gibt die Alphatranzparenz an (1 = fest und am schnellsten).
room_set_view(ind, vind, vis, xview, yview, wview, hview, xport, yport, wport, hport, hborder, vborder, hspeed, vspeed, obj) Setzt den View mit Index vind (0-7) für den Raum mit dem angegebenen Index. vis gibt an, ob der View sichtbar ist. xview, yview, wview, und hview geben die Position des Views im Raum an. xport, yport, wport, und hport geben die Position auf dem Bildschirm an. Wenn der View einem Objekt folgt müssen hborder und vborder den minimalen Abstand um das Objekt angeben. hspeed und vspeed geben die maximale Geschwindigkeit an, mit der der View sich bewegen kann. obj ist der Name oder der Index einer Instanz, der gefolgt werden soll.
room_set_view_enabled(ind, val) Gibt an ob die View für den Raum mit dem angegeben Index eingeschaltet werden soll oder nicht.
room_add() Fügt einen neuen Raum hinzu. Es gibt den Index den Raumes zurück. Bedenke dass der Raum nicht Teil der Raumreihenfolge ist. So hat der neue Raum keinen vorhergehenden oder nachfolgenden Raum. Wenn du in einen hinzugefügten Raum gehen willst, musst du den Index des Raumes angeben.
room_duplicate(ind) Fügt eine Kopie des Raumes mit dem angegeben Index. Es gibt den Index des Raumes zurück.
room_assign(ind, room) Verbindet den Raum mit dem Raum ind. Somit wird der Raum kopiert.
room_instance_add(ind, x, y, obj) Fügt eine neue Instanz des Objektes obj zu dem Raum mit dem angegeben Index. Es gibt den Index der Instanz zurück.
room_instance_clear(ind) Zerstört alle Instanzen des Raumes mit dem angegeben Index.
room_tile_add(ind, back, left, top, width, height, x, y, depth) Fügt eine neues Tile im Raum auf der angegebenen Position ein. Es gibt den Index des Tiles zurück. back ist der Hintergrund wo der Tile genommen wird, left, top, widh und height geben den Teil des Hintergrundes an, welcher das Tile formt. x, y ist die Position des Tiles im Raum und depth ist die Zeichentiefe des Tiles an.
room_tile_add_ext(ind, back, left, top, width, height, x, y, depth, xscale, yscale, alpha) Gleiche wie vorher aber diesmal kannst du einen Skalierungsfaktor in x und y Richtung und eine Alphatransparenz für das Tile angeben.
room_tile_clear(ind) Zerstört alle Tiles vom angegebenen Raum.

Dateien, Registry und Programme ausführen

In einem fortgeschritteneren Spiel willst du möglicherweise Daten aus einer Datei lesen, die du mit dem Spiel mitlieferst. Oder du möchtest Informationen für weitere Benutzung beim nächsten Spielen zwischenspeichern. Und in einigen Situationen möchtest du auch externe Programme ausführen.

Dateien

Es ist nützlich externe Dateien in Spielen zu verwenden. Du kannst z.B. eine Datei machen, die beschreibt, wann etwas bestimmtes passiert. Du kannst auch Informationen speichern, die beim nächsten Starten des Spieles verwendet werden (beispielsweise den aktuellen Raum). Die folgenden Funktionen kann man zu Verarbeiten von Textdateien nutzen:

file_text_open_read(fname) Öffnet die angegebene Datei zum Lesen. Die Funktion gibt die ID der Datei zurück, welche für die anderen Funktionen gebraucht wird. Du kannst mehrere Dateien gleichzeitig öffnen (maximal 32). Vergesse nicht sie nach dem Verarbeiten zu schließen.
file_text_open_write(fname) Öffnet die angegebene Datei zum Schreiben, erstellt sie, falls sie nicht existiert. Die Funktion gibt die ID der Datei zurück, welche für die anderen Funktionen gebraucht wird.
file_text_open_append(fname) Öffnet die angegebene Datei zum Anfügen von Daten am Ende, erstellt sie, falls sie nicht existiert. Die Funktion gibt die ID der Datei zurück, welche für die anderen Funktionen gebraucht wird.
file_text_close(fileid) Schließt die Datei mit der gegebenen ID.
file_text_write_string(fileid, str) Schreibt einen String in die Datei mit der gegebenen ID.
file_text_write_real(fileid, x) Schreibt eine reelle Zahl in die Datei mit der gegebenen ID.
file_text_writeln(fileid) Schreibt ein "Neue-Zeile"-Zeichen in die Datei mit der gegebenen ID.
file_text_read_string(fileid) Liest einen String aus der Datei mit der gegebenen ID und gibt diesen zurück. Ein String endet am "Neue-Zeile"-Zeichen.
file_text_read_real(fileid) Liest eine reelle Zahl und gibt diese zurück.
file_text_readln(fileid) Überspringt den Rest der Zeile und beginnt in der nächsten.
file_text_eof(fileid) Gibt an, ob wir das Dateiende erreicht haben.

Um Dateien im Dateisystem zu ändern kannst du folgende Funktionen nutzen:

file_exists(fname) Gibt zurück, ob die Datei mit dem angegebenen Namen existiert (true) oder nicht (false).
file_delete(fname) Löscht die Datei mit dem angegebenen Namen.
file_rename(oldname, newname) Benennt die Datei mit dem Namen oldname in newname.
file_copy(fname, newname) Kopiert die Datei namens fname in newname.
directory_exists(dname) Gibt zurück, ob das angegebene Verzeichnis existiert oder nicht.
directory_create(dname) Erstellt ein Verzeichnis mit dem angegebenen Namen (inklusive dem Pfad), falls es nicht existiert.
file_find_first(mask, attr) Gibt den Namen der ersten Datei zurück, die mit der Maske und den Attributen übereinstimmt. Existiert keine solche Datei, wird ein Leerstring zurückgegeben. Die Maske kann einen Pfad und Auslassungszeichen enthalten, z.B. "C:\Temp\*.doc". Die Attribute geben die zusätzlichen Dateien an. (Die normalen Dateien werden also immer zurückgegeben, wenn sie mit der Maske übereinstimmen). Folgende Konstanten können als Attribute verwendet werden:
fa_readonly schreibgeschützte Dateien
fa_hidden versteckte Dateien
fa_sysfile Systemdateien
fa_volumeid Volume-ID Dateien
fa_directory Verzeichnisse
fa_archive archivierte Dateien
file_find_next() Gibt den Namen der nächsten Datei zurück, die mit der vorher angegebenen Maske und den Attributen übereinstimmt. Existiert keine solche Datei, wird ein Leerstring zurückgegeben
file_find_close() Muss nach allen file_find-Funktionen aufgerufen werden, um Speicher freizugeben.
file_attributes(fname, attr) Gibt zurück, ob die Datei alle Attribute hat, die in attr angegeben sind. Benutze Kombinationen der oben angegebenen Konstanten.

Die folgenden Funktionen können genutzt werden um Dateinamen zu verarbeiten. Beachte das sie nicht mit den Dateien sondern nur mit dem Namen arbeiten.

filename_name(fname) Gibt den Namen der Datei mit Erweiterung aber ohne Pfad wieder.
filename_path(fname) Gibt den Pfad der Datei inklusive des finalen Backslashs zurück.
filename_dir(fname) Gibt das Verzeichnis der Datei zurück, welches normalerweise der Pfad ohne den finalen Backslash ist.
filename_drive(fname) Gibt das Laufwerk der Datei zurück.
filename_ext(fname) Gibt die Dateierweiterung wieder, inklusive des Punktes.
filename_change_ext(fname, newext) Gibt den angegebenen Dateinamen, mit der Erweiterung an (inklusive des Punktes), welche zu einer neuen Erweiterung verändert wurde. Indem ein leerer string angegeben wird kann die Erweiterung gelöscht werden.

In seltenen Fällen kann es sein, das du Daten aus einer binären Datei lesen musst. Die folgenden Low-Level-Routinen existieren hierfür:

file_bin_open(fname, mod) Öffnet die Datei mit dem angegebenen Namen. Der Modus gibt an, was mit der Datei getan werden kann: 0 = lesen, 1 = schreiben, 2 = beides). Die Funktion gibt die ID zurück, welche für andere Funktionen benötigt wird. Du kannst mehrere Dateien auf einmal öffnen (maximal 32). Vergesse nicht sie zu schliessen wenn du mit ihnen fertig bist!
file_bin_rewrite(fileid) Schreibt die Datei mit der angegebenen ID neu, d.h. löscht sie und beginnt am Anfang.
file_bin_close(fileid) Schliesst die Datei mit der angegebenen ID.
file_bin_size(fileid) Gibt die Dateigrösse (in Byte) der Datei mit der angegebenen ID wieder.
file_bin_position(fileid) Gibt die aktuelle Position (in Bytes; 0 ist die erste Position) in der angegebenen Datei ID zurück.
file_bin_seek(fileid, pos) Bewegt den Dateizeiger an die neue angegebene Position. Um etwas anzufügen, fahre den Dateizeiger auf den Wert der Dateigröße.
file_bin_write_byte(fileid, byte) Schreibt ein binäres Byte in die Datei mit der ID fileid.
file_bin_read_byte(fileid) Liest ein binäres Byte aus der Datei mit der ID fileid.

Wenn der Spieler in seinen Einstellungen den sicheren Modus aktiviert hat, sind einige dieser Routinen eingeschränkt, es ist dir nicht erlaubt einen Pfad anzugeben, so das nur Dateien im Programmordner geschrieben werden können.

Die folgenden drei nur-lesbaren Variablen können dir nützlich werden:

game_id* Eindeutige ID deines Spieles. Du kannst diese nutzen, um z.B. einen einmaligen Dateinamen zu erstellen.
working_directory* Arbeitsverzeichnis deines Spieles. (ohne den finalen Backslash.)
temp_directory* Temporäres Verzeichnis deines Spieles. Du kannst hier temporär Dateien speichern. Sie werden am Spielende entfernt.

Manchmal möchtest du vielleicht dem Spieler die Möglichkeit geben, dem Spiel Kommandozeilenargumente zu übergeben (z.B. für Cheats oder spezielle Modi). Um diese Argumente zu bekommen, kannst du diese zwei Funktionen verwenden:

parameter_count() Gibt die Anzahl der Kommandozeilenparameter zurück (Achtung: der Name des Programmes ist auch einer davon)
parameter_string(n) Gibt Kommandozeilenparameter n zurück. Der erste Parameter (der Programmname) hat den Index 0.

Du kannst Umgebungsvariablen mit folgender Funktion lesen:

environment_get_variable(name) Gibt den Wert der Umgebungsvariablen mit dem gegebenen Namen zurück (als String).

Registry

Wenn du nur wenige Daten zwischen verschiedenen Spielstarts speichern willst, existiert ein einfacherer Mechanismus als eine Datei zu nutzen. Du kannst die Registry verwenden. Die Registry ist eine große Datenbank, die Windows verwendet, um alle Einstellungen für Programme zu speichern. Ein Eintrag hat einen Namen und einen Wert. Du kannst Strings und Zahlen verwenden. Folgende Funktionen existieren dazu:

registry_write_string(name, str) Erstellt einen Eintrag in der Registry mit dem gegebenen Namen und einem String-Wert.
registry_write_real(name, x) Erstellt einen Eintrag in der Registry mit dem gegebenen Namen und einem Zahlenwert.
registry_read_string(name) Gibt den String zurück, der im Eintrag name steht. (Falls der Eintrag nicht existiert, wird ein Leerstring zurückgegeben)
registry_read_real(name) Gibt den Zahlenwert zurück, der im Eintrag name steht. (Falls der Eintrag nicht existiert, wird 0 zurückgegeben)
registry_exists(name) Gibt zurück, ob der gegebene Name existiert.

Tatsächlich sind die Werte in der Registry in Schlüsseln gruppiert. Die obigen Funktionen arbeiten alle in einem speziellen Schlüssel, der für dein Spiel erstellt wurde. Dein Spiel kann dies verwenden, um bestimmte Informationen während des Verlaufes zu speichern oder zu laden. Du kannst auch Werte aus anderen Schlüsseln lesen. Natürlich kannst du sie auch schreiben, sei damit aber vorsichtig. Du könntest SEHR LEICHT DEIN SYSTEM ZERSTÖREN. (Das Schreiben ist im sicheren Modus nicht gestattet.) Beachte, das die Schlüssel wiederum in Gruppen sortiert sind. Die folgende Routine arbeitet in der Gruppe HKEY_CURRENT_USER. Du kannst aber die Wurzelgruppe ändern. Verwende beispielsweise zum Herausfinden des temporären Verzeichnisses folgenden Aufruf:

  path = registry_read_string_ext('\Environment','TEMP');

Die folgenden Funktionen existieren hierfür.

registry_write_string_ext(key, name, str) Erstellt einen Eintrag im angegebenen Schlüssel mit dem gegebenen Namen und einem String-Wert.
registry_write_real_ext(key, name, x) Erstellt einen Eintrag im angegebenen Schlüssel mit dem gegebenen Namen und einem Zahlenwert.
registry_read_string_ext(key, name) Gibt den String zurück, der Eintrag name im Schlüssel key steht. (Falls der Eintrag nicht existiert, wird ein Leerstring zurückgegeben)
registry_read_real_ext(key, name) Gibt den Zahlenwert zurück, der im Schlüssel key im Eintrag name steht. (Falls der Eintrag nicht existiert, wird 0 zurückgegeben)
registry_exists_ext(key, name) Gibt zurück, ob der gegebene Name im Schlüssel existiert.
registry_set_root(root) Ändert das Stammverzeichnis für die anderen Funktionen. Verwende folgende Werte:
0 = HKEY_CURRENT_USER
1 = HKEY_LOCAL_MACHINE
2 = HKEY_CLASSES_ROOT
3 = HKEY_USERS

INI Dateien

Um bestimmte Programmeinstellungen zu speichern, wird oft eine INI-Datei verwendet. INI-Dateien enthalten verschiedene Bereiche. Jeder Bereich enthält einige Name-Wert-Paare. Eine typische INI-Datei sieht etwa so aus:

[Form]
Top=100
Left=100
Caption=Das beste Spiel aller Zeiten
[Game]
MaxScore=12324

Diese Datei enthält zwei Bereiche: Einen mit Namen "Fenster" und einen Bereich "Spiel". Der erste Bereich enthält drei Paare. Die ersten beiden sind Zahlen, während das dritte ein String ist. S olche INI-Dateien sind einfach zu erstellen und zu verändern. Die folgenden Funktionen existieren im Game Maker, um Daten zu lesen und zu schreiben:

ini_open(name) Öffnet die INI-Datei mit dem gegebenen Namen. Die Datei muss sich im selben Ordner wie das Spiel befinden!
ini_close() Schliesst die aktuell geöffnete INI-Datei.
ini_read_string(section, key, default) Liest den String mit dem Namen key im Bereich section. Existiert der String nicht, wird default zurückgegeben.
ini_read_real(section, key, default) Liest die Zahl mit dem Namen key im Bereich section. Existiert die Zahl nicht, wird default zurückgegeben.
ini_write_string(section, key, value) Schreibt einen String mit dem Namen key in den Bereich section.
ini_write_real(section, key, value) Schreibt eine Zahl mit dem Namen key in den Bereich section.
ini_key_exists(section, key) Gibt zurück, ob der Name key in dem Bereich section existiert.
ini_section_exists(section) Gibt zurück, ob der Bereich section existiert.
ini_key_delete(section, key) Löscht den Schlüssel key aus dem Bereich section.
ini_section_delete(section) Löscht den Bereich section.

Programme ausführen

Game Maker hat auch die Möglichkeit, externe Programme aufzurufen. Es gibt zwei Funktionen dafür: execute_program startet ein Programm, möglicherweise mit Argumenten. Die Funktion kann auf das Programm warten (das Spiel wird unterbrochen) oder nicht. execute_shell öffnet eine Datei. Das kann irgendeine Datei sein, mit der ein Programm verknüpft ist (z.B. ein *.txt- Datei - hier wird Notepad gestartet). Es kann auch eine Datei sein. Die Funktion kann nicht warten, also fährt das Spiel fort.

execute_program(prog, arg, wait) Führt das Programm prog mit den Argumenten arg aus. wait legt fest, ob das Spiel warten soll.
execute_shell(prog, arg) Führt das Programm (oder die Datei) in der Shell aus.

Beide Funktionen funktionieren nicht, wenn "secure mode" in den Voreinstellungen aktiviert ist. Das kannst du mit der folgenden schreibgeschützten Variable überprüfen::

secure_mode* Ob das Spiel im "secure mode" läuft oder nicht.

Data structures - Datenstrukturen

Diese Funktionalität ist nur in der registrierten Version des Game Maker verfügbar.

In Spielen muss man oftmals Informationen speichern. Beispielsweise musst du eine Liste von Dingen speichern, die eine Person mit sich führt oder du willst die Orte speichern, die noch erkundet werden müssen. Du kannst dafür Arrays (Datenfelder) verwenden. Wenn du aber kompliziertere Operationen ausführen willst, wie zum Beispiel Sortieren der Daten oder die Suche nach einem bestimmten Datenfeld, musst du große Teile von GML-Code schreiben, die langsam in der Ausführung sein können.

Um dies zu vermeiden besitzt Game Maker eine Anzahl eingebauter Datenstrukturen, auf die mittels Funktionen zugegriffen werden kann. Zur Zeit sind sechs verschiedene Arten von Datenstrukturen verfügbar: stacks (stapel), queues (Reihen), lists (Listen), maps (Abbildungen), priority queues (vorrangige Reihen) und grids (Gitter). Jede dieser Datenstrukturen wurde für den vorgesehenen Einsatzzweck optimiert (siehe unten).

Alle Datenstrukturen funktionieren vom Prinzip her gleich. Du kannst eine Datenstruktur mit einer Funktion erstellen, welche eine id für die Struktur zurückgibt. Du verwendest diese id, um auf die Struktur zuzugreifen. Wenn du die Struktur nicht mehr benötigst, vernichtest du sie, um Speicherplatz zu sparen. Du kannst soviele Strukturen gleichzeitig verwenden, wie du willst. Alle Strukturen können Zeichenketten (strings) oder reelle Werte (real values) speichern.

Beachte das die Datenstrukturen nicht beim Speichern eines Spieles gespeichert werden. Dazu musst du dann eigene Mechanismen entwickeln.

Beim Vergleichen von Werten, beispielsweise beim Suchen in einer map oder beim Sortieren einer Liste, muss Game Maker entscheiden, wann zwei Werte gleich sind. Für strings und integer values (ganzzahlige Werte) sieht die Sache einfach aus aber bei reellen Zahlen können leicht gleiche Zahlen durch Rundungsfehler verschieden werden. Zum Beispiel: (5/3)*3 wird nicht gleich 5 sein. Um dies zu vermeiden, wird eine Genauigkeit verwendet. Falls der Unterschied zwischen zwei Werten kleiner als diese Genauigkeit ist, werden sie als gleich betrachtet. Voreingestellt ist eine Genauigkeit von 0.0000001. du kannst diese Genauigkeit (precision) verändern durch folgende Funktionen:

ds_set_precision(prec) Setzt die Genauigkeit, die bei Vergleichen zugrunde liegt.

Diese Genauigkeit wird für alle Datenstrukturen verwendet, nicht aber für andere Vergleiche in GML!

Informationen über Datenstrukturen können auf folgenden Seiten gefunden werden:

Stacks
Queues
Lists
Maps
Priority Queues
Grids

Stacks - Stapel

Eine Stapel-Datenstruktur wird auch LIFO ("Last-In First-Out" zuletzt rein - zuerst raus)Struktur genannt. Du kannst Werte auf einen Stapel legen und sie wieder, durch runterziehen vom Stapel, entfernen. Der Wert, welcher als letzter auf den Stapel gelegt wurde, ist auch derjenige, der zuerst wieder entnommen wird. Stacks (Stapel) werden oft verwendet, wenn man "interrupts" (Unterbrechungen) behandelt oder rekursive Funktionen. Die folgenden Funktionen existieren für stacks (Stapel):

ds_stack_create() Erstellt einen neuen stack. Die Funktion liefert eine ganze Zahl als Rückgabewert, welche fortan als id verwendet werden muss, um aus anderen Funktionen auf diesen speziellen stack zugreifen zu können. Du kannst mehrere stacks erstellen.
ds_stack_destroy(id) Vernichtet den stack mit der angegebenen id und gibt den belegten Speicher wieder frei. Vergiss nicht diese Funktion aufzurufen, wenn du die Struktur nicht mehr benötigst.
ds_stack_clear(id) Löscht den stack mit der angegebenen id, d.h. alle Daten werden entfernt, die Struktur bleibt aber erhalten.
ds_stack_size(id) Gibt die Anzahl der im stack abgelegten Werte wieder.
ds_stack_empty(id) Gibt an, ob der stack leer ist. Das ist das gleiche, wie prüfen auf Größe 0.
ds_stack_push(id, val) Legt einen Wert auf den stack.
ds_stack_pop(id) Ermittelt den Wert, der zuoberst auf dem stack liegt und entfernt ihn vom stack.
ds_stack_top(id) Ermittelt den Wert, der zuoberst auf dem stack liegt - ohne ihn zu entfernen.

Queues - Reihen

Ein queue (Reihe) ist sowas ähnliches, wie ein stack (Stapel) aber arbeitet nach dem FIFO (First-In First-Out) Prinzip (Zuerst rein - zuerst raus). Der Wert, der zuerst in den queue gegeben wird, wird auch als erster wieder entnommen. Es funktioniert ähnlich wie eine Warteschlange an der Supermarktkasse. Die Person, die ganz vorne steht, wird zuerst bedient. Queues werden gewöhnlich verwendet, um Dinge zu speichern, die noch bearbeitet werden werden müssen aber es gibt noch viele andere Verwendungszwecke. Die folgenden Funktionen gibt es (Beachte, dass die ersten fünf äquivalent zu den stack-Funktionen sind; alle Datenstrukturen besitzen diese 5 Funktionen).

ds_queue_create() Erstellt eine neue queue. Die Funktion liefert eine ganze Zahl als id zurück, welche fortan verwendet werden muss, um auf aus anderen Funktionen auf diese queue zuzugreifen. Du kannst mehrere queues erstellen.
ds_queue_destroy(id) Vernichtet die queue mit der angegebenen id und gibt den belegten Speicher frei. Vergiss nicht, diese Funktion aufzurufen, wenn du die Struktur nicht mehr benötigst.
ds_queue_clear(id) Löscht die queue mit der angegebenen id. Alle Daten werden daraus entfernt aber die Struktur bleibt erhalten.
ds_queue_size(id) Gibt die Anzahl der gespeicherten Werte wieder, die in der queue gespeichert sind.
ds_queue_empty(id) Gibt an, ob die queue leer ist. Das ist das Gleiche, wie prüfen auf Größe 0.
ds_queue_enqueue(id, val) Schiebt einen Wert in die queue.
ds_queue_dequeue(id) Gibt den Wert an, der am längsten in der queue steht und entfernt ihn daraus.
ds_queue_head(id) Gibt den Wert an, der am Anfang der queue steht, daß ist der Wert, welcher am längsten in der queue ist. > (Der Wert wird nicht enfernt.)
ds_queue_tail(id) Gibt den Wert am Ende der queue wieder, das ist der Wert, der zuletzt hinzugefügt wurde. > (Der Wert wird nicht entfernt.)

Lists - Listen

Eine Liste speichert eine Sammlung von Werten in einer bestimmten Ordnung. Du kannst Werte am Ende anfügen oder irgendwo in der Mitte der Liste einfügen. Du kannst die Werte über einen Index adressieren. Zudem kannst du die Elemente sowohl in absteigender, als auch in aufsteigender Reihenfolge ordnen. Listen können in vielerlei Weise verwendet werden, beispielsweise um eine Gruppe veränderlicher Werte zu speichern. Sie werden durch einfache arrays (Felder) implementiert aber weil dies mit compiliertem Programmcode erfolgt, sind sie um einiges schneller als wenn du selber ein array verwendest. Die folgenden Funktionen stehen zur Verfügung:

ds_list_create() Erstellt eine neue Liste. Die Funktion gibt eine ganze zahl als id wieder, welche fortan verwendet werden muss, um auf diese Liste zugreifen zu können.
ds_list_destroy(id) Vernichtet die Liste mit der angegebenen id und gibt den belegten Speicher wieder frei. Vergiss nicht diese Funktion aufzurufen, wenn du die Struktur nicht mehr benötigst.
ds_list_clear(id) Löscht die Liste mit der angegebenen id - alle Daten werden entfernt aber die Liste nicht vernichtet.
ds_list_size(id) Gibt die Anzahl der in der Liste gespeicherten Werte wieder.
ds_list_empty(id) Gibt an, ob die Liste leer ist. Das ist dasgleiche, wie prüfen auf Größe 0.
ds_list_add(id, val) Fügt einen Wert ans Ende der Liste an.
ds_list_insert(id, pos, val) Fügt einen Wert an der Position "pos" der Liste ein. Die erste Position ist Position 0, die letzte "size-1".
ds_list_replace(id, pos, val) Ersetzt den Wert an Position "pos" in der Liste durch den neuen Wert (val).
ds_list_delete(id, pos) Entfernt den Wert an Position "pos" aus der Liste. (Position 0 ist das erste Element.)
ds_list_find_index(id, val) Finde die Position, die den angegebenen Wert beinhaltet. Falls der Wert nicht vorhanden ist, > wird -1 zurückgegeben.
ds_list_find_value(id, pos) Gibt an, ob der Wert an der angegebenen Position in der Liste gespeichert ist.
ds_list_sort(id, ascend) Sortiert die Werte in der Liste. Wenn "ascend" "true" ist, in aufsteigender Reihenfolge, > ansonsten in absteigender.

Maps - Abbildungen

In ziemlich vielen Situationen musst du Pärchen, bestehend aus einem Schlüssel und einem Wert, speichern. Zum Beispiel kann ein Charakter eine Anzahl verschiedener Dinge besitzen und eine bestimmte Anzahl dieser Dinge. In so einem Fall ist das Ding der Schlüssel (key) und die Zahl der Wert (value). Abbildungen verwalten solche Pärchen - sortiert nach keys (Schlüsseln). Du kannst Pärchen zur Abbildung hinzufügen und nach Werten suchen, die bestimmten Schlüsseln entsprechen. Weil die Schlüssel sortiert sind, kannst auch die vorhergehenden und die darauffolgenden Schlüssel finden. Manchmal ist es auch nützlich eine map (Abbildung) zu verwenden, um einfach nur Schlüssel abzulegen - ohne einen korrespondieren Wert. In so einem Fall, verwende einfach einen Wert von 0. Die folgenden Funktionen gibt es:

ds_map_create() Erstellt eine neue map (Abblidung). Die Funktion gibt eine ganzzahlige id wieder, welche in anderen Funktion verwendet werden muss, um auf diese map zuzugreifen.
ds_map_destroy(id) Vernichtet die map mit der angegebenen id und gibt den belegten Speicher wieder frei. Vergiss nicht diese Funktion aufzurufen, wenn du die Struktur nicht mehr brauchst.
ds_map_clear(id) Löscht die map mit der angegebenen id und entfernt alle Daten daraus aber vernichtet die map nicht.
ds_map_size(id) Liefert die Anzahl der Schlüssel-Wert-Pärchen, die in der map gespeichert sind.
ds_map_empty(id) Gibt an, ob die map leer ist. Das ist das Gleiche, wie zu testen, ob die Größe 0 ist.
ds_map_add(id, key, val) Fügt ein key-value pair (Schlüssel-Wert-Paar) zu der map hinzu.
ds_map_replace(id, key, val) Ersetzt den Wert entsprechend dem Schlüssel durch einen neuen Wert.
ds_map_delete(id, key) Löscht den Schlüssel und dazugehörenden Wert aus der map. (Falls mehrere Einträge mit dem gleichen Schlüssel vorhanden sind, wird nur einer gelöscht.)
ds_map_exists(id, key) Gibt an, ob der Schlüssel in der map vorhanden ist.
ds_map_find_value(id, key) Liefert den Wert entsprechend des angegebenen Schlüssels.
ds_map_find_previous(id, key) Liefert den größten Schlüssel in der map, der noch kleiner als der angegebene Schlüssel ist. (Beachte, dass der Schlüssel wiedergegeben wird, nicht der Wert. Du kannst die vorherige Funktion verwenden, um den Wert zu ermitteln.)
ds_map_find_next(id, key) Liefert den kleinsten Schlüssel in der map, der noch größer als der angegebene Schlüssel ist.
ds_map_find_first(id) Liefert den kleinsten Schlüssel der map.
ds_map_find_last(id) Liefert den größten Schlüssel der map.

Vorrangige Listen/Reihen

In einer vorrangigen Reihe/Liste werden eine Anzahl von Werten gespeichert, jeder mit einer Priorität. Du kannst die Werte mit der höchsten und niedrigsten Priorität ermitteln. Durch das Verwenden dieser Datenstruktur kannst du bestimmte Dinge, nach ihrer Wichtigkeit geordnet bearbeiten. Folgende Funktionen existieren:

ds_priority_create() Erstellt eine neue "priority queue". Die Funktion gibt einen ganzzahligen Wert wieder, der als id fungiert, welche in allen anderen Funktionen verwendet werden muss, um auf diese bestimmte "priority queue" zugreifen zu können.
ds_priority_destroy(id) Vernichtet die "priority queue" mit der angegebenen id; dabei wird der belegte Speicher freigegeben. Vergiss nicht diese Funktion aufzurufen, wenn die Struktur nicht mehr brauchst.
ds_priority_clear(id) Löscht die "priority queue" mit der angegebenen id; dabei werden alle Daten gelöscht aber nicht die "priority queue" selber vernichtet.
ds_priority_size(id) Gibt die Anzahl der Werte wieder, die in der "priority queue" gespeichert sind.
ds_priority_empty(id) Gibt wieder, ob die "priority queue" leer ist. Dies ist dasgleiche wie testen, ob die Größe 0 ist.
ds_priority_add(id, val, prio) Fügt einen Wert mit der gegebenen Priorität zur "priority queue" hinzu.
ds_priority_change_priority(id, val, prio) Ändert die Prioriät des angegebenen Wertes in der "priority queue".
ds_priority_find_priority(id, val) Gibt die Priorität des angegebenen Wertes in der "priority queue" wieder.
ds_priority_delete_value(id, val) Löscht den angegeben Wert (mit seiner Priorität) aus der "priority queue".
ds_priority_delete_min(id) Gibt den Wert mit der kleinsten Priorität wieder und löscht diesen aus der "priority queue".
ds_priority_find_min(id) Gibt den Wert mit der kleinsten Priorität wieder aber löscht diesen nicht aus der "priority queue".
ds_priority_delete_max(id) Gibt den Wert mit der größten Priorität wieder und löscht diesen aus der "priority queue".
ds_priority_find_max(id) Gibt den Wert mit der größten Priorität wieder aber löscht diesen nicht aus der "priority queue".

Raster

Ein Raster ist ein einfaches zweidimensionales Array. Ein Raster hat eine Breite und eine Höhe. Die Struktur erlaubt es Zellen im Raster mit Werten zu befüllen und diese wieder auszulesen, indem deren Index angegeben wird (Welcher bei x und y bei 0 anfängt. Du kannst aber auch den Wert von Gebieten angeben, Werte hinzufügen und die Summe, das Maximum, das Minimun und den Durchschnitt eines Gebietes auslesen. Die Struktur ist nützlich um beispielsweise ein Spielfeld darzustellen. Auch wenn alle Funktionen auch über ein zweidimensionales Array gelöst werden können ist es dennoch besser das Raster zu nehmen, da es sehr viel schneller ist. Die folgenden Funktionen existieren:

ds_grid_create(w, h) Erstellt ein neues Raster mit der angegebenen Höhe und Breite. Die Funktion gibt eine ID als Zahl zurück, die in allen anderen Funktionen angegeben werden muss.
ds_grid_destroy(id) Vernichtet das Raster mit der angegebenen id; dabei wird der belegte Speicher freigegeben. Vergiss nicht diese Funktion aufzurufen, wenn die Struktur nicht mehr brauchst.
ds_grid_resize(id, w, h) Ändert die Rastergröße auf w und h. Bestehende Zelle behalten ihren Wert.
ds_grid_width(id) Gibt die Breite des angegebenen Rasters zurück.
ds_grid_height(id) Die die Höhe des angegegebenen Rasters zurück.
ds_grid_clear(id, val) Leert das angegebene Raster mit dem Wert (kann eine Zahl oder ein String sein).
ds_grid_set(id, x, y, val) Setzt den wert der angegebenen Zelle (kann eine Zahl oder ein String sein)
ds_grid_add(id, x, y, val) Fügt den angegebenen Wert dem Raster hinzu.
ds_grid_multiply(id, x, y, val) Multipliziert den Wert der angegebenen Zelle mit Val. Nur für Zahlen gültig.
ds_grid_set_region(id, x1, y1, x2, y2, val) Setzt alle Zellen des angegebenen Bereiches auf einen Wert (kann eine Zahl oder ein String sein).
ds_grid_add_region(id, x1, y1, x2, y2, val) Fügt den angegebenen Wert in den Bereich des Rasters hinzu.
ds_grid_multiply_region(id, x1, y1, x2, y2, val) Multipliziert die Werte der angegebenen Zellen mit val. Nur für Zahlen gültig.
ds_grid_set_disk(id, xm, ym, r, val) Setzt die Werte aller Zellen im Kreis mit Mittelpunkt (xm,ym) und Radius r.
ds_grid_add_disk(id, xm, ym, r, val) Fügt val allen Werten des Kreises mit Mittelpunk (xm,ym) und Radius r hinzu.
ds_grid_multiply_disk(id, xm, ym, r, val) Multipliziert die Werte des Kreises mit Mittelpunkt (xm,ym) und Radius r mit val.
ds_grid_get(id, x, y) Gibt den Wert der angegebenen Zelle im Raster id zurück.
ds_grid_get_sum(id, x1, y1, x2, y2) Gibt die Summe der Werte in der angegeben Region zurück. Funktioniert nur mit Zahlen.
ds_grid_get_max(id, x1, y1, x2, y2) Gibt den Maximalwert der Zellen in der angegeben Region zurück. Funktioniert nur mit Zahlen.
ds_grid_get_min(id, x1, y1, x2, y2) Gibt den Minimalwert der Zellen in der angegeben Region zurück. Funktioniert nur mit Zahlen.
ds_grid_get_mean(id, x1, y1, x2, y2) Gibt den Durschnittswert der Zellen in der angegeben Region zurück. Funktioniert nur mit Zahlen.
ds_grid_get_disk_sum(id, xm, ym, r) Gibt die Summe der Werte der Zellen im Kreis zurück.
ds_grid_get_disk_min(id, xm, ym, r) Gibt den Minimalwert der Zellen im Kreis zurück.
ds_grid_get_disk_max(id, xm, ym, r) Gibt den Maximalwert der Zellen im Kreis zurück.
ds_grid_get_disk_mean(id, xm, ym, r) Gibt den Durchschnittswert der Zellen im Kreis zurück.
ds_grid_value_exists(id, x1, y1, x2, y2, val) Gibt an ob der Wert in der Region existiert.
ds_grid_value_x(id, x1, y1, x2, y2, val) Gibt die x-Koordinate der Zelle an, in der der Wert existiert.
ds_grid_value_y(id, x1, y1, x2, y2, val) Gibt die y-Koordinate der Zelle an, in der der Wert existiert.
ds_grid_value_disk_exists(id, xm, ym, r, val) Gibt an ob der Wert im Kreis existiert.
ds_grid_value_disk_x(id, xm, ym, r, val) Gibt die x-Koordinate der Zelle an, in der der Wert existiert.
ds_grid_value_disk_y(id, xm, ym, r, val) Gibt die y-Koordinate der Zelle an, in der der Wert existiert.

Partikel erstellen

Diese Funktionen sind nur in der registrierten Version des Game Maker verfügbar.

Partikelsysteme sind für das Erstellen von Spezialeffekten geeignet. Partikeln sind kleine Elemente (repräsentiert von einem kleinen Sprite, einem Pixel oder einer kleinen Form). Solche Partikeln bewegen sich herum, sie befolgen vorher bestimmte Regeln und können die Farbe, während sie sich bewegen, ändern. Viele solcher Partikel untereinander können z.B. ein Feuerwerk, Regen,Schnee, Sternenfelder, fliegende Trümmer, usw. erzeugen.

Game Maker beinhaltet ein umfassendes Partikelsystem, das zum Erstellen von großartigen Effekten benutzt werden kann. Es ist wirklich nicht einfach zu benutzen, deshalb lies vorher dieses Kapitel sorgfältig durch. Ein Partikelsystem hat viele Parameter und es ist nicht immer einfach zu verstehen, wie der gewünschte Effekt erreicht werden kann.

Erstens gibt es die Partikeltypen. Ein Partikeltyp definiert einen besonderen Teil des Partikels. Solche Typen haben viele Parameter die die Form, Größe, Farbe und Bewegung des Partikels beschreiben.

Zweitens gibt es Partikelsysteme. Es können verschiedene Partikelsysteme im Spiel existieren. Ein Partikelsystem kann Partikel verschiedener Typen haben. Ein Partikelsystem hat "Emitter", die Partikel erstellen, entweder kontinuierlich oder in Salven. Es kann auch "Attractors" haben die Partikel anziehen. Zuletzt gibt es "Destroyers" die Partikel zerstören. Wenn Partikel einmal im System erstellt wurden werden sie automatisch durch das System verarbeitet (aktualisiert und gezeichnet).

Informationen über Partikel können auf den folgenden Seiten gefunden werden:

Einfache Effekte
Partikeltypen
Partikelsysteme
Emitters
Attractors
Destroyers
Deflectors
Changers
Beispiel: Feuerwerk

Einfache Effekte

Der einfachste Weg das Partikelsystem zur Nutzen führt zu den Effekten. Effekte werden über das Partikelsystem geregelt aber du musst dich nicht um Details kümmern. Du gibst einfach nur den Effekt, die Stelle an der er sein soll, seine Größe und seine Farbe an. Das ist alles.

Es gibt einige verschiedene Effekte:

  • ef_explosion
  • ef_ring
  • ef_ellipse
  • ef_firework
  • ef_smoke
  • ef_smokeup
  • ef_star
  • ef_spark
  • ef_flare
  • ef_cloud
  • ef_rain
  • ef_snow

Einige werden meist nur in eine Step erzeugt (wie die Explosion) und andere in jedem Step (wie der Rauch oder der Regen). Beachte hierbei das Regen und Schnee immer am oberen Rand des Bildschirms erzeugt werden, egal was eingegeben wurde.

Auch wenn das jetzt sehr eingeschränkt aussieht kann es dennoch gute Effekte erzeugen. Beispielsweise indem man ein kleines Wölkchen roten Rauches jeden Schritt unter einem Raumschriff erzeugt, sieht es aus wie ein kleiner Brand. Die folgenden 2 Funktionen für Effekte existieren:

effect_create_below(kind, x, y, size, color) Erstellt den angegeben Effekt (siehe oben) an der angegeben Position. Die Größe ist folgendermaßen zu verstehen: 0 = klein, 1 = normal, 2 = groß. color gibt die zu verwendende Farbe an. Der Effekt wird unter den Instanzen erzeugt, in einer Depth von 100000.
effect_create_above(kind, x, y, size, color) Dasselebe wie vorher, diesmal aber mit einer Tiefe von -100000.

Wenn du alle Effekte loswerden willst rufe folgende Funktion auf:

effect_clear() Entfernt alle Effekte.

Partikeltypen

Ein Partikeltyp beschreibt die Form, Farbe und Bewegung einer bestimmten Art eines Partikels. Du musst einen Partikeltyp nur zu Beginn des Spieles erstellen. Danach kann er in jedem Partikelsystem des Spieles verwandt werden. Partikeltypen haben eine große Zahl an Parametern um alle Einstellungen ändern zu können. Indem diese korrekt eingestellt werden kann man nahezu alle Arten von Effekten erzeugen. Wir diskutieren diese Einstellungen nun.

Es gibt folgende Routinen um sie zu erstellen und zu zerstören:

part_type_create() Erstellt einen neuen Partikeltyp. Die Funktion gibt den Index des Typs zurück. Dieser Index muss in alle Aufrufen benutzt werden, um die Eigenschaften des Partikeltyps zu setzen.
part_type_destroy(ind) Zerstört den Partikeltyp ind. Rufe diese Funktion auf wenn du es nicht mehr brauchst um Platz zu sparen.
part_type_destroy_all() Zerstört alle Partikeltypen die erstellt wurden.
part_type_exists(ind) Gibt zurück, ob der angegebene Partikeltyp existiert.
part_type_clear(ind) etzt den Partikeltyp ind auf seine voreingestellten Einstellungen zurück.

Die Partikelform

Ein Partikel hat eine Form. Diese Form wird durch ein Sprite bestimmt. Du kannst jedes Sprite benutzen, und es gibt 15 eingebaute Sprites. Diese sind alle 64x64 Pixel groß und haben Alphawerte, sodass sie sehr schön in den Hintergrund übergehen. Sie werden durch die folgenden Konstanten bestimmt:
  • pt_shape_pixel
  • pt_shape_disk
  • pt_shape_square
  • pt_shape_line
  • pt_shape_star
  • pt_shape_circle
  • pt_shape_ring
  • pt_shape_sphere
  • pt_shape_flare
  • pt_shape_spark
  • pt_shape_explosion
  • pt_shape_cloud
  • pt_shape_smoke
  • pt_shape_snow

Mit der folgenden Funktion kannst du die Form einstellen:

part_type_shape(ind, shape) Setzt die Form auf eine der oben angegebenen Konstanten (standardmäßig pt_shape_pixel).

Du kannst auch ein eigenes Sprite als Partikel benutzen. Sollte das Sprite noch mehrere Subimages besitzen kannst du angeben wie mit ihnen verfahren werden soll. Du kannst zufällig eines auswählen, das Sprite animieren, am Anfang oder an einer zufälligen Stelle der Animation starten usw. Hierfür kannst du die folgende Funktion benutzen.

part_type_sprite(ind, sprite, animat, stretch, random) Stellt dein eigenes Sprite für den Partikeltypen ein. Mit animate gibst du an ob das Sprite animiert werden soll (1) oder nicht (0). Mit stretch (1 oder 0) gibst du an, ob die Animation über die Lebenszeit des Partikels gestreckt werden soll. Und mit random (1 oder 0) Kannst du festlegen ob ein zufälliges Subimage zum starten verwandt werden soll.

Wenn du das Sprite für den Partikeltyp gewählt hast (entweder eine Standardform oder deine eigene) kannst du dessen Größe angeben. Eine Größe von 1 ist die normale Größe des Sprites. Ein Partikeltyp kann so definiert sein das alle Partikel dieselbe Größe oder unterschiedliche Größen besitzen. Du kannst den Raum der möglichen Größen bestimmen. Du kannst auch festlegen, ob die Größe sich über die Lebenszeit verändert und ob ob die Größe etwas hin und her wandert, was dem Partikel einen Blinkeffekt verleiht.

part_type_size(ind, size_min, size_max, size_incr, size_wiggle) Setzt die Größenparameter des Partikels. Du gibst die minimalste Startgröße, die maximalste Startgröße, den Größenzuwachs in jeden Step (nutze eine negative Zahl um ihn zu schrumpfen) und die Menge an "wackelnder" Größenänderung an. (Die Standardgröße ist 1 und normalerweise ändert sich die Größe nicht.)
part_type_scale(ind, xscale, yscale) Stellt die horizontale und vertikale Saklierung ein. Dieser Faktor wird mit der Größe multipliziert. Es ist sehr nützlich wenn du die Skalierung in die x- und y-Richtung unterschiedlich einstellen willst.

Die Partikel haben auch eine Ausrichtung. Wiederum kann die Ausrichtung für alle Partikel gleich , unterschiedlich und über die Lebenszeit veränderlich sein. Die Winkel geben die Richtung gegen den Uhrzeigersinn an, in Grad gemessen.

part_type_orientation(ind, ang_min, ang_max, ang_incr, ang_wiggle, ang_relative) Stellt die Ausrichtungseigenschaften für den Partikeltypen ein. Die gibts die minimale Ausrichtung, die maximale Ausrichtung, die Änderung in jedem Step und das "Wackeln" pro Winkel an. (Standardwerte sind 0.) Du kannst auch festlegen ob die Werte relativ (1) oder absolut (0) zur aktuellen Bewegungsrichtung sind. Z.B. indem man alle Werte auf 0, aber qng_relative auf 1 setzt, wird die Partikelausrichtung exakt der Bewegungsrichtung des Partikels folgen.

Farbe und Farbmischung

Die Partikel werden eine Farbe haben. Es gibt verschiedene Möglichkeiten die Farbe eines Partikels einzustellen. Der einfachste Weg ist eine einfache Farbe einzustellen. Du kannst auch zwei oder drei Farben angeben, zwischen denen der Partikel dann auf seiner Lebenszeit interpoliert wird. Beispielsweise kann der Partikel weiß starten und mit der Zeit immer schwärzer werden. Eine andere Möglichkeit ist es das du einstellst, dass alle Partikel andere Farben besitzen sollen, ausgewählt aus einem vorgegebenen Farbraum. Du kannst einen Bereich entweder in Rot, Grün und Blau, oder in Farbton, Sättigung und Wert angeben.

Die Standardfarbe ist weiß. Wenn du ein Sprite mit eigenen Farben nutzt willst du normalerweise auch diese sehen, also muss keine Farbe eingestellt werden.

part_type_color1(ind, color1) Gibt eine einfache Farbe an, die der Partikel benutzen soll.
part_type_color2(ind, color1, color2) Gibt zwei Farben an, zwischen denen der Partikel interpoliert.
part_type_color3(ind, color1, color2, color3) Dasselbe, aber diesmal mit drei Farben die die Farben beim Start, in der Mitte und am Ende repräsentieren.
part_type_color_mix(ind, color1, color2) Mit dieser Funktion kannst du den Partikel anweisen, eine zufällige Mixtur zwischen den beiden Farben anzunehmen. Diese Farbe bleibt während des Lebens des Partikels gleich.
part_type_color_rgb(ind, rmin, rmax, gmin, gmax, bmin, bmax) Kann genutzt werden um einzustellen, das jeder Partikel einen festen Farbwert hat, der aber aus einem Farbraum kommen soll. Du gibst den Bereich mit Rot-, Grün- und Blaukomponente der Farbe an (jede zwischen 0 und 255).
part_type_color_hsv(ind, hmin, hmax, smin, smax, vmin, vmax) Kann genutzt werden um einzustellen, das jeder Partikel einen festen Farbwert hat, der aber aus einem Farbraum kommen soll. Du gibst den Bereich mit Farbton-, Sättigungs- und Wertkomponente der Farbe an (jede zwischen 0 und 255).

Daneben kannst du auch einen Alphawert festlegen. Die eingebauten Partikelformen haben schon etwas Alphatransparenz, aber du kannst dies dazu nutzen um einen Partikel über eine Zeit hinweg verschwinden zu lassen.

part_type_alpha1(ind, alpha1) Stellt einen einfachen Alphawert (0-1) für den Partikeltyp ein.
part_type_alpha2(ind, alpha1, alpha2) Dasselbe, aber diesmal mit Start- und Endwert, dazwischen wird interpoliert.
part_type_alpha3(ind, alpha1, alpha2, alpha3) Diesmal drei Werte, aus denen die Transparenz interpoliert wird.

Normalerweise werden Partikel wie Sprites auf den Hintergrund gemischt. Aber du kannst auch additives Mischen benutzen. Die gibt den Explosionen z.B. den letzten Schliff.

part_type_blend(ind, additive) Stellt ein ob additives (1) oder normales (0) Mischen angewandt wird.

Leben und Tod

Partikel existieren nur eine begrenzte Zeit lang, ihre Lebenszeit. Danach verschwinden sind. Die Lebenszeit wird in Steps gemessen. Du kannst die Lebenszeit (oder einen Bereich von Lebenszeiten) für jeden Partikeltyp bestimmen. Partikel können neue Partikel eines anderen Typs erzeugen. Es gibt hierfür zwei Möglichkeiten. Sie können in jedem Step oder beim Tod neue Partikel erzeugen. Sei aber behutsam, die Gesamtzahl an Partikeln das nicht zu hoch werden.

part_type_life(ind, life_min, life_max) Setzt die Lebenszeitgrenzen des Partikels. (Standardmäßig beide 100.)
part_type_step(ind, step_number, step_type) Setzt die Zahl und den Typ des Partikels, der in jedem Step von dem angegebenen Partikel erzeugt wird. Wenn du einen negativen Wert angibst, wird in jeden Step ein Partikel mit der Chance von -1/Wert erzeugt. So ergibt beispielsweise ein Wert von -5 durchschnittlich alle 5 Steps einen Partikel.
part_type_death(ind, death_number, death_type) Setzt die Zahl und den Typ des Partikels, der generiert wird, wenn der angegebene Partikel stirbt. Auch hier können negative Werte verwendet werden. Beachte, das der Partikel nur am Ende seiner Lebenszeit andere Partikel erzeugt, nicht bei Berührung eines Destroyers (siehe unten).

Partikelbewegung

Partikel können sich während ihrer Lebenszeit bewegen. Sie haben eine Anfangsgeschwindigkeit (oder einen Bereich) und eine Richtung, beide können sich während der Lebenszeit ändern. Auch kann die Gravitation, die einen Partikel in eine bestimmte Richtung zieht, gewählt werden.Die folgenden Funktionen existieren hierfür:

part_type_speed(ind, speed_min, speed_max, speed_incr, speed_wiggle) Setzt die Geschwindigkeitseigenschaften eines Partikeltyps. (Standardmäßig sind alle Werte 0.) Du gibst eine minimale und eine maximale Geschwindigkeit an. Ein zufälliger Wert zwischen diesen Grenzen wird dann gewählt, wenn der Partikel erzeugt wird. Du kannst einen Geschwindigkeitszuwachs in jedem Step einstellen. Negative Werte bremsen den Partikel (die Geschwindigkeit fällt aber nie unter 0). Schließlich kannst du etwas "Wackelgeschwindigkeit" angeben.
part_type_direction(ind, dir_min, dir_max, dir_incr, dir_wiggle) Setzt die Richtungseinstellungen des Partikels. (Standardmäßig sind alle Werte 0.) Wiederum gibst du hier einen Bereich an (gegen den Uhrzeigersinn in Grad; 0 ist eine Bewegung nach rechts). Um beispielsweise einen Partikel in eine zufällige Richtung zu bewegen wähle 0 und 360 als Werte. Du kannst einen Richtungszuwachs für jeden Step angeben, und eine "Wackelrichtung".
part_type_gravity(ind, grav_amount, grav_dir) Setzt die Gravitationseigenschaften. (Standardmäßig gibt es keine Gravitation.) Du gibst den Wert der Gravitation an, der in jedem Step hinzugefügt wird, und die Richtung. Z.B. 270 für eine Abwärtsbewegung.

Partikelsysteme

Partikel leben in Partikelsystemen. Um also Partikel in deinem Spiel zu haben, musst du ein oder mehrere Partikelsysteme erstellen. Es können verschiedene Partikelsysteme sein. Beispielsweise, wenn dein Spiele einige Bälle hat und jeder Ball soll einen Schweif Partikel haben, hat jeder Ball sein eigenes Partikelsystem. Der einfachste Weg mit Partikelsystemen umzugehen ist, zuerst eines zu erstellen und dann die Partikel darin zu erstellen, und die vorher angegeben Partikeltypen zu verwenden. Aber wie wir später sehen werden, können Partikelsysteme Emitters enthalten, welche automatisch Partikeln produzieren, Attractors die sie anziehen und Destroyers die sie zerstören.

Wenn einem Partikelsystem Partikel hinzugefügt wurden werden diese automatisch aktualisiert und in jedem Step gezeichnet. Es ist keine weitere Aktion nötig. Um es möglich zu machen, das Partikel hinter, vor oder zwischen Instanzen gezeichnet werden können hat jeder Partikel eine Tiefe, ähnlich wie die Instanzen und Tiles.

Partikelsysteme leben nach ihrer Erstellung ewig. Auch wenn du den Raum wechselst oder das Spiel neu startest, die Systeme und Partikel bleiben. Stelle also wirklich sicher, das du sie zerstörst wenn du sich nicht mehr brauchst.

Die folgenden Funktionen arbeiten mit Partikelsystemen:

part_system_create() Erstellt ein neues Partikelsystem. Es gibt den Index des Typs zurück. Der Index muss in jedem Aufruf darunter verwendet werden um die Eigenschaften des Partikelsystem zu setzen.
part_system_destroy(ind) Zerstört das Partikelsystem ind. Rufe die Funktion auf, wenn du das System nicht mehr brauchst, um Speicher zu sparen.
part_system_exists(ind) Gibt zurück ob das angegebene Partikelsystem existiert.
part_system_clear(ind) Setzt das Partikelsystem ind auf seine voreingestellten Einstellungen zurück, zerstört alle Partikel, Emitters und Attractors darin.
part_system_draw_order(ind, oldtonew) Setzt die Reihenfolge in welcher das Partikelsystem die Partikels zeichnet. Wenn oldtonew true ist, werden die ältesten Partikel zuerst gezeichnet und die neuen liegen über ihnen (voreingestellt). Sonst werden die neuen Partikel zuerst gezeichnet. Das kann einen anderen Effekt ergeben.
part_system_depth(ind, depth) Setzt die Depth des Partikels. Diese kann genutzt werden, um Partikel hinter, vor oder zwischen Instanzen zu zeichnen.
part_system_position(ind, x, y) Setzt die Position an der ein Partikel gezeichnet wird. Dies ist normalerweise nicht nötig, aber wenn die Partikel z.b. relativ zu einem sich bewegenden Objekt sein sollen ist dies nützlich.

Wie oben schon gesagt, wird das Partikelsystem automatisch aktualisiert und gezeichnet. Aber manchmal ist es nicht das, was du möchtest. Um dies zu umgehen kannst du das automatische Zeichnen/Aktualisierung abstellen und selber entscheiden wann du dies tun möchtest. Hierfür existieren folgende Funktionen:

part_system_automatic_update(ind, automatic) Gibt an ob der Partikeltyp automatisch (1) oder manuell (0) aktualisiert wird. Standart ist 1.
part_system_automatic_draw(ind, automatic) Gibt an ob der Partikeltyp automatisch (1) oder manuell (0) gezeichnet wird. Standart ist 1.
part_system_update(ind) Diese Funktion aktualisier alle Partikel des Systemes und löst die Emitter aus. Du musst dies nur ausführen wenn nicht automatisch aktualisiert wird. (Auch wenns manchmal nützlich ist dies ein paar mal aufzurufen um Schwung in das System zu kommen.)
part_system_drawit(ind) Diese Funktion zeichnet die Partikel des Systemes. Du musst dies nur ausführen wenn nicht automatisch gezeichnet wird. Es sollte im Draw Event eines Objektes ausgeführt werden.

Die folgenden Funktion arbeiten mit Partikel des Partikelsystems:

part_particles_create(ind, x, y, parttype, number) Diese Funktion erstellt eine Anzahl von Partikel des angegeben Types auf Position (x,y) im System.
part_particles_create_color(ind, x, y, parttype, color, number) Diese Funktion erstellt die Zahl number an Partikeln an der Position (x,y) im System mit der angegebenen Farbe. Dies ist nur nützlich wenn der Partikeltyp nur eine Farbe (oder gar keine) hat.
part_particles_clear(ind) Diese Funktion zerstört alle Partikel im System.
part_particles_count(ind) Diese Funktion gibt die Anzahl der Partikel im System zurück.

Emitters

Emitter erstellen Partikel. Sie können entweder ein kontinuierlichen Strom von Partikeln oder können eine Anzahl von Partikel herausstossen, wenn die jeweilige Funktion aufgerufen wird. Ein Partikelsystem kann eine beliebige Anzahl an Emitters haben. Ein Emitter hat folgende Eigenschaften:
  • xmin, xmax, ymin, ymax Die Ausdehnung der Region, in der die Partikel erstellt werden.
  • shape Die Form der Region. Es kann folgende Werte haben:
    • ps_shape_rectangle
    • ps_shape_ellipse
    • ps_shape_diamond
    • ps_shape_line
  • distribution Die benutze Verteilung zum Generieren der Partikel. Es kann folgende Werte haben:
    • ps_distr_linear Lineare Verteilung, es ist überall in der Region gleichviel möglich.
    • ps_distr_gaussian Gauss-Verteilung, es werden mehr Partikel in der Mitte als auf der Seite der Region verteilt.
  • particle type Der Typ der erstellten Partikel
  • number Die Anzahl der Partikel, die in jedem Schritt erzeugt werden. Wenn dieser Wert kleiner als 0 ist, wird jedem Schritt ein Partikel mit der Chance -1/number erzeugt. Beispielsweise ein Wert von -5 erzeugt durchschnittlich einen Partikel in jedem fünften Schritt.

Die folgenden Funktionen sind verfügbar, um Emitter zu setzen und diese Partikel erstellen zu lassen. Bedenke, dass jede davon den Index des Partikelssystems bekommt welcher als erstes Argument übergeben werden muss.

part_emitter_create(ps) Erstellt einen neuen Emitter im angegebenen Partikelsystem. Die Funktion gibt den Index des Typs zurück. Dieser Index muss in allen Aufrufen unten verwendet werden um die Eigenschaften des Emitters zu setzen.
part_emitter_destroy(ps, ind) Zerstört den Emitter ind im Partikelsystem. Rufe die Funktion auf wenn du Speicher sparen willst.
part_emitter_destroy_all(ps) Zerstört alle Emitters im Partikelsystem die erstellt wurden.
part_emitter_exists(ps, ind) Existiert der angegebene Emitter im Partikelsystem oder nicht.
part_emitter_clear(ps, ind) Setzt den Emitter ind auf seine Voreinstellungen zurück.
part_emitter_region(ps, ind, xmin, xmax, ymin, ymax, shape, distribution) Setzt die Region und Verteilung des Emitters.
part_emitter_burst(ps, ind, parttype, number) Stösst eine Anzahl von Partikeln des angegebenen Typs vom Emitter hinaus.
part_emitter_stream(ps, ind, parttype, number) Von diesem Moment an werden number Partikel des gegebenen Typs in jedem Schritt von dem Emitter erzeugt. Wenn kleiner als 0, wird jedem Schritt ein Partikel mit der Chance -1/number erzeugt. Beispielsweise ein Wert von -5 erzeugt durchschnittlich einen Partikel in jedem fünften Schritt.

Attractors

Neben Emitters kann ein Partikelsystem auch Attractors enthalten. Ein Attractor zieht die Partikel an (oder drückt sie weg). Ein Partikelsystem kann beliebig viele Attractors haben. Es wird empfohlen nur wenige davon zu benutzen, weil sie den Vorgang verlangsamen. Ein Attractor hat folgende Eigenschaften:
  • x, y Die Position des Attractor.
  • force Die Anziehungskraft des Attractor. Wie die Kraft wirkt, hängt von den folgenden Parametern ab.
  • dist Die maximale Entfernung, wo der Attractor noch einen Effekt hat. Nur Partikel, die näher als diese Entfernung sind, werden angezogen.
  • kind Die Art des Attractor. Die folgenden Werte existieren:
    • ps_force_constant Die Kraft ist konstant und unabhängig von der Entfernung.
    • ps_force_linear Die Kraft steig linear an. Bei der maximalen Entfernung ist die Kraft 0, während auf der Position des Attractor der gegebene Wert erreicht wird.
    • ps_force_quadratic Die Kraft wächst quadratisch.
  • additive Wird die Kraft zur Geschwindigkeit und Richtung in jedem Schritt (true) addiert oder nur der Position des Partikels (false) hinzugefügt. Wenn dieser Wert gesetzt ist, beschleunigt das Partikel zum Attractor, während es sich sonst mit konstanter Geschwindigkeit bewegt.

Die folgenden Funktionen existieren um Attractors zu definieren. Bedenke, dass jede den Index des Partikelsystems bekommen welches als erstes Argument übergeben werden muss:

part_attractor_create(ps) Erstellt einen neuen Attractor im angegebenen Partikelsystems. Es gibt den Index des Typs zurück. Der Index muss in allen Aufrufen zum Setzen der Eigenschaften des Attractors angegeben werden.
part_attractor_destroy(ps, ind) Zerstört den Attractor ind im Partikelsystem. Wenn du ihn nicht mehr brauchst, rufe das auf um Speicher zu sparen.
part_attractor_destroy_all(ps) Zerstört alle Attractor im Partikelsystem welche erstellt wurden.
part_attractor_exists(ps, ind) Gibt zurück, ob der den angegebene Attractor im Partikelsystem existiert.
part_attractor_clear(ps, ind) Setzt den Attractor ind auf seine Voreinstellung zurück.
part_attractor_position(ps, ind, x, y) Setzt die Position des Attractor ind auf (x, y).
part_attractor_force(ps, ind, force, dist, kind, aditive) Setzt den Force Parameter des Attractor ind.

Destroyers

Destroyer zerstören Partikel wenn sie in ihrer Region erscheinen. Ein Partikelsystem kann eine beliebige Anzahl von Destroyers haben. Ein Destroyer hat die folgenden Eigenschaften:
  • xmin, xmax, ymin, ymax Die Ausdehnung der Region wo die Partikel zerstört werden.
  • shape Form der Region. Es kann folgende Werte haben:
    • ps_shape_rectangle
    • ps_shape_ellipse
    • ps_shape_diamond

Die folgenden Funktionen existieren um Destroyers zu definieren. Bedenke, dass jede den Index des Partikelsystems bekommen welches als erstes Argument übergeben werden muss.

part_destroyer_create(ps) Erstellt einen neuen Destroyer im angegebenen Partikelsystem. Es gibt den Index des Typs zurück. Der Index muss in allen Aufrufen zum Setzen der Eigenschaften des Destroyer angegeben werden.
part_destroyer_destroy(ps, ind) Zerstört den Destroyer ind im Partikelsystem. Wenn du den Destroyer nicht mehr brauchst, rufe das auf um Speicher zu sparen.
part_destroyer_destroy_all(ps) Zerstört alle Destroyer im Partikelsystem welche erstellt wurden.
part_destroyer_exists(ps, ind) Gibt zurück ob der angegebene Destroyer im Partikelsystem existiert.
part_destroyer_clear(ps, ind) Setzt den Attractor ind auf seine Voreinstellung zurück.
part_destroyer_region(ps, ind, xmin, xmax, ymin, ymax, shape) Setzt die Region des Destroyers.

Deflectors

Deflectors lenken Partikeln ab, wenn sie in diese Region kommen. Nur die Position des Partikels ist hier berücksichtigt, nicht die Größe, Form oder das Sprite. Ein Partikelsystem kann eine beliebige Anzahl von Deflectors haben. Ein Deflector hat die folgenden Eigenschaften:
  • xmin, xmax, ymin, ymax Die Ausdehnung der Region wo die Partikeln abgelenkt werden.
  • kind Art des Deflectors. Es kann folgende Werte haben:
    • ps_deflect_horizontal lenkt die Partikel horizontal ab, typisch für vertikale Wände
    • ps_deflect_vertical lenkt die Partikel vertikal ab, typisch für horizontale Wände
  • friction Die Menge der Reibung als Folge des Einschlages mit dem Deflector. Je höher die Menge desto mehr wird der Partikel beim Einschlag ausgebremst.

Die folgenden Funktionen existieren um Deflectors zu definieren. Bedenke, dass jede den Index des Partikelsystems bekommt, welches als erstes Argument übergeben werden muss.

part_deflector_create(ps) Erstellt einen neuen Deflector im angegebenen Partikelsystems. Es gibt den Index des Typs zurück. Der Index muss in allen Aufrufen zum Setzen der Eigenschaften des Deflectors angegeben werden.
part_deflector_destroy(ps, ind) Zerstört den Deflector ind im Partikelsystem. Wenn du sie nicht mehr brauchst, rufe das auf um Speicher zu sparen.
part_deflector_destroy_all(ps) Zerstört alle Deflectors im Partikelsystem welche erstellt wurden.
part_deflector_exists(ps, ind) Gibt zurück ob der angegebene Deflector im Partikelsystem existiert.
part_deflector_clear(ps, ind) Setzt den Deflector ind auf seine Voreinstellung zurück.
part_deflector_region(ps, ind, xmin, xmax, ymin, ymax) Setzt die Region des Deflectors.
part_deflector_kind(ps, ind, kind) Setzt die Art des Deflectors.
part_deflector_friction(ps, ind, friction) Setzt die Reibung des Deflectors.

Changers

Changers ändern Partikel, wenn sie in diese Region kommen. Ein Partikelsystem kann eine beliebige Anzahl von Changers haben. Ein Changer hat die folgenden Eigenschaften:
  • xmin, xmax, ymin, ymax Die Ausdehnung der Region wo die Partikel geändert werden.
  • shape Die Art der Region. Es kann folgende Werte haben:
    • ps_shape_rectangle
    • ps_shape_ellipse
    • ps_shape_diamond
  • parttype1 Gibt an welcher Partikeltyp geändert wird.
  • parttype2 Gibt an in welchen Partikeltyp geändert wird.
  • kind Die Art des Changers. Es kann folgende Werte haben:
    • ps_change_motion Ändert nur den Bewegungsparameter des Partikels, nicht die Farbe und Form der Lebenszeiteinstellung
    • ps_change_shape Ändert nur den Formparamter wie Größe und Farbe und Form
    • ps_change_all Ändert alle Parameter, das bedeutet, dass das Partikel zerstört wird und ein neuer Typ erstellt wird.

Die folgenden Funktionen existieren um Changer zu definieren. Bedenke, dass jeder den Index des Partikelsystems bekommen welches als erstes Argument übergeben werden muss.

part_changer_create(ps) Erstellt einen neuen Changer im angegebenen Partikelsystem. Es gibt den Index des Typs zurück. Der Index muss in allen Aufrufen zum Setzen der Eigenschaften des Deflector angegeben werden.
part_changer_destroy(ps, ind) Zerstört den Changer ind im Partikelsystem. Wenn du sie nicht mehr brauchst, rufe das auf um Speicher zu sparen.
part_changer_destroy_all(ps) Zerstört alle Changers im Partikelsystem welche erstellt wurden.
part_changer_exists(ps, ind) Gibt zurück ob der angegebene Changer im Partikelsystem existiert.
part_changer_clear(ps, ind) Löscht den Changer ind auf seine Voreinstellung.
part_changer_region(ps, ind, xmin, xmax, ymin, ymax, shape) Setzt die Region des Changers.
part_changer_types(ps, ind, parttype1, parttype2) Setzt die Einstellung, welcher Partikeltyp der Changer in welchen anderen Typ umwandeln soll.
part_changer_kind(ps, ind, kind) Setzt die Art des Changers.

Beispiel: Feuerwerk

Hier ist ein Beispiel eines Partikelsystems, das ein Feuerwerk erstellt. Das Feuerwerk benützt zwei Partikeltypen: eines das die Raketen gestaltet und eines das das eigentliche Feuerwerk gestaltet. Die Rakete generiert die Feuerwerkpartikel wenn sie explodiert. Wir generieren auch einen Emitter im Partikelsystem, der regelmässig Raktetenpartikel entlang des unteren Bildschirmrandes ausstößt. Dafür brauchen wir ein Objekt. Im creation event schreiben wir folgenden Code, der Partikeltypen, Partikelsystem und Emitter erstellt:

{
  // make the particle system
  ps = part_system_create();
  // the firework particles
  pt1 = part_type_create();
  part_type_shape(pt1,pt_shape_flare);
  part_type_size(pt1,0.1,0.2,0,0);
  part_type_speed(pt1,0.5,4,0,0);
  part_type_direction(pt1,0,360,0,0);
  part_type_color1(pt1,c_red);
  part_type_alpha2(pt1,1,0.4);
  part_type_life(pt1,20,30);
  part_type_gravity(pt1,0.2,270);
  // the rocket
  pt2 = part_type_create();
  part_type_shape(pt2,pt_shape_sphere);
  part_type_size(pt2,0.2,0.2,0,0);
  part_type_speed(pt2,10,14,0,0);
  part_type_direction(pt2,80,100,0,0);
  part_type_color2(pt2,c_white,c_gray);
  part_type_life(pt2,30,60);
  part_type_gravity(pt2,0.2,270);
  part_type_death(pt2,150,pt1);    // create the firework on death
  // create the emitter
  em = part_emitter_create(ps);
  part_emitter_region(ps,em,100,540,480,490,ps_shape_rectangle,ps_distr_linear);
  part_emitter_stream(ps,em,pt2,-4);   // create one every four steps
}

Das ist der Trick. Stelle sicher das Partikelsystem (und auch Partikeltyp) zerstört werden, wenn du den Raum wechselst. Ansonsten läuft das Feuerwerk für immer.

Multiplayer Spiele

Diese Funktionen sind nur in der registrierten Version vom Game Maker verfügbar.

Gegen den Computer zu spielen macht Spaß. Aber gegen andere menschliche Spieler zu spielen kann noch wesentlich mehr Spaß machen. Es ist außerdem vergleichsweise einfach solche Spiele zu machen, da keine komplizierte künstliche Intelligenz für den Computergegner programmiert werden muss. Natürlich kannst du zwei Spieler vor den selben Monitor setzen und verschiedene Tasten oder andere Eingabegeräte verwenden, aber es ist sehr viel interessanter, wenn jeder Spieler vor seinem eigenen Rechner sitzen kann oder der andere Spieler sogar auf der anderen Seite des Ozeans ist . Game Maker unterstützt Multiplayer-Spiele. Beachte aber bitte, dass es schwierig ist, gut synchronisierte stabile Netzspiele zu entwickeln. Dieses Kapitel bietet eine kurze Beschreibung der Möglichkeiten. Auf der Internetseite gibt es ein eigenes Tutorial zu diesem Thema mit mehr Informationen.

Eine Verbindung aufbauen

Damit zwei Computer miteinander kommunizieren können, brauchen sie ein Kommunikationsprotokoll. Wie die meisten Spiele bietet Game Maker vier verschiedene Verbindungstypen: IPX, TCP/IP, Modem und serielle Verbindung. IPX arbeitet fast vollständig transparent und kann zum Spielen in lokalen Netzwerken verwendet werden. Es muss allerdings vorher installiert werden (wenn es nicht funktioniert, schau in der Windows Hilfe nach oder öffne die Netzwerkeigenschaften und füge das IPX-Protokoll hinzu). TCP/IP ist das Internet-Protokoll und kann dazu genutzt werden, mit anderen Spielern aus dem Internet zu spielen, vorausgesetzt deren IP-Adresse ist bekannt. Im lokalen Netzwerk funktioniert es auch ohne bereitgestellte IP-Adressen. Eine Modemverbindung wird durch ein Modem aufgebaut. Für die Nutzung müssen einige Modem-Einstellungen (ein Initialisationsstring und eine Telefonnummer) angegeben werden. Eine serielle Verbindung (eine direkte Verbindung zwischen den Computern) erfordert einige Anschlussparameter. Um diese Verbindungstypen zu initialisieren gibt es vier GML Funktionen:

mplay_init_ipx() initialisiert eine IPX-Verbindung.
mplay_init_tcpip(addr) initialisiert eine TCP/IP Verbindung. addr ist ein String welcher die Internet- oder IP-Adresse enthält, z.B. 'www.gameplay.com' oder '123.123.123.12', möglicherweise gefolgt von einer Port-Nummer (z.B. ':12'). Nur wenn man eine Verbindung aufbaut (siehe unten) braucht man eine Adresse. Im LAN sind sie nicht nötig.
mplay_init_modem(initstr, phonenr) initialisiert eine Modem Verbindung. initstr ist der Initialisierungsstring für das Modem (kann leer sein). phonenr ist ein String, der die anzurufende Telefonnummer enthält (z.B. '0201234567'). Die Nummer wird nur für den Verbindungsaufbau benötigt (siehe unten).
mplay_init_serial(portno, baudrate, stopbits, parity, flow) initialisiert eine serielle Verbindung(COM). portno ist die Port Nummer (1-4). baudrate ist die zu benutzende Baudrate (100-256K). stopbits zeigt die Anzahl der stopbits an (0 = 1 bit, 1 = 1.5 bit, 2 = 2 bits). parity gibt die Parität an (0=keine, 1=ungerade, 2=gerade, 3=Markierung). Und flow gibt die Datenflusskontrolle an (0=keine, 1=xon/xoff, 2=rts, 3=dtr, 4=rts und dtr). Ein typischer Aufruf wäre mplay_init_serial(1,57600,0,0,4). Gib 0 als erstes Argument an, um ein Dialogfenster zu öffnen, in dem der Benutzer Einstellungen ändern kann.

Dein Spiel sollte eine dieser Funktionen exakt einmal aufrufen. Alle Funktionen geben zurück, ob sie erfolgreich waren. Sie sind nicht erfolgreich, wenn die Protokolle nicht installiert oder unterstützt sind. Um zu überprüfen, ob eine Verbindung verfügbar ist, verwende folgende Funktion:

mplay_connect_status() gibt den Status der momentanen Verbindung an. 0 = keine Verbindung, 1 = IPX Verbindung, 2 = TCP/IP Verbindung, 3 = Modem Verbindung, 4 = serielle Verbindung.

Um die Verbindung abzubrechen, nutze folgende Funktion:

mplay_end() beendet die momentane Verbindung.

Bei einer TCP/IP-Verbindung kann es erforderlich sein, einem potentiellen Mitspieler deine IP-Adresse mitzuteilen. Dafür gibt es diese Funktion:

mplay_ipaddress() gibt die IP Addresse des eigenen PCs als String an (z.B. '123.123.123.12'). Diesen String kann man beispielsweise irgendwo auf dem Bildschirm anzeigen lassen. Anmerkung: Diese Routine ist langsam - ruf sie nicht permanent auf!

Erstellen und Teilnehmen an Sessions

Wenn du mit einem Netzwerk verbunden bist, können mehrere Spiele in diesem Netzwerk stattfinden. Hier werden sie "Sessions" (Sitzungen) genannt. Diese unterschiedlichen "Sessions" können verschiedenen oder einem Spiel entsprechen. Ein Spiel muss sich eindeutig im Netzwerk identifizieren. Glücklicherweise macht der Game Maker das für dich. Das einzige, was du wissen musst ist: Wenn du die "Game-ID" änderst, ändert sich auch diese Identifikation hier. Auf diese Weise kannst du verhindern, dass Leute mit alten Version gegen welche mit neuen Versionen spielen.

Wenn du ein neues Multiplayerspiel erstellen willst, musst du eine neue Session starten. Nutze hierfür folgende Funktion:

mplay_session_create(sesname, playnumb, playername) erstellt eine neue Session auf der momentanen Verbindung. sesname ist ein String, der den Namen der Session angibt. playnumb ist die maximale Spieleranzahl in diesem Spiel (0=beliebig). playname ist der Name des Spielers. Die Funktion gibt zurück ob sie erfolgreich war.

Eine Instanz des Spiels muss die Session erstellen. Die anderen Instanzen sollten dieser Session beitreten. Das ist etwas schwieriger. Du musst zuerst schauen, welche Sessions verfügbar sind und dann an einer teilnehmen. Drei wichtige Routinen gibt es dafür:

mplay_session_find() sucht alle Sessions, die noch Spieler akzeptieren und gibt die Anzahl der gefundenen zurück.
mplay_session_name(numb) gibt den Namen der Session mit der Nummer numb an(0 ist die erste Session).Diese Funktion kann nur nach der voranstehenden aufgerufen werden.
mplay_session_join(numb, playername) an der Session mit der Nummer numb (0 ist die erste Session) wird teilgenommen. playername ist der Name des Spielers. Diese Funktion gibt zurück, ob sie erfolgreich war.

Es gibt eine weitere Funktion, die den Session-Modus ändert. Sie sollte vor dem Erstellen einer Session ausgeführt werden:

mplay_session_mode(move) bestimmt ob ein anderer Rechner die Session übernimmt, wenn der momentane Server ausfällt. move sollte entweder true (wahr) oder false (falsch, ist voreingestellt).

Um den Verbindungsstatus zu prüfen verwende:

mplay_session_status() gibt den Status der momentanen Session an. 0 = keine Session, 1 = erstellte Session, 2 = an Session teilgenommen.

Ein Spieler kann folgende Routine nutzen, um eine Session zu stoppen:

mplay_session_end() beendet die Session für diesen Spieler.

Spieler

Jede Instanz des Spiels, die an einer Session teilnimmt ist ein Spieler. Wie zuvor erwähnt, haben Spieler Namen. Drei Funktionen befassen sich damit:
mplay_player_find() sucht alle Spieler in der momentanen Session und liefert die Anzahl der gefundenen.
mplay_player_name(numb) gibt den Namen des Spielers mit der Nummer numb an (0 ist der erste Spieler, immer du selbst). Diese Funktion kann nur nach voranstehender Funktion ausgeführt werden.
mplay_player_id(numb) gibt die eindeutige ID des Spielers mit der Nummer numb an (0 ist der erste Spieler, immer du selbst). Diese Funktion kann nur ausgeführt werden, wenn die oberste ausgeführt wurde. Diese ID wird benutzt um Nachrichten an einzelne Spieler zu schicken und zu empfangen.

Gemeinsame Daten

Gemeinsame Daten sind wahrscheinlich der einfachste Weg ein Spiel zu synchronisieren. Die gesamte Kommunikation wird dir vom Leib gehalten. Es gibt einen Satz von 1000000 Werten, welcher eine gemeinsame Basis für alle ist. Jedes Spiel kann jeden Wert lesen und ändern. Game Maker stellt sicher, dass jedes Spiel dieselben Werte sieht. Werte können reelle Zahlen oder Zeichenketten sein. Es gibt nur 2 Funktionen:

mplay_data_write(ind, val) schreibt den Wert val (string oder real) in Position ind (zwischen 0 und 1000000).
mplay_data_read(ind) gibt den Wert von Position ind an (zwischen 0 und 1000000). Anfangs sind alle Werte auf 0.

Um die Daten auf den verschiedenen Rechnern zu synchronisieren kannst du entweder einen verlässlichen Modus verwenden, der sicherstellt, das die Änderungen auch auf dem anderen Rechner ankommen (aber es ist langsam) oder nicht verlässlich. Um das zu ändern, benutze:

mplay_data_mode(guar) legt fest, ob die verlässliche oder die unsichere Übertragungsmethode für gemeinsame Daten verwendet werden soll. guar sollte true (wahr, voreingestellt) oder false (falsch) sein.

Messages (Nachrichten)

Der zweite Kommunikationsmechanismus, den Game Maker unterstützt, ist das Senden und Empfangen von Nachrichten. Ein Spieler kann eine Nachricht an einzelne oder alle Spieler senden. Spieler bemerken eingehende Nachrichten und können entsprechend reagieren. Nachrichten können in einem zuverlässigen Modus verschickt werden, bei dem man sicher gehen kann, dass sie ankommen (allerdings kann das langsam sein) oder in einem unsicheren Modus, der schneller ist.

Dafür gibt es folgende Funktionen:

mplay_message_send(player, id, val) sendet eine Nachricht an den Spieler player (ID oder Name; bei einer 0 wird die Nachricht an alle gesendet). id ist ein ganzzahliger Wert (real oder string). Die Nachricht wird im unsicheren Modus gesendet. Wenn val einen String enthält, dann ist dessen maximal erlaubte Länge 30000 Zeichen.
mplay_message_send_guaranteed(player, id, val) sendet eine Nachricht an den Spieler player (ID oder Name; bei einer 0 wird die Nachricht an alle gesendet). id ist ein ganzzahliger Wert (real oder string). Die Nachricht wird im sicheren Modus gesendet. Wenn val einen String enthält, dann ist dessen maximal erlaubte Länge 30000 Zeichen.
mplay_message_receive(player)empfängt nächste Nachricht aus der Warteschlange, welche vom angegebenen Spieler player kam (ID oder Name). Nutze 0 für Nachrichten von jedem Spieler. Die Funktion gibt wieder, ob tatsächlich eine neue Nachricht da ist. Wenn dem so ist, geht es hiermit an den Inhalt:
mplay_message_id() gibt den "message identifier" der letzten empfangenen Nachricht zurück.
mplay_message_value() gibt den Wert (Inhalt) der letzten empfangenen Nachricht zurück.
mplay_message_player() gibt den Spielers an, der die letzte empfangene Nachricht versandt hat.
mplay_message_name() gibt den Namen des Spielers an, der die letzte empfangene Nachricht versandt hat.
mplay_message_count(player) gibt die Anzahl verbleibender Nachrichten von Spieler player in der Warteschlange an (bei 0 werden alle Nachrichten gezählt).
mplay_message_clear(player) löscht alle verbleibenden Nachrichten von Spieler player aus der Warteschlange (bei 0 werden alle Nachrichten gelöscht).

Ein paar Anmerkungen sind hier sachdienlich: Erstens musst du, wenn du eine Nachricht an einen Spieler senden willst, dessen player-ID kennen. Wie schon erwähnt bekommst du sie mit der Funktion: mplay_player_id(). Diese player-ID eird auch benutzt, um Nachrichten von einzelnen Spielern zu empfangen. Alternativ kannst du den Namen das Spielers als String angeben. Wenn mehrere Spieler den selben Namen haben, bekommt nur der erste die Nachricht.

Zweitens wunderst du dich vielleicht, dass jede Nachricht eine ganzzahlige Nachrichten-id hat. Der Grund ist, dass es hilft, unterschiedliche Arten von Nachrichten zu versenden. Der Empfänger kann die Art der Nachricht anhand der id prüfen und entsprechend reagieren. (Weil Nachrichten nicht sicher ankommen, ist es problematisch, wenn id und Wert nicht mit derselben Nachricht gesendet werden.)

DLL's benutzen

Diese Funktionen sind nur in der registrierten Version vom Game Maker verfügbar.

In Fällen, in denen dir die Funktionalität von GML nicht ausreicht, kannst du die Möglichkeiten nutzen, sie mit Plug-Ins zu erweitern. Ein Plug-in hat die Form einer DLL("Dynamic Link Library"). In einer solchen DLL kann man Funktionen definieren. Diese Funktionen können in jeder Programmiersprache programmiert werden, in der man DLLs erstellen kann(z.B.C/C++, Delphi usw.). Allerdings solltest du dazu schon einige Programmierkenntnisse haben. Plug-In Funktionen müssen ein bestimmtes Format haben. Sie können 0 bis 11 Argumente enthalten, von denen jedes entweder eine reelle Zahl (double in C) oder ein null-terminierter String sein kann (Momentan sind für mehr als 4 Argumente nur reelle Zahlen unterstützt). Die Funktionen können entweder eine reelle Zahl oder einen null-terminierten String zurückgeben.

In Delphi erstellst du eine DLL indem du zuerst im Menü Datei Neu und dann DLL auswählst. Hier ist ein Beispiel einer in Delphi erstellten DLL, die du in Game Maker benutzen kannst. (Beachte, dass dies Delphi Code ist, kein GML Code!)

library MyDLL;

uses SysUtils, Classes;

function MyMin(x,y:double):double; cdecl;
begin
if x<y then Result := x else Result := y;
end;

var res : array[0..1024] of char;

function DoubleString(str:PChar):PChar; cdecl;
begin
StrCopy(res,str);
StrCat(res,str);
Result := res;
end;

exports MyMin, DoubleString;

begin
end.

Diese DLL definiert zwei Funktionen: MyMin gibt die kleine von zwei reellen Zahlen zurück und DoubleString hängt einen String an sich selbst an. Beachte, dass du vorsichtig mit dem Speicher umgehen solltest. Deshalb habe ich den resultierenden Wert als global String definiert. Außerdem wird hier die cdecl Aufrufkonvention verwendet. Du kannst entweder cdecl- oder stdcall-Aufrufkonventionen verwenden. Wenn du die DLL in Delphi kompilierst erhältst du eine Datei MyDLL.DLL. Diese Datei muss ins Arbeitsverzeichnis deines Spiels (oder an irgendeinen anderen Ort, an dem sie von Windows gefunden werden kann).

Um diese DLL in Game Maker nutzen zu können, musst du zuerst die externen Funktionen definieren, die du benutzen willst und welche Art von Argumenten verwendet werden. Dafür gibt es folgende Funktion in GML:

external_define(dll,name,calltype,restype,argnumb,arg1type,arg2type, ...) Definiert eine externe Funktion. dll ist der Name der DLL-Datei, name ist der Name der Funktionen. calltype ist die genutzte Aufruf-Konvention (nutze hierfür entweder dll_cdecl oder dll_stdcall). restype ist der Typ des Rückgabewerts(ty_real oder ty_string). argnumb ist die Anzahl der Argumente (0-11). Als nächstes musst du für jedes Argument dessen Typ festlegen (wieder ty_real oder ty_string). Sind mehr als 4 Argumente vorhanden, dann müssen diese alle vom Typ ty_real sein.

Diese Funktion liefert die ID der externen Funktion und muss für das Aufrufen verwendet werden. Im oberen Beispiel müsste am Anfang des Spiels folgender GML Code stehen:

{
global.mmm = external_define('MYOWN.DLL','MyMin',dll_cdecl,
ty_real,2,ty_real,ty_real);
global.ddd = external_define('MYOWN.DLL','DoubleString',dll_cdecl,
ty_string,1,ty_string);
}

Nun, kannst du die Funktionen, immer wenn du sie brauchst, mit folgender Funktion aufrufen:

external_call(id, arg1, arg2, ...) Ruft die externe Funktion mit der gegebenen ID und den gegebenen Argumenten auf. Die richtige Anzahl der Argumente und deren richtiger Typ(real oder string) müssen angegeben werden. Die Funktion gibt das Ergebnis der externen Funktion zurück.

Also kann man beispielsweise schreiben:

{
aaa = external_call(global.mmm,x,y);
sss = external_call(global.ddd,'Hello');
}

Wenn die DLL nicht mehr gebraucht wird, sollte man sie besser freigeben.

external_free(dll) Gibt die DLL mit dem gegebenen Namen frei. Das ist dann erforderlich, wenn das Spiel die DLL entfernen soll. Solange die DLL nicht freigegeben ist, kann sie auch nicht entfernt werden. Am besten sollte man das beispielsweise in einem Event machen, welches das Spiel beendet.

Du wirst dich vielleicht wundern, wie du eine DLL-Funktion schreiben kannst, die etwas im Spiel bewirkt. Zum Beispiel könntest du eine DLL schreiben wollen, die Instanzen eines Objektes in deinem Spiel erstellt. Der einfachste Weg ist deine DLL einen String zurückgeben zu lassen, der ein Stück GML Code enthält. Dieser String kann dann mit dieser Funktion ausgeführt werden:

execute_string(str) Führt den String als GML Code aus.

Alternativ kannst du die DLL eine Datei mit einem Script erstellen lassen, das dann ausgeführt werden kann (diese Funktion kann auch dazu benutzt werden, das Verhalten eines Spieles nachträglich zu beeinflussen).

execute_file(fname) Führt die Datei als GML Code aus.

Nun kannst du eine externe Funktion aufrufen und dann den resultierenden String z.B. folgendermaßen ausführen:

{
ccc = external_call(global.ddd,x,y);
execute_string(ccc);
}

In manchen seltenen Fällen, kann es sein, dass deine DLL den Handle des Hauptfensters des Spiels benötigt. Diesen kann man durch folgenden Code erhalten und dann an die DLL weitergeben:

window_handle() Gibt den Handle für das Spielfenster zurück

Beachte, dass DLLs im Secure-Mode nicht genutzt werden können.

Externe DLLs zu benutzen ist ein mächtiges Instrument. Aber nutze es bloss, wenn du genau weißt was du tust.

3D Grafiken

Diese Funktionen sind nur in der Registrierten Version des Game Makers verfügbar.

Game Maker ist zwar nur dafür gedacht 2-dimensionale Spiele zu erstellen, trotzdem gibt es einige Funktionen, die 3-dimensionale Grafiken erlauben. Bevor du damit anfängst gibt es einige Sachen, die du wissen musst.

  • Die 3D Funktionalität in Game Maker ist auf den Grafik-Teil beschränkt. Für andere Aspekte Eines 3D Spiels gibt es keinerlei Unterstützung. Sobald du die 3D-Unterstützung nutzt, wirst du unter Umständen Probleme mit anderen Teilen von Game Maker bekommen, z.B. Views, depth Ordnung, usw. Die Erweiterung ist begrenzt und hat eine sehr niedrige Priorität weiter entwickelt zu werden. Erwarte deshalb keine Unterstützung für 3d-Models, usw.
  • Wenn du die 3D-Unterstützung benutzt, gibt es einige andere Dinge die nicht mehr benutzt werden können.
    • Du kannst in deinen Räumen keine Hinter- und Vordergründe mehr benutzen.
    • Du kannst die Mausposition nicht mehr verwenden, weil die 2D-Mauskoordinaten nicht in 3d-Koordinaten konvertiert werden. Du kannst immer noch die Mauskoordinaten auf dem Bildschirm benutzen, musst aber selbst Berechnungen anstellen, oder überhaupt keine Maus benutzen.
    • Du kannst keine Tiles mehr benutzen. Sie werden nicht mehr richtig passen.
    • Die Kollision werden immer noch die 2D-Koordinanten der Instanzen benutzen, es gibt folglich keine 3D Kollisionsprüfungen. Trotzdem kann kann man das manchmal benutzen. (Wenn du den Raum als Darstellung einer Flachen Welt benutzt (z.B. für Renn- oder FPS Spiele) Aber in anderen Situationen musst du selbst Prüfungen anstellen.)
  • Alle 3D Funktionen werden allein durch Code angesteuert, deswegen solltest du sehr erfahren in GML sein und gut wissen wie Game Maker funktioniert, weil du sonst sicher Probleme bekommen wirst.
  • Du musst einige Grundkenntnisse über 3d Grafiken besitzen. Ich werde Begriffe, wie Perspektive, Projektionen, Hidden Surface removal, Licht und Nebel, benutzen, ohne sie wirklich zu erklären.
  • Es gibt keinen 3D-Modeller in Game Maker. Außerdem ist keine Möglichkeit geplant 3D-Models zu laden.
  • Du musst vorsichtig arbeiten, damit das Spiel mit einer akzeptablen Geschwindigkeit läuft, weil die Funktionen nicht auf Geschwindigkeit ausgelegt sind.

Wenn dich das alles nicht entmutigt hat, lies weiter.

Informationen über 3D-Grafiken können auf den folgenden Seiten gefunden werden:

Den 3D Modus aktivieren
Einfaches Zeichen
In 3D Polygone zeichnen
Einfache Formen zeichnen
Die Welt anzeigen
Transformationen
Nebel
Licht
Modelle erzeugen
Abschließende Worte

Den 3D Modus aktivieren

Wenn du den 3D Modus benutzen willst, musst du Game Maker in den 3D Modus umschalten. Du kannst später auch wieder in den 2D Modus schalten, wenn du willst. Folgende Funktionen existieren hierfür.

d3d_start() Den 3D Modus aktivieren.
d3d_end() Den 3D Modus deaktivieren.

Alle Funktionen, die 3D Unterstützung steuern, haben ein d3d_ am Anfang ihres Namens.

Den 3D Modus zu aktivieren wird folgende Änderungen hervorrufen: 1. Wird Hidden surface removal aktiviert (ein 16-bit z-Buffer wird benutzt). D.h., dass bei jedem Pixel nur das Object mit dem niedrigsten z-wert (= depth-wert) gezeichnet wird. Wenn Instanzen die selbe depth haben ist es unklar, was passiert. Stell sicher, dass Instanzen, die sich überlappen könnten, nicht dieselbe depth haben!

2. Wird die normale orthografische Projektion durch eine perspektivische ersetzt. Das bedeutet folgendes: Normalerweise ist die Größe der Instanzen unabhängig von ihrer depth. Mit einer perspektivischen Projektion erscheinen Instanzen, die eine größere depth haben, als kleiner. Wenn die depth 0 beträgt ist die Größe nicht geändert (außer Wenn die Projektion geändert wurde; seihe unten). Der Blickpunkt der Kamera ist in einer bestimmten Distanz über dem Raum/View platziert (Diese Distanz ist gleich mit der Breite des Raums/Views; Das ergibt eine angemessene Standard Projektion). Es können nur Instanzen gezeichnet werden, die sich vor der Kamera befinden, benutze also keine dephts die kleiner als -(Raum/View_Breite) sind.

3. Wird die vertikale Y-Achse umgedreht. Während normalerweise der Punkt(0, 0) in der linken oberen Ecke liegt, liegt er im 3D-Modus in der linke unteren Ecke, wie es für 3D Sichten üblich ist.

Du kannst das Hidden Surface Removal und die perspektivische Projektion ausschalten, indem du folgende Funktionen benutzt.

d3d_set_hidden(enable) Aktiviert Hidden Surface Removal (true) oder deaktiviert es (false).
d3d_set_perspective(enable) Aktiviert die Benutzung einer perspektivischen Projektion (true) oder deaktiviert sie (false).

Einfaches zeichnen

Sobald der 3D-Modus aktiviert wurde, kannst du Game Maker benutzen, wie du es gewohnt bist (Außer den Ausnahmen, die am Anfang behandelt wurden). Die Objekte werden einfach in verschiedenen Größen erscheinen, was von ihren depths abhängt und du kannst sogar Views benutzen. Eine Funktion könnte dabei nützlich sein. Wenn du einige Sachen aus einem Stück Code heraus zeichnest, könnte es nützlich für dich sein die zum Zeichen verwendete depth zu ändern.

d3d_set_depth(depth) Setzt die zum Zeichen verwendete depth.

Bitte beachte, dass sobald eine neue Instanz gezeichnet wird, wird die depth auf die der neuen Instanz gesetzt.

Polygone zeichnen in 3D

Das Problem der "alten" Methode zu zeichnen liegt darin, dass das Sprite oder Polygon immer in einer xy-Ebene liegt, d. h. alle Ecken haben die selbe depth. Für echten 3D muss man in der Lage sein, Punkte mit verschiedenen depths zu haben, deshalb werden wir von nun an von z-Koordinaten sprechen anstatt von depths. Für oben genanntes Problem gibt es einige spezial Versionen der erweiterten Zeichenfunktionen:

d3d_primitive_begin(kind) Beginn einer 3D Primitive folgender Art: pr_pointlist, pr_linelist, pr_linestrip,pr_trianglelist,pr_trianglestrip oder pr_trianglefan.
d3d_vertex(x, y, z) Füge einen Vertex (x, y, z) zum Primitive hinzu und benutze die voreingestellten Farb- und Alpha-Werte.
d3d_vertex_color(x, y, z, col, alpha) Füge einen Vertex (x, y, z) zum Primitive hinzu mit seinen eigenen Farb- und Alpha-Werten. Dies erlaubt Primitives zu erstellen, der Farbe und Alpha sich sanft verändern.
d3d_primitive_end() Beende die Beschreibung des Primitives. Diese Funktion zeichnet es auch.

Z. B. um einen Tetraeder zu zeichnen (dreiseitige Pyramide), die auf der z = 0 Ebene steht und mit der Spitze bei z = 200, kann man folgenden Code benutzen:

{
d3d_primitive_begin(pr_trianglelist);
d3d_vertex(100,100,0);
d3d_vertex(100,200,0);
d3d_vertex(150,150,200);
d3d_vertex(100,200,0);
d3d_vertex(200,200,0);
d3d_vertex(150,150,200);
d3d_vertex(200,200,0);
d3d_vertex(100,100,0);
d3d_vertex(150,150,200);
d3d_vertex(100,100,0);
d3d_vertex(100,200,0);
d3d_vertex(200,200,0);
d3d_primitive_end();
}

Wenn du das nun benutzen würdest, würdest du nichts weiter sehen, als ein Dreieck, weil die Spitze des Tetraeders vom Sichtpunkt aus hinter ihm sein wird. Außerdem ist es schwer, verschiedene Dreiecke zu sehen, wenn man dieselbe Farbe benutzt. Später werden wir Möglichkeiten kennen lernen, um den Sichtpunkt zu verändern. Farben zuzuweisen ist mit der Funktion draw_set_color(col) zwischen den Vertizen möglich. Man kann auch texturierte Polygone in 3D zeichnen. Es funktioniert genauso wie es im "Erweiterte Zeichenfunktionen" der Dokumentation beschrieben ist. Aber dieses Mal braucht man 3D Varianten der Grundfunktionen. Eines musst du bedenken: In einer Textur ist die Position (0,0) in der Linken oberen Ecke, aber oft, wenn Projektionen verwendet werden, die untere linke Ecke ist (0,0). In einem solchen Fall könntest du die Textur Vertikal spiegeln.

d3d_primitive_begin_texture(kind, texid) Beginne einen 3D Primitive der angegebenen Art und mit der angegebenen Textur.
d3d_vertex_texture(x, y, z, xtex, ytex) Füge einen Vertex (x, y, z), mit den Textur Koordinaten xtex & ytex, zum Primitive hinzu mit der eingestellten Farbe und Alpha geblendet.
d3d_vertex_texture_color(x, y, z, xtex, ytex, col, alpha) Füge einen Vertex (x, y, z), mit den Textur Koordinaten xtex & ytex, zum Primitive hinzu mit der angegebenen Farbe und Alpha geblendet.
d3d_primitive_end() Beende die Beschreibung des Primitives. Diese Funktion zeichnet ihn auch.

Z.B. kann man folgenden Code benutzen, um einen Hintergrund zu zeichnen , der in der Entfernung verschwindet:

{
var ttt;
ttt = background_get_texture(back);
d3d_primitive_begin_texture(pr_trianglefan,ttt);
d3d_vertex_texture(0,480,0,0,0);
d3d_vertex_texture(640,480,0,1,0);
d3d_vertex_texture(640,480,1000,1,1);
d3d_vertex_texture(0,480,1000,0,1);
d3d_primitive_end();
}

Ein Dreieck hat eine Vorder- und Rückseite. Die Vorderseite ist als die Seite definiert, auf der die Vertices im Gegenuhrzeigersinn definiert wurden. Normalerweise wird Vorder- und Rückseite gezeichnet, Wenn man aber eine Geschlossene Forma hat, ist es Verschwendung von Rechenzeit, weil die inneren Seiten der Dreiecke nie zu sehen sein werden. In diesem Fall kannst du Backface Culling aktivieren. Das spart ca. 50% Rechenzeit, weil nur die Vorderseiten gezeichnet werden, jedoch musst du die Dreiecke richtig definieren. Folgende Funktion existiert:

d3d_set_culling(cull) Gibt an BFC zu starten (true) , oder zu deaktivieren (false).

Einfache Formen zeichnen

Es existieren einige Funktionen, um einfache Formen, wie Blöcke und Wände zu zeichnen. Sie Funktionieren auch mit eingeschaltetem BFC.

d3d_draw_block(x1, y1, z1, x2, y2, z2, texid, hrepeat, vrepeat) Zeichnet einen Block in der derzeitigen Farbe mit den angegebenen, sich gegenüberliegenden, Ecken und der angegebenen Textur. Benutze -1, um keine Textur zu verwenden. Hrepeat gibt an, wie oft die Textur horizontal auf dem Face wiederholt werden soll. vrepeat macht das selbe vertikal.
d3d_draw_cylinder(x1, y1, z1, x2, y2, z2, texid, hrepeat, vrepeat, closed, steps) Zeichnet einen vertikalen Zylinder in der angegebenen Begrenzung mit der angegebenen Textur. Hrepeat gibt an, wie oft die Textur horizontal auf dem Face wiederholt werden soll. vrepeat macht das selbe vertikal. Closed gibt an, ob der Zylinder oben und unten geschlossen sein soll. steps gibt die Anzahl der Schritte, in denen es rotiert wird, an. Ein Standardwert wäre 24.
d3d_draw_cone(x1, y1, z1, x2, y2, z2, texid, hrepeat, vrepeat, closed, steps) Zeichnet einen vertikalen Kegel in der angegebenen Begrenzung mit der angegebenen Textur. Hrepeat gibt an, wie oft die Textur horizontal auf dem Face wiederholt werden soll. vrepeat macht das selbe vertikal. Closed gibt an, ob der Kegel oben und unten geschlossen sein soll. steps gibt die Anzahl der Schritte, in denen es rotiert wird, an. Ein Standardwert wäre 24.
d3d_draw_ellipsoid(x1, y1, z1, x2, y2, z2, texid, hrepeat, vrepeat, steps) Zeichnet einen Ellipsoid in der angegebenen Begrenzung mit der angegebenen Textur. Hrepeat gibt an, wie oft die Textur horizontal auf dem Face wiederholt werden soll. vrepeat macht das selbe vertikal. Closed gibt an, ob der Zylinder oben und unten geschlossen sein soll. steps gibt die Anzahl der Schritte, in denen es rotiert wird, an. Ein Standardwert wäre 24.
d3d_draw_wall(x1, y1, z1, x2, y2, z2, texid, hrepeat, vrepeat) Zeichnet eine Wand mit den angegebenen Ecken und der angegebenen Textur. Hrepeat gibt an, wie oft die Textur horizontal auf dem Face wiederholt werden soll. vrepeat macht das selbe vertikal.
d3d_draw_floor(x1, y1, z1, x2, y2, z2, texid, hrepeat, vrepeat) Zeichnet einen Boden mit den angegebenen Ecken und der angegebenen Textur. Hrepeat gibt an, wie oft die Textur horizontal auf dem Face wiederholt werden soll. vrepeat macht das selbe vertikal.

Der folgende Code zeichnet 2 Blöcke:

{
  var ttt;
  ttt = background_get_texture(back);
  d3d_draw_block(20,20,20,80,40,200,ttt,1,1);
  d3d_draw_block(200,300,-10,240,340,100,ttt,1,1);
}

Viewing the world

Normalerweise schaut man an der negativen z-Achse entlang. Oft will man in 3D-Spielen die Art auf die man die Welt betrachtet, ändern. Beispielsweise möchtest du in einem EGO-Shooter wahrscheinlich, dass die sich die Kamera ein bisschen über der xy-Ebene bewegt. Um den Blickpunkt zu verändern gibt es zwei Funktionen.

d3d_set_projection(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup) Definiert von wo man wie die Welt betrachtet. Man gibt den Punkt von dem aus man alles betrachtet, den Punkt auf den man schaut und den up-Vektor an.

Diese Funktion bedarf etwas Erklärung. Um die Projektion zu setzen, braucht man zuerst die Position von der man schaut. welche von den Argumenten (xfrom,yfrom,zfrom) bestimmt wird. Als nächstes braucht man die Position, die man ansieht(xto,yto,zto). Zuletzt können wir die Kamera immer noch um die Linie vom Viewpoint zum Looking Point drehen, um dies zu definieren geben wir einen Up-Vektor (xup,yup,zup) (Die Richtung die In der Camera oben ist) als Argument. Z.B: Um an der xy-Eben entlang zu sehen kann folgendes benutzt werden

{
d3d_set_projection(100,100,10,200,100,10,0,0,1);
}
Man schaut vom Punkt 100, 100 und 10 über der Ebene, in die Richtung des Punktes 200, 100. Der up-Vektor zeigt zu z. Stell dir vor, du hättest ein Objekt, das die Kamera mit ihren Koordinaten darstellt. Es würde eine Position und eine direction (vielleicht sogar einen speed). Du kannst dieses Objekt nun leicht als Kamera definieren, indem du folgenden Code benutzt:

{
with (obj_camera)
d3d_set_projection(x,y,10,
x+cos(direction*pi/180),y-sin(direction*pi/180),10,
0,0,1);
}

Das könnte jetzt ein bisschen kompliziert aussehen. Wir schauen von der Kameraposition (x, y) aus, 10 über dem Boden. Um den Punkt zu erhalten zu dem wir schauen (die nächsten 3 Parameter), müssen wir ein wenig Trigonometrie benutzen. Schließlich benutzen wir den up-Vektor wie oben.

Anmerkung! Wenn Game Maker beginnt einen Raum zu zeichnen, wird der Viewpoint zurückgesetzt. Folglich ist das erste, das du tun musst, wenn du die Szene zeichnest, die Projektion so einzustellen, wie du sie brauchst. Das muss in einem Draw-Event geschehen!

Es gibt außerdem noch eine erweiterte Version obiger Funktion:

d3d_set_projection_ext(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup, angle, aspect, znear, zfar) Eine erweiterte Version, bei der man auch den Winkel des Blickfeldes, das Bild-Seitenverhältnis und die Clipping planes angeben kann.

Die zusätzlichen Parameter funktionieren wie folgt: Nachdem Position, Zielpunkt und up-Vektor angegeben wurden, kann man immer noch den Öffnungsgrad der Linse ändern, welcher das Blickfeld bestimmt. Der Standartwert ist 45 Grad. Als nächstes wird das Bild-Seitenverhältnis angegeben. Normalerweise wird ein Wert verwendet, der dem des Rooms entspricht. Zuletzt kommen die Clipping Planes. Objekte, die näher als znear sind, werden nicht gezeichnet. Das Gleiche gilt für Objekte, die weiter entfernt als zfar liegen.Es kann wichtig sein, diese Parameter auf gut durchdachte Werte zu setzen, weil sie auch die Genauigkeit der z-Vergleiche beeinflussen. Wenn der Abstand der beiden zu groß ist, ist die Genauigkeit sehr niedrig. Normalerweise werden 1 und 32000 als Werte benutzt. znear muss größer als 0 sein!

Manchmal braucht man kurzzeitig eine Orthografische Projektion, weil sie verwendet wird, wenn 3D nicht aktiviert ist, z.B. um ein HUD (Head-Up-Display = Anzeigen) zu zeichnen. Dafür kann man folgende Funktionen verwenden:

d3d_set_projection_ortho(x, y, w, h, angle) Setzt eine normale orthografische Projektion, in der angegebenen Größe und Position im Raum, um den angegebenen Winkel gedreht.
d3d_set_projection_perspective(x, y, w, h, angle) Setzt eine perspektivische Projektion auf den angegebenen Bereich im angegebenen Winkel.

Normalerweise wird es dazu benutzt, um z.B. die Punkte anzeigen zu lassen. Zusätzlich zu oben genannter Funktion sollte das Hidden Surface Removal deaktiviert werden, weil die Information unabhängig von der derzeitigen depth drawen wollen. Das folgende Beispiel zeigt wie man eine Anzeige mit der Punktzahl realisiert.

{
draw_set_color(c_black);
d3d_set_projection_ortho(0,0,room_width,room_height,0);
d3d_set_hidden(false);
draw_text(10,10,'Score: ' + string(score));
d3d_set_hidden(true);
}

Transformationen

Transformationen erlauben es, den Ort an dem gezeichnet wird, zu verändern. Beispielsweise kann die Funktion zum Blöcke zeichnen nur Achsenparallele Blöcke zeichnen. Wenn man zuerst eine Rotations-Transformation definiert, kann man auch rotierte Blöcke zeichnen. Sprites werden auch immer parallel zur xy-Ebene gezeichnet. Auch hier schafft eine Transformation Abhilfe. Es gibt zwei Arten von Funktionen: Solche, die eine Transformation setzen, und solche, die sie addieren.

d3d_transform_set_identity() Setzt die Transformation zurück.
d3d_transform_set_translation(xt, yt, zt) Setzt die Transformation auf eine Verschiebung um den angegebenen Vektor.
d3d_transform_set_scaling(xs, ys, zs) Setzt die Transformation auf ein Scaling mit den angegebenen Werten.
d3d_transform_set_rotation_x(angle) Setzt die Transformation auf eine Rotation um die x-Achse mit dem angegebenen Winkel.
d3d_transform_set_rotation_y(angle) Setzt die Transformation auf eine Rotation um die x-Achse mit dem angegebenen Winkel.
d3d_transform_set_rotation_z(angle) Setzt die Transformation auf eine Rotation um die x-Achse mit dem angegebenen Winkel.
d3d_transform_set_rotation_axis(xa, ya, za, angle) Setzt die Transformation auf eine Rotation um die angegebene Achse mit dem angegebenen Winkel.
d3d_transform_add_translation(xt, yt, zt) Fügt eine Verschiebung um die angegebenen Werte hinzu.
d3d_transform_add_scaling(xs, ys, zs) Fügt ein Scaling mit den angegebenen Werten hinzu.
d3d_transform_add_rotation_x(angle) Fügt eine Rotation um die x-Achse um den angegeben Winkel hinzu.
d3d_transform_add_rotation_y(angle) Fügt eine Rotation um die y-Achse um den angegeben Winkel hinzu.
d3d_transform_add_rotation_z(angle) Fügt eine Rotation um die z-Achse um den angegeben Winkel hinzu.
d3d_transform_add_rotation_axis(xa, ya, za, angle) Fügt eine Rotation um die angegebene Achse um den angegeben Winkel hinzu.
Bedenke, dass Rotationen und Scalings immer relativ zum Ursprung der Welt sind. Wenn das Objekt, das du zeichnen willst, nicht beim Ursprung ist wird es sich bei diesen Transformationen auch woanders hinbewegen. Um also z.B. ein Objekt um seine eigene x-Achse zu rotieren, muss es zuerst zum Ursprung Verschoben werden. Dafür sind die Funktionen zum hinzufügen gut.

Die folgenden Beispiele werden das wahrscheinlich besser erklären. Stell dir vor, wir hätten ein sprite spr, dass wir auf der Position (100,100,10) zeichnen wollen. Dafür kann man folgenden Code benutzen.

{
d3d_transform_set_translation(100,100,10);
draw_sprite(spr,0,0,0);
d3d_transform_set_identity();
}

Weil wir jetzt eine Verschiebung benutzen, sollten wir das Sprite bei der Position (0,0) zeichnen. (Das setzt voraus, dass die depth 0 ist. Wenn du nicht sicher bist, dann setze die depth zuerst.) Wenn wir das in unserem EGO-Shooter verwenden würden, könnten wir das sprite nicht sehen, weil es immer noch parallel zu xy-Ebene ist. Wir müssen um 90 Grad an der x- oder y-Achse drehen. Deshalb fügen wir eine Rotation hinzu. Merke dir die Reihenfolge: zuerst drehen, dann verschieben. Folgender Code kann verwendet werden.

{
d3d_transform_set_identity();
d3d_transform_add_rotation_x(90);
d3d_transform_add_translation(100,100,10);
draw_sprite(spr,0,0,0);
d3d_transform_set_identity();
}

Manchmal will man kurzzeitig die derzeitige Transformation speichern, z.B. um eine zusätzliche Transformation hinzuzufügen und die alte dann wieder zu aktivieren (das passiert oft, wenn man hierarchische Models zeichnet). Deswegen kann man die aktuelle Transformation auf einen Stack legen und sie später wieder davon nehmen. Folgenden Funktionen existieren:

d3d_transform_stack_clear() Leert den Stack.
d3d_transform_stack_empty() Gibt zurück, ob der Stack leer ist.
d3d_transform_stack_push() legt die derzeitige Transformation auf den Stack und gibt zurück, ob genug platz dafür war. (Nach einiger Zeit wird dir der Raum auf dm Stack ausgehen)
d3d_transform_stack_pop() Nimmt die Oberste Transformation vom Stack und aktiviert sie. Gibt zurück, ob eine Transformation auf dem Stack war.
d3d_transform_stack_top() Aktiviert die oberste Transformation, nimmt sie aber nicht von Stack. Gibt zurück, ob eine Transformation auf dem Stack war.
d3d_transform_stack_discard() Entfernt die oberste Transformation vom Stack, aktiviert sie aber nicht. Gibt zurück, ob eine Transformation auf dem Stack war.

Transformationen zu benutzen ist sehr mächtig, aber du musst immer daran denken, die Transformation zurück zu setzen, wenn du fertig bist.

Nebel

Nebel kann in 3D-Spielen verwendet werden, um Objekte in der Entfernung verschwommen erscheinen, oder ganz verschwinden zu lassen. Das hilft Atmosphäre zu schaffen und macht es möglich Objekte, die weit entfernt sind, nicht zu zeichnen. Dafür existiert folgende Funktion:
d3d_set_fog(enable, color, start, end) Aktiviert oder deaktiviert Nebel. color gibt die Nebelfarbe an. start und end schließen den Bereich ein, indem die Nebeldichte bis ans Maximale zunimmt.

Um besser zu verstehen was hier passiert,es gibt zwei Typen von Nebel, tabellenbasierender und vertexbasierender Nebel. Der erste kalkuliert die Werte auf einer Pixelbasis. Der zweite kalkuliert die Werte für jeden Vertex und interpoliert den Rest. Der erste Typ ist besser, wird aber nicht immer unterstützt. Game Maker versucht tabellenbasierenden Nebel zu verwenden, geht es nicht wird aber auf vertexbasierenden Nebel umgeschaltet (ausser das überhaupt kein Nebel unterstützt wird). Beachte, das manche Grafikkarten tabellenbasierenden Nebel unterstützen, man diesen aber abstellen kann. In diesem Fall könnte der Bildschirm schwarz sein!

Licht

Szenen, die du mit den jetzt bekannten Funktionen zeichnest, sehen relativ flach aus, weil es kein Licht gibt. Die Farben der Dreiecke sind, unabhängig von ihrer Richtung, gleich. Um realistischere Szenen zeichnen zu können, musst du Lichter aktivieren und sie an der richtigen Stelle platzieren. Richtig beleuchtete Szenen zu schaffen ist nicht leicht, aber ihr Effekt ist sehr gut.

Um Licht zu aktivieren kannst du folgende Funktion verwenden:

d3d_set_lighting(enable) Aktiviert oder deaktiviert die Benutzung von Licht.

Wenn Licht benutzt wird, wird zuerst die Farbe für jeden Vertex in einem Polygon bestimmt. Als nächstes wird die Farbe aller internen Pixel mithilfe dieser Werte berechnet. Dies kann auf zwei verschiedene Wege geschehen: Entweder bekommt das ganze Polygon die selbe Farbe, oder die Farbe verläuft weich über das Polygon (Smooth Shading). Normalerweise wird Letzteres verwendet, kann aber mit folgender Funktion geändert werden:

d3d_set_shading(smooth) Aktiviert oder deaktiviert Smooth Shading.

Um Licht nutzen zu können, musst du Lichter definieren. Es gibt zwei Arten von Lichtern: gerichtete Lichter (Lichter, die nur in eine Richtung strahlen, wie z.B. ein Scheinwerfer) und Punktlichter (wie eine Glühbirne). Lichter haben eine Farbe. (Es werden nur diffuse lichter unterstützt.) Die folgenden Funktionen existieren, um Lichter zu definieren und zu benutzen:

d3d_light_define_direction(ind, dx, dy, dz, col) Definiert ein gerichtetes Licht. ind ist der Index des Lichtes (eine kleine positive Ganzzahl). (dx,dy,dz) ist die Richtung des Lichts, col die Farbe (oft c_white). Diese Funltion aktiviert das Licht nicht.
d3d_light_define_point(ind, x, y, z, range, col) Definiert ein Punktlicht. ind ist der Indes des Lichtes (eine kleine positive Ganzzahl). (x,y,z) ist die Position des Lichtes. range gibt an, wie weit das Licht scheint. Die Intensität des Lichtes wird über diese Strecke abnehmen. col ist die Farbe des Lichtes. Diese Funktion aktiviert das Licht nicht.
d3d_light_enable(ind, enable) Aktiviert oder deaktiviert das Licht mit dem Index ind.

Wie ein Objekt das Licht reflektiert hängt von dem Winkel zwischen der Richtung des Lichts und dem normal-Vektor (Ein Vektor, der von der Oberfläche wegzeigt) der Oberfläche zusammen. Folglich musst du, um belichtete Objekte zu erstellen, nicht nur die Position der Vertexe definieren, sondern auch ihre Normalen. Dafür gibt es vier weitere Fuktionen, die die Vertexe der Primitives erzeugen:

d3d_vertex_normal(x, y, z, nx, ny, nz, xtex, ytex) Fügt den Vertex (x,y,z) zum Primitive hinzu, mit dem normal Vektor (nx,ny,nz) mit der Position (xtex,ytex) in der Textur, Farbmischung und Alphawerten hinzu.
d3d_vertex_normal_color(x, y, z, nx, ny, nz, xtex, ytex, col, alpha) Fügt den Vertex (x,y,z) mit der Position (xtex,ytex) in der Textur, mit seiner eigenen Farbe und Alpha zum Primitive hinzu, mit dem normal Vektor (nx,ny,nz).
d3d_vertex_normal_texture(x, y, z, nx, ny, nz, xtex, ytex) Fügt den Vertex (x,y,z) zum Primitive hinzu, mit dem normal Vektor (nx,ny,nz) und den Texturkoordinaten (xtex,ytex).
d3d_vertex_normal_texture_color(x, y, z, nx, ny, nz, xtex, ytex, col, alpha) Fügt den Vertex (x,y,z) zum Primitive hinzu, mit dem normal Vektor (nx,ny,nz) und den Texturkoordinaten (xtex,ytex), mit seinen eigenen Farb- und Alpha Werten geblendet.

Die Funktionen, die die einfachen Formen zeichnen, setzen ihre normal-Vektoren automatisch richtig.

Modelle erstellen

Wenn du große Modelle zeichnen willst ist es umständlich die ganzen Daten in jedem Step neu zu definieren. Um das zu umgehen kannst du Modelle erzeugen. Ein Modell besteht aus Primitiven und Formen. Wenn ein Modell erzeugt wurde kannst du es überall mit nur einem Funktionsaufruf zeichnen. Modelle können auch aus Dateien geladen und in sie gespeichert werden.

Bevor wir uns die Funktionen ansehen gibt es einen wichtigen Punkt: das Behandeln von Texturen. Wie schon gesagt werden Texturen aus Sprites und Hintergründen generiert. Die Indexe können zu verschiedenen Zeitpunkten verschieden sein. Deswegen kann ein Modell keine Texturinformation beinhalten. Nur beim Zeichnen kannst du die Textur bestimmen. Deswegen kannst du in einem Model nur eine Textur nutzen. Sonst musst du sie entweder zu einer zusammenfügen (und vorsichtig mit dem Koordinaten arbeiten) oder du musst mehrere Modelle nehmen. Der Vorteil ist das du dasselbe Modell mit mehreren Texturen zeichnen kannst.

Zum Erstellen, Laden, Speichern und Zeichnen existieren folgende Funktionen:

d3d_model_create() Erstellt ein Modell und gibt seinen Index zurück. Dieser Index wird in alle anderen Funktionen gebraucht.
d3d_model_destroy(ind) Zerstört das Modell, gibt seinen Speicher frei.
d3d_model_clear(ind) Leert das Modell, entfernt all seine Primitive.
d3d_model_save(ind, fname) Speichert das Modell in die angegebene Datei.
d3d_model_load(ind, fname) Läd das Modell aus der angegebenen Datei.
d3d_model_draw(ind, x, y, z, texid) Zeichnet das Modell an Position (x,y,z). texid ist die gewählte Textur. -1 bedeutet keine Textur. Wenn du das Objekt ändern willst nutze die zuvor beschriebenen Transformationsroutinen.

Für jede Primitive Funktion existiert ein Gegenstück für ein Modell. Die Funktionen sind dieselben, ausser das das erste Argument der Modellindex ist, und keine Texturinformation gebraucht wird.

d3d_model_primitive_begin(ind, kind) Fügt ein 3D Primitiv des angegebenen Typs hinzu: pr_pointlist, pr_linelist, pr_linestrip,pr_trianglelist,pr_trianglestrip oder pr_trianglefan.
d3d_model_vertex(ind, x, y, z) Fügt den Vertex (x,y,z) dem Modell hinzu.
d3d_model_vertex_color(ind, x, y, z, col, alpha) Fügt den Vertex (x,y,z) dem Modell hinzu, mit seiner eigenen Farbe und seinem Alphawert.
d3d_model_vertex_texture(ind, x, y, z, xtex, ytex) Fügt den Vertex (x,y,z) dem Modell hinzu, mit Position (xtex,ytex) in der Textur.
d3d_model_vertex_texture_color(ind, x, y, z, xtex, ytex, col, alpha) Fügt den Vertex (x,y,z) dem Modell mit Farbe und Alphawert hinzu.
d3d_model_vertex_normal(ind, x, y, z, nx, ny, nz) Fügt den Vertex (x,y,z) dem Modell hinzu, mit normalem Vektor (nx,ny,nz).
d3d_model_vertex_normal_color(ind, x, y, z, nx, ny, nz, col, alpha) Fügt den Vertex (x,y,z) dem Modell hinzu, mit normalem Vektor (nx,ny,nz), und mit eigener Farbe und Alphawert.
d3d_model_vertex_normal_texture(ind, x, y, z, nx, ny, nz, xtex, ytex) Fügt den Vertex (x,y,z) dem Modell hinzu, mit normalem Vektor (nx,ny,nz), mit Texturposition.
d3d_model_vertex_normal_texture_color(ind, x, y, z, nx, ny, nz, xtex, ytex, col, alpha) Fügt den Vertex (x,y,z) dem Modell hinzu, mit normalem Vektor (nx,ny,nz), mit Textur und Farbwerten.
d3d_model_primitive_end(ind) Beendet die Beschreibung eines Primitiven.

Neben Primitiven kannst du auch grundlegende Formen hinzufügen. Wiederum schauen die Funktionen fast gleich aus aber eben mit Modellindex und ohne Texturinformation:

d3d_model_block(ind, x1, y1, z1, x2, y2, z2, hrepeat, vrepeat) Fügt einen Block hinzu.
d3d_model_cylinder(ind, x1, y1, z1, x2, y2, z2, hrepeat, vrepeat, closed, steps) Fügt einen Zylinder hinzu.
d3d_model_cone(ind, x1, y1, z1, x2, y2, z2, hrepeat, vrepeat, closed, steps) Fügt einen Kegel hinzu.
d3d_model_ellipsoid(ind, x1, y1, z1, x2, y2, z2, hrepeat, vrepeat, steps) Fügt einen Ellipsoiden hinzu.
d3d_model_wall(ind, x1, y1, z1, x2, y2, z2, hrepeat, vrepeat) Fügt eine Wand hinzu.
d3d_model_floor(ind, x1, y1, z1, x2, y2, z2, hrepeat, vrepeat) Fügt einen Boden hinzu.

Das Benutzen von Modellen bringt ordentlich Geschwindigkeitszuwachs in deinem 3D Spiel, nutze sie wann immer es geht!

Abschliessende Worte

Die 3D Funktionen in Game Maker können für ein paar schöne 3D-Spiele genutzt werden, aber sie sind sehr beschränkt und überlassen dir viel Arbeit. Erwarte nicht dein eigenes Quake damit machen zu können. Game Maker ist und bleibt ein Programm um 2-Dimensionale Spiele zu erstellen.

Werbung Werbung

GameMaker Handbuch