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

1

11.02.2012, 16:59

[ SFML ] Probleme mit Tasten

Drücke ich die Leertaste einmal -> Sprite soll erscheinen
Drücke ich die Leertaste wieder -> Sprite soll verschwinden

Ganz einfach oder? Für mich leider nicht.
Es ist fasst schon lächerlich aber ich kriegs einfach nicht hin, es ist im Grunde einfach nur ein Logikproblem.


Zum besseren Verständnis hier etwas pseudo-Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool Sprite_Aktiv;

    if(Leertase == gedrückt  && Sprite_Aktiv == false)
    {   
              
                 //Sprite erstellen und initialisieren
    
         Sprite_Aktiv = true;

    
    }
    else if(Leertaste == gedrückt && Sprite_Aktiv == true)
    {
        
              //Sprite löschen

          Sprite_Aktiv = false; 
    
    }


Das Problem ist das ja sobald der bool auf true gesetzt wird (am ende der if-Anweisung), die else-if-Anweisung ausgeführt wird und den Sprite löscht.

Ich hab damit rumprobiert den bool erst auf true zu setzen, wenn die Taste losgelassen wird.
Ergebnis: Die if-Anweisung wird tausend mal ausgeführt und beim zweiten mal stürtzt das Programm ab.


MFG Dastan

valentin

Treue Seele

Beiträge: 212

Wohnort: Schweiz

Beruf: Schüler

  • Private Nachricht senden

2

11.02.2012, 17:10

Ergebnis: Die if-Anweisung wird tausend mal ausgeführt und beim zweiten mal stürtzt das Programm ab.

Was genau meinst du damit?

Zur Not könntest du mithilfe sf::Sleep(time); ne Wartezeit einbauen.
visit me on deviantArt!
http://v-alentin.deviantart.com/

There is no programming language, no matter how structured, that will prevent programmers from making bad programs. //Larry Flon

3

11.02.2012, 17:42

Zitat

Was genau meinst du damit?

Zur Not könntest du mithilfe sf::Sleep(time); ne Wartezeit einbauen.



Also die Sache mit dem tausendfachen ausführen ist so, die Funktion ( die den Code enthält) wird so lange/so oft ausgeführt bis man die Leertaste loslässt, dass bedeutet wiederrum wenn ich Sprite_Aktiv erst auf true schalte wenn ich die Taste loslasse, kann solange die Taste gedrückt bleibt die if-Anweisung beliebig oft ausgeführt werden.
Etwas verwirrender Satz aba ich hoffe irgendwie verständlich. :hmm:

Für den Abstürtz gilt ähnliches im Endeffekt versucht es einfach etwas zu löschen das garnicht mehr existiert.

Und ja Wartezeiten könnte ich irgendwie noch als Ausweg benützen , aber irgendwie gerfällt mir das nich, also das der Spieler nur lange genug die Leertaste drücken muss um das Game zu crashen.

Geheim

Treue Seele

Beiträge: 202

Wohnort: Salzburg

Beruf: Schüler

  • Private Nachricht senden

4

11.02.2012, 20:07

Wie du schon gesagt hast, löscht du den bool sofort wieder und das in jedem einzelnen Frame: Du erstellst, du löscht....
Zu allererst, würde ich den Sprite nicht jedesmal neu erstellen, sondern nur 1 mal und ihn entweder Rendern oder eben nicht Rendern!
Erstellt du jedesmal einen neuen bool? Wenn ja, ist er nach jedem Frame wieder false (oder true) den auch nur 1 mal erstellen!

Und für das Problem mit dem tausendfachen Ausführen: Versuch doch etwas zu machen, was nur 1 mal das Signal gibt und nicht jeden Frame
Kleiner Tipp: Du setzt einen bool auf "true" immer wenn du die Leertaste drückst, und wenn du sie nicht drückst logischerweiße auf "false"^^

MfG Geheim!

5

12.02.2012, 12:12

Zitat

Zu allererst, würde ich den Sprite nicht jedesmal neu erstellen, sondern nur 1 mal und ihn entweder Rendern oder eben nicht Rendern!
Erstellt du jedesmal einen neuen bool? Wenn ja, ist er nach jedem Frame wieder false (oder true) den auch nur 1 mal erstellen!



Mit dem Rendern hast du recht, ich hab mir irgedwie schon gedacht das es auch für die Performance nicht das beste ist das ständig erstellen und initialisieren usw., ich versuch das mal umzumünzen.
Der bool wird in einer Header-Datei deklariert, das hab ich nur für das Verständnis über die Anweisungen gepackt.

Jedoch besteht das Problem weiterhin. ;(

MfG Dastan

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

6

12.02.2012, 12:30

Zur Not könntest du mithilfe sf::Sleep(time); ne Wartezeit einbauen.

Vergiss das lieber wieder schnell.

Du musst einfach prüfen ob im letzten Frame die Leertaste nicht gedrückt wurde.

In einer solchen Situation solltest du nach jedem delete den Zeiger auf NULL setzen(außer im Destruktor natürlich) oder einen gültigen Wert mit Hilfe von new zuweisen. Ebenso solltest du vor jedem new delete aufrufen(außer im Konstruktor). Wenn du das nicht machst kannst du mit Memoryleaks und Zugriffsverletzungen rechnen.

In dem Fall wäre es aber tatsächlich besser das Sprite einfach nicht zu zeichnen wenn es nicht angezeigt werden soll.

edit: Übrigens kannst du anstelle von "Sprite_Aktiv == true" auch einfach "Sprite_Aktiv" schreiben. Das funktioniert weil Sprite_Aktiv schon den Datentyp bool hat. Ebenso kannst du den !-operator nutzen um "Sprite_Aktiv == false" kurz zu schreiben "!Sprite_Aktiv". Wenn der Compiler den vergleich nicht sowieso wegoptimiert hast du durch diese Schreibweise sogar einen etwas schnelleren Code.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »NachoMan« (12.02.2012, 12:46)


Geheim

Treue Seele

Beiträge: 202

Wohnort: Salzburg

Beruf: Schüler

  • Private Nachricht senden

7

12.02.2012, 13:17

Versuch dir dein Problem mal Schritt für Schritt vorzustellen: Was du haben willst und was du hast
Zum Beispiel bei deinem ersten Post: Du willst: 1 Mal Leertaste drücken, dann wird der Sprite erstellt (gezeichnet), nochmal 1 mal Leertaste drücken, der Sprite wird gelöscht (nicht gezeichnet)

Dein Code: Wenn du die Leertaste drückst UND der Sprite nicht erstellt wurde (nicht gezeichnet wird), wird er erstellt (gezeichnet)
Wenn du die Leertaste drückst UND der Sprite wurde erstellt (gezeichnet), wird er gelöscht (nicht gezeichnet)

Problem: Das zweite wird Immer ausgeführt, das hast du schonmal gerausgefunden
Mögliche Lösung: Du verwendest einen bool, der immer "true" wird wenn du die Leertaste drückst und immer "false" wird wenn nicht (NACH deinen if-Anweisungen) und hängst ihn in deine 2 if-Anweisungen hinten dran mit "&& bool == false", weil dein PC zu diesem Zeitpunkt noch nicht weiß, dass du die Leertaste gedrückt hast, das erfährt er ja erst später!

MfG Geheim!

8

12.02.2012, 16:46

Na endlich ich habs gerafft. :D
Danke Leute!

Eine Sache währe da aber noch die mich irgendwie verwundert.

Zitat

In einer solchen Situation solltest du nach jedem delete den Zeiger auf NULL setzen(außer im Destruktor natürlich)


Ich setze aber eig. Immer im Destruktor ein Delete und dannach den Zeiger auf NULL, was ist verkehrt daran? :wacko:
Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
CSprite::~CSprite()
{
    
    delete(pSprite);
    pSprite = NULL;
    delete(pTexture);
    pTexture = NULL;

}


Zurück zum Topic,
falls irgendjemand ein ähnliches Problem hat versuch ich das ganze nochmal kurz zu erklären.

Pseudo-Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    if(Leertaste == gedrückt && !Stopit)
{

     Stopit = true;

    if(!Sprite_Aktiv)
    {
       
          // Sprite Rendern
          SpriteAktiv = true;

    }
    else if (Sprite_Aktiv)
    {
          // Sprite nicht Rendern bzw. einfach nix tun
      Sprite_Aktiv= false;

    }
   
} 
else if (Leertaste == nicht gedrückt && Stopit) 
{
    
     Stopit = false;
}


Es passiert quasi etwas wenn die Leertaste gedrückt ist und der Stopit auf false und wenn die Leertaste nicht gedrückt ist und Stopit auf true.
Um das mehrmalige Ausführen zu verhindern setzt man z.B. Stopit auf true während die Leertaste gedrückt ist, den dann, joa, passiert halt einfach nix.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

9

12.02.2012, 16:56

Ich setze aber eig. Immer im Destruktor ein Delete und dannach den Zeiger auf NULL, was ist verkehrt daran?

Der Zeiger wird nach dem Destruktoraufruf sowieso nichtmehr genutzt. Du verschwendest also nur Zeit.

Wenn du schöneren Code anstrebst solltest du dir den mal anschauen und überlegen was dort passiert:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
if(Leertaste == gedrückt)
{
     if(!Stopit)
     {
          Stopit = true;
          // von Rendern auf nicht rendern und anders herum umschalten.
          Sprite_Aktiv = !Sprite_Aktiv;
     }
} 
else
{
     Stopit = false;
}


Der !-Operator(nicht-Operator) macht übrigens aus true false und aus false true.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »NachoMan« (12.02.2012, 17:05)


10

12.02.2012, 17:39

Erstmal großes Dankeschön für den Tipp ^^


Zitat

Der Zeiger wird nach dem Destruktoraufruf sowieso nichtmehr genutzt. Du verschwendest also nur Zeit.


Alles klar, ich werds mir merken.


MfG Dastan

Werbeanzeige