SnakeKlon

Fu3L

Top Contributor
Hallo^^
Nachdem mein Breakout-Klon mich wegen der schwierigen Kollisionserkennung frustriert hatte, wollte ich mal etwas leichtes schreiben, um ein wenig das Erfolgserlebnis eines fertigen Programms zu genießen. Deswegen habe ich einen kleinen Snake-Klon geschrieben.

Moment ist er sehr einfach gehalten. Steuerung mit wsad oder den Pfeilstasten, Pause mit P.
Eigentlich bewegt sich die Schlange Zelle für Zelle über das Spielfeld, aber durch ein paar Tricks beim Zeichnen bewegt sich immerhin der Kopf stetig.
Die Sounds habe ich mit sfxr erstellt, ein seeeehr nützliches Tool für jeden Minispiele-Programmierer^^ ;)
Vllt erweitere ichs demnächst noch um Level mit Hindernissen oder ner Highscoreliste, mal sehen^^
Probierts einfach mal aus ;)

Edit: Neue Version hochgeladen mit dem vllt Soundfix für eRaaaa
 

Anhänge

  • SnakeGame.jar
    243,9 KB · Aufrufe: 297
Zuletzt bearbeitet:

Empire Phoenix

Top Contributor
Wirkt auf jdenfall sauber, keine hänger und ruckler, gut :)

Ich kenne noch nen ursnake aus predos zeiten, da hatteste pro level 20 einsammeln müssen, dann hat sich nen ausgang geöffnet, wennde dadurch bist ist neues level geladen mit immer mehr hindernissen. Viele buchstaben eigenen sich btw gut als hindernisse, nen T nen H nen U usw.

Evtl, könnteste die blockgörße etwas kleiner machen, und dafür den speed schneller, ist relativ langsam.
 

eRaaaa

Top Contributor
So ganz klappt das mit dem Sound bei mir aber nicht. Zwei mal kam Sound, dabei hats aber ganz schön gestockt und danach kam nichts mehr (Ubuntu 10.10)

In den Source jetzt rein zu gucken oder mir die Lib an zu schauen habe ich gerade keine Lust :p
 

Fu3L

Top Contributor
Danke fürs Interesse.
@Empire Phoenix: Ich hatte erst ein 20x20 Grid, das erschien mir (bei der langsamen Geschwindigkeit) zu langsam^^ Mal sehen, ob ich noch dran schraube. Vllt mach ich auch, dass es schneller schneller wird, wenn man die Cyanfarbenen Nahrungsblöcke einsammelt (die sorgen für eine Beschleunigung, sodass ein "Tick" 25 ms kürzer dauert, bis minimal 200 ms pro Tick (Startwert ist 400))
An Level, die erreicht werden müssen, hatte ich gar nicht gedacht, da lässt sich drüber nachdenken ;)

@eRaaaa: Bei der Soundklasse hab ichs mir recht einfach gemacht:

Java:
import java.applet.Applet;
import java.applet.AudioClip;

public class Sound {
	private static AudioClip rub = Applet.newAudioClip(Sound.class.getClassLoader().getResource("sounds/rub.wav"));
	private static AudioClip failedToConsume = Applet.newAudioClip(Sound.class.getClassLoader().getResource("sounds/failedToConsume.wav")); 
	private static AudioClip consumed = Applet.newAudioClip(Sound.class.getClassLoader().getResource("sounds/consumed.wav")); 
	private static AudioClip dConsumed = Applet.newAudioClip(Sound.class.getClassLoader().getResource("sounds/dConsumed.wav")); 
	private static AudioClip failure = Applet.newAudioClip(Sound.class.getClassLoader().getResource("sounds/failure.wav")); 
	
	private static boolean mute = false;
	private static boolean muteMov = true;
	
//Wird aktuell gar nicht mehr verwendet
	public static void rub() {
		if(!mute && !muteMov) {
			rub.play();
		}
	}
	public static void failedToConsume() {
		if(!mute) {
			failedToConsume.play();
		}
	}
	public static void consumed() {
		if(!mute) {
			consumed.play();
		}
	}
	public static void dConsumed() {
		if(!mute) {
			dConsumed.play();
		}
	}
	public static void failure() {
		if(!mute) {
			failure.play();
		}
	}
	
	public static void mute(boolean b) {
		mute = b;
	}
	
	public static void muteMov(boolean b) {
		muteMov = b;
	}
	
} //ENd Sound

Geladen werden die Sounds bei dir ja anscheinend, also müsste es eigentlich irgendwo anders liegen?
 

Fu3L

Top Contributor
Könnte helfen...
Aber habs nochma nachgelesen, ich meine, das werde intern generell von einem neuen Thread abgespielt... Mal testen^^
 
Zuletzt bearbeitet:

Fu3L

Top Contributor
So, habs mal in nen extra Thread gepackt, ka, obs hilft. Neue Version im ersten Post ;)

Java:
package sound;

import java.applet.Applet;
import java.applet.AudioClip;

public class Sound {
//Rest weggelassen
	private static AudioClip rub = Applet.newAudioClip(Sound.class.getClassLoader().getResource("sounds/rub.wav"));
	
	private static boolean mute = false;
	private static boolean muteMov = true;
	
	public static void rub() {
		if(!muteMov) {
			play(rub);
		}
	}
	public static void failedToConsume() {
		play(failedToConsume);
	}
	public static void consumed() {
		play(consumed);
	}
	public static void dConsumed() {
		play(dConsumed);
	}
	public static void failure() {
		play(failure);
	}
	
	private static void play(final AudioClip a) {
		if(!mute) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					a.play();				
				}
			}).start();
		}
	}
	
	public static void mute(boolean b) {
		mute = b;
	}
	
	public static void muteMov(boolean b) {
		muteMov = b;
	}
} //ENd Sound
 

Fu3L

Top Contributor
Doof :(
Aber woran kann das liegen? Bei meinem Breakout-Klon wird auch hin und wieder mal der eine oder andere Ton verschluckt, aber größtenteils klappts..
Obwohl ich Leute nicht mag, die ihre Fehler direkt auf die API schieben, hab ich die Vermutung, dass es an der Sound-API liegt. Den besten Ruf hat die ja eh nicht^^
 
Y

yyannekk

Gast
also bei mir funzen die sounds
was mich ganz leicht stört ist dass die schlange mit verzögerung lenkt bzw erst dann lenkt wenn sie an der richtigen position dafür ist, das fühlt sich irgendwie nicht ganz sauber an.
da würde ich entweder die schlange schneller machen dass es nicht auffällt oder die "vierecke" (oder positionen oder was auch immer xD ) kleiner. ich mein das ist nur ne kleinigkeit aber mich hats irgendwie n bissel gestört
sonst isses gut gelingen denk ich
 

Fu3L

Top Contributor
Danke fürs Spielen :)

Das mit der Bewegung ist tatsächlich etwas "ungünstig". Ich hatte das Snake Spiel von meinem ersten Handy im Kopf, als ich meins kreiert habe und da bewegte die Schlange sich nur Quadrant für Quadrant und so habe ich meins gebaut. Erst im Nachhinein kam die flüssige Animation am Kopf.. Ich weiß nicht, ob ich es noch irgendwann einmal updaten werde. Erstmal der Breakoutklon ;)
Aber wenn, dann wird alles flüssiger ;)
 

recab

Mitglied
also ich finds ganz lustig ^^ habe 147 punkte erreicht aber nur i-wie 4 von den "großen" eingesammelt ^^ war lustig so halbes spielfeld blau :3
 

Kr0e

Gesperrter Benutzer
Abgesehen davon, dass ich jedes mal denke, mein Herz bleibt stehen wenn ich verliere, ist es ein kleines lustiger Gamechen =)
 

Fu3L

Top Contributor
Jo, ich hängs an.

Keine Garantie auf besonders schönen Programmierstil, aber es sollte schon annehmbar sein ;)

Musste es als 7zip archivieren, da es als zip zu groß gewesen wäre. Das Programm 7zip kann dieses entpacken ;)

@Kr0e: Danke :) Demnächst gibts nochn Spiel von mir, dass ich für die Ludum Dare 48h Competition gebaut habe, es muss nur noch feingeschliffen werden ;)
 

EnHancEd[]

Aktives Mitglied
bei mir funktioniert die Steuerung nicht richtig, wenn man etwas schneller hintereinander z.B. hoch , rechts, hoch, links drückt wird nur ein Befehl wargenommen.. aber ansonsten gut gelungen :) Die Größe von der Schlange ist gut gelungen.

greetz
 

Fu3L

Top Contributor
bei mir funktioniert die Steuerung nicht richtig, wenn man etwas schneller hintereinander z.B. hoch , rechts, hoch, links drückt wird nur ein Befehl wargenommen..

Es ist in dem Sinne weniger ein Bug als ein Feature. ;) Die Schlange bewegt sich auf einem Gitter und somit wird, sobald ein Feld vollkommen erreicht / ausgefüllt ist, genau ein Bewegungsbefehl ausgeführt und zwar der letzte. Wie bereits gesagt, hab ich das Spiel schnell gemacht, um mal wieder was fertig zu haben, nachdem der Breakoutklon so lange dauerte (ist im Übrigen mitlerweile fertig, baue nur noch ein paar Level, wenn ich mal Zeit hab^^ ;))
 

DarXun

Aktives Mitglied
Guten Morgen Fu3L,

ich habe mir gerade mal deinen Quellcode des SnakeKlons angeschaut.

Soweit ich das verstanden habe, mißt du die Zeit vor und nach dem Ausführen der Spiellogik und dem darauffolgenden Zeichnen.
Diese Zeit wird im nächsten Durchlauf der Loop dann der Methode doLogic mitgegeben.

Jetzt der eigentliche Knackpunkt (für mich):
Ist es richtig, dass du nur bei einer bestimmten Größe von 'delta' die Logik neu "berechnen" lässt?
D.h., sollte ein Durchlauf der Loop zu schnell gewesen sein, so wird nichts getan und gewartet, bis genügend Zeit verstrichen ist, bis die Logik neu berechnet wird? (evtl. um das Spielgeschehen flüssig erscheinen zu lassen?)

Wenn das soweit richtig von mir verstanden ist:
Siehst du diese Vorgehensweise als optimal oder könntest du dir bessere/andere Möglichkeiten zum Umsetzen der GameLoop vorstellen?

Mit freundlichen Grüßen

DarXun~
 

Fu3L

Top Contributor
Hallo,
ich erkläre es dir gerne:
Erst wollte ich schreiben: "Müsste delta eine gewisse Größe haben, damit ich was tue, wäre ja auch irgendwo ein if zu sehen ;)", als Eclipse dann gestartet war, sah ich, dass es tatsächlich drin steht^^ Das ist aber hier ein Sonderfall, weil die Schlange sich eben nur mit einer gewissen (sich steigernden) Geschwindigkeit über ein Spielgitter bewegt. D.h. ich brauche auch nur den Zustand des Spiels neu zu berechnen, wenn ein neues Feld erreicht werden soll. Da der Schlangenkopf sich kontinuierlich bewegt (was ich erst nachträglich eingebaut habe), siehst du, dass ich doch mehr FPS habe, als die, die nach dem if in GameState möglich wären.

Allgemein gibt es zwei Varianten:
1)Das Spiel läuft in einer Schleife wirklich kontinuierlich. Damit sind dann FPS von weit über 1000 möglich, wenn fast nichts getan werden muss. Für größere Spiele wird das meist angeboten.
2)Das Spiel läuft in einer Schleife, wird aber auch immer für einige Millisekunden schlafen gelegt pro Durchlauf, um Strom und evtl. auch Lüftergeräusche zu sparen und andere Anwendungen im Hintergrund nicht auszubremsen (meist bei kleineren Spielen).

Es gibt allerdings auch in den großen Spielen meist die Möglichkeit, dass die FPS zB auf 60 begrenzt werden. Dann könnte irgendwo ein Thread.sleep() genutzt werden, um jeden Durchlauf etwas zu verlängern. Wie das bei ganz großen Spielen gemacht wird, kann ich nicht sagen, aber ein einfaches "continue;" wird designmäßig nicht gerade schön, da die ständig durchlaufende while-Schleife dann trotzdem CPU-Zeit in einem Kern verschwendet.

Das delta spielt dabei und das ist, soweit ich weiß, in allen großen Engines so, eine sehr wichtige Rolle:
Hast du mal einen lag im Spiel, ob nun verursacht durch das Spiel selbst, oder einen anderen Prozess, der Vorrang hat, so ist delta umso größer. Da man zB die Bewegung normal in Abhängigkeit von delta betreibt (delta * velocity), bewegen sich die Figuren dann einfach etwas mehr auf einmal, um diesen lag auszugleichen. Alte DOS-Spiele laufen teilweise heute mit wirklich unspielbar enormer Geschwindigkeit,weil damals einfach ein while(true) {} ohne irgendein sleep genutzt wurde und einfach jeder Durchlauf genau gleich verändert hat :D
Allerdgins kann es widerrum nötig sein, dass das Physiksystem dann doch aus einem großen delta mehrere Durchläufe macht, um zB zu vermeiden, dass ein Objekt einfach eine Wand durchläuft, weils dann schon dahinter ist^^

(PS: Die Frage und diese Antwort kamen zuerst per PN zustande, aber auf mal war die Antwort lang und so profitiert vielleicht noch jemand anders davon)
 

Neue Themen


Oben