Schwarz/weiß nach 17 sekunden



  • Hallo Volks,

    Ich probiere gerade das bekannte Spiel Pacman mit Direct Draw nach zu programmieren.

    Leider bin auf dem Gebiet der Grafikprogrammierung neu. Mein Pacman läuft wunderbar, nur nach eine bestimmten Zeit (ca 17 sekunden) , wird das Spiel plötzlich Schwarz-Weiß.

    Kennt jemand vieleicht das Problem, oder hatte jemand vieleicht das selbe Problem schon einmal?

    Ihr könnt meine Source hier runterladen:

    http://www.freewebs.com/leckdenbieber/Pacman.rar

    PS.: Da man zum Compilen die ddraw.lib braucht, habe ich die bereits Compilierte .exe Datei in das Debug-Verzeichniss gelegt.



  • MemLeaks mit der GDI?

    Bye, TGGC (Wähle deine Helden)



  • TGGC hat recht...
    Hab mir mal deinen Sourcecode angeschaut nimms mir nicht übel aber der SOURCE ist zum KOTZEN 😉
    Problem liegt daran dass du Brushes und Pens erzeugst sie aber nicht nach Verwendung löscht was natürlich den fatalsten Fehler darstellt den ein C/++ Programmierer überhaupt machen kann 🤡

    Folglich müssten die 2 Methoden in denen du zeichnest so heißen: (ps ich hab jetzt einfach nur die falschen stellen umgeändert soll nicht heißen dass das hier sinnvoll ist)

    void CPacman::DrawHim(HDC hdc)
    {
    	CalcMount();
    
    	POINT pOldPoint;
    	//grundriss
        HBRUSH brush = CreateSolidBrush(m_col);
    	SelectObject(hdc, brush);
    	Ellipse(hdc, m_nX, m_nY,m_nX + m_cnPacSize, m_nY + m_cnPacSize);
    	//Auge
        HBRUSH brush2 = CreateSolidBrush(RGB(0,0,0));
    	SelectObject(hdc, brush2 );
    	switch(m_nWay) {
    	case 0: Ellipse(hdc, m_nX+25, m_nY+7,m_nX + 30, m_nY + 12); break;
    	case 1: Ellipse(hdc, m_nX+20, m_nY+7,m_nX + 25, m_nY + 12); break;
    	case 2: Ellipse(hdc, m_nX+10, m_nY+19,m_nX + 15, m_nY + 24); break;
    	case 3: Ellipse(hdc, m_nX+10, m_nY+20,m_nX + 15, m_nY + 25); break;
    	}
    	//gesicht
        HPEN pen  = CreatePen( PS_SOLID, 5 , RGB(0,0,0));
    	SelectObject(hdc, pen);
    	for(int i = m_nMouthStateMin; i < m_nMouthStateMax; i++) {
    		MoveToEx(hdc, m_nX + ( m_cnPacSize / 2),m_nY + ( m_cnPacSize / 2) , (LPPOINT) & pOldPoint);
    		LineTo(hdc, m_vMouth[i].x,m_vMouth[i].y);
    	}
        DeleteObject(brush); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        DeleteObject(brush2);
        DeleteObject(pen);
    }
    
    void CPacMap::DrawMap(HDC hdc)
    {
    
    	int x = 0,y = 0 ; //beim ersten feld
    
        HBRUSH brush = CreateSolidBrush( RGB(0,0,0) );
    	SelectObject(hdc, brush );
    
        HPEN pen = CreatePen(PS_SOLID, 0 , RGB(255,150,150) );
    	SelectObject(hdc, pen );
    	for(x = 0; x < m_mapmaxx; x++)
    		for(y = 0; y < m_mapmaxy; y++)
    		{
    			switch( m_map[x][y] )
    			{
    			case '1' : Rectangle(hdc, x * FieldSize + xt, 
    								      y * FieldSize + yt,
    									  x * FieldSize + FieldSize + xt, y * FieldSize + FieldSize + yt);
    					   break;
    			}								
    		}
    	//Fressen zeichnen
        HBRUSH brush2 = CreateSolidBrush( RGB(0,255,100) );
    	SelectObject(hdc, brush2 );
        HPEN pen2 = CreatePen(PS_SOLID, 0 , RGB(100,255,100) );
    	SelectObject(hdc, pen2 );
    		for(int i = 0; i < m_vFood.size(); i++) {
    			Rectangle(hdc, m_vFood[i].x - 4, m_vFood[i].y - 4,
    					   m_vFood[i].x + 4, m_vFood[i].y + 4);
    		}
    
        DeleteObject(brush); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        DeleteObject(pen);
        DeleteObject(brush2);
        DeleteObject(pen2);
    
    }
    


  • Auch find ich das Stückchen genial 🤡 :

    //Mit dem Zeichnen Beginnen
    lpddsBack->Blt(&fill_area, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); //Backbone buffe SChwarz färben
    lpddsBack->GetDC((HDC *) & hdc);  // Grafikkontext Hohlen
    pac.DrawHim(hdc);				  //Packman zeichen
    map.DrawMap(hdc);				  //Map Zeichnen
    lpddsBack->ReleaseDC(hdc);	      //Gerätekontext Freigeben
    lpddsPrimary->Flip(NULL, DDFLIP_WAIT);  //Backbone buffen auf den Bildschirm Flippen
    

    😃 😃 😃



  • Hab gerade den Thread gesehen und wollte nachvollziehen, was los ist und im aktuellen Quelltext scheint er das Problem jetzt anders gelöst zu haben 😃

    void CPacMap::DrawMap(HDC hdc)
    {
    
    	int x = 0,y = 0 ; //beim ersten feld
    
    	SelectObject(hdc, CreateSolidBrush( RGB(0,0,0) ) );
    	SelectObject(hdc, CreatePen(PS_SOLID, 0 , RGB(255,150,150) ) );
    	for(x = 0; x < m_mapmaxx; x++)
    		for(y = 0; y < m_mapmaxy; y++)
    		{
    			switch( m_map[x][y] )
    			{
    			case '1' : Rectangle(hdc, x * FieldSize + xt, 
    								      y * FieldSize + yt,
    									  x * FieldSize + FieldSize + xt, y * FieldSize + FieldSize + yt);
    					   break;
    			}								
    		}
    	//Fressen zeichnen
    	SelectObject(hdc, CreateSolidBrush( RGB(0,255,100) ) );
    	SelectObject(hdc, CreatePen(PS_SOLID, 0 , RGB(100,255,100) ) );
    		for(int i = 0; i < m_vFood.size(); i++) {
    			Rectangle(hdc, m_vFood[i].x - 4, m_vFood[i].y - 4,
    					   m_vFood[i].x + 4, m_vFood[i].y + 4);
    		}
    }
    

    Schaue dir mal diesen Code zur Laufzeit mit dem Taskmanager an, vielleicht geht dir dann ein Licht auf 😉

    int main() {
    	long long x=0;
    
    	while(true) {
    		new int[x*=x];
    	}
    
    	return 0;
    }
    


  • masterofx32 schrieb:

    Hab gerade den Thread gesehen und wollte nachvollziehen, was los ist und im aktuellen Quelltext scheint er das Problem jetzt anders gelöst zu haben 😃

    Wir reden schon über den gleichen Quelltext nur ich hab ihn halt umgeändert 🙄



  • Ohh, Logikfehler meinerseits 😉
    Ich dachte, du hättest den Code vorher/nachher gepostet, aber dabei ist dein erster Codeblock ja ein ganz anderer. Deswegen dachte ich, er hätte das DeleteObject zu umgehen versucht, indem er keine Handle-Variable erstellt. Naja, ich hab mich wenigstens amüsiert 🤡



  • ah vielen dank für eure Antworten, mit dem Löschen von den GDI objeckten funktioniert es so.

    Ich dachte das diese GDI Objekte nur Handels wären, weil sie ja mit der Windows Notation "H" anfangen. Und HANDELS muss man gewöhnlicher Weise ja nicht löschen, weil sie ja statisch erzeugt werden. Das HPen etc... neuen SPeicherplatz dynamisch erzeugt , konnte ich ja nicht ahnen , da die SDK Hilfe solche Informationen auch net hat (oder ich sie überlesen habe 😮).

    nochmals vielen Dank 👍



  • HPEN und HBRUSH sind Handles 😉



  • @Chillor: Unsinn.

    dali schrieb:

    TGGC hat recht...

    Unnötig zu betonen.

    Bye, TGGC (Wähle deine Helden)



  • Ich werds mir merken...



  • Chill0r schrieb:

    Und HANDELS muss man gewöhnlicher Weise ja nicht löschen

    Eigentlich schon, oder zumindest freigeben. Fast alle Handles müssen auf irgendeine Art und Weise freigegeben werden. Und bei solchen, wo du das nicht mitbekommst, wird es beim Programmende gemacht. Das sind aber relativ wenige.

    Chill0r schrieb:

    Das HPen etc... neuen SPeicherplatz dynamisch erzeugt , konnte ich ja nicht ahnen , da die SDK Hilfe solche Informationen auch net hat (oder ich sie überlesen habe 😮).

    Das letzte trifft es schon eher. Nachzulesen zB im Beispiel "Creating Colored Pens and Brushes".

    Da sind übrigens noch mehr Fehler bzw Verbesserungsmöglichkeiten in deinem Code:

    MSDN schrieb:

    Do not delete a drawing object (pen or brush) while it is still selected into a DC.

    OK, im originalen Code fehlen die DeleteObject Aufrufe sowieso. Aber damit ist es noch nicht getan.

    double nStep = (3.1415926535897932384626433832795 - (3.1415926535897932384626433832795/4)) / 15; 
    	double x,y,alpha = 3.1415926535897932384626433832795/4;
    

    Schon mal daran gedacht, für sowas 'ne Konstante zu verwenden? Du könntest ihr auch 'nen vollkommen abgefahrenen Namen geben ... wie zB pi.

    Zu hPrevInstance in WinMain

    MSDN schrieb:

    Handle to the previous instance of the application. This parameter is always NULL.

    Wozu also die Abfrage?

    Schau dir nochmal die Signatur einer Fenster-Nachrichtenfunktion an.

    case VK_ESCAPE: running=false; return 0;
    

    Ist zwar nicht falsch, ich würde hier dem Fenster aber eher eine WM_CLOSE Nachricht senden. Dann hast du schon mal eine globale Variable eliminiert.

    case WM_DESTROY:
    		{
    			PostQuitMessage (0) ; 
    			return 0 ;
    		} break;
    

    Wozu break, wenn vorher 'eh returned wird?

    Du erzeugst einen Thread, der letztendlich eine Endlosschleife ist? Nicht gerade die feine Art.

    So, das waren nur mal die Sachen, die mir so spontan aufgefallen sind. 🙂


Anmelden zum Antworten