Wie höre ich auf, mich während der Fenstergröße in XNA zu dehnen?

8

In meinem Fenstermodus XNA-Spiel beendet das Spiel die Aktualisierung des Fensters, wenn der Benutzer die Größe des Fensters ändert, und der zuletzt gezeichnete Frame wird gedehnt und verzerrt, bis der Benutzer die Maus loslässt und die Größenänderung abgeschlossen ist.

Gibt es eine Möglichkeit, das Spiel während des Größenänderungsereignisses "normal" weiterlaufen zu lassen, Frames zu aktualisieren und den Bildschirm neu zu zeichnen?

Mir ist klar, dass es möglicherweise nicht möglich oder empfehlenswert ist, die Render-Schleife während der Größenänderung aufrechtzuerhalten, da Hardware-verwaltete Ressourcen kontinuierlich erstellt und zerstört werden. Gibt es jedoch eine Möglichkeit, das hässliche Dehnen zu stoppen? Idealerweise lassen Sie den vorhandenen Rahmen oben links nicht skaliert oder mit einem schwarzen Bildschirm, wenn dies nicht möglich ist.

Bradley Uffner
quelle
Registrieren Sie ein Ereignis für die Fenstergröße und aktualisieren Sie die GraphicsDevice-Auflösung. Dies kann das Seitenverhältnis aktualisieren und die Dehnung korrigieren.
Gustavo Maciel
Ich weiß nichts über C # / XNA, aber in C ++ / D3D hatte ich gerade die Renderschleife in einem vom Hauptthread getrennten Thread mit der Nachrichtenschleife ausgeführt. Der Hauptthread führt die Puffergrößenänderung durch, wenn ein Größenänderungsereignis auftritt, das über einen Mutex synchronisiert wird.
1
Gustavo, ich behandle dieses Ereignis bereits für andere Zwecke im Spiel. Leider wird es erst ausgelöst, nachdem der Benutzer die Maus losgelassen hat, wenn die Größenänderung abgeschlossen ist.
Bradley Uffner
Dieses Frage / Antwort-Paar könnte hilfreich sein. Hier erfahren Sie, wie Sie mit dem Rendern fortfahren können (obwohl das Dehnen nicht behoben wird).
Andrew Russell

Antworten:

3

Es gibt mindestens 3 Nachrichten, die Sie verfolgen können.

  • WM_SIZE- Fenstergrößenänderung, Mini / Maximierung, Vollbild- / Fensterumschaltung. Sie müssen in wParam lesen, um herauszufinden, was genau passiert ist, und in lParam nach der aktuellen Größe suchen.
  • WM_ENTERSIZEMOVE - Beginnen Sie mit der Fenstergröße im Fenstermodus
  • WM_EXITSIZEMOVE - Fenstergröße im Fenstermodus beenden

Normalerweise möchten Sie nicht, dass die Größe Ihrer App in jedem Frame zwischen WM_ENTERSIZEMOVE und WM_EXITSIZEMOVE geändert wird, da dies zu langsam und hässlich ist. Aber probieren Sie es aus, es ist sicherlich schön als zu dehnen, vielleicht wird es Ihnen gefallen =)

case WM_SIZE:
    // Save the new client area dimensions.
    m_ptViewportSize.x  = LOWORD(lParam);
    m_ptViewportSize.y = HIWORD(lParam);
    if( wParam == SIZE_MINIMIZED )
    {
        m_bAppSuspended = true;
        m_bMinimized = true;
        m_bMaximized = false;
    }
    else if( wParam == SIZE_MAXIMIZED )
    {
        m_bAppSuspended = false;
        m_bMinimized = false;
        m_bMaximized = true;
        OnResize();
    }
    else if( wParam == SIZE_RESTORED )
    {
        // Restoring from minimized state
        if( m_bMinimized )
        {
            m_bAppSuspended = false;
            m_bMinimized = false;
            OnResize();
        }
        // Restoring from maximized state
        else if( m_bMaximized )
        {
            m_bAppSuspended = false;
            m_bMaximized = false;
            OnResize();
        }
        else if( m_bResizing )
        {
            // Resizing in processs
            // You woldn't wanto to handle a massive stream of
            // WM_SIZE here because buffers resizing is very slow
        }
        else
        {
            // Resizing finished and you can handle it. For ex. with 
            // m_SwapChain->SetFullscreenState
            OnResize();
        }

    }
    return 0;

// WM_EXITSIZEMOVE is sent when the user grabs the resize bars.
case WM_ENTERSIZEMOVE:
    m_bAppSuspended = true;
    m_bResizing  = true;
    g_pTimer->Stop();
    return 0;
// WM_EXITSIZEMOVE is sent when the user releases the resize bars.
// Here we reset everything based on the new window dimensions.
case WM_EXITSIZEMOVE:
    m_bAppSuspended = false;
    m_bResizing  = false;
    g_pTimer->Start();
    OnResize();
    return 0;
Ivan Aksamentov - Tropfen
quelle
1
Das Behandeln von Windows-Nachrichten in .NET umfasst das Überschreiben System.Windows.Forms.Form.WndProc(). Wenn Sie in XNA arbeiten, haben Sie keinen direkten Zugriff auf a Form, um diese Methode zu überschreiben. Dies ist zwar möglich, aber kein trivialer Arbeitsaufwand und müsste das Design von XNA umgehen.
Cypher
Sollte sich jemand für diesen Weg entscheiden, sollte sich diese Liste der wm_ * -Konstanten als nützlich erweisen: pinvoke.net/default.aspx/Constants/WM.html
Cypher
Wie andere gesagt haben, würde ich immer noch eine Möglichkeit brauchen, die XNA "Engine" kurzzuschließen und sie während der richtigen Ereignisse wieder zeichnen zu lassen. Nach allem, was ich sagen kann, geht XNA während des Größenänderungsvorgangs sozusagen "schlafen".
Bradley Uffner