GLBasic Benutzerhandbuch

Main sections

10 Das erste Spiel

One More



Über das Spiel


Das ursprüngliche Spiel (denke ich), war ein Teil eines Spiels, das LOGO von Starbyte für den Amiga500 genannt wurde. Ziel ist, alle farbigen Punkte von einem Spielfeld zu entfernen. Wann immer der Spieler einen Block anklickt, ändert er dessen Status und den der vier angrenzenden Blöcke.

Also, klickt man auf den Mittelpunkt dieses Spielfelds:
###
###
###
sähe es danach so aus:
#+#
+++
#+#

Dieses Spiel ist recht einfach zu programmieren und läßt eine Menge Raum für eigene Ideen. Es ist auch nett, da wir Computer erzeugte Spielstufen haben können. Wir lassen einfach den Computer zufällig Punkte anklicken. Das Spielen ist ziemlich schwierig, sobald der Computer mehr als etwa 10 Punkte angeklickt hat...

Neues Projet


Nach dem Start von GLBasic den Kopf "Neues Projekt" auswählen, und einen Namen + Pfad angeben. z.B. ..\GLBasic\Projects\OneMore

Das Hauptprogramm



Nun, der Grundcode sieht etwa so aus (Pseudo-code):
main:
WENN level_komplett DANN neues_level_erstellen
WENN maus_geklickt DANN steine_aendern
spielfeld_anzeigen
GEHE_ZU main

Zuerst benötigen wir ein Spielfeld (playfield), um zu speichern ob ein Block aktiviert oder deaktiviert (leer) ist. Wir verwenden den Wert 0 für leer, da der DIM Befehl immer alle Werte mit 0 belegt und folglich veranlasst, dass die erste WENN Aussage ausgewertet wird - ein neues Level wird für uns erstellt.

// --------------------------------- //
// Project: OneMore

DIM playfield[10][10]
    level = 0


Jetzt, haben wir ein Feld, das "playfield" genannt wird von der Größe 10x10 Zahlen. Wir können die Zellen über die Indizes 0-9 ansprechen.Siehe DIM Befehl.
  // Hauptprogramm
main:
MOUSESTATE mx, my, b1, b2
PRINT "<=", mx, my-8
SHOWSCREEN
GOTO main
END


Kompilieren und laufen lassen. Schaut nett aus, aber macht nicht viel. Wir haben einen Zeiger, den wir mit der Maus verschieben können. Am besten alle verwendeten Befehle in deren Referenz nachlesen. Die PRINT Zeile ist unser Mauszeiger. Man kann später ein nettes Sprite dafür laden und verwenden. Das my-8 verschiebt die Anzeige um eine halbe Zeichenhöhe. Das SHOWSCREEN nicht vergessen!

Spielfeld anzeigen



Jetzt, möchten wir die playfield-Daten anzeigen, also fügen wir eine neue SUB hinzu. Drücke dazu den SUB-Knopf und gebe den Namen "ShowPlayfield" ein.

// ------------------------------------------------------------- //
// -=# SHOWPLAYFIELD #=-
// ------------------------------------------------------------- //
SUB ShowPlayfield:
    LOCAL x, y, color[]

DIM color[2]
    color[0] = RGB( 50, 50, 255) // Not set
    color[1] = RGB( 50, 255, 50) // Set

    DRAWRECT 0,0, 320, 320, RGB(255,255,255)
    FOR x=0 TO 9
        FOR y=0 TO 9
            DRAWRECT x*32+1, y*32+1, 30, 30, color[playfield[x][y]]
        NEXT
    NEXT
    PRINT "Klicks: "+clicks, 360, 120
    PRINT "Level: "+level, 360, 160
ENDSUB // SHOWPLAYFIELD




Hier erstellen wir ein lokales Feld, das color (=Farbe) genannt wird und weisen dem ersten Index [ 0 ] Blau zu und dem zweiten Index [ 1 ] Grün. Zunächst zeichnen wir ein weißes Viereck, das über den gesamten Berich des Spielfelds gezogen wird. Dann kommt eine doppelte FOR Schleife. Eine für x und dann wiederum für jedes x noch ein y für jede Zeile. Für jede Zelle füllen wir ein Rechteck mit der Zellenfarbe. Wir benutzen color[ playfield[x][y] ] für den RGB-Wert. So erhält 0 das Blau, 1 bekommt Grün. Weiter informieren wir den Benutzer über das gegenwärtige Level und die Anzahl der Mausklicks bis jetzt für dieses Level.
Füge diese Zeile im Hauptprogamm unterhalb der "MOUSESTATE-" Zeile hinzu:
   GOSUB ShowPlayfield


Kompiliere + starte das Spiel. Sieht schon besser aus, aber macht noch nicht viel?

Interaktion



Zunächst, fügen wir eine Funktion mit dem FUNKTIONS-Knopf hinzu und tragen den Namen "Change" ein. Die Argumente sind: x, y
Dieses ist der Punkt, an dem wir die playfield-Felder ändern möchten.

// ------------------------------------------------------------- //
// -=# CHANGE #=-
// ------------------------------------------------------------- //
FUNCTION Change: x, y
    // Diese Variablen sind LOCAL definiert:
    // x, y
    IF x>=0 AND x<10 AND y>=0 AND y<10
        set = playfield[x][y] // Alten Zustand holen
        
        IF set = TRUE
            set=FALSE
        ELSE
            set=TRUE
        ENDIF
        // order einfach:
        // set = 1-set
        playfield[x][y]=set // Neuen Zustand setzen
    ENDIF
ENDFUNCTION



In dieser Funktion setzen wir das playfield[x][y] auf 1, wenn es 0 war und umgekehrt. Aber wir überprüfen auch, ob der Punkt x, y die 0-9, 0-9 Grenzen überschreitet. Wenn das so ist, ändern wir nichts, sonst kommt eine Fehlermeldung vom laufenden Programm: DIM ausserhalb zulässigem Bereich.

Füge jetzt eine Funktion mit dem FUNKTIONS-Knopf hinzu. Gebe den Namen "Click" und die Argumentliste: x, y an.

Dieses ist der Punkt, der angeklickt werden soll.

// ------------------------------------------------------------- //
// -=# CLICK #=-
// ------------------------------------------------------------- //
FUNCTION Click: x, y
    // Diese Variablen sind als LOCAL definiert:
    // x, y
    clicks=clicks+1
    Change(x-1, y)
    Change(x+1, y)
    Change(x, y)
    Change(x, y-1)
    Change(x, y+1)
ENDFUNCTION


Hier ändern (Change) wir den Wert des angeklickten Punktes und seiner Nachbarn. Weiter erhöhen wir die Variable für die getätigten Mausklicks um 1. Ändere das Hauptprogramm, so dass es wie folgt aussieht:

DIM playfield[10][10]

    level = 0

    // Hauptprogramm
    start:
        MOUSESTATE mx, my, b1, b2
        IF b1
            IF mousefree THEN Click(mx/32, my/32)
            mousefree=FALSE
        ELSE
            mousefree=TRUE
        ENDIF
    
        GOSUB ShowPlayfield
        PRINT "<=", mx, my-8
        SHOWSCREEN
    GOTO start
END



Die Variable mousefree gibt uns an, ob der Spieler die Maustaste seit dem letzen Click() immer noch gedrückt hält. Wenn ja, wird die Schleife solange durchlaufen, bis er die Maustaste wieder losgelassen hat. Starte jetzt das Programm. Es sollte ganz nett aussehen. Mach Dich mit der Funktionsweise des Spiels vertraut. Klicke zufällig einige Male und versuche, das Brett wieder zu löschen. Macht das Spaß?

Level



Fügen wir eine SUB "NewLevel" hinzu:
// ------------------------------------------------------------- //
// -=# NEWLEVEL #=-
// ------------------------------------------------------------- //
SUB NewLevel:
    LOCAL x, y, i

    // Spielfeld löschen - um sicher zu gehen
    FOR x=0 TO 9
        FOR y=0 TO 9
            playfield[x][y]=FALSE
        NEXT
    NEXT

    level=level+1
    // Zufällig 'rumklicken
    FOR i=0 TO level
        Click(RND(9), RND(9))
    NEXT
    clicks=0
    GOSUB ShowPlayfield
    PRINT "Level: "+level + " - bereit?", 0, 360
    SHOWSCREEN
    MOUSEWAIT
ENDSUB // NEWLEVEL


In dieser SUB, löschen wir zuerst das playfield, um wirklich sicher zu gehen, dass es leer ist. Zunächst erhöhen wir die "level" Variable. Dann lassen wir den Computer ein paar mal zufällig Click()en und setzen die Anzahl der clicks auf 0, da der Spieler ja noch nicht geklickt hat. Jetzt kann der Computer schon Level erzeugen, aber noch nicht feststellen, ob ein Level gelöst wurde.
Dazu fügen wir eine FUNCTION ein mit dem Namen: "IsLevelComplete":

// ------------------------------------------------------------- //
// -=# ISLEVELCOMPLETE #=-
// ------------------------------------------------------------- //
FUNCTION IsLevelComplete:
    LOCAL x, y

    FOR x=0 TO 9
        FOR y=0 TO 9
            IF playfield[x][y]=TRUE THEN RETURN FALSE
        NEXT
    NEXT
    RETURN TRUE
ENDFUNCTION


Hier prüfen wir einfach in einer doppelten Schleife, ob eine Zelle gesetzt (TRUE = 1) ist. Wenn ja, geben wir FALSE zurück. Das Level ist also noch nicht leer. Wenn die Schleife durchläuft ohne durch ein RETURN herauszuspringen, muss davon ausgegangen werden, dass das Feld leer ist. Also geben wir TRUE zurück.
Um das komplette Spiel zu testen, füge bitte folgenden Code im Hauptprogramm unter "main:" ein:

        IF IsLevelComplete()
            GOSUB NewLevel
            mousefree=FALSE
        ENDIF


Starte das Spiel. Wie fühlt man sich, wenn man ein völlig qualifiziertes Computerspiel geschrieben hat?
Wenn Du
BLENDSCREEN "images"+level".bmp" 

der SUB NewLevel hinzufügst, ist das Spiel sogar besser als die ursprüngliche Amiga-Version! Ist das nicht ein großartiges Gefühl? Du bist jetzt der Herr dieses Computers. Sage ihm, was zu tun ist, und er folgt Deinem Befehl. Du kannst Welten mit einigen einfachen Befehlen erschaffen. Hier ist der komplette Quellcode, falls Du etwas verpasst haben solltest:


// --------------------------------- //
// Project: OneMore

DIM playfield[10][10]

    level = 0

    // Hauptprogramm
    start:
        IF IsLevelComplete()
            GOSUB NewLevel
            mousefree=FALSE
        ENDIF

        MOUSESTATE mx, my, b1, b2
        IF b1
            IF mousefree THEN Click(mx/32, my/32)
            mousefree=FALSE
        ELSE
            mousefree=TRUE
        ENDIF
    
        GOSUB ShowPlayfield
        PRINT "<=", mx, my-8
        SHOWSCREEN
    GOTO start
END

// ------------------------------------------------------------- //
// -=# SHOWPLAYFIELD #=-
// ------------------------------------------------------------- //
SUB ShowPlayfield:
    LOCAL x, y, color[]

DIM color[2]
    color[0] = RGB( 50, 50, 255) // Not set
    color[1] = RGB( 50, 255, 50) // Set

    DRAWRECT 0,0, 320, 320, RGB(255,255,255)
    FOR x=0 TO 9
        FOR y=0 TO 9
            DRAWRECT x*32+1, y*32+1, 30, 30, color[playfield[x][y]]
        NEXT
    NEXT
    PRINT "Clicks: "+clicks, 360, 120
    PRINT "Level: "+level, 360, 160
ENDSUB // SHOWPLAYFIELD


// ------------------------------------------------------------- //
// -=# CLICK #=-
// ------------------------------------------------------------- //
FUNCTION Click: x, y
    // These values are defined LOCAL:
    // x, y
    clicks=clicks+1
    Change(x-1, y)
    Change(x+1, y)
    Change(x, y)
    Change(x, y-1)
    Change(x, y+1)
ENDFUNCTION


// ------------------------------------------------------------- //
// -=# CHANGE #=-
// ------------------------------------------------------------- //
FUNCTION Change: x, y
    // These values are defined LOCAL:
    // x, y
    IF x>=0 AND x<10 AND y>=0 AND y<10
        set = playfield[x][y] // alten Zustand merken
        
        IF set = TRUE
            set=FALSE
        ELSE
            set=TRUE
        ENDIF
        // oder einfach nur:
        // set = 1-set
        playfield[x][y]=set // Neuen Zustand setzen
    ENDIF
ENDFUNCTION


// ------------------------------------------------------------- //
// -=# NEWLEVEL #=-
// ------------------------------------------------------------- //
SUB NewLevel:
    LOCAL x, y, i

    // Spielfeld lösche - nur um sicher zu gehen
    FOR x=0 TO 9
        FOR y=0 TO 9
            playfield[x][y]=FALSE
        NEXT
    NEXT

    level=level+1
    
    // Zufällig 'rumklicken
    FOR i=0 TO level
        Click(RND(9), RND(9))
    NEXT
    clicks=0
    GOSUB ShowPlayfield
    PRINT "Level: "+level + " - bereit?", 0, 360
    SHOWSCREEN
    MOUSEWAIT
ENDSUB // NEWLEVEL


// ------------------------------------------------------------- //
// -=# ISLEVELCOMPLETE #=-
// ------------------------------------------------------------- //
FUNCTION IsLevelComplete:
    LOCAL x, y

    FOR x=0 TO 9
        FOR y=0 TO 9
            IF playfield[x][y]=TRUE THEN RETURN FALSE
        NEXT
    NEXT
    RETURN TRUE
ENDFUNCTION

See also...