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