Come posso smettere di allungare durante il ridimensionamento della finestra in XNA?


8

Nel mio gioco XNA in modalità finestra quando l'utente ridimensiona la finestra, il gioco smette di aggiornare la finestra e l'ultimo fotogramma disegnato viene allungato e distorto fino a quando l'utente rilascia il mouse e il ridimensionamento viene completato.

C'è un modo per far funzionare il gioco "normalmente", aggiornando i frame e ridisegnando lo schermo, durante l'evento di ridimensionamento?

Mi rendo conto che mantenere il ciclo di rendering attivo durante il ridimensionamento potrebbe non essere possibile o consigliato a causa delle risorse gestite dall'hardware che vengono continuamente create e distrutte, ma c'è un modo per fermare il brutto allungamento? Idealmente, lasciando la cornice esistente non scalata in alto a sinistra, o con uno schermo nero se ciò non è possibile.


Registrare un evento per il ridimensionamento della finestra e aggiornare la risoluzione GraphicsDevice. Ciò può aggiornare le proporzioni e correggere l'allungamento.
Gustavo Maciel,

Non so di C # / XNA, ma in C ++ / D3D avevo appena il loop di rendering in esecuzione in un thread separato dal thread principale con il loop dei messaggi. Il thread principale esegue il ridimensionamento del buffer quando si verifica un evento di ridimensionamento, sincronizzato tramite un mutex.

1
Gustavo, gestisco già quell'evento per altri scopi nel gioco. Sfortunatamente non si attiva fino a quando l'utente non rilascia il mouse una volta completata la ridimensionamento.
Bradley Uffner,

Questa coppia di domande / risposte potrebbe essere utile. Ti dice come continuare il rendering (anche se non corregge lo stretching).
Andrew Russell,

Risposte:


3

Ci sono almeno 3 messaggi che puoi monitorare.

  • WM_SIZE- ridimensionamento della finestra, mini / ingrandimento, commutazione a schermo intero / finestra. Leggerai in wParam per scoprire cosa è successo esattamente e in lParam per le dimensioni attuali.
  • WM_ENTERSIZEMOVE - inizia il ridimensionamento della finestra in modalità finestra
  • WM_EXITSIZEMOVE - termina il ridimensionamento della finestra in modalità finestra

Di solito non vorrai ridimensionare la tua app ogni frame tra WM_ENTERSIZEMOVE e WM_EXITSIZEMOVE perché è troppo brutto e brutto. Ma provalo, è sicuramente bello che allungare, forse ti piacerà =)

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;

1
La gestione dei messaggi di Windows in .NET comporta la sostituzione System.Windows.Forms.Form.WndProc(). Quando si lavora in XNA, non si ha accesso diretto a a Formper sovrascrivere quel metodo. Sebbene sia possibile farlo, non è una banale quantità di lavoro e dovrebbe eludere il design di XNA.
Cypher,

Se qualcuno dovesse scegliere di seguire questo percorso, questo elenco di costanti di wm_ * dovrebbe rivelarsi utile: pinvoke.net/default.aspx/Constants/WM.html
Cypher,

Come altri hanno già detto, avrei ancora bisogno di un modo per cortocircuitare il "motore" XNA e farlo riaccendere durante gli eventi corretti. Da quello che posso dire XNA sorta di "va a dormire" durante la procedura di ridimensionamento.
Bradley Uffner,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.