Forum: PC-Programmierung C - Hilfestellung zu Snake-Game


von Müller (Gast)


Lesenswert?

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ß

von Mark B. (markbrandis)


Lesenswert?

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 ;-)

: Bearbeitet durch User
von B. S. (bestucki)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Müller (Gast)


Lesenswert?

@Mark

Wieso komm ich nicht auf sowas ? ;)

Genial werd mich direkt ransetzen, ich danke dir.

von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wie wär's mit so einem Display?

https://www.youtube.com/watch?v=rqNEdBNwlp8

von Müller (Gast)


Angehängte Dateien:

Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.