Problem bei Minispiel



  • Das zu einem minimal kompilierbaren Beispiel reduzieren, mit dem sich dein Problem reproduzieren lässt.



  • Dabei den Code besser aufteilen. Funktionalitäten, die sich auf einen Aspekt beziehen in eigene .h und .cpp legen. zB

    - Klasse
    - Konsolefunktionen
    - Bewegung und schießen (also das Spiel selbst)
    - main (nur zum starten des Spiel)

    etc. Möglichst so, das Du diese Dateien unabhängig voneinander testen kannst. Dann kannst Du das Problem auch näher benennen, ohne gleich den gesamten Code zu zeigen.



  • Ich habe mal wieder C++ missbraucht[...]

    Der Code sieht auch entsprechend scheiße aus.



  • Vielen Dank wörtner. So etwas ist immer sehr motivierend für Anfänger.

    Ich hatte lieber alles gepostet und die wichtigen Stellen wo mein Problem eigentlich liegt markiert mit Kommentaren. Ich dachte, falls jemand das Problem sucht, hätte er es einfach kopieren und compilen können ohne erst Dateien anzulegen.

    @Schlangenmensch. Kann man C++ schreiben, komplett ohne Elemente die in C enthalten sind? Alles was ich hier geschrieben habe, kommt aus C++ Tutorials. Sicherlich geht das auch besser und kürzer, aber soweit bin ich noch nicht.

    Ich werde nochmal eine gekürzte Version hier posten. Bin gerade nicht am Rechner.



  • Zhavok schrieb:

    Ich hatte lieber alles gepostet und die wichtigen Stellen wo mein Problem eigentlich liegt markiert mit Kommentaren.

    Das hast Du aber nicht gemacht, um anderen ein Gefallen zu tun, sondern weil Du selbst bei dem Code nicht durchblickst. Deshalb den Code aufteilen und falls Du meinst, das Problem liegt beim threading, diese Geschichte selbst noch mal in einem eigenen kleinen Programm durchspielen.

    Wobei ich stark bezweifele, das man dies überhaupt in einem Konsolenspiel benötigt. Die heutige Rechenleistung ist stark genug, um nacheinander mehrere Eingaben abzufangen, darauf zu reagieren und trotzdem den Eindruck von Gleichzeitigkeit zu erzeugen (wir sind ja nicht beim BASIC eines alten 8-Bitter, aber selbst damit konnte man solch kleine Dinge erstellen).
    Falls es wirklich die Konsolenausgabe ist, die verzögert reagiert, gibt es entsprechende WinAPI-Funktionen, die Du dann statt <iostream> nutzen kannst.

    Sorry für den ganzen Text, aber ich stand auch mal an entsprechender Stelle, Du musst ja nicht das Selbe durchmachen müssen. Und auch unfreundliche Reaktionen können helfen, denn erstens überlegt man seine Formulierungen, was soll man bei "C++ missbrauchen" schon erwarten? Und man überlegt sich erst selbst Strategien zur Fehlersuche, bevor man dann fragt bzw werden diese Strategien angeboten wie zB ein Minimalbeispiel zeigen.



  • Den Kommentar "Allgemeine Variablen" hab ich für mich gemacht. das mit dem "Hier Threadaufruf" und "Hier Thread" hab ich geschrieben, damit ihr gleich wisst wo mein Problem liegt. Mein Problem ist auch nicht, dass die Konsolen Ausgabe verzögert reagiert, sondern, dass einfach alles wild durcheinander flimmert. Ich habe auch nicht das Problem gehabt und 5min später hier gepostet. Das war alles etwas anders.

    Alles lief an sich reibungslos. Ich konnte die Figuren getrennt voneinander bewegen. Dann wollte ich die Schüsse einbauen. Das Problem was mir dabei erschien, war einfach, dass sobald der Schuss abgefeuert war, sich die Figuren nicht mehr bewegten. Das erschien mir logisch, da ja eigentlich das Programm der Reihe nach abgearbeitet wird. Also sozusagen Figuren bewegen, schießen, warten bis der Schuss getroffen hat oder auf der rechten Seite des Konsolen Fensters ist, dann weiter bewegen. Das spielt sich natürlich nicht sehr schön wenn man jedes mal warten muss bis der Schuss da ist 😃 . Also suchte ich nach einer Möglichkeit das dual laufen zu lassen und fand ein Thema über Threads. Ich versuchte dann unterschiedliche Möglichkeiten. Einmal mit std::thread, einmal mit pthread und dann noch mit WINAPI Thread(). An sich hat das auch funktioniert. Der Schuss und die Bewegung liefen gleichzeitig. Allerdings laufen dann ja gleichzeitig 2 while-Schleifen, welche die Konsole leeren und dannach wieder alles ausgeben. Es sieht dann einfach bunt durcheinander gewürfelt aus. Sobald man schießt und sich bewegt, buggen alle Ausgaben der Konsole durcheinander. Wenn ich die Zeiten in den while schleifen hoch nehme, verringert sich das durcheinander-buggen, allerdings lassen sich dadurch auch die Spieler nicht mehr so schnell bewegen oder der Schuss ist zu langsam.
    Wenn ich jetzt hier bei dem Script was ich gepostet habe einfach die Zeichen der Figuren, die Möglichkeit sie zu bewegen usw. weglasse, so wird der Fehler nicht entstehen, da dann ja nichts falsch dargestellt werden kann. Das war auch der Grund weshalb ich alles gepostet habe. Das ich nicht 600 Zeilen schreibe bei einem Logikfehler habe ich schon verstanden. Und wenn ich erst paar Stunden mit dem Problem kämpfen würde, hätte ich mich hier auch nicht gemeldet. Allerdings sitze ich jetzt schon den 3. Tag und komme nicht weiter.



  • Zhavok schrieb:

    Alles lief an sich reibungslos. Ich konnte die Figuren getrennt voneinander bewegen. Dann wollte ich die Schüsse einbauen. Das Problem was mir dabei erschien, war einfach, dass sobald der Schuss abgefeuert war, sich die Figuren nicht mehr bewegten. Das erschien mir logisch, da ja eigentlich das Programm der Reihe nach abgearbeitet wird. Also sozusagen Figuren bewegen, schießen, warten bis der Schuss getroffen hat oder auf der rechten Seite des Konsolen Fensters ist, dann weiter bewegen. Das spielt sich natürlich nicht sehr schön wenn man jedes mal warten muss bis der Schuss da ist 😃 .

    Auch auf die Gefahr, zum Schwätzer zu werden. Aber wenn der Schuss und die Bewegung gleichzeitig ablaufen sollen, musst Du dies auch so programmieren. Dazu benötigt man erstmal kein threading.

    Du schießt den Schuss ab, die "Kugel" bewegt sich ein Feld. Punkt. Die Figur, das Bein oder so, bewegt sich ein Feld. Die zweite Figur, dessen Arm oder so bewegt sich ein Feld. Und wieder von vorne. Die Kugel bewegt sich ein Feld weiter, die Figuren ... etc. Dies geschieht so schnell, das Du in dabei sogar den Hintergrund animieren könntest bzw sleeps() einbauen musst. Aber halt immer nur ein Feld (oder zwei, darüber kann man dann unterschiedliche Geschwindigkeiten vorgaukeln) gleichzeitig, bei allem was animiert werden soll. Nicht erst die Flugbahn schreiben und dann die Bewegung der Figuren.



  • wenn ich das richtig verstehe, könnte ich zum Beispiel in die Funktion, welche fürs aktualisieren zuständig ist eine Abfrage schreiben, ob ein Schuss ausgelöst wurde und wenn ja, von wem und in welche richtung etc. Dann würde ich mir den Thread sparen und hätte auch keine 2 while Schleifen. Das werde ich ausprobieren. So habe ich das noch nicht betrachtet. Vielen Dank 👍 👍 👍

    Eine Frage hätte ich noch. Weißt du was Schlangenmensch meint mit "Dass ist kein C++" ? Also was er geschrieben hat mit printf und struct statt class stimmt ja. Allerdings verstehe ich nicht weshalb es trotzdem kein C++ ist.



  • Zhavok schrieb:

    Der Schuss und die Bewegung liefen gleichzeitig. Allerdings laufen dann ja gleichzeitig 2 while-Schleifen, welche die Konsole leeren und dannach wieder alles ausgeben.

    Hier habe ich erst mal aufgehört zu lesen:
    Es ist meistens keine gute Idee, die Konsole zu leeren und alles neu auszugeben. Besser ist es, nur die Positionen auf der Konsole zu verändern, die auch anders aussehen müssen.
    Wenn Du also aus XXXYYXXX auf der Konsole XXXZZXXX machen willst, nicht die Konsole leeren und neu ausgeben, sondern nur die YY mit ZZ überschreiben.
    Schon hast Du die meisten Flackerprobleme gelöst.

    Des weiteren ist es wahrscheinlich keine gute Idee, wenn Deine beiden Threads völlig unabhängig voneinander die Konsole beschreiben können, denn dann hast Du wahrscheinlich wirklich ein ziemliches Durcheinander.

    Eventuell ist es besser, eine Funktion zu haben, der man ein Zeichen und eine Position übergibt, die dann dieses Zeichen an die entsprechende Position schreibt und dafür zu sorgen, dass diese Funktion nicht von verschiedenen Threads gleichzeitig ausgeführt werden kann; aber zuerst mal würde ich testen, wie es aussieht, wenn man wirklich immer nur die Konsolenpositionen beschreibt, die man wirklich ändern möchte.



  • Belli schrieb:

    Es ist meistens keine gute Idee, die Konsole zu leeren und alles neu auszugeben. Besser ist es, nur die Positionen auf der Konsole zu verändern, die auch anders aussehen müssen.

    Richtig. War mir gar nicht klar, das der TO dies tatsächlich so gemacht hat.

    Also wenn zB die Kugel animiert wird, nicht die gesamte Konsole neu zeichnen (edit: wobei dies nicht mal so tragisch wäre, aber auf keinen Fall vorher leeren), sondern nur das vorherige Feld der Kugel mit dem Hintergrundzeichen, was hier wohl ein Leerzeichen sein wird, überschreiben.



  • Das ist auch ein interessanter Ansatz Belli. Zum ersetzen würde ich meine setpos Funktion benutzen gefolgt mit cout.

    void setpos(int x, int y)
    {
    	CursorPosition.X = x;
    	CursorPosition.Y = y;
    	SetConsoleCursorPosition(console, CursorPosition);
    }
    


  • Nicht cout, dafür gibts auch Windows-Konsole - Funktionen! Die sind auch viel schneller!



  • @ TO

    Und wenn Du daran Interesse hast, findest Du im geschlossenen Win32-Konsole Bereich auch eine fertige Anwendung, um diese Funktionen recht simpel anzuwenden.

    Ich selbst habe auch entsprechende Funktionen geschrieben, die sind aber primär dafür gedacht, Grafiken in der Konsole darzustellen. Aber eigentlich ist das Jacke wie Hose. Der Reiz entsteht erst durch die Animation. Und wenns in der Konsole komplex werden soll, ist man eben bei den WinAPI-Funktionen besser aufgehoben.


Anmelden zum Antworten