Problem mit globalem Objekt
-
ch ein Game of life programmiert, anfangs nur für die Konsole, habe es aber letzten Endes doch noch einmal grafisch überarbeitet. Nun bin ich auf folgendes Problem gestoßen:
Ich erstelle mein Game-Objekt global, damit ich sowohl in der Nachrichtenschleife der WinMain als auch in der WndProc darauf zugreifen kann. In der Nachrichtenschleife führe ich die Generation durch, das sieht wie folgt aus (UpdateWindow(), RegelnAnwenden(), WeltenTasuchen()). Im WM_ PAINT case Block führe ich die Display-Methode meines Objektes aus.. Und genau hier liegt das Problem, nichts passiert... Ändere ich die Display-Methode so ab, dass nichts gezeichnet wird, sondern die Zellen über die MessageBox ausgegeben werden (Nur um mich zu versichern das der Fehler nicht in der Game-Klasse liegt) scheint jede Zelle in meiner Spielwelt tot zu sein (Was sie nicht sind!). Führe ich die Display-Methode nun nicht im WM_PAINT case aus, sondern in der Nachrichtenschleife direkt hinter der Generation stimmt die Ausgabe allerdings.
Da das Game-Objekt global deklariert wurde müsste der Inhalt der darin befindlichen Spielwelt eigentlich sowohl in der WinMain als auch in der WndProc übereinstimmen?! Stehe grade echt auf dem Schlauch.. Wo könnt der Fehler liegen?// Global Game GameOfLife(SCREEN_WIDTH, SCREEN_HEIGHT); WinMain { // ... while (true) { if (PeekMessage(&mMessage, NULL, 0, 0, PM_REMOVE)) { // Nachrichten übersetzen TranslateMessage(&mMessage); // Nachricht zur Fensterprozedur senden DispatchMessage(&mMessage); if (mMessage.message == WM_QUIT) break; } else { // ---------------------------------------- // Game Code hier einfügen GameOfLife.Generation(); } } // ... } WndProc { // ... case WM_PAINT: { Paintstruct ps; HDC hDc = BeginPaint(hWnd, &ps); GameOfLife.Display(hDc); hDc = EndPaint(hWnd, &ps); } break; // ... }
Bitte um Hilfe... MfG Inv151673
-
// delete
-
Poste bitte Code der 1:1 aus deinem Projekt rauskopiert worden ist. In modifiziertem Code Fehler suchen ist einfach uninteressant.
-
GameOfLife.cpp
#include <GameOfLife.h> Game GameOfLife(SCREEN_WIDTH, SCREEN_HEIGHT); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow ) { HWND hWnd; WNDCLASSEX WndClass; RECT WindowRect; MSG mMessage; ZeroMemory(&WndClass, sizeof(WNDCLASSEX)); WndClass.cbSize = sizeof(WNDCLASSEX); WndClass.style = CS_HREDRAW | CS_VREDRAW; WndClass.lpfnWndProc = WndProc; WndClass.hInstance = hInstance; WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // WndClass.hbrBackground = (HBRUSH)COLOR_WINDOW; WndClass.lpszClassName = L"MainWindow"; RegisterClassEx(&WndClass); // Fenstergröße korrigieren WindowRect = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT }; AdjustWindowRect( &WindowRect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, NULL ); hWnd = CreateWindowEx( NULL, L"MainWindow", // Fensterklasse L"Game of life", // Fenstertitel WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, // Fenster-Styles CW_USEDEFAULT, // X-Position CW_USEDEFAULT, // Y-Position SCREEN_WIDTH, // Breite SCREEN_HEIGHT, // Höhe NULL, NULL, // Menü hInstance, // Instanz NULL ); ShowWindow(hWnd, iCmdShow); // Spiel initialisieren GameOfLife.Initialize(1, hWnd); // 1 = Conway while (true) { if (PeekMessage(&mMessage, NULL, 0, 0, PM_REMOVE)) { // Nachrichten übersetzen TranslateMessage(&mMessage); // Nachricht zur Fensterprozedur senden DispatchMessage(&mMessage); if (mMessage.message == WM_QUIT) break; } else { // ---------------------------------------- GameOfLife.Generation(); } } return mMessage.wParam; } LRESULT CALLBACK WndProc( HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam ) { switch (uiMessage) { case WM_PAINT: { PAINTSTRUCT ps; HDC hDc = BeginPaint(hWnd, &ps); GameOfLife.Display(hDc); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); return 0; break; } // Alle Nachrichten "bearbeiten", welche nicht im // switch-Block abgefangen wurden return DefWindowProc(hWnd, uiMessage, wParam, lParam); }
Die Display-Methode aus Game.cpp
void Game::Display(HDC hDc) { int iWidth = pWorld->GetWidth(), iHeight = pWorld->GetHeight(); for (int y = 0; y < iHeight; y++) { for (int x = 0; x < iWidth; x++) { if (pWorld->GetCell(x, y).uiCell) SetPixel(hDc, x, y, RGB(0, 0, 255)); else SetPixel(hDc, x, y, RGB(225, 255, 255)); } } }
-
Wm_paint wird nur wenn nötig aufgerufen, du bräuchtest also einen timer, welcher das fenster ständig invalidiert, wenn du die malarbeiten in wm_paint erledigen möchtest. Anstatt der messageBox empfehle ich dir einen richtigen Debugger.
-
Soweit ich weiss solltest du die
DefWindowProc
nicht aufrufen wenn duWM_PAINT
selbst behandelst. Statt dessen einfach 0 zurückgeben.
Wird aber an deinem Problem nix ändern.Wirf mal ein
InvalidateRect(hWnd, 0, false);
nach demGameOfLife.Generation();
rein.Und das
roflo schrieb:
Anstatt der messageBox empfehle ich dir einen richtigen Debugger.
würde ich dir auf empfehlen. Lern so früh wir möglich mit dem Debugger umzugehen. Der ist nicht nur beim Fehler-Finden nützlich, sondern hilft mMn. auch gut zu verstehen was in einem Programm abgeht - gerade wenn man noch Anfänger ist.
-
Was erwartest Du? Das Programm läuft ja nicht weiter...
Also was passiert:
Dein Programm läuft durch die Nachrichtenschelifen, holt Input Nachrichten und verteilt diese.
Auf diesem Weg werden dann auch zwischendrin WM_PAINT Nachrichten erzeugt.Wenn DU jetzt eine Messagebox anzeigst, dann muss Dir klar sein, dass diese eine eigene Nachrichtenschleife hat. Das heißt es werden weiterhin WM_PAINT Nachrichten erzeugt und Input Nachrichten abgerufen und verarbeitet, aber Deine Nachrichtenschleife läuft nicht mehr...
Da Dein Update aber in der Nachrichtenschleife läuft wird entsprechend auch keine nächste Generation erzeugt.
Damit Dein Spiel auch nicht in jedem Nachrichten Zyklus eine Generation erzeugt, würde ich Dir raten auch die Erzeugung der Generation in einen WM_TIMER Handler zu verlagern in die Fensterklasse oder über einen globalen Timer Callback abzuhandeln.