Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > Цикл обработки сообщений игры


Автор: konekt 11.8.2008, 22:10
Изменяю цикл обработки сообщений следующим образом:

MSG mssg;

PeekMessage(&messg,NULL,0,0,PM_NOREMOVE);

while(mssg.message!=WM_QUIT){
          
          if(PeekMessage(&mssg,NULL,0,0,PM_REMOVE)){
                     TranslateMessage(&mssg);
                     DispatchMessage(&mssg);
           }
          else{
                      ///Нет сообщений для обработки - выполнить код игры
                     Render();
           }
}
Вроде бы цикл обработки сообщений должен постоянно вызывать Render()
Но на самом деле такого у меня не происходит. Если кто знает причину то помогите разобраться.

Автор: Mazzi 12.8.2008, 08:34
поставь в обе ветви ( if   и    else) счётчики для подсчёта количества входов в каждую ветвь.

Увидишь куда чаще заходишь.

Автор: konekt 12.8.2008, 12:17
Счетчики ставил. Получается, что функция Render() никогда не вызывается, а должна , по идеи, вызываться все время smile .
Зато сообщение WM_PAINT вызывается постоянно. Логика вроде в этом коде есть и он ДОЛЖЕН вызывать функцию Render() но он НЕ ВЫЗЫВАЕТ.

Автор: Mazzi 12.8.2008, 12:30
Ветвь else не вызовется никогда, перенеси свой render в ветвь if и всё.

Добавлено через 2 минуты и 7 секунд
А не вызовется, потому, что для этого нужно, чтобы не было  сообщения для функции. А без сообщения не вызовется твоя функция обработки сообщений. Понял?

Автор: konekt 12.8.2008, 22:53
Вообще вставить функцию Render() в тело if веще хорошая, но этот код взят из книги по DirectX9 Алена Торна и по всем параметрам должен работать.
Если есть сообщений для обработки, то должна выполняться ветвь if, а если нет сообщений (тоесть я не посылаю окну ни-каких команд) должна выполняться ветвь else, которая минуте Translant Message и DispatchMassage. 

Автор: Supersedes 13.8.2008, 07:32
Код

ZeroMemory( &msg, sizeof( msg ) );
while ( msg.message != WM_QUIT ) {
    if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    } else render();
}


Все прекрасно работает. Ищи ошибку где-нить еще. Кстати у тебя я надеюсь "messg" и "mssg" -- это одно и то же!?

Автор: konekt 17.8.2008, 10:01
Спасибо за цикл. Видно что он идентичен моему. Messg=mssg, просто я не могу копировать исходники т.к. интернет подключен к другому компьютеру.

Но к сожалению, этот цикл тоже не работает. Так как я пишу с помощью Visual Studio 2008 и свой проект создавал как не Win32 а как EmptyProgect.  У меня все работает если функцию Render() запихать в if, но должен работать в теле else и код от Supersedes тому наглядный пример.
 

Автор: mes 17.8.2008, 11:04
и свой проект создавал как не Win32 а как EmptyProgect
a где расположен цикл обработки?

Автор: Rickert 18.8.2008, 03:22
Перенеси функцию Render в обработку WM_PAINT - самый правильный вариант. ИМХО

Автор: Supersedes 18.8.2008, 07:07
Rickert, далеко не самый правильный вариант.

Автор: Rickert 18.8.2008, 07:39
Supersedes, утверждение без аргументов - сотресание воздуха.

Автор: Supersedes 18.8.2008, 08:15
Rickert
Цитата

Перенеси функцию Render в обработку WM_PAINT - самый правильный вариант.

Цитата

Supersedes, утверждение без аргументов - сотресание воздуха.


Абсолютно с тобой согласен!! Читай что сам пишешь!

Автор: Rickert 18.8.2008, 08:40
А программисту разве нужно уже всё разжёвывать чтобы он понял, что отрисовка сцены OpenGL, после отрисовки самого окна - это логично smile 

Автор: Supersedes 18.8.2008, 08:53
Rickert, во-первых я не уверен что konekt на самом деле достаточно опытный программист.
Во-вторых, если бы ты сам был хорошим программистом, то ты наверняка бы понял что именно хочет автор статьи!
То что функцию render() надо запихнуть в WM_PAINT это по-моему и так понятно.. Тем не менее я думаю что автор статьи хотел чтобы данная фунция выполнялась постоянно и, соответственно постоянно отрисовывалась сцена. В данном случае изречение: 
Цитата

Перенеси функцию Render в обработку WM_PAINT - самый правильный вариант. ИМХО

неуместно smile 

Автор: Rickert 18.8.2008, 09:25
У человека есть проблема - я предложил решение. Все остальные наши разговоры неуместны в этой теме, предлогаю продолжить через ЛС.

Автор: konekt 18.8.2008, 09:52
Спасибо что пытаетесь помочь. Да программист я не опытный, но запихать в WM_PAINT это так мной было и сделано с самого начала ковыряния с этим кодом, так как по другому пока не работает кроме как установки функции в тело if что предложил мне Mazzi. 
Цитата
Ветвь else не вызовется никогда, перенеси свой render в ветвь if и всё.



и я бы особо и не парился, но зная что WM_PAINT вызывается только когда нужно перерисовать окно когда оно например закрыто, а потом мы вытаскиваем его наружу, мне очень странно и пока не понятно почему оно вызывается постоянно. Наблюдая за другими окнами и смотря какие им посылаются сообщения я не вижу, чтобы им посылалось бесконечно WM_PAINT. 

Да и само то что взятый из Тутора по DirectX цикл обработки сообщений который мне предложил Supersedes идентичен моему - он тоже не работает. 

Так вот скажите - это что инициализация DirectDraw вызвала такой шквал сообшений WM_PAINT в мое окно. Тогда почему взятый из учебника цикл (который по логике должен работать - я ведь не сам его придумал) не работает.

Автор: Supersedes 18.8.2008, 10:09
konekt, я был бы очень признателен если ты выволил весь код целиком. Думаю стало бы намного понятнее что к чему!

Цитата

Да и само то что взятый из Тутора по DirectX цикл обработки сообщений который мне предложил Supersedes идентичен моему - он тоже не работает.

Заметь я не предлагал тебе свой код. Я просто сказал что у меня он прекрасно работает smile 

Rickert
Цитата

У человека есть проблема - я предложил решение. Все остальные наши разговоры неуместны в этой теме, предлогаю продолжить через ЛС.

Мне очень грустно об этом говорить, но решение ты не предложил... Если хочешь то можем поговорить об этом в аське. Мой UIN: 373706950
Знаешь что такое UIN !?))

Автор: konekt 23.8.2008, 12:24
Supersedes, вываливать то особо и нечего. Стандартное Windowoe приложение в котором происходит инициализация DirectDraw. Затем стандартный цикл обработки переделывается в тот что я привожу (он взят из книги). 
Если я правильно понимаю работу стандартного цикла, то приложение ждет когда поступит сообщение, если оно поступает то начинается его обработка, если сообщений нет - программа бездействует.
Так вот мой новый цикл должен заставлять программу не бездействовать в это время, а выполнять функцию Render() в которую может быть запихано все, что угодно. Но этого не происходит.
Может быть я слишком тупой и мой вопрос уже всех достал. Но где в моих рассуждениях может быть ошибка. 

Автор: Rickert 25.8.2008, 02:22
konekt, текст функции WndProc в студию.

Автор: Supersedes 25.8.2008, 06:45
konekt, да, покажи нам WndProc.

Автор: Rpahut 25.8.2008, 11:38
Из хелпа по winapi(WM_PAINT):
Цитата

The system sends this message when there are no other messages in the application’s message queue.

так чо оно должно быть там постоянно, хотя чтобы сказать наверняка нужно глубоко копнуть в винапи.

И мне класть на книги и туторы - моя голова мне подсказывает следующий код:
Код

while (true) {
    while (PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE)) {
        if (GetMessage(&Msg, NULL, 0, 0)) {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
        else {
            return TRUE;
        }
    }
    Render();
}

Автор: Supersedes 27.8.2008, 07:15
Rpahut,
Код

while (true) {
    while (PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE)) {
        if (GetMessage(&Msg, NULL, 0, 0)) {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
        else {
            return TRUE;
        }
    }
    Render();
}


Код

    for ( ; ; ) {
        if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
            if ( msg.message == WM_QUIT ) break;
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        render();
    }

в чем разница?

Автор: VK_Techno 12.9.2008, 09:47
Как вариант:
при обработке WM_CREATE (или где-нибудь рядом) запустить таймер с помощью SetTimer() на, скажем, 30 мс. В обработчике WM_TIMER (или функции таймера, указатель на которую передали SetTimer()) вызвать Render().

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)