Du solltest es nicht so machen dass du ein Image hast, dass du um zehn nach oben verschiebst oder so. Damit verlierst du irgendwann die Kontrolle. Verwende ein Array, in dem du den Status aller Felder speicherst, also ob es leer ist, oder ob ein Schlangenkopf drin ist, oder ein Futter, oder ein Schlangenschwanz.
Arrays sind eine Art Listen, in denen du numeriert Daten speichern kannst.
Damit du dein zweidimensionales Spielfeld speichern kannst, brauchst du auch ein zweidimensionales Array:
Delphi-Quellcode:
var
array2d:array [0..100 {der x-Wert des Arrays geht von null bis hundert}, 0..100 {der y-Wert auch}] of integer {in jedem Feld des Arrays kannst du einen Integer-Wert speichern};
//Beispiele des Zugriffs:
array2d[7,8]:=9; //ins Feld mit der x-Koordinate 7 und der y-Koordinate 8 im Array
label1.caption:=inttostr(array2d[15,16])); //den Wert in den Koordinaten x:15/y:16 des Arrays auslesen und im Label ausgeben
Arrays verhalten sich genauso wie "normale" Variablentypen, nur dass sie eben noch zusätzlich eine Angabe der Koordinaten innerhalb des Arrays brauchen.
Auf die einzelnen Elemente kannst du dann gut in for-Schleifen zugreifen:
Delphi-Quellcode:
var
a:array [1..100,1..100] of string;
x,y:integer;
begin
for x:=0 to 100 do
for y:=0 to 100 do
a[x,y]:='Hallo';
end;
dieser Code setzt in jedes der 100x100 Felder des Arrays den Text 'Hallo', so dass dieser dann 10000 mal innerhalb des Arrays gespeichert ist.
Ich hoffe das war einigermaßen verständlich
jetzt sollst du dein komplettes Spielfeld speichern in einem solchen Array:
Delphi-Quellcode:
var
spielfeld:array[1..64,1..48 {Spielfeld besteht aus 64x48 Feldern}] of integer; {die Inhalte der einzelnen Felder des Spielfeldes speicherst du als Integer-Werte (0 = Leeres Feld, 1 = Futter, 2 = Schlangenkopf, 3 = Schwanz)}
Als nächstes solltest du dann eine Prozedur schreiben (am besten nimmst du einen neuen Timer, stellst das Intervall so niedrig wie möglich und schreibst den Code dann in die Timer.Click), welche das Spielfeld, über das du genaue Informationen im Array gespeichert hast, auf den Canvas zeichnet. Zuerst musst du in der form.create vier Bilder in tbitmap-Variablen laden, eines für 'Leer', eines für 'Kopf' etc. Die sieht dann etwa so aus:
Delphi-Quellcode:
var
x,y:integer;
feldtyp:integer;
begin
for x:=1 to 64 do begin //alle Horizontalen Reihen nacheinander durchgehen und darstellen
for y:=1 to 48 do begin //für jede Horizontale Reihe von oben nach unten in dieser Reihe alle Felder durchlaufen
//und diese Felder dann aktualisieren bzw. den Inhalt des Arrays bei diesen Koordinaten dort anzeigen
feldtyp:=spielfeld[x,y] //den Wert des Spielfeldarrays bei den gegebenen Koordinaten auslesen
//und dann das entsprechende Bitmap an den Koordinaten auf dem Canvas ablegen:
case feldtyp of
0: form1.canvas.draw(leer,x*16,y*16);
1: form1.canvas.draw(kopf,x*16,y*16);
2: form1.canvas.draw(schwanz,x*16,y*16);
3: form1.canvas.draw(futter,x*16,y*16);
end;
end;
end;
end;
Leer, Kopf, Schwanz und Futter sind hier natürlich die in der form.create geladenen Bitmap-Variablen.
Die Koordinaten, an denen das Bitmap abgelegt wird, werden berechnet, indem der x- und y-Wert mit 16 multipliziert werden, also verwende ich hier eine Größe der einzelnen Felder von 16x16 Pixeln. Du musst die Bitmap-Dateien natürlich entsprechend anpassen oder eine andere Größe verwenden.
Jetzt zur Bewegung:
du solltest vielleicht noch ein Array machen, in dem die Ausrichtung der einzelnen Elemente, also Schwanzteile etc. gespeichert wird. Die Ausrichtung speicherst du auch für jedes Kästchen auf dem Bildschirm.
Mach noch einen Timer, und immer wenn der schlägt, dann wird die Schlange bewegt. Das wird schon schwieriger *g*
Du musst einfach nur auf die Spielfeldvariable zugreifen, und diese entsprechend verändern. Also einfach mal mit einer For-Schleife durchsuchen und z.B. nach einem Kopf-Feld suchen. Wenn du eins gefunden hast, dann setzt du das Feld eins weiter vorne auch auf Kopf. Das alte setzt du auf Leer. Wenn im Umkreis um das alte Feld (4 möglichkeiten) ein Schwanzteil ist, welches in die Richtung dieses Feldes zeigt, dann musst du dieses auf dieses Feld setzen und das Feld, auf dem es früher war, löschen. Damit schreitest du solange fort und ziehst die Schlange Teil für Teil so lange nach vorne bis du das Ende erreichst, also kein Feld mehr findest, das in die Richtung des geräumten zeigt.
Wenn der Kopf der Schlange beim Vorrücken auf ein Futterteilchen stößt, dann machst du es so, dass du das letzte Teil der Schlange, bei dem du hinten ankommst, nicht mehr nachziehst, sondern diese Bewegungsrunde lang einfach 'liegen' lässt, also zwar das alte vorschiebst, allerdings das alte nicht durch einen freien Raum ersetzt sondern durch ein einfaches Schwanzteil ersetzt. Und schon ist die Schlange um ein Schwanzteil länger.
Dann erzeugst du an einer mit ramdom ausgewählten Stelle im Array ein neues Futterteilchen. Achte aber darauf dass du nicht versehentlich eines der Schwanzteile überschreibst:
Delphi-Quellcode:
var
x,y:integer;
begin
randomize; //evtl. auch in der form.create erledigbar
x:=random(64)+1;
y:=random(48)+1; //zufallskoordinaten zuweisen
while spielfeld[x,y]<>0 //solange das Spielfeld mit den x- und ykoordinaten ungleich Null, also kein freies Feld ist,
begin
x:=random(64)+1;
y:=random(48)+1; //neue Koordinaten erzeugen
end;
//jetzt kannst du mit absoluter Sicherheit sagen dass die Koordinaten ein freies Feld anzeigen, da du ja so lange neue erzeugt hast, bis das Feld frei war.
//deshalb kannst du jetzt ein Futterteilchen an den Koordinaten erzeugen:
spielfeld[x,y]:=3;
end;
Ich würde dir auch auf jenden Fall
meinen Snake-Klon ans Herz legen, da werden alle Tipps, die ich dir soeben gegeben habe, umgesetzt. Der Code ist dabei.