Hallo liebes Forum,
wir müssen für die Techniker-Schule(ETechnik) in einem Fach(nennt sich
bei uns ITA) inden wir im ersten Jahr C-Programmieren, ein
"Jahresprojekt" erstellen, in Einzelarbeit, wird dann gewertet wie eine
Klausur/Klassenarbeit. Im zweiten Jahr werden wir dann mit den
C-Kenntnissen in Richtung Mikrocontroller-Programmierung einsteigen(AVR
und später Arduino). Naja soviel dazu.
Ich hatte vor ein "simples" Snake Game in einer Konsolenanwendung unter
Windows anzufertigen.
Mein "Lastenheft" sieht folgendermaßen aus:
- Statisches Snake-Game, also keine dynamische Bewegung, nur mit
entsprechender Taste(Hoch,Runter,Links,Rechts)
- Bei Kollision mit sich selbst oder dem "Map-Rand" -> Spiel-Ende
- Bei Kollision mit dem "Essen" vergrößerung der "Snake".
- Diverse "custommizeable" Parameter(wachsgröße, geschwindigkeit,
mapgröße etc)
- Bei Spielende Anzeige einer Punkte.
- Bei erreichen einer Gewinner Punktzahl -> Spiel Ende
- Das ganze soll grafisch sein, also kein Text
- Das Ganze geschehen, erfolgt über ein Global angelegtes "Map-Array",
welches ein Struct mit (unsigned char) R, G, B ist.
Zum Testen der "Grafik" nutze ich SetPixel, ich weiß dass das Langsam
ist, werde aber erst wenn alles soweit funktioniert, mich genauestens
über BitBlt und Co. informieren.
Das erstmal dazu. Meine konkrete Fragestellung lautet wie folgt:
- Wie realisiert/speichert man die Snake, wenn sich diese bereits durch
Bewegungen verwinkelt hat, beispielsweise der User hat nach rechts
gedrückt und dann ein paar mal hoch, und dann ein paar mal links. Dann
ist die Snake ja U-Formig.
Wie kann man sowas am geschicksten in Variablen ablegen?
Ich habe bisher ein eigenes Struct für die Snake angelegt, welches
start_x, start_y, end_x und end_y beinhaltet. Jedoch ist mir sehr
schnell aufgefallen dass das nur Sinn macht, wenn sich die Snake nur
rechts oder links bewegt ;)
Ich will von euch keinen Code oder so, ich brauche nur einen Ansatz oder
Stichwort, mit dem ich auf die richtige Fährte gelockt werde ;)
Wenn ich meinen bisherigen Code anhängen soll, dann sagt das bitte.
Lieben Gruß
Müller schrieb:> - Wie realisiert/speichert man die Snake, wenn sich diese bereits durch> Bewegungen verwinkelt hat, beispielsweise der User hat nach rechts> gedrückt und dann ein paar mal hoch, und dann ein paar mal links. Dann> ist die Snake ja U-Formig.>> Wie kann man sowas am geschicksten in Variablen ablegen?
Du hast eine Menge von Koordinaten. Eben alle die Punkte, an denen die
Schlange bisher war. Einen Punkt kann man als struct anlegen, er hat
typischerweise eine x- und eine y- Koordinate (bei einer 2D-Spielwelt).
Eine Menge von Punkten kann man nun als ein Array von structs im
Speicher ablegen. Wie groß muss dieses sein? Nun, maximal so groß bis
der Bildschirm voll ist. Wobei die meisten Schlangen wohl nicht so lange
leben ;-)
Müller schrieb:> - Wie realisiert/speichert man die Snake, wenn sich diese bereits durch> Bewegungen verwinkelt hat, beispielsweise der User hat nach rechts> gedrückt und dann ein paar mal hoch, und dann ein paar mal links. Dann> ist die Snake ja U-Formig.
Ich würde mit folgendem Ansatz beginnen:
Lege dir eine Liste an, in der du die Koordinaten der einzelnen Glieder
der Schlange speicherst. Bewegt sich die Schlange, entfernst du den
letzten Eintrag und fügst vorne einen neuen Eintrag ein. Vor dem
Einfügen musst du noch prüfen, ob der Kopf ausserhalb des Spielfelds ist
oder bereits ein Eintrag mit den Gleichen Koordinaten existiert. Hat die
Schlange das Essen eingesammelt, unterdrückst du das Entfernen des
letzten Glieds während den nächsten X Bewegungen.
Ich weiss, dass es elegantere Möglichkeiten gibt, aber denke, dass diese
für den Anfang einfach umzusetzen ist.
Die Schlong hat zum einen eine Gesamtlänge, die durch Fressen größer
wird, und zum anderen besteht sie neben dem Kopf aus Segmenten, die sich
an diesen anschließen.
Macht die Snake eine Kurve, entsteht ein neues Segment, wobei aneinander
granzende Segmente immer einen Winkel von 90° haben, d.h. ein "Knick" in
der Snake darf nur 90° nach rechts oder links gehen.
Beim Zeichnen geht man nun entlang der Segmente, wobei das erste Segment
durch die Bewegung um 1 Einheit länger wird, und das letzte Segment um 1
Einheit kürzer. Wenn die Snake was gefressen hat, dann wird das letzte
Segment nicht verkürzt für eine bestimmte Zeit, wodurch die Snake dann
wächst.
Wobei snake üblicherweise auf einem Spielraster gespielt wird, das
wesentlich gröber ist, als es die Pixelauflösung des Monitors ist. D.h.
du wirst dir da nicht die Pixelkoordinaten speichern (obwohl das
natürlich auch ginge), sondern die Rasterkoordinaten.
Snake eignet sich damit auch ganz wunderbar, um in einer Text-Konsole
gespielt zu werden, wodurch man um den ganzen Grafikkram mehr oder
weniger rumkommt. Das "Spielfeld" ist dann zum Beispiel ein 80*24 Raster
(24 Textzeilen zu je 80 Spalten) und die Snake besteht ganz einfach aus
einer Abfolge von Zeilen/Spalten Positionen, die zb wie schon gesagt in
einem Array gespeichert werden. Zum Zeichnen der Snake geht man einfach
das Array durch und malt an die bestreffende Position zb ein '#' hin.
Die frühen Snakes haben da natürlich dann in die vollen gegriffen und
abhängig aus den Positionsdaten vor bzw. nach einer bestimmten Array
Position anstelle eines '#' eines der verfügbaren 'Grafik-Sonderzeichen'
(Haken links, Haken rechts, waagrecht, senkrecht, ...) ausgewählt, so
dass sich ein durchgehendes Band ergibt.
Da gibt es mehrere Möglichkeiten.
Über das Verlängern der Snake bzw. deren Bewegung wurde ja schon
geschrieben.
Hallo liebe Leute,
falls es jemand interessiert, nach etwa 3 kompletten neuschreiben der
Bewegungsroutinen, habe ich es jetzt so hinbekommen, dass sich die Snake
relativ in alle Richtungen bewegen kann. Am Anfang hatte ich fast 1700
Zeilen Code ;) Jetzt sind es immerhin "nur" 700.
Es sind jetzt zwar einige seltsame Bugs aufgetaucht, die ich mir noch
nicht erklären kann, hab ich jetzt auch nicht weiter geschaut, keine
Lust mehr.
Um ein paar zu nennen:
- Nach Zick-Zack Bewegungen(Rechts, Hoch, Rechts, Hoch) kommt es, wenn
man aufeinmal Konstant Bewegungen(Rechts, Rechts, Rechts) ausführt, zu
seltsamen Artefakten am Ende der Snake. (Vermutlich muss ich irgendwo
Merker einbauen und das rauslöschen erweitern). Das korrigiert sich
jedoch später wieder, wenn man weiter Konstante Bewegungen in eine
Richtung ausführt.
- Kollisionserkennung zum Essen funktioniert gar nicht, das versteh ich
momentan noch gar nicht warum, aber mal schauen, worans liegt.
- Wenn ich den jeweiligen Stack-Sortier-Teil(die for-schleife z.b. Zeile
636) parallel ausführen will mittels OpenMP, führt das extrem seltsamen
Bugs.
Das ganze ist "Stack"-basiert. Wenn eine Bewegung ausgeführt, wird immer
das letzte(im Array ab 0) "Element" gelöscht. Dann das Array
heruntersortiert und etwas neues draufgepackt.
Falls es jemanden interessiert, kann sich ja jemand den Code antuen.
Hint: Funktioniert nur mit Windows.
Schönen Abend noch.