Interrupts in C++?



  • Hi,

    ich hätte eine Frage: gibt es in C/C++ die Möglichkeit, Interrupts zu definieren? (Es soll hier keine Schnittstelle etc. überwacht werden, sondern nach verstreichen einer bestimmten Zeitspanne eine Unterfunktion ausgeführt werden)

    Der Hintergrund: ich sitze gerade an der Umsetzung eines Snake-Clones 😃 , die Ausgabe des Spielfeldes auf der Konsole ist allerdings etwas "flimmrig", da die Ausgabefunktion nur nach "Berechnung" des neuen Spielfeldes aufgerufen wird (ca. alle 100ms), dementsprechend niedrig ist die Wiederholrate.
    Wenn es nun aber die Möglichkeit gäbe, über einen Interrupt die Funktion alle 10ms aufzurufen, sähe die Sache ganz anders aus.

    Viele Grüße



  • Jain. Direkt ein Sprachmittel von C++ ist es nicht. Allerdings kannst du Inline Assembler schreiben, wenn du magst.
    Allerdings klingt das eher danach, dass du threads suchst..
    boost::thread ist recht einfach und Plattformunabhängig.



  • Warum willst du das Spielfeld neuzeichnen, wenn es noch nicht neu berechnet ist? BTW wenn du für ein Snake-Spielfeld 100ms brauchst machst du was verkehrt.



  • Hi,

    erstmal danke für die schnellen Antworten!

    @Bashar: ich dachte, wenn ich permanent das Spielfeld neu auf den Bildschirm zeichne, wäre die Wiederholrate etwas höher...

    Das mit den 100ms war mehr so ein Richtwert.

    Der Code sieht momentan folgendermaßen aus, ich entschuldige mich jetzt mal gleich vorweg für mein "PfuscherC" 😃

    Also,

    /*--- #includes of the form <....> -------------------------------------------------*/
    
    #include <stdio.h>       /* Einbinden notwendiger I/O Funktionen (F-Prototypen)     */
    #include <stdlib.h>      // Zum Einbinden der notwendigen Funktionen zum Erstellen
    #include <time.h>        // einer Zufallszahl
    #include <conio.h>
    #include <windows.h>
    
    /*----------------------------------------------------------------------------------*/
    /* Funktionsprototypen:			                                                    */
    /*----------------------------------------------------------------------------------*/
    
    void printfield(char field [60][60]);
    
    /*----------------------------------------------------------------------------------*/
    /* Funktionsdefinition: main                                                        */
    /*----------------------------------------------------------------------------------*/
    
    int main(void)
    
    {
        /*----------------------------------------------------------------------------------*/
        /* Definition der notwendigen Variablen                                             */
        /*----------------------------------------------------------------------------------*/
        int x = 0;       //x-Koordinate
        int y = 0;       //y-Koordinate
    	char input = ' ';
    
    	char field [60][60] = {""};
    	int pos [16][2] = {0};
    
    	int i = 0;
    	int j = 0;
    	int k = 0;
    	int l = 0;
    	int flag = 0;
    
    	int xbuffer = 0;
    	int ybuffer = 0;
    
    	int laenge = 6;
    
       /*----------------------------------------------------------------------------------*/
       /* Hauptprogramm:							                                       */
       /*----------------------------------------------------------------------------------*/
    
    	while (true)
    	{
    
    		/*----------------------------------------------------------------------------------*/
    		/* Einlesen von Tastaturkommandos:   			                                    */
    	    /*----------------------------------------------------------------------------------*/
    
    		//Verschieben der "alten" Kopfpositionen nach rechts im Vektor
    		for (i = 15; i > 0; i--)
    		{
    			pos [i][0] = pos[i-1][0];
    			pos [i][1] = pos[i-1][1];
    		}
    
    		if (kbhit())
    		{
    			input = getch();
    		}
    
    		system("cls");
    
    		if (input == 'w')
    		{
    			y--;
    		}
    		if (input == 's')
    		{
    			y++;
    		}
    
    		if (input == 'a')
    		{
    			x--;
    		}
    
    		if (input == 'd')
    		{
    			x++;
    		}
    
    		//Speichern der "Kopfposition":
    
    		pos[0][0] = x;
    		pos[0][1] = y;
    
    		/*----------------------------------------------------------------------------------*/
    		/* Aktualisieren der Schlange:					                                    */
    	    /*----------------------------------------------------------------------------------*/
    
    		//Löschen des "alten" Spielfeldes:
    
    		for (i = 0; i < 60; i++)
    		{
    			for (j = 0; j < 60; j++)
    			{
    				field [j][i] = ' ';
    			}
    		}
    
    		//Einfügen der Schlangenteile:
    
    		for (i = 0; i < laenge; i++)
    		{
    			xbuffer = pos[i][0];
    			ybuffer = pos[i][1];
    
    			field[xbuffer][ybuffer] = '*';
    		}
    
    		printfield(field);
    
    		//Sleep (100);
    	}
    
     return(0);                         /* Fehlercode 0 - Rückgabe an Betriebssystem  */
    
    }
    
    /*----------------------------------------------------------------------------------*/
    /* Funktionsdefinition:							                                    */
    /*----------------------------------------------------------------------------------*/
    
    void printfield(char field [60][60])
    {
    	int i = 0;
    	int j = 0;
    
    	//Ausgabe der oberen Begrenzung:
    
    	/*printf(" ");
    
    	for (i = 0; i < 60; i++)
    	{	
    		printf("-");
    	}
    
    	printf("\n");*/
    
    	for (i = 0; i < 60; i++)
    	{
    		//printf("|");
    
    		for (j = 0; j < 60; j++)
    		{
    			printf("%c", field[j][i]);
    		}
    
    		printf("\n");
    	}
    
    	/*printf(" ");
    
    	for (i = 0; i < 60; i++)
    	{
    		printf("-");
    	}*/
    
    }
    

    Für mich ist das die einfachse, und logischste "Durchführung"...

    Viele Grüße



  • PfuscherC

    Dann sei dir mal gesagt, dass du hier im C++ Forum bist. Und wenn du etwas hinpfuscht, dann lass es doch bitte C++ sein. Ansonsten geh besser ins C-Forum.

    Ist denn jetzt deine Frage beantwortet? Oder hast du noch ein Problem?



  • Bei 100ms wärst du bei 10 Bildern pro Sekunde. Das Auge braucht in etwa 24 fps. Dank der ungleichmäßigen Ausgabe sind aber ca. 40+ wünschenswert.

    Also in eta 25ms Verzögerung. Wobei du da die Berechnung an sich mit einbeziehen könntest. Aber dein Problem wird wohl eher die Verzögerung in der Konsolenausgabe sein.

    Sinnvoller ist da vermutlich die Nutzung entsprechender APIs und dann nur gezielt die Felder in der Konsole zu zeichnen, die sich tatsächlich geändert haben.



  • Also erst möchte ich mich entschuldigen, für denn Fall, dass ich hier jemanden beleidigt haben sollte 🙂

    Das, was mich stört, ist das Flimmern, welches auftritt, wenn der Konsoleninhalt gelöscht, und dann gleich wieder neu beschrieben wird.

    Gibts da vllt. eine Funktion (Konsolenbefehl?), die das irgendwie behebt?

    @Fellhuhn: Hast du vllt. ein Beispiel (Link) für mich, wie ich die APIs benutzen müsste?

    Viele Grüße



  • Du kannst auch versuchen dir eine Entwicklungsumgebung zu besorgen, die grafische Darstellung jenseits der Konsole gestattet. Sieht besser aus und ist auch garnicht so schwer zu verstehen.



  • Schau mal hier: http://www.c-plusplus.net/forum/viewtopic-var-t-is-131915.html
    oder frag in dem dazugehörigen Forum mal nach. Hier geht es in der Regel nur um reines C++ und das befasst sich nicht weiter mit Konsolen etc.


  • Administrator

    Console Functions - MSDN

    Da hat es auch überall Beispiele dabei. Ansonsten im WinAPI Forum nachfragen.
    Sowieso ist es mir ein Rätsel, wieso du im C++ Forum gelandet bist. Was hat dein Problem oder Code mit C++ zu tun?

    Grüssli



  • lol

    mache das auch grad mit dem snake, allerdings auch in C++ 😉

    das mit dem flimmern stört echt
    ist die consolenausgabe überhaupt flott genug dafür?

    mh das mit den threads würde das so ungefähr klappen?

    thread 1 -> berechnungen des spiels mit tastenabfrage
    thread 2 -> zeichenn auf der console
    
    parralleles starten von thread 1 und 2
    

    würde das hinhauen oder kommen die beiden sih ins gehege von wegen der eine thread berechent grad noch die position und der adnere gibt auf einmal schon wieder alles aus, das aber nur ungenügend bzw falsch
    (dachte jetzt an die thread sachen aus der winapi)



  • @Sky
    Was du beschreibst ist ein Nebenläufigkeitsproblem. Für solche Fällte gibt es Mutex oder im komplexeren Fall Semaphoren. (siehe Google und Thread-API)

    Die Konsole gibt aber Zeichen-/Zeilenweise aus, daher ist cout da nicht geeignet. Entweder gleich eine GUI verwenden oder aber entsprechende Konsolen-APIs bei denen nicht gescrollt wird und man einzelne Zeichen an bestimmten Konsolenpositionen ansprechen kann.



  • Für 2D-Grafikprogrammierung sind die C-API SDL oder die C++-Bibliothek SFML zu empfehlen (für SFML gibt es auch ein C-Binding). Wobei ich stark zu SFML tendiere, da es viel schneller und meiner Ansicht nach auch benutzerfreundlicher ist.

    Threads dafür zu verwenden finde ich leicht übertrieben.



  • ist die consolenausgabe überhaupt flott genug dafür?

    Absolut.

    Sofern du die Betriebsspezifischen Funktionen benutzt geht das recht flott.
    Da kann man sogar 3D Anwendungen drinnen machen. 😉
    (Sieh hier, LTC. ca. 10 Post)
    Allerdings bei höheren Frameraten bringst du ein flackern kaum noch weg. (Habs mal mit einer Art Doppelpufferung versucht, wurde aber nur schlimmer).



  • drakon schrieb:

    Sofern du die Betriebsspezifischen Funktionen benutzt geht das recht flott. Da kann man sogar 3D Anwendungen drinnen machen. 😉

    LoL !
    du freak... 😃

    aber cool

    das heisst wie könnte man das denn machen, also das flimmern eindämmen?

    dachte bis jetzt cout wäre der flaschenhals (oder ist ers immer noch, sollte ich eher die funktionen aus der msdn nehmen für die console?) deshalb hab ich erstmal das spielfeld in einen string gepackt und den dann gesamt ausgegeben...

    für die console benutze ich die improved console...



  • Ja, also ich habe ausschlieslich WinAPI Funktionen genommen um zu rendern. Habe mir dafür ein paar Klassen geschrieben, damit ich das ganze angenehm handeln kann.

    http://msdn.microsoft.com/en-us/library/ms682073(VS.85).aspx

    Ist dazu unumgänglich. 😉

    Für dich von Interesse sollte vor allem das hier sein:
    http://msdn.microsoft.com/en-us/library/ms682662(VS.85).aspx

    Und für Farbe:
    http://msdn.microsoft.com/en-us/library/ms687407(VS.85).aspx

    Ich habe, wie schon gesagt, probiert das ganze zu Buffern, indem ich mit CreateConsoleScreenBuffer einen neuen Buffer erstellt habe und den dann füllen und regelmässig mit SetConsoleActiveScreenBuffer switchen, damit ich nicht direkt auf die Konsole schreibe. Das Ergebnis war schreklich. 😉
    Funktioniert nicht, da irgendwie die ganze Konsole anfängt zu flackern. (Also nicht nur der Inhalt).



  • mh wobei

    ich gucke anchehr nochmal rein
    ich denke ich werds hinkriegen dass nicht immer alles neu gezeichnet werden muss

    die frisch geänderten felder reichen eigendlich...



  • Hi,
    du hast doch gemeint du arbeitest mit der IC!?
    Da kann man doch ganz einfach an eine Stelle in der Konsole "springen" die geändert werden muss und dann mit deiner lieblings Ausgabefunktion ein neues Zeichen setzten.

    z.B bewegt sich die Schlange:

    von-->|--------------------|
          |                    |
          | ~~~~~@             |
          |                    |
          |--------------------|
    nach-->|--------------------|
           |                    |
           |  ~~~~~             |
           |      @             |
           |--------------------|
    

    Jetzt kannste ja den aktuellen "Kopf" durch ein "Körper" Zeichen tauschen, einen neuen "Kopf" zeichnen und das Ende um Eins verkürzen!?

    Dann sollte das Flacker schon mal stark eingedämmt sein ;).

    Gruß Pingu



  • jop hab ich auch gleich vor...

    muss nur erstmal die zeit finden 😉

    problem ist: da muss man für denken xD msuste man für den rest eig nicht...


Anmelden zum Antworten