Ergebnis 1 bis 14 von 14

Thema: [Tutorialreihe] Dein erstes Spiel mit Game Maker Studio 2 - Beispiel: Onna Gokoro

  1. #1

    [Tutorialreihe] Dein erstes Spiel mit Game Maker Studio 2 - Beispiel: Onna Gokoro


    Umaiki Games präsentiert
    Dein erstes Spiel mit Game Maker Studio 2
    Case Study: Onna Gokoro




    Einleitung:

    Hallo RPG-Atelier!
    Das Game Maker Studio (GMS) ist eine vielseitige integrierte Entwicklungsumgebung (IDE), die es einem ermöglicht, schnell und komfortabel 2D-Spiele unterschiedlichster Genre zu designen. GMS war die Grundlage für sehr erfolgreiche Titel wie Hotline Miami, Undertale, Downwell, Nuclear Throne und Hyper Light Drifter. Der neuste Ableger, das Game Maker Studio 2 (GMS2), steht in den Startlöchern und kann als Betabuild erworben werden. GMS2 hat einen ausgezeichneten Map- und Spriteeditor und stellt eine wunderbare Basis dar, um mit dem Erstellen von Videospielen anzufangen! GMS2 steckt euch nicht in ein Korsett wie der RPG-Maker, verlangt dafür aber deutlich mehr/überhaupt erst Skriptarbeit.

    Damit euch der Anfang nicht schwer fällt, werde ich euch mit diesem Tutorial bei den ersten Schritten begleiten. Wir verwenden das beliebte RPG-Maker-Spiel Onna Gokoro von Sabaku als Beispiel und versuchen es im Game Maker Studio 2 nachzubauen! Dabei werden wir verschiedene Funktionen und Ansätze beim Arbeiten mit dem Game Maker Studio 2 kennenlernen.


    Wenn Fragen oder Anregungen aufkommen, schreibt sie gerne in diesen Thread! So können wir uns Stück für Stück einen schönen Leitfaden für GMS2-Einsteiger erarbeiten!

    Hier die Liste der bisherigen Lektionen:

    Lektion 1: Projekt starten und erste Schritte beim Titelbildschirm!

    Lektion 2: Cursor-Bewegung!

    Geändert von Schotti (03.12.2016 um 23:55 Uhr)

  2. #2
    Lektion 1: Projekt starten und erste Schritte beim Titelbildschirm!

    Heute werden wir ein Projekt öffnen und den GMS2 soweit einstellen, dass wir ein schönes Titelbild starten können. Diese Lektion umfasst:

    • Einen Raum mit Kameras und Viewport einstellen
    • Ein Objekt mit Draw-Event erstellen
    • Ein kleines Skript schreiben


    Wir öffnen über "File -> New Project" ein neues Projekt und machen es zu einem Game Maker Language (GML)-basierten Projekt. Mit dem GMS2 können wir auch über Drag N Drop Spiele erstellen, wir nutzen jedoch die Skriptsprache, da wir so schneller und effizienter sind! Je nach gewähltem Modus wird die IDE den entsprechenden Bedürfnissen angepasst.



    Rechts sehen wir das Ressourcen-Fenster. Das Ressourcen-Fenster ist eine Bibliothek der unterschiedlichen Assets, Skripte, Maps, Objekte etc. die wir in den GMS2 importiert oder dort drin erstellt haben. Im Sprite-Unterpunkt seht ihr zwei Sprites, die ich dort direkt mit der Maus reingezogen habe: spr_titlescreen und spr_cursor. Beim GMS können Sprites direkt aus einem Ordner ins IDE gezogen werden und müssen nicht extra importiert werden. Ich verwende spr_ vor dem eigentlichen Namen, damit ich direkt rauslesen kann, was genau sich dahinter verbirgt, in dem Fall also Sprites. spr_titlescreen ist eine 320x240 große Grafik, die unser Hintergrund für den Titelbildschirm ist. spr_cursor wird ein herzförmiger Cursor (15x13) sein, mit dem wir die Titelmenü-Unterpunkte anvisieren werden. rm_titlescreen ist der default-Raum, den ich nur über Rechtsklick umbenannt habe. Räume sind wie Maps beim RPG-Maker und können mit Objekten gefüllt werden. f_titlescreen in die Schriftart, die ich im Titelmenü gerne hätte.



    Hier nochmal ein paar Worte zu der Schriftart: über Rechtsklick auf "Fonts"und "Create" öffnet sich das unten abgebildete Fenster. Ich verwende Bitstream Vera Sans Mono als eine frei verfügbare Schriftart, die auf den gängigen Font-Webseiten gedownloaded werden kann. Grundsätzlich können alle(!) auf dem Rechner installierte Schriftarten verwendet werden.




    Das sind alle Ressourcen, die wir für die heutige Lektion brauchen. Als nächstes Klicken wir auf rm_titlescreen und öffnen den Raumeditor. Dieser sieht wie folgt aus:

    Layer funktionieren wie bei Photoshop und ermöglichen unterschiedliche Hintergründe, Objekte und ähnliches in ihnen unterzubringen. Hätten wir zum Beispiel zwei Background-Layer, könnten wir so zwei unterschiedliche Hintergrundgrafiken im Raum anzeigen lassen und so leicht Parallax-Effekte oder ähnliches erzeugen.



    Bei den Eigenschaften (Properties) des Raums können wir unterschiedliche Einstellungen vornehmen. Auf die gehen wir jetzt im Detail ein:

    Unter Room Settings stellen wir die Größe des Raums ein. Da unser Sprite 320x240 groß ist, wird auch unser Raum diese Dimensionen haben.
    Unter Viewports und Cameras erstellen wir eine Camera, die unseren Bildabschnitt darstellt. Stellt euch vor, ihr habt einen Raum mit den Dimensionen 6000x6000. Natürlich könnt ihr diesen nicht vollständig auf einem Bildschirm abbilden sondern habt einen Bildabschnitt mit der gewünschten Auflösung, der über diesen Raum wandert. Zusätzlich stellen wir den Viewport an. Der Viewport entspricht der Übertragung der Spielauflösung durch die Camera auf das eigentliche Spielfenster. Wir wählen einen Faktor von 2 und damit 640x480, damit wir beim Spielen überhaupt was sehen können! Pixelgrafiken sollten stets um ganze Vielfache der ursprüngliche Grafik vergrößert werden, damit keine Artefakte entstehen.



    Abschließend klicken wir auf den Background-Layer und fügen den Titlescreen-Sprite als Hintergrundgrafik ein. Damit ist der erste Abschnitt fertig! Bevor wir an den Wahlmöglichkeiten arbeiten, sollten wir uns erstmal vergewissern, ob alles so funktioniert wie wir es uns vorgestellt haben.



    Wir starten das Spiel über den Playbutton oben links. Das GMS2 geht davor aus, dass der erste Raum in der Ressourcenreihenfolge auch der erste Raum im Spiel ist. Lasst uns auf Play drücken und schauen was passiert!



    Folgendes Fenster sollte bei euch erscheinen. Falls es nicht der Fall ist, ist bis hierher etwas schief gelaufen. Geht nochmal durch das Tutorial und schreibt gegebenfalls in den Thread, damit ich euch helfen kann!



    Nun wollen wir als letzten Teil dieser Lektion die Schrift einfügen. Dazu brauchen wir ein Objekt, welches das Zeichnen kontrolliert. Dazu Rechtsklick auf "Objects" im Ressourcenfenster und dann "Create", wodurch sich das Objektfenster öffnet. Wir benennen es in obj_titlemenu und fügen über Add Event ein Draw-Event hinzu! Ein Draw-Event ist ein Codefragment, welches jeden Frame gelesen wird und Text oder Sprites zeichnet.



    Im Draw-Event habe ich folgenden Code reingeschrieben:
    Über Doppelslash könnt ihr Kommentare einfügen im Code, sehr praktisch um diesen organisiert zu halten. Unter defaultsettings habe ich die Schriftfarbe und die die Schriftart festgelegt, welche ab jetzt genutzt werden soll. Unter get camera id speichere ich in der Variable cam die ID der Kamera, die wir im Roomeditor angelegt haben. Das ist wichtig, da wir so die x-und y-Werte unserer Schrift nicht in Bezug auf den Raum sondern in Bezug auf unseren Bildschirmabschnitt wählen können.

    Unter draw text schreiben wir unseren Text für die Menüauswahlen. Die Funktion lautet draw_text(x,y, "string"). Die obere linke Ecke hat die (x,y)-Koordinaten (0,0), die untere rechte Ecke ist (320x240). Damit der Text unabhängig von der Größe des Raums ist und nur vom Bildschirmabschnitt abhängt, nehmen wir als x-Wert camera_get_view_x(cam) und addieren die gewünschte Verschiebung von x = 0 dazu.

    Unter draw cursor zeichnen wir den Cursorsprite. Die Funktion lautet draw_sprite(sprite, subimage, x, y). Subimage ist wichtig, wenn der Sprite aus mehreren Animationsframes besteht, auf die wir zugreifen wollen. Da es ein einfacher Sprite bei uns ist, ist subimage = 0.



    Nun öffnen wir wieder unseren Raum und ziehen über das Ressourcenfenster unser neues Objekt obj_titlemenu dort rein. Jetzt testen wir das Ganze und schauen wie es aussieht:



    Schon nicht schlecht, aber irgendwie ist die Schriftart langweilig und nicht so gut leserlich, da es keinen Schatten gibt. Lasst uns noch schnell ein neues Skript schreiben, um dieses Problem zu lösen! Mit Skripten können eigene Funktionen wie draw_text(); geschrieben werden und das macht unseren Code übersichtlich! Rechtsklickt im Ressourcenfenster auf "Scripts" und erschafft ein neues über "Create"!

    Was genau passiert im Skript? Wir wollen eine neue Funktion mit dem Namen draw_text_shadow(); In der Klammer sind die Argumente, die wir der Funktion zur Verfügung stellen, damit es was schönes damit macht. Dies ist zum einem x- und y-Positionen, die in argument0 und argument1 gespeichert werden. Warum ich die Infos in xx und yy speichere? Weil x und y schon fest eingebaute Variablen vom Objekt sind, und diese wollen wir nicht! Anschließend setzen wir die Farbe auf shadow_color (argument4) und zeichnen unseren Text, dieser ist aber um 1 Pixel nach rechts und unten verschoben, damit er wie ein Schatten aussieht! Anschließend setzen wir die Farbe wieder auf die Schriftfarbe (argument3) und zeichnen auf der "richtigen Position" unseren Text drüber. Anschließend setzen wir die Schriftfarbe wieder auf default, falls wir z.B. nen gelben Text wollten.



    Nun passen wir unser Draw-Event im obj_titlemenu mit diesem neuen Skript an und definieren über die make_color_rgb()-Funktion die Farbe unseres Schatten. Der Code des Draw-Events sollte nun so aussehen:



    Fertig! Lasst uns das Endergebnis anschauen. Schöner Schatten, oder? In der nächsten Lektion werden wir den Cursor auf Tasten reagieren lassen (und sogar Gamepad!) und so das Startmenü funktional gestalten. Hinterlasst doch einen Kommentar/euer Feedback und bis nächste Woche!


  3. #3
    Da ich den Game Maker nicht habe bringt mir das Tutorial natürlich recht wenig, aber ich finds geil, dass ihr das macht.

  4. #4
    Ich habe auch keine Erfahrungen mit dem Game Maker. Was sind denn die wesentlichen Unterschiede zum RPG Maker? Hier interessieren mich vor allem die auf die Erstellung eines 2D-Rollenspiels bezogenen Möglichkeiten.

  5. #5
    @real Troll
    Der wesentlichste Unterschied ist wohl, dass der Game Maker nicht spezialisiert ist. Das ist Fluch und Segen zugleich. Auf der einen Seite bietet das Werkzeug viel mehr Möglichkeiten, auf der anderen Seite erfordert es auch mehr Einarbeitung, es sei denn in der neusten Version gibt es jetzt schon Presets für Rollenspiele.

  6. #6
    Großartige Sache!
    Da ich mir vor geraumer Zeit Game Maker Studio gekauft hatte, mich in naher Zukunft mehr damit auseinandersetzen wollte und dann ohnehin nach Tutorials für den Einstieg gesucht hätte, kommt diese Tutorialreihe hier wie gerufen. Alles schön Schritt für Schritt, in leicht verdaulichen Happen und großzügig bebildert... Ich bin schon mal gespannt auf die kommenden Lektionen.

  7. #7
    Ich hab dein Tutorial jetzt durch.
    Als erste Lektion ist es wirklich sehr gut geeignet und man kommt zu einem schönen Ergebnis. Der Aufbau ist auch erste Sahne. Allerdings sehe ich da zwei gravierende Problemzonen.

    1) Es gibt sehr vieles, das du nicht ausreichend bis gar nicht erklärst. Du erläuterst, wie du vorgehst und man kann es problemlos nachbauen, aber an einigen Stellen bleibt u.a. das Verständnis für das, was man da eigentlich tut, auf der Strecke.
    Warum z.B. haben wir die Farbe unter den defaultsettings eingestellt? (Genaugenommen nutzen wir diese gar nicht bzw. nicht als solche.) Du erwähnst ja noch den Fall einer möglichen gelben default color. Stattdessen stellen wir die weisse Farbe (im späteren Verlauf) jedes mal auf's Neue manuell ein. An dieser Stelle müsste es so wie bei der Farbe des Schattens geschrieben werden.
    Beispielsweise:

    c_default = c_white;

    Es wäre auch sinnvoll, zu erwähnen, warum man einmal c_white schreibt und ein anderes mal eine Farbe über make_color_rgb festlegt.


    2) Für den Anfang sind es zuviele Informationen. Bei dem Teil mit dem Schatten hast du mich komplett verloren.
    Die Sache mit dem Skript ist viel zu kompliziert für den Einstieg. Du hast gut erklärt, was in dem Script selbst passiert, aber nicht, wie man dieses verwendet oder wie ein Script an sich funktioniert. Argumente oder die vertauschte Reihenfolge von Argument 3 und 4 (ich kann mir denken warum, aber das wird nicht auf jeden zutreffen) sind hier nicht nachvollziehbar.
    Sinnvoller wäre an der Stelle gewesen, es erstmal einfacher, wenn auch weniger elegant zu lösen. Den Text beispielsweise simpel zweimal mit dem gleichen Code-Block zeichnen und nur die Werte usw. anpassen. Hier kann man dann auch gut erwähnen, dass wir das zu einem späteren Zeitpunkt nochmal aufgreifen um es eben eleganter, für ein besseres Verständnis aber erstmal so lösen.
    Ich gehe mal davon aus, dass du Scripts bereits eingeführt hast, da wir diese in der nächsten Lektion wieder nutzen werden. Trotzdem finde ich, dass man dies ans Ende der Titelmenüreihe setzen sollte. Viel wichtiger, als es auf Anhieb möglichst ordentlich zu machen, ist, zu verstehen was man tut. Optimierungen sollten zugunsten eines leichteren Einstiegs auf einen späteren Zeitpunkt verlegt werden. Das Tempo ist für die erste Lektion einfach deutlich zu hoch.

    Wenn du es unbedingt bereits einführen willst, dann muss es ausreichend erklärt werden. Dein Beispiel eignet sich durchaus gut, um dies in wenigen Worten zu erreichen. Sofern man es nicht doch irgendwie begriffen haben sollte, müsste man sich momentan anderweitig in einem solchen Umfang in das Thema einlesen, dass es den Rahmen des Tutorials sprengen würde. Wenn man es erstmal verstanden hat, ist so ein Script nurnoch eine Kleinigkeit, aber bevor es soweit ist, kann man sich daran die Zähne ausbeissen.
    Eine andere Möglichkeit wäre, einmal klar und deutlich zu sagen, dass wir einiges im Rahmen dieser Lektion, um den Lernenden nicht zu überfordern, unkommentiert lassen, mit dem Hinweis, später (gut und gerne auch in einer anderen Lektion) im Einzelnen darauf einzugehen. Dies sollte dann aber auch möglichst bald geschehen, damit der rote Faden nicht verloren geht.


    Da es sich um einen Einstiegskurs handelt, muss man es aus der entsprechenden Perspektive betrachten. Du hast bereits ausreichend Erfahrung und weisst natürlich, was du tust. Ebenso werden Leute mit Programmiererfahrung sicher schnell dahintersteigen. Die Wahrscheinlichkeit, dass sich ein Anfänger nicht zurechtfindet, ist aber enorm groß.
    Der Sinn eines Tutorials sollte es nicht sein, dem Lernenden zu zeigen, wie man es nachbaut, sondern ihm beizubringen, es hinterher selber bauen zu können. Momentan geht es leider, wenn man es ganz hart ausdrückt, eher in Richtung Malen-nach-Zahlen.

  8. #8
    Zitat Zitat von real Troll Beitrag anzeigen
    Ich habe auch keine Erfahrungen mit dem Game Maker. Was sind denn die wesentlichen Unterschiede zum RPG Maker? Hier interessieren mich vor allem die auf die Erstellung eines 2D-Rollenspiels bezogenen Möglichkeiten.
    Kelven hat es eigentlich schon ganz gut zusammengefasst. Du kannst jeden Aspekt deines RPGs so gestalten wie du möchtest, vom Menü hin zum Kampfsystem. Diese gestalterische Freiheit kommt aber auch daher, dass du jeden Aspekt selber skripten musst. Das hört sich schwerer an als es ist, da der GMS2 eine Vielzahl an Funktionen in der Rückhand hat, die man einfach implementieren kann (z.B. Collision, etc.).

    Zitat Zitat von Les Beitrag anzeigen
    Großartige Sache!
    Da ich mir vor geraumer Zeit Game Maker Studio gekauft hatte, mich in naher Zukunft mehr damit auseinandersetzen wollte und dann ohnehin nach Tutorials für den Einstieg gesucht hätte, kommt diese Tutorialreihe hier wie gerufen. Alles schön Schritt für Schritt, in leicht verdaulichen Happen und großzügig bebildert... Ich bin schon mal gespannt auf die kommenden Lektionen.
    Freut mich! Einen Großteil der Codefragmente wirst du auch im GMS1 nutzen können, das Tutorial ist aber für den GMS2 ausgelegt.

    @Nagasaki:
    Danke für dein Feedback und das es dir gefallen hat! So ein Feedback ist mir wichtig, damit ich weiß, an welchen Stellen ich zu schnell war und wo nochmal Nachholbedarf herrscht. Ich werde die Hinweise nochmal einpflegen, um es aber schonmal kurz anzuskizzieren:

    a) die draw_text(x, y, string)-Funktion hat keine Farbauswahl, deswegen schreibe ich aus Prinzip vor jedem Drawevent die Defaultfarbe und den Defaultfont hin für Funktionen, die beide nicht vorher einstellen. Werde ich an dieser Stelle besser erklären.
    b) c_white ist eine Standardfarbe, die im GMS schon vorgegeben ist. Das Grau für den Schatten ist nicht vorhanden, deswegen muss es über make_color_rgb(); festgelegt werden. Dieser Sprung war zu weit, ich werde das im Text schöner beschreiben, damit jeder besser mitkommt.

    Nun zu deinem zweiten Punkt, ich werde kurz meine Designphilosophie und die damit verbundenen Baustellen erklären:

    Lektion 1 nimmt eine Sonderstellung in diesem Tutorial ein. Mein Ziel war es, dass am Ende der Lektion ein schönes Endergebnis vorliegt und der User sagen kann: "Ja, ich hab was erschaffen!". Ich finde, so etwas motiviert mehr als ein Tutorial, wo nach 4-5 Lektionen erst die ersten Ergebnisse angeschaut werden können. Für dieses Endergebnis habe ich eine etwas längere Lektion in Kauf genommen. bei denen manche Funktionen nur grob angerissen werden. Manches zu grob, deswegen werde ich ein paar Punkte nach deinen Vorschlägen überarbeiten.

    Der User wird also einmal grob über paar Funktionen geführt und kriegt ein Gefühl für das IDE und wie man Sprites importiert und etwas codet. Er hat nun ein schönes und sichtbares Fundament, auf dem ich in den nächsten Lektionen sehr kleinschrittig aufbauen und wert darauf legen kann, dass er jeden Schritt genau nachvollzieht. Aus der groben Übersicht wird nun Detailwissen Lektion 2 wird z.B. ein beweglicher Cursor sein, etwas was deutlich weniger Code ist und das Thema Skripte und Objekte nochmal aufgreift und erklärt. Das schöne dabei: Nach Lektion 2 haben wir ebenfalls ein schön sichtbares Endergebnis: Ein Cursor, den man hoch und runter bewegen kann!

    Ich hoffe, dass erklärt den Aufbau von Lektion 1 und warum er eine Sonderstellung in diesem Tutorial einnimmt! Keine Angst, mit diesem Tempo wird es definitiv nicht weitergehen

  9. #9
    Danke für die Erklärungen. Ja, der Skriptaspekt klingt erst mal abschreckend (und sieht auf den Beispielbildern auch abschreckend aus ). Ich glaube, ich locke mein beinahe verschrecktes Interesse mit ein paar schönen Videos werbender Anwendungsbeispiele aus seinem Unterschlupf hervor. Die Suche nach "Game Maker RPG" spuckt eine durchaus ansehnliche Trefferzahl aus.
    Gibt es denn besonders empfehlenswerte* Projekte?

    *Sei es, weil sie staunen lassen, sei es, weil sie eine spezifische Game-Maker-Möglichkeit besonders gut illustrieren.

  10. #10






    Sind einige international ausgezeichnete Spiele, die auf dem Gamemaker entstanden sind. Game-Maker-spezifische Möglichkeiten sind schwer zu nennen. Es ist eben eine deutlich allgemeinere Engine. Wenn es 2D ist, kannst du es damit umsetzen (<- das ist die spezielle Möglichkeit, die Gamemaker bietet).
    Das beinhaltet auch Sachen wie vernünftigen Gamepad Support, Netcode, Shader...

    Hier noch ein Showreel von 2016:

    Geändert von Tako (27.11.2016 um 18:29 Uhr)

  11. #11
    Lektion 2: Cursor-Bewegung!

    In der letzten Lektion haben wir unseren ersten Titelbildschirm gebastelt. Heute werde wir lernen, wie wir unseren Cursor mittels Tastendruck bewegen können! Damit nähern wir uns einen weiteren Schritt hin zum funktionierenden Menü! Diese Lektion umfasst:

    • Was sind Variablen?
    • Mehr Wissen über Skripte
    • Funktion von Alarms in GMS2


    Fangen wir nochmal bei Skripten an. Was genau ist ein Skript? Skripte sind Codezeilen, die immer wieder Verwendung während unseres Projekts finden. Da wir nicht jedesmal die gleichen Codezeilen eintippen wollen und unseren Code übersichtlich halten möchten, lohnen sich Skripte sehr! Skripte können unterschiedlich genutzt werden. Eine Möglichkeit ist die Codeauslagerung. Diese Methode werden wir gleich beim Input-Skript nutzen. Hierbei wird ein Codefragment, der immer wieder Anwendung findet, in ein Skript ausgelagert und kann über skript(); aufgerufen wurden. Der GM2 wird an der Stelle der Aufrufung dieses Codefragment reinkopieren.

    Eine andere Möglichkeit ist es, ein Skript zu schreiben, dem wir Argumente zuschicken. So können wir z.B. ein Skript namens addition(argument0, argument1); schreiben. Wir übermitteln dem Skript dann zwei Zahlen und kriegen dann vom Skript den addierten Zahlenwert zurückgeschickt. Der GM2 hat solche Skripte selber schon eingebaut als Funktionen, wie z.B. die keyboard_check();-Funktion.

    Das Additionsskript würde wie folgt aussehen:



    Die dem Skript zugeschickten Argumente argument0 und argument1 werden in Variable a und b gespeichert, danach werde beide addiert und der neu errechnete Wert wird in Variable c gespeichert. Variable c wird dann vom Skript wieder zu dem Code zurückgeschickt, der das Skript aufgerufen hat.


    Lasst uns dies an einem praktischem Beispiel vertiefen und verinnerlichen! Über Rechtsklick auf Scripts im Ressourcenfenster öffnen wir ein neues Skript und schreiben folgendes rein:



    Der GM2 hat als Funktion keyboard_check(argument0);, das ist quasi ein Skript, dem wir als Argument eine Taste vorgeben, und die Funktion gibt uns aus, ob sie gedrückt ist (true) oder nicht gedrückt ist (false). Warum argument0? Der GM2 fängt beim Zählen immer bei 0 an. Wenn wir also diese Funktion aufrufen, kriegen wir ein "ja, gedrückt" oder "nein, nicht gedrückt" zurück. Diese Information speichern wir in eine Variable. Eine Variable im GMS2 kann unterschiedliche Datentypen speichern, sei es nun Zahl, String oder Boolean (true/false, 0/1). Die Variable muss beim GMS2 nicht vorher einem Typen zugeordnet werden. Das ganze sieht dann so aus:

    right_key = keyboard_check(vk_right) or keyboard_check(ord("D"));

    Übersetzt heißt es in dem Fall: Wenn die rechte Pfeiltaste (vk_right) gedrückt wurde, wird in der Variable right_key der Wert true abgespeichert, ansonsten false. Dieses Spiel machen wir auch für die anderen 3 Pfeiltastenrichtungen und wir haben sehr nützliche Codezeilen, die wir immer wieder aufrufen können über scr_input();, wenn wir die Tastenaufrufe in Variablen gespeichert haben möchten.

    ---

    Gehen wir nun zu unserem bisher einzigen Objekt über, obj_titlemenu. Doppelklickt auf ihn. Wir fügen ein paar Codezeilen hinzu! Als erstes fügen für über Add Event ein neues Event hinzu, ein Create-Event. Code im Create-Event werden nur einmal aufgerufen, und zwar wenn das Objekt im Spiel erschaffen wird. Sonst nicht mehr! Schreibt folgendes rein:



    Wir haben zwei Variablen initiiert, also dem Objekt gesagt, dass es sie gibt und er sie sich merken soll, cursor und max_cursor. Unser Titelmenü hat drei Unterpunkte, "Start", "Load" und "End", diese entsprechen den Zahlenwerten 0, 1, 2. Nicht vergessen, wir fangen bei 0 an zu zählen! In der variable cursor speichern wir ab, bei welchem Unterpunkt wir uns befinden, bei 0 also bei "Start". Als weitere Variable initiieren wir max_cursor. Diese Variable speichert den Wert ab, die den maximalen Unterpunkt im Menü widerspiegelt, also 2 und damit "End"! Warum das wichtig ist, erfahren wir gleich.

    Als nächstes fügen wir ein Step-Event hinzu. Der Code im Step-Event wird jeden Frame abgerufen, immer und immer wieder. Hier schreiben wir rein, wie sich cursor verändert, wenn wir eine Taste drücken. Folgender Code kommt rein:



    Was haben wir getan? Zuerst haben wir scr_input(); aufgerufen. Damit steht uns für den weiteren Code die Variablen up_key und down_key zur Verfügung, da sie in dem von uns geschriebenen Skript initiiert werden. Sehr praktisch und nur eine Zeile Code!

    Anschließend folgt ein if-Statement. Der Aufbau ist z.B. if(argument0 == true) {führe diesen Code aus}.
    Wir überprüfen also, ob die Bedingung für argument0 (in dem Fall: argument0 ist true) erfüllt ist und führen dann den Code aus, ansonsten bleibt dieser unangetastet! Das ist sehr praktisch, da wir so Code selektieren können! Die Bedingungen können ganz unterschiedlich sein, von argument > 10 (argument0 ist größer als 10) bis hin zu argument0 = "Peter" (wenn das Argument Peter beinhaltet, wird der Code ausgeführt). In meinem Fall steht if(down_key), das ist eine Kurzschreibweise. down_key ist entweder true/1 oder false/0. Wenn in der if-Abfrage nur der Variablenname steht, wird automatisch geprüft, ob die Variable true/1 ist und dann wird der Code ausgeführt.

    In unserem Fall steht also if (down_key){cursor++}. Wenn die Taste nach unten gedrückt wird, dann wird der Code in der geschwungenen Klammer ausgeführt, in dem Fall also cursor++, das bedeutet, die Variable cursor wird um 1 erhöht.

    Ich hoffe, diese Erklärung war verständlich genug, sonst fragt nochmal nach!

    Wir überprüfen also, ob down_key gedrückt wurde. Wenn ja, wird der cursor um 1 erhöht (cursor++;). Das Problem hierbei ist, dass wir die Werte so über einen Maximalwert von 2 erhöhen können, bis wir mit dem Cursor aus dem Bildschirm rausfliegen! Aus diesem Grund bauen wir ein weiteres if-Statement ein, welches den Cursor wieder auf 0 setzt, wenn die cursor-variable über den Wert von max_cursor und damit 2 ist.

    Das gleiche Prinzip gilt für den up_key. Kleine Transferübung: schaut euch den Code an und versucht ihn selber nachzuvollziehen! Wenn ihr euch sicher seid, lest weiter. Wenn nicht, lasst einen Kommentar da

    Als nächstes Modifizieren wir das Draw-Event aus der vorherigen Lektion. Wir ändern den y-Wert beim spr_cursor! Zuvor stand da ein Wert von 145, bezogen auf die Camera. Nun modifizieren wir es zu 145 + 18*cursor.



    Warum? Die Unterpunkte auf dem Bildschirm sind 18 Pixel voneinander entfernt. Wir müssen mit dem Cursor also mit jedem Menüpunkt 18 Pixel runtergehen (nicht vergessen: bei GMS2 ist (0,0) oben links und größere y-Werte bedeuten Schritte nach unten). Der Ausdruck 18*cursor tut genau dies! Wenn wir beim Menupunkt "Start" sind, hat die variable cursor einen Wert von 0 und damit addieren wir nix zur ursprünglichen Position des Cursors (wie wir auch wollen!). Mit cursor = 1 sind es 18 Pixel und mit cursor = 2 sind es 36 Pixel. Pfiffig!

    Lasst uns nun auf Play drücken und dann Ergebnis unserer Arbeit anschauen! Ich habe dies mal als gif aufgenommen und wild auf den Tasten rumgedrückt:



    Es funktioniert! Aber: es ist zu schnell! Warum? Die Antwort liegt im Step-Event. Wir überprüfen jeden Frame (bei uns aktuell: 30 frames pro Sekunde), ob die Taste gedrückt ist und das führt zu einem irrsinnigem Tempo (halt 30 mal pro Sekunde!). Hinweis an dieser Stelle: ihr seid beim GMS2 nicht auf 30 frames beschränkt und könnt auch auf 60 fps oder höher gehen. Dann wird der Code im Step-Event aber 60 mal pro Sekunde abgefragt (wie ihr seht: doppelte Leistung erforderlich).

    Wir müssen also GMS2 beibringen, dass er unsere Taste nicht bei jedem Step abfragt, damit es nicht zu schnell wird! Aus diesem Grund werden wir als letzten Teil unserer Lektion einen Alarm bauen.

    Fangen wir beim Create-Event unseres Objekts an, dieses modifizieren wir nun! Wir initiieren eine neue Variable, sie heißt pressed. In ihr speichern wir die Information, ob eine Taste gedrückt wurde oder noch nicht. Am Anfang ist natürlich keine Taste gedrückt, wir schreiben also hin: pressed = false;



    Als nächstes gehen wir zum Step-Event. Folgende Änderung nehmen wir vor:



    WIr überprüfen, bevor wir den Cursor nach unten bewegen über cursor++; nicht nur, ob down_key stimmt sondern prüfen auch, dass keine Taste vorher gedrückt wurde, über die pressed-Variable. Folgendes passiert nun: wenn pressed gleich false ist und die Taste nach unten gedrückt wurde, bewegt sich der Cursor nach unten UND die variable pressed wird auf true gesetzt. Wenn wir nun die Taste weiterhin gedrückt haben und das if-statement im nächsten Step nochmal abgefragt wird, dann wird der Code nicht ausgelöst, da die variable pressed nun true ist! Im Endeffekt bedeutet es: Man kann die Taste nur einmal bewegen, danach reagiert das System nicht mehr durch Cursorverschiebung. Das wollen wir nicht, deswegen führen wir einen Alarm ein. Wir schreiben alarm[0] = 5;, das bedeutet, dass der Code im alarm[0]-Event nach 5 steps/frames einmal ausgeführt wird. Und was schreiben wir in alarm[0]-Event rein? Folgenden Code, nachdem wir alarm[0] über Add Event eingefügt haben:



    Was passiert im alarm[0]-Event? Wir setzen pressed wieder auf false. Im Endeffekt bedeutet das jetzt: das if-Statement wird, wenn es einmal ausgelöst wurde, erst nach 5 Frames wieder ausgelöst werden können! Wir haben jetzt einen Code, der bei Tastendruck nach unten nicht jedem Frame nach unten springt sondern nur jeden fünften! Das sieht als gif so aus:



    Und damit beenden wir Lektion 2 und haben einiges über Skripte, Variablen und Alarms gelernt... und können unseren wunderschönen Herzcursor auf und ab bewegen!

    Freue mich über eure Kommentare/Feedback und bis nächste Woche!

  12. #12
    Hey Schotti,
    ich finde es großartig dass Du nun eine RPG-spezifische Tutorialreihe für das GMS2 herausbringst. Auch die Themenwahl ist für mich als "praktisch Veranlagter" sehr passend.

    Ich kann die Einwände zu den Skripten verstehen, bin aber aufgrund meines Umgangs mit den neueren RPG Makern bereits das Lesen von Skripten gewohnt und weiss somit direkt "sauberen/eleganten" Code zu schätzen. An dieser Stelle kann ich aber auch nur nochmal hervorheben, dass man sich davon nicht einschüchtern lassen, sondern es als Möglichkeit betrachten sollte. So sind beispielsweise "endlich" pixelgenaue und performante AKS möglich!

    Jedenfalls werde ich mich in den nächsten Tagen mal hinsetzen und alles Erlernte umsetzen. Mit dem Hinweis zum korrekten Skalieren von Pixelgrafiken ist mir auch schon geholfen - Widescreen sollte dann mit etwas Rechnung auch möglich sein. Weiter so!

    Geändert von ChimaereJade (24.12.2016 um 15:31 Uhr)

  13. #13
    Lektion 3: Transition - Part I!

    In der letzten Lektion haben wir unseren Titelbildschirm gebastelt und einen Cursor implementiert, der sich mit den Pfeiltasten steuern lässt. Sehr gut! Heute werden wir uns an einen Bildschirmübergang setzen, der richtig schön retro ist! Wir lernen:

    • Import von animierten Sprites
    • Steuerung der Animation
    • Der Einsatz von Grids


    Auf gehts! Als erstes erstellen wir einen animierten Sprite. Dieser Spritestrip besteht aus 11 Sprites mit einer Größe von 16x16 Pixel. Ziel der Animation ist es, aus einem transparentem 16x16 Sprite ein komplett schwarz gefülltes 16x16 Sprite werden zu lassen. In welcher Art und Weise oder Form ihr dies tut, ist euch selber überlassen. In diesem Beispiel ist es eine Kreisform, in SANTRIA nutze ich z.B. einen Rhombus. Eurer Kreativität ist keine Grenze gesetzt! Fügt die einzelnen Sprites anschließend in folgender Weise zu einer png aneinander:



    Als nächstes importieren wir dieses File. Wir fügen es wie immer per Drag n Drop in den Sprite-Ordner des Ressourcenbaums. Folgendes Fenster erscheint:


    Wir klicken nun doppelt auf das Vorschaubild des Sprites (neben dem großen Plus), um den Image-Editor des GMS2 zu öffnen. Über den Reiter Image -> Convert to Frames können wir unser Bild nun zuschneiden und GMS2 beibringen, wieviele und wie groß die Einzelbilder für die Animation sind. Fancy! Füllt das Fenster nun mit den nötigen Daten aus:



    Wir haben 11 Einzelbilder, die 16x16 groß sind. Soweit so gut! Fertig ist unser animierter Sprite mit dem Namen spr_transition. Herzlichen Glückwunsch, du weißt nun, wie man Animationen einpflegt! Nun wollen wir diese Sprites gleichmäßig über unseren Bildschirm verteilen und ihre Animation abspielen lassen. Lasst uns erstmal ein Objekt mit dem Namen obj_transition_controller erstellen und folgende Code-Zeilen in das Create-Event schreiben:



    Folgende Überlegungen stecken hinter diesem Code:
    Wir speichern die Pixel-Höhe und Pixel-Breite unseres Spielbildschirms in die Variablen resolution_x und resolution_y. Wie ihr aus den Daten sehen könnt, hat unser Spielfeld die Größe 320x240. Anschließend speichern wir die Größe unseres Transition-Sprites, welches praktischerweise 16 Pixel hoch und breit ist. gridsize ist damit 16. Der nächste Schritt ist zu bestimmen, wie oft nun unser Sprite in Höhe und Breite auf unseren Bildschirm passt. Wir teilen also unsere Bildschirmbreite durch die Sprite-Breite bzw. die Bildschirmhöhe durch die Sprite-Höhe und stellen fest, dass unser Sprite 20 mal in die Breite und 15 mal in die Höhe passt. Diese Werte sind in heightgrid und widthgrid gespeichert. Warum Grid? Wir teilen nun unseren Bildschirm in Zeilen und Spalten auf, jede Zelle entspricht der Größe unseres Transitionsprites. Nun wollen wir jede Zelle mit einem Objekt füllen, welches unseren Transition-Sprite trägt. Wir könnten nun 20x15 Objekte an die richtige Stelle manuell setzen... oder wir machen es uns einfacher und lassen dies GMS tuen! Dazu nutzen wir zwei verschachtelte for-Schleifen. Die erste for-Schleife ist folgendermaßen aufgebaut:

    for (j = 0; j < heightgrid; j++){}

    Zuerst wird die Variable j initialisiert und auf 0 gesetzt. Diese Variable nutzen wir, um unsere x-Position auf dem Grid zu zählen. Anschließend wird überprüft, ob die Bedingung noch erfüllt ist, in dem Fall, dass j kleiner ist als die maximale Anzahl an Objekten in x-Richtung, heightgrid. Wenn dies der Fall ist, wird der Code in den geschwungenen Klammern ausgeführt und abschließend das letzte Statement der for-Schleife ausgeführt, j++, gleichbedeutend mit der Erhöhung von j um 1. Was wir mit der for-Schleife bewerkstelligen, ist einmal durch alle Zeilen durchzugehen! Sehr gut. Wir wollen aber nicht nur stumpf die Zeilen durchgehen sondern bei jeder Zeile zuerst die Spalte einmal durcharbeiten, bevor es zur nächsten Zeile geht. Deswegen arbeiten wir mit zwei ineinander verschachtelten for-Schleifen und arbeiten uns durch das Grid. j entspricht also der Zeilenposition und i die Spaltenposition! Das ganze Prozedere kann man sich so vorstellen:



    Die Transitionobjekte werden über die Funktion instance_create_layer(x, y, Layer, Objektname); auf den Bildschirm gesetzt. Die nötige x und y-Position wissen wir durch die Variabeln i und j, welche mit der Sprite-Breite bzw. Höhe multipliziert werden. Wir nutzen den default Layer für Objekte, also "Instances". Voila! 300 Objekte werden ins Spiel geworfen, ohne diese mühsam per Hand in den Raum reinzusetzen! Ok, nun wollen wir das eigentliche Transition-Objekt basteln. Erstellt ein Objekt mit dem Namen obj_transition und schreibt folgendes in das Create-Event, nachdem ihr dem Objekt unser Transition-Sprite zugewiesen habt:



    Mit image_speed setzen wir fest, wie schnell den einzelnen Frames unserer Animation abgespielt werden. Anschließend lernen wir ein neues Event kennen, das Animation End-Event, welches wir über Add Event und Other hinzufügen. Der Code im Animation End-Event wird einmal abgerufen, wenn die Animation des Sprites, welches dem Objekt zugewiesen ist, durch ist. Hier schreiben wir folgendes rein:



    Wir sorgen hier dafür, dass der image_speed auf 0 gesetzt wird, der Sprite also nicht zum nächsten Frame springt und das animieren beendet und setzen fest, dass ab jetzt nur noch image_index = 10; also der letzte Sprite der Animation angezeigt wird (unser Strip hat 11 Bilder und wir zählen von 0, also ist das letzte Bild 10!). Fertig ist das Transition-Objekt. Damit kommen wir nun auch zum letzten Teil des Tutorials. Geht hierfür in das Stepevent des allerersten Objekts, welches ihr erschaffen habt und schreibt folgendes rein (rotes Kästchen):



    Über die Entertaste erschaffen wir nun das Controller-Objekt, welches in seinem Create-Event die einzelnen Transition-Objekte an die richtige Position setzt. Diese Objekte spielen ihre Animation einmal ab und bleiben beim letzten Frame ihrer Animation stehen... TOTALE FINSTERNIS auf dem Bildschirm

    Das Endergebnis sieht nach Enterdruck wie folgt aus:



    Wunderschön! Ich hoffe, ihr habt ein wenig mehr über GMS2 gelernt und hattet Spaß beim Durcharbeiten des Tutorials. In den nächsten Parts lernen wir, wie wir die Objekte zeitversetzt erschaffen und die Transition so umbauen, dass wir wirklich in einen anderen Raum übergehen!

  14. #14
    Hey Schotti, ich habe nun endlich mal etwas Zeit gefunden und mich mit der Hilfe deiner Tutorialreihe ein klein wenig mit dem Game Maker 2 auseinandergesetzt. Bei dem Script im ersten Teil habe ich auch nicht durchgeblickt, weshalb ich die Schatten jetzt nur mit Nagasakis Variante darstelle. Davon abgesehen habe ich aber auch gleich versucht ein bisschen herumzuexperimentieren, da ich so mehr lerne als nur durch simples Nachbauen. Mein bisheriger Stand sieht folglich so aus:

    Bis jetzt sind deine Tutorials echt eine riesige Hilfe und ich freue mich schon auf weitere Teile

    Gruß
    Stoep

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •