Problem bei Minispiel



  • Hallo Community,

    Ich habe mal wieder C++ missbraucht für Dinge, wofür es eigentlich nicht vorgesehen ist^^. Und zwar habe ich ein kleines Spiel in der Konsole geschrieben, wo es darum geht, das zwei Spieler sich bewegen können ((W,A,S,D) && (Num1, Num2, Num3 und Num5)) und sich gegenseitig beschießen ((Q,E) && (4,6)). Das ganze habe ich mir nur als Übrung für mich vorgenommen, also nicht wundern^^. Ich habe für das schießen einen Thread erstellt. Dieser wird auch ausgeführt. Allerdings flimmert dann alles durcheinander und ich weiß nicht, ob das Problem ist, dass die Konsole das nicht so verarbeiten kann, oder ob ich einfach etwas falsch mache. Ich schreibe euch hier mal den Quellcode, vielleicht kann mir ja jemand helfen. 🙂 👍

    #include <iostream>
    #include <stdio.h>
    #include <windows.h>
    #include <string>
    
    HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD CursorPosition;
    
    class Player
    {
        public:
            int Ang;
            int Leb;
            char Kopf = 1;
            char Hals = 435;
            char Koerper = 435;
            char Lhand = 92;
            char Rhand = 47;
            char Lbein = 47;
            char Rbein = 92;
            bool hasShoot1;
    
            int Kopf_X, Kopf_Y, Hals_X, Hals_Y, Koerper_X, Koerper_Y, Lhand_X, Lhand_Y, Rhand_X, Rhand_Y, Lbein_X, Lbein_Y, Rbein_X, Rbein_Y;
    
        private:
    
    };
    
    Player P1;
    Player P2;
    
    void SetWindow(int Width, int Height)
    {
        _COORD coord;
        coord.X = Width;
        coord.Y = Height;
    
        _SMALL_RECT Rect;
        Rect.Top = 0;
        Rect.Left = 0;
        Rect.Bottom = Height - 1;
        Rect.Right = Width - 1;
    
        HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);      // Get Handle
        SetConsoleScreenBufferSize(Handle, coord);            // Set Buffer Size
        SetConsoleWindowInfo(Handle, TRUE, &Rect);            // Set Window Size
    }
    
    void cls()
    {
    
      DWORD n;
      DWORD size;
      COORD coord = {0};
      CONSOLE_SCREEN_BUFFER_INFO csbi;
      HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
      GetConsoleScreenBufferInfo ( h, &csbi );
      size = csbi.dwSize.X * csbi.dwSize.Y;
      FillConsoleOutputCharacter ( h, TEXT ( ' ' ), size, coord, &n );
      GetConsoleScreenBufferInfo ( h, &csbi );
      FillConsoleOutputAttribute ( h, csbi.wAttributes, size, coord, &n );
      SetConsoleCursorPosition ( h, coord );
    
    }
    
    void setpos(int x, int y)
    {
    	CursorPosition.X = x;
    	CursorPosition.Y = y;
    	SetConsoleCursorPosition(console, CursorPosition);
    }
    
    void go(int richtung)
    {
    
        switch (richtung)
        {
    
            case 0 :
            {
                if (P1.Kopf_Y >= 1)
                {
                    P1.Kopf_Y -= 1;
                    P1.Hals_Y -= 1;
                    P1.Koerper_Y -= 1;
                    P1.Lhand_Y -= 1;
                    P1.Rhand_Y -= 1;
                    P1.Lbein_Y -= 1;
                    P1.Rbein_Y -= 1;
                }
                break;
            }
    
             case 1 :
            {
                if (P1.Lhand_X >= 1)
                {
                    P1.Kopf_X -= 1;
                    P1.Hals_X -= 1;
                    P1.Koerper_X -= 1;
                    P1.Lhand_X -= 1;
                    P1.Rhand_X -= 1;
                    P1.Lbein_X -= 1;
                    P1.Rbein_X -= 1;
                }
                break;
            }
    
            case 2 :
            {
                if (P1.Lhand_X <= 235)
                {
                    P1.Kopf_X += 1;
                    P1.Hals_X += 1;
                    P1.Koerper_X += 1;
                    P1.Lhand_X += 1;
                    P1.Rhand_X += 1;
                    P1.Lbein_X += 1;
                    P1.Rbein_X += 1;
                }
                break;
            }
    
            case 3 :
            {
                if (P1.Kopf_Y <= 78)
                {
                    P1.Kopf_Y += 1;
                    P1.Hals_Y += 1;
                    P1.Koerper_Y += 1;
                    P1.Lhand_Y += 1;
                    P1.Rhand_Y += 1;
                    P1.Lbein_Y += 1;
                    P1.Rbein_Y += 1;
                }
                break;
            }
    
            case 4 :
            {
                if (P2.Kopf_Y >= 1)
                {
                    P2.Kopf_Y -= 1;
                    P2.Hals_Y -= 1;
                    P2.Koerper_Y -= 1;
                    P2.Lhand_Y -= 1;
                    P2.Rhand_Y -= 1;
                    P2.Lbein_Y -= 1;
                    P2.Rbein_Y -= 1;
                }
                break;
            }
    
             case 5 :
            {
                if (P2.Lhand_X >= 1)
                {
                    P2.Kopf_X -= 1;
                    P2.Hals_X -= 1;
                    P2.Koerper_X -= 1;
                    P2.Lhand_X -= 1;
                    P2.Rhand_X -= 1;
                    P2.Lbein_X -= 1;
                    P2.Rbein_X -= 1;
                }
                break;
            }
    
            case 6 :
            {
                if (P2.Lhand_X <= 235)
                {
                    P2.Kopf_X += 1;
                    P2.Hals_X += 1;
                    P2.Koerper_X += 1;
                    P2.Lhand_X += 1;
                    P2.Rhand_X += 1;
                    P2.Lbein_X += 1;
                    P2.Rbein_X += 1;
                }
                break;
            }
    
            case 7 :
            {
                if (P2.Kopf_Y <= 78)
                {
                    P2.Kopf_Y += 1;
                    P2.Hals_Y += 1;
                    P2.Koerper_Y += 1;
                    P2.Lhand_Y += 1;
                    P2.Rhand_Y += 1;
                    P2.Lbein_Y += 1;
                    P2.Rbein_Y += 1;
                }
                break;
            }
    
            default : {std::cout << "ERROR - Bewegung"; break;}
    
        }
    }
    
    void refresh()
    {
        cls();
    
        setpos(1,1);
         std::cout << " Spieler 1: " << P1.Leb << "                                                                                                                                                                                                               Spieler 2: " << P2.Leb;
    
        setpos(P1.Kopf_X,P1.Kopf_Y);
        std::cout << P1.Kopf;
        setpos(P1.Hals_X,P1.Hals_Y);
        std::cout << P1.Hals;
        setpos(P1.Koerper_X,P1.Koerper_Y);
        std::cout << P1.Koerper;
        setpos(P1.Lhand_X,P1.Lhand_Y);
        std::cout << P1.Lhand;
        setpos(P1.Rhand_X,P1.Rhand_Y);
        std::cout << P1.Rhand;
        setpos(P1.Lbein_X,P1.Lbein_Y);
        std::cout << P1.Lbein;
        setpos(P1.Rbein_X,P1.Rbein_Y);
        std::cout << P1.Rbein;
    
        setpos(P2.Kopf_X,P2.Kopf_Y);
        std::cout << P2.Kopf;
        setpos(P2.Hals_X,P2.Hals_Y);
        std::cout << P2.Hals;
        setpos(P2.Koerper_X,P2.Koerper_Y);
        std::cout << P2.Koerper;
        setpos(P2.Lhand_X,P2.Lhand_Y);
        std::cout << P2.Lhand;
        setpos(P2.Rhand_X,P2.Rhand_Y);
        std::cout << P2.Rhand;
        setpos(P2.Lbein_X,P2.Lbein_Y);
        std::cout << P2.Lbein;
        setpos(P2.Rbein_X,P2.Rbein_Y);
        std::cout << P2.Rbein;
    
    }
    
    void *shoot1R(void *dummy)                  //////////////////////////////////////////////////////////////////<- Hier Thread
    {
        int shoot1_X;
        int shoot1_Y;
        bool stopWhile = false;
    
        shoot1_X = P1.Lhand_X + 1;
        shoot1_Y = P1.Lhand_Y;
    
        char shoot1Symb = 16;
    
        while(shoot1_X <= 235 && !stopWhile)
        {
    
            setpos(shoot1_X,shoot1_Y);
            std::cout << shoot1Symb;
            shoot1_X++;
            Sleep (5);
            refresh();
            if ((shoot1_X == P2.Lhand_X) && (shoot1_Y == P2.Lhand_Y)) {P2.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P2.Lbein_X) && (shoot1_Y == P2.Lbein_Y)) {P2.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P2.Kopf_X) && (shoot1_Y == P2.Kopf_Y)) {P2.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P2.Koerper_X) && (shoot1_Y == P2.Koerper_Y)) {P2.Leb -= 5; stopWhile = true;}
        }
    
        return NULL;
    }
    
    void shoot1L()
    {
    
        int shoot1_X;
        int shoot1_Y;
        bool stopWhile = false;
    
        shoot1_X = P1.Lhand_X + 1;
        shoot1_Y = P1.Lhand_Y;
    
        char shoot1Symb = 17;
    
        while(shoot1_X >= 1 && !stopWhile)
        {
    
            setpos(shoot1_X,shoot1_Y);
            std::cout << shoot1Symb;
            shoot1_X--;
            Sleep (5);
            refresh();
            if ((shoot1_X == P2.Lhand_X) && (shoot1_Y == P2.Lhand_Y)) {P2.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P2.Lbein_X) && (shoot1_Y == P2.Lbein_Y)) {P2.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P2.Kopf_X) && (shoot1_Y == P2.Kopf_Y)) {P2.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P2.Koerper_X) && (shoot1_Y == P2.Koerper_Y)) {P2.Leb -= 5; stopWhile = true;}
    
        }
    
    }
    
    void shoot2R()
    {
    
        int shoot1_X;
        int shoot1_Y;
        bool stopWhile = false;
    
        shoot1_X = P2.Lhand_X + 1;
        shoot1_Y = P2.Lhand_Y;
    
        char shoot1Symb = 16;
    
        while(shoot1_X <= 235 && !stopWhile)
        {
    
            setpos(shoot1_X,shoot1_Y);
            std::cout << shoot1Symb;
            shoot1_X++;
            Sleep (5);
           refresh();
            if ((shoot1_X == P1.Lhand_X) && (shoot1_Y == P1.Lhand_Y)) {P1.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P1.Lbein_X) && (shoot1_Y == P1.Lbein_Y)) {P1.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P1.Kopf_X) && (shoot1_Y == P1.Kopf_Y)) {P1.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P1.Koerper_X) && (shoot1_Y == P1.Koerper_Y)) {P1.Leb -= 5; stopWhile = true;}
    
        }
    
    }
    
    void shoot2L()
    {
    
        int shoot1_X;
        int shoot1_Y;
        bool stopWhile = false;
    
        shoot1_X = P2.Lhand_X + 1;
        shoot1_Y = P2.Lhand_Y;
    
        char shoot1Symb = 17;
    
        while(shoot1_X >= 1 && !stopWhile)
        {
    
            setpos(shoot1_X,shoot1_Y);
            std::cout << shoot1Symb;
            shoot1_X--;
            Sleep (5);
            refresh();
            if ((shoot1_X == P1.Lhand_X) && (shoot1_Y == P1.Lhand_Y)) {P1.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P1.Lbein_X) && (shoot1_Y == P1.Lbein_Y)) {P1.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P1.Kopf_X) && (shoot1_Y == P1.Kopf_Y)) {P1.Leb -= 5; stopWhile = true;}
            if ((shoot1_X == P1.Koerper_X) && (shoot1_Y == P1.Koerper_Y)) {P1.Leb -= 5; stopWhile = true;}
    
        }
    
    }
    
    void End(int Player)
    {
    
        cls();
        setpos(100,30);
        std::cout << "Spieler " << Player << " hat gewonnen!!!";
        Sleep (8000);
    
    }
    
    int main(int argc, char *argv[])
    {
    
        SetWindow(239,83);
    
        ///////Allgemeine Variablen///////
        int richtung;
        P1.Leb = 100;
        P2.Leb = 100;
        P1.hasShoot1 = false;
    
        //////////////////////////////////
    
        P1.Kopf_X = 7;
        P1.Kopf_Y = 8;
        setpos(P1.Kopf_X,P1.Kopf_Y);
        std::cout << P1.Kopf;
    
        P1.Hals_X = 7;
        P1.Hals_Y = 9;
        setpos(P1.Hals_X,P1.Hals_Y);
        std::cout << P1.Hals;
    
        P1.Koerper_X = 7;
        P1.Koerper_Y = 10;
        setpos(P1.Koerper_X,P1.Koerper_Y);
        std::cout << P1.Koerper;
    
        P1.Lhand_X = 6;
        P1.Lhand_Y = 9;
        setpos(P1.Lhand_X,P1.Lhand_Y);
        std::cout << P1.Lhand;
    
        P1.Rhand_X = 8;
        P1.Rhand_Y = 9;
        setpos(P1.Rhand_X,P1.Rhand_Y);
        std::cout << P1.Rhand;
    
        P1.Lbein_X = 6;
        P1.Lbein_Y = 11;
        setpos(P1.Lbein_X,P1.Lbein_Y);
        std::cout << P1.Lbein;
    
        P1.Rbein_X = 8;
        P1.Rbein_Y = 11;
        setpos(P1.Rbein_X,P1.Rbein_Y);
        std::cout << P1.Rbein;
    
        P2.Kopf_X = 230;
        P2.Kopf_Y = 8;
        setpos(P2.Kopf_X,P2.Kopf_Y);
        std::cout << P2.Kopf;
    
        P2.Hals_X = 230;
        P2.Hals_Y = 9;
        setpos(P2.Hals_X,P2.Hals_Y);
        std::cout << P2.Hals;
    
        P2.Koerper_X = 230;
        P2.Koerper_Y = 10;
        setpos(P2.Koerper_X,P2.Koerper_Y);
        std::cout << P2.Koerper;
    
        P2.Lhand_X = 229;
        P2.Lhand_Y = 9;
        setpos(P2.Lhand_X,P2.Lhand_Y);
        std::cout << P2.Lhand;
    
        P2.Rhand_X = 231;
        P2.Rhand_Y = 9;
        setpos(P2.Rhand_X,P2.Rhand_Y);
        std::cout << P2.Rhand;
    
        P2.Lbein_X = 229;
        P2.Lbein_Y = 11;
        setpos(P2.Lbein_X,P2.Lbein_Y);
        std::cout << P2.Lbein;
    
        P2.Rbein_X = 231;
        P2.Rbein_Y = 11;
        setpos(P2.Rbein_X,P2.Rbein_Y);
        std::cout << P2.Rbein;
    
        bool GameRun = true;
        while (GameRun)
    
        {
    
            if(P1.Leb <= 0) {GameRun = false; End(2);}
            if(P2.Leb <= 0) {GameRun = false; End(1);}
    
            if (GetAsyncKeyState (0x57))
    		{
                richtung = 0;
                go(richtung);
                refresh();
    		}
    
    		 if (GetAsyncKeyState(0x41))
    		{
                richtung = 1;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(0x44))
    		{
                richtung = 2;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(0x53))
    		{
                richtung = 3;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(VK_NUMPAD5))
    		{
                richtung = 4;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(VK_NUMPAD1))
    		{
                richtung = 5;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(VK_NUMPAD3))
    		{
                richtung = 6;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(VK_NUMPAD2))
    		{
                richtung = 7;
                go(richtung);
                refresh();
    		}
    
            if (GetAsyncKeyState(0x45))
    		{
    		    pthread_t test;
    		    pthread_create (&test, NULL, shoot1R, NULL);    ///////////////////////////////////////<- Hier Threadaufruf
    
    		}
    
            if (GetAsyncKeyState(0x51))
    		{
    		    shoot1L();
    
    		}
    
            if (GetAsyncKeyState(VK_NUMPAD6))
    		{
    		    shoot2R();
    
    		}
    
            if (GetAsyncKeyState(VK_NUMPAD4))
    		{
    		    shoot2L();
    
    		}
    
    		Sleep (20);
    
        }
    
        main(NULL,NULL);
    
        return 0;
    
    }
    


  • Ein paar Anmerkungen:

    1.Bitte C++ Code Tags verwenden, mit Syntax Highlighting kann man den Spaß besser lesen.

    2.Dass ist kein C++. Wenn es hoch kommt einfaches C. Das Keyword Class macht kein C++ Code. Auf den ersten Blick, könntest du das durch ein 'Struct' und cout durch prinft ersetzen und das würde auch ein C Compiler übersetzen.

    3. Ein bisschen technischer, du erstellst zwar ein Thread, aber du hast keine Synchronisation. Du hast also keine Ahnung, wann der fertig ist und wo dein Hauptthread an der Stelle ist.

    4. Du greifst in der Funktion, die du in einem extra Thread ausführst, auf eine globale Variable zu. Ich bin deinen Code jetzt nicht im 100%igen Detail durch gegangen, aber du greifst da bestimmt im Hauptthread auch drauf zu. Da brauchst du zum Beispiel mutexes.

    5. Jetzt wieder allgemeiner.: Globale Variablen sind meistens eine schlechte Idee, auch wenn es nur zum üben ist.

    6. Wenn du Lesern einen gefallen tun willst, lass die Mengen an Leerzeilen weg, die du teilweise hast, nur um noch eine Klammer zu schließen.


  • Mod

    Schlangenmensch schrieb:

    1.Bitte C++ Code Tags verwenden, mit Syntax Highlighting kann man den Spaß besser lesen.

    Er nutzt die richtigen Tags. Es ist bloß ein Feature des Parsers, dass er sich die Mühe spart, wenn jemand einen Roman postet (siehe die Überschrift des Codefeldes), den sowieso niemand lesen wird.



  • Schon wieder was gelernt 😃



  • Also wie kann ich das machen, dass es gehighlightet wird? 🙂 😕



  • 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.


Log in to reply