Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Daedra22

Treue Seele

  • »Daedra22« ist der Autor dieses Themas

Beiträge: 115

Wohnort: Osten

Beruf: Student Informationstechnik

  • Private Nachricht senden

1

27.05.2013, 11:02

Menue- und Spiel-Funktion, als While-Schleifen hintereinander. mit gegenseitiger Abfrage

Hallo wie der Titel schon verrät, versuche ich für mein Tic Tac Toe spiel, nach und vor jedem spiel das Menue zu öffnen und somit die Abfrage zu gewährleisten, ob das Spiel beendet oder neu gestartet wird.

Ich habe dazu 2 Variablen,

----------------------------------
bool Spiel=false;

bool Menue=true;

while(Menue==true)
{
SDL_BlitSurface(Menue,NULL,screen,NULL);

if("Auf neues Spiel geklickt wird")
{Spiel=true;
Menue=false;
}
}

while(Spiel==true)
{
"Lade Spielgrafik, Starte Spiel usw";
if("Spiel ist zuende")
{Menue=true;
Spiel=false;
}
}



----------------

so wäre die Abfrage stark vereinfacht, das Problem ist, dass ich das Spiel einmal aus dem Menue aus starten kann, danach wenn es aber vorbei ist, das Menue nicht aufgerufen wird, sondern das Spiel beendet wird, also die while schleife geht zuende und springt nicht zurück zur vorherigen while schleife, wie kann ich gewährleisten, dass die while schleifen sich ständig gegenseitig abfragen, also immer wenn menue true ist, dass menue offen ist und immer wenn Spiel true ist, das Spiel offen, aber niemals beide variablen gleichzeitig true sein können.

Danke für die Hilfe, schonmal im Voraus
Who are you? - I am a game designer.
No you are not! - I am a game designer.
What kind of a designer ? - I am a game designer.
You mean you play games ? - I am a game designer.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

27.05.2013, 11:29

Na so laufen die beiden Schleifen hintereinander ab und wenn die zweite beendet wird ist das Programm zu Ende. Das heißt, du musst beide zusammen in eine Schleife stecken. Soll nur ein Wert true sein, so kannst du dir statt der Bool Variablen eine einzelne Variable für den aktuellen Spielstand anlegen. Dafür gibt es Enumerationen.

C-/C++-Quelltext

1
2
3
4
5
6
enum Spielzustand
{
menu,
game,
ende
}

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Spielzustand zustand = menu;
while(zustand != ende)
{
    while(zustand == menu)
    {
        if(Escape gedrückt)
        {
            zustand = ende;
        }
        if(Enter gedrückt)
        {
            zustand = ende;
        }
    }
    while(zustand == game)
    {
        // Spielcode
    }
}

Sowas in der Richtung. Natürlich geht das auch vollig anders. Wenn du schon ein wenig mehr Erfahrung hast, so guck dir doch mal an was ein Zustandsautomat ist. Das Zustands-Muster wäre eine Implementierung dazu. Wenn du jetzt jeden Zustand deines Programms (Menu, Game, Intro, etc) als Klasse umsetzt und mit Polymorphie arbeitest, so kannst du den aktuellen Zustand updaten, rendern und austauschen. Weiterführend kannst du danach mal nach GameStates bei Google suchen. Da findest du normal einiges dazu, wie man solche Zustandsautomaten in Spielen für genau das verwendet. Wenn man das verstanden hat wird das ganze direkt um einiges Übersichtlicher. Auch im Wiki haben wir einen Artikel zu dem Thema. Die Implementierung dort gefällt mir persönlich nicht besonders, aber meine Meinung ist ja auch nicht Gesetz:) Gucks dir einfachmal an.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Daedra22

Treue Seele

  • »Daedra22« ist der Autor dieses Themas

Beiträge: 115

Wohnort: Osten

Beruf: Student Informationstechnik

  • Private Nachricht senden

3

27.05.2013, 13:27

eine elegante Lösung, die sogar funktioniert, vielen dank.

wieder was dazu gelernt :D
-------------------------------


mit der lösung kommt, dass nächste problem, ich häng es hier einfach mal heran, weil es ja mit dem menue was zu tun hat.

Ich hab also mein Menü welches aus einer Grafik mit den Feldern: Neues Spiel, Fortsetzen und Beenden.

Dank der Enum-Idee funktioniert, dass ganze auch. Das Problem ist aber nun, dass die Position des Feldes "Neues Spiel" über der Position des Feldes des Tic Tac Toe feldes ist, sodass ich beim klick auf neues spiel, beim wechsel zum spielfeld, ich ausversehen schon ein feld mit einem kreuz/kreis fülle, dh das feld unter neues spiel wird sofort gefüllt, obwohl der zustand beim herunterdrücken der maustaste noch im menu ist, dh die abfrage erfolgt im moment als ich auf neues spiel klicke.

Code:


also

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
while(zustand!=ende){
while(zustand==menu) {  while(SDL_PollEvent(&event))     {  switch(event.type)   {   case SDL_MOUSEBUTTONDOWN:   {x2=event.motion.x;     y2=event.motion.y;  } break;    case SDL_QUIT:  zustand=ende;          break;      }
    }
    if(y2>=....)                //Wenn also auf neues Spiel geklickt wird, wechselt der "zustand"    {                      //evt. SDL_Delay(2000); klappt aber auch dann nicht
while(zustand==spiel)   {
        while(SDL_PollEvent(&event))                //Gleichzeitig ist hier eine Abfrage, die besagt,                       dass wenn   {       switch(event.type)   {      case SDL_MOUSEBUTTONDOWN:    {          x=event.motion.x;      y=event.motion.y;
 } break;
        case SDL_QUIT:          {           zustand=ende;           }           break;  }
        if(y>=....)              //dann wird dies und dies Feld gefüllt, Problem dass das Feld beim Wechsel vom Zustand schon gefüllt wird                                            }

}



auch wenn ich SDL_Delay(2000), benutze bevor ich den spielstand wechsel, also um sicherzugehen, dass wenn ich mit der maus auf neues game drücke, ich bevor der modus wechselt schon die maus losgelassen habe, damit ich nicht ein feld "versehentlich fülle", klappt es trotzdem nicht,

Dass heißt ich Drücke auf neues Game, es wartet die 2 Sekunden ab, dann modus wechsel , ich hab nach ca 1 Sek die Maus losgelassen, dann wechselt der Modus und trotzdem ist, das Feld darunter gefüllt, und ich frage mich warum, denn ich wechsel den modus erst nachdem ich gedrückt habe ...

sry, dass ich anscheinend das forum auf trapp halte, aber das scheint mir jeder logik zu widersprechen ..., sry für dieses code format, aber ich komme mit den einstellungen noch nicht so gut klar, hab schon 4 mal versucht, den code in diesem block besser zu gestalten ohne erfolg, keine ahnung warum ..
Who are you? - I am a game designer.
No you are not! - I am a game designer.
What kind of a designer ? - I am a game designer.
You mean you play games ? - I am a game designer.

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »Daedra22« (27.05.2013, 14:33)


Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

4

27.05.2013, 14:45

Ignoriere doch einfach Events ,wenn du gerade die states wechselst. Sprich, wenn dein State Game ist und der davor Menu, dann ignorierst du die letzten Events. Oder sagen wir, du ignorierst für N Sekunden Events. Einfach die Sekunden von SDL_GetTicks speichern int last = SDL_GetTicks(); und sobald SDL_GetTicks() > (last + 2000) empfängst du wieder Events.

Interessanter Link dazu: http://www.libsdl.org/intro.de/usingtimers.html
Das ganze Tutorial ist recht gut für Neueinsteiger: http://www.libsdl.org/intro.de/toc.html
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Architekt« (27.05.2013, 14:55)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

27.05.2013, 15:20

Noch schöner wäre es ja, wenn es so funktionieren würde wie gedacht. Soll heißen, pro Mausklick nur eine Eingabe. Dafür kannst du einerseits auf Mausrelease Events warten und erst dann die Aktion ausführen. Sobald die Maus also losgelassen wird, benutzt du die Eingabe. Noch schöner wäre es den Mausklick abzufragen. Soll heißen, das Event wird nur ein mal pro Mausklick gefeuert und nicht solange die Maus gedrückt wird. Du kannst gucken ob es bei SDL direkt ein Event dafür gibt, oder dir mit ein wenig Code selbst was basteln. Du kannst zum Beispiel eine Klasse für die Maus schreiben, welche weiß wie ihr Zustand diesen und den letzten Frame war. Damit kannst du Mausklicks dann nur ein einziges mal behandeln.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Daedra22

Treue Seele

  • »Daedra22« ist der Autor dieses Themas

Beiträge: 115

Wohnort: Osten

Beruf: Student Informationstechnik

  • Private Nachricht senden

6

27.05.2013, 18:50

Noch schöner wäre es ja, wenn es so funktionieren würde wie gedacht. Soll heißen, pro Mausklick nur eine Eingabe. Dafür kannst du einerseits auf Mausrelease Events warten und erst dann die Aktion ausführen. Sobald die Maus also losgelassen wird, benutzt du die Eingabe. Noch schöner wäre es den Mausklick abzufragen. Soll heißen, das Event wird nur ein mal pro Mausklick gefeuert und nicht solange die Maus gedrückt wird. Du kannst gucken ob es bei SDL direkt ein Event dafür gibt, oder dir mit ein wenig Code selbst was basteln. Du kannst zum Beispiel eine Klasse für die Maus schreiben, welche weiß wie ihr Zustand diesen und den letzten Frame war. Damit kannst du Mausklicks dann nur ein einziges mal behandeln.
Uff, dass scheint mir etwas zu komplex für solch ein triviales problem.
Einfach die Sekunden von SDL_GetTicks speichern int last = SDL_GetTicks(); und sobald SDL_GetTicks() > (last + 2000) empfängst du wieder Events.

Ich habe mir nun die Lösung von Architekt ans Herz gelegt, nur leider funktioniert sie nur zum Teil. Die Abfrage nach last habe ich vor dem Wechsel des Menues.

Hier der Quelltext mal schöner
http://codepad.org/OpqxY4A3

Ok also das ganze mit Satzzeichen:

Das Problem besteht darin, dass nachdem nun ich das Spiel aus dem Menü starte, es nicht mehr in das Menü zurückkehrt, sondern sich immer wiederholt.
Damit ist gemeint, dass wenn ich 3 Kreise/Kreuze in einer Reihe voll habe, die Grafik für (Spieler 1 / Spieler 2 /unentschieden) erscheint.
Danach aber nur für wenige Millisekunden die Grafik Menü erscheint und das Spiel wieder von vorn beginnt.

Fazit: Der Kompiler scheint anzunehmen, dass ich schon auf das Feld " Neues Spiel" geklickt habe. Eventuell hat er die x und y Variable von der Anfangsabfrage gespeichert.
Und nimmt nun an, dass ich mit der Maus über dem gleichen Feld ("neues Spiel" bin) und darauf wieder geklickt habe.
Aber ich habe nach dem Beenden des Spiels nichts gedrückt, wodurch das Neustarten des Spiels ein Fehler ist.


Fazit2: Es ist das gleiche Problem welches ich vorher hatte, nur umgekehrt.
Das Spielfeld erscheint obwohl nicht "neues Spiel" gedrückt wurde, der Zustand "menu" wird aber trotzdem aufgerufen, da die Felder immer geleert werden.
Eventuell muss ich wieder die Zeitabfrage vom Spiel ins Menü benutzen, obwohl ich dies schon ohne Erfolg versucht habe.

Fazit3: Eventuell ist die Schorsch`se Methode doch geeigneter. Oder ich benutze Tastatur- Events um die Abfrage zu differenzieren.
Who are you? - I am a game designer.
No you are not! - I am a game designer.
What kind of a designer ? - I am a game designer.
You mean you play games ? - I am a game designer.

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Daedra22« (27.05.2013, 19:11)


Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

7

27.05.2013, 18:57

Du schreibst leider mit wenigen Satzzeichen, was es schwer macht, dir zu folgen. Und wenn der Code nicht richtig eingerückt ist, dann poste ihn lieber auf so einer Seite: http://codepad.org/
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Daedra22

Treue Seele

  • »Daedra22« ist der Autor dieses Themas

Beiträge: 115

Wohnort: Osten

Beruf: Student Informationstechnik

  • Private Nachricht senden

8

27.05.2013, 19:15

Ok, habe alles nach deinen Wünschen angepasst :D
Who are you? - I am a game designer.
No you are not! - I am a game designer.
What kind of a designer ? - I am a game designer.
You mean you play games ? - I am a game designer.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

27.05.2013, 19:19

Du musst es ja nicht so kompliziert machen. Du guckst am Anfang deiner Hauptschleife einfach jeden Frame ob die Maus grad gedrückt wird. Du weißt also ob die Maus im aktuellen Frame gedrückt wird. Wenn du jetzt zusätzlich speicherst, ob die Maus im letzten Frame gedrückt wurde, dann kannst du damit ganz leicht Mausklicks erkennen. Wird die Maus im aktuellen Frame gedrückt und im letzten nicht, dann handelt es sich um einen Mausklick. Wird die Maus aktuell nicht gedrückt ist es egal und wir die Maus im aktuellen Frame gedrückt und wurde auch im letzten Frame schon gedrückt, so ist der gesuchte Moment des Klicks schon vorbei. Wie gesagt ich würde mir sowas in eine Klasse kapseln aber im Prinzip reichen 2 bool Variablen für den aktuellen Zustand und den des letzten Frames aus.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

10

27.05.2013, 19:35

Der Code ist ein wenig wirr. Versuch dich mal an Schorsch Lösung, die sollte ohnehin besser geeignet sein. ;)
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Werbeanzeige