Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.04.2015, 21:09   #11
StriderX
Форумчанин
 
Регистрация: 21.04.2014
Сообщений: 115
По умолчанию

Цитата:
Сообщение от NEoMASTERR Посмотреть сообщение
И Что ждать пока винда сама решит когда игроку видеть соперников?) Я навязываю ей, думаю так и другие движки делают
У вас ошибка с тем, что по таймеру надо НЕ рисовать. Вам необходимо вернуться назад в "доDLLелье" и произвести повторную декомпозицию систем (желательно при этом забить на WinAPI - на начальном этапе и без него хватит проблем). Напишу предельно сжато по архитектуре.
Наша игра что-то рисует. Когда? Всегда, в этом её смысл:
Код:
while true do begin
    Draw(); // строим и отправляем изображение на экран
end;
Статичная картинка скушная, хотим движения:
Код:
while true do begin
    Update(); // пересчитываем физику
    Draw(); // строим и отправляем изображение на экран
end;
Теперь хотелось бы получить реакцию от игрока:
Код:
while not FTerminated do begin // должен же игрок как-то выйти из игры
    while OperationSystem.HaveMessage do begin // ОС есть что сказать? (мыша, клавиатура, всякие свернуть\развернуть и т.п.)
        ProcessMessage(OperationSystem.GiveMeOneMessagePlease); // реагируем на её запрос
    end;
    Update();
    Draw();
end;
Всё отлично, но изображение мерцает (несколько раз меняем цвет одного пикселя):
Код:
while not FTerminated do begin
    while OperationSystem.HaveMessage do begin
        ProcessMessage(OperationSystem.GiveMeOneMessagePlease);
    end;
    Update();
    Render(); // теперь рисуем в битмап\буфер
    Present(); // отправляем буфер на экран
end;
Прекрасно, но персонажи при перемещении дёргаются и вообще при каждом запуске ведут себя по-разному. Это у нас ошибки округления и неравномерные дельты по времени, фиксируем:
Код:
while not FTerminated do begin
    while OperationSystem.HaveMessage do begin
        ProcessMessage(OperationSystem.GiveMeOneMessagePlease);
    end;

    someStepCollector += deltaTime;
    stepCount := Trunc(someStepCollector / stepTime);
    someStepCollector -= stepCount * stepTime;
    if stepCount > 0 then
    for i := 0 to stepCount - 1 do begin
        FixedUpdate(); // физика тут
    end;

    BeforeRender(); // интерфейс и анимации тут
    Render();
    Present();
end;
Теперь мы начинаем сжигать ЦПУ, у нас ФПС под 2000, а надо всего 60 - пора снижать нагрузку. Нагрузку может снизить Present, если будет ожидать сигнал монитора\видеокарты "айда рисовать" (VSync). Ммм... но мы не можем доверять этим бездушным железкам:
Код:
while not FTerminated do begin
    while OperationSystem.HaveMessage do begin
        ProcessMessage(OperationSystem.GiveMeOneMessagePlease);
    end;

    someStepCollector += deltaTime;
    stepCount := Trunc(someStepCollector / stepTime);
    someStepCollector -= stepCount * stepTime;
    if stepCount > 0 then
    for i := 0 to stepCount - 1 do begin
        FixedUpdate();
    end;

    someRenderCollector += deltaTime;
    if (someRenderCollector > renderTime) then begin // пропускаем лишние рендеры
        someRenderCollector -= Trunc(someRenderCollector / renderTime) * renderTime;
        BeforeRender();
        Render();
    end;
    Present(); // всё равно всегда презентуем
    SleepEx(5); // ну так-то можно и немного поспать (Ex значит, что нас дёрнут, если для нас будет сообщение от ОС)
end;
Что касается VCL. Сообщения от ОС вместо вас отработает именно он. Вам остаётся написать то, что ниже while OperationSystem.HaveMessage - это Appliction.OnIdle. Туда всё и суём. Связываться с Present'ом не наш путь: у нас он либо уже готовый от OpenGL\DirectX, либо просто рисуем на канву формы и пусть она сама себя презентует (нафиг нам этот WM_PAINT, у нас вон какой VCL есть).
Если нельзя, но очень хочется, то Present должен у нас рисовать в еще один Bitmap (а если точнее, то просто обменять местами указатели - фронт буфера с бэк буфером). После этого он засылает ОС сигнал, что изображение обновлено (а тот же инвалидейт подойдёт). Когда ОС прилетит со своим WM_PAINT мы отдаём ей наш фронт-буфер (мы понятия не имеем сколько раз и когда нас спросят об этом - отдаём всегда, когда просят, а не по таймеру или другим хотелкам).
Можно пошастать по опенсурсному Asphyre и посмотреть, а как оно работает (заодно посмотреть на правильно написанный AsphyreTimer.pas).
StriderX вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Рисование средствами WinApi maksim_serg Microsoft Office Excel 1 09.12.2014 08:07
WinApi рисование в VBA Desha Помощь студентам 5 05.12.2012 12:32
рисование в WINAPI Alt_Shift Помощь студентам 3 03.07.2011 20:14
Рисование в WinApi nazavrik Win Api 13 30.08.2009 23:54
Рисование на форме созданной на WinApi N!ckeL Win Api 3 30.04.2008 19:02