Вывод символов в полноэкранном режиме Free Pascal

Темы, связанные с проектированием и программированием roguelike-игр

Модераторы: Sanja, Максим Кич

Аватара пользователя
Эльф
Сообщения: 115
Зарегистрирован: 12 июл 2007, 16:39

Вывод символов в полноэкранном режиме Free Pascal

Сообщение Эльф » 28 сен 2009, 17:21

Итак, классическая история. Часть с Бискапом, нервно курящим в сторонке, я, с вашего позволения пропущу, и перейду сразу к проблемам.

Итак, печалит скорость отрисовки символов на экране. В оконном режиме это малозаметно (хотя определенные паузы есть и там), но при переходе в полноэкранный режим начинается ужас. Полностью заполнить экран символами занимает 4-5 секунд. Перерисовывать узкий участок (скажем, в поле зрения ГГ), ясное дело, быстрее, но при этом скачет по экрану курсор.

Выведение на экран, ясное дело, происходит путем выведения каждого конкретного символа. Других способов я придумать не могу - выведение построчно хорошо, но идет только одним цветом.

Как я понимаю, cursoroff убирает курсор несколько читерским способом, вроде засовывания его за пределы экрана, и во время отрисовки он все равно будет появляться. Есть ли какой-то более радикальный способ убрать его? Есть ли способ повысить скорость вывода символов на экран? В DoomRL (он ведь на фрипаскале?) я таких проблем не видел, сталбыть есть какой-то способ решения?

inb4 "пиши на с"

Аватара пользователя
Aerton
Сообщения: 503
Зарегистрирован: 11 авг 2007, 02:58
Откуда: Новосибирск
Контактная информация:

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Aerton » 28 сен 2009, 19:14

4-5 секунд - это слишком медленно даже для 286, что-то явно не так.

Автор DoomRL использует собственную библиотеку http://valkyrie.chaosforge.org/
Исходники открыты, можно посмотреть как там сделано, или же просто использовать её.

Аватара пользователя
warchief
Сообщения: 300
Зарегистрирован: 11 янв 2008, 09:55
Откуда: Озеро снов

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение warchief » 29 сен 2009, 03:07

Выведение на экран, ясное дело, происходит путем выведения каждого конкретного символа.
Вы делаете немного не правильно (и от языка это не зависит). Нельзя сразу обрабатывать символ и тут же его выводить - вы ведь так и делаете? Для того чтобы ускорить процесс советую разделить обработку символов и ее вывод. Вот например, во многих библиотеках для C (curse к примеру) есть такая функция - reflesh() иногда Paint() или RePaint(). то есть не имеет значения что вы пытаетесь вывести на экран какой-нибудь функцией write(). Пока вы не вызовите функцию обновления экрана, ничего на нем не появится. Это теория, а вот практика (так как я забыл pascal писать буду на C, но сложности не должно вызвать):

Создаем символ (им удобно будет пользоваться)

Код: Выделить всё

struct ColorChar
{
    char ch; // сама буква
    color clr; // цвет этой буквы (синий, зеленый или еще какой)
}

Создаем массив экрана (именно его мы будем заполнять нужными символами)

Код: Выделить всё

struct Display
{
   ColorChar clrchr[80][25]; // просто содержит двумерный массив цветных символов равный размеру экрана консоли
};
Теперь функция Paint() (для вас это процедура, которая ничего не возвращает и ничего не принимает)

Код: Выделить всё

void Paint()
{
    // идет обычный перебор двумерного массива
    for (int y = 0; y < 10; y++)
    {
         for(int x = 0; x < 10; x++)
         {
              // смотрим какой тип у клетки и присваиваем для нее нужный символ и цвет
              if (Map[x][y] == wall)
              {
                  Display.clrchr[x][y].ch = '#';
                  Display.clrchr[x][y].clr = black;
              }
              // и делаем так до тех пор пока не просмтрим всю карту и не определим какие символы для какой клетки нужно рисовать
              ......
         }
    }
// теперь вывод на экран, снова перебираем двумерный массив равный размеру экрана консоли
    for (int y = 0; y < 25; y++)
    {
         for(int x = 0; x < 80; x++)
         {
               // функция вывода на экран, первый параметр - координата x, второй - координата y, третий - символ который должен вывестись неа экран, четвертый цвет этого символа
               write (x, y, Display.clrchr[x][y].ch, Display.clrchr[x][y].clr);
         }
    }
}
Надеюсь идея понятна? Так можно не только выводить карту но и вставлять текст, вместо того чтобы сразу выводить его на экран мы помещаем его в память и только при отрисовке он будет выведен.

Сама идея проста - заполняем буфер экрана (в данном примере это массив Display) символами, когда он будет полностью заполнен мы вызвав нужную функцию выводим этот массив на экран. Кстати все современные трехмерные игры работают по такому принципу, этот процесс в них называется буферизацией. То есть сначала картинка а точнее один кадр создается в памяти но не отображается на экран, когда кадр будет готов, он выводится на экран, а в это время в памяти создается следующий кадр.

Если будут вопросы по этой идее я постараюсь ответить

Аватара пользователя
Aerton
Сообщения: 503
Зарегистрирован: 11 авг 2007, 02:58
Откуда: Новосибирск
Контактная информация:

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Aerton » 29 сен 2009, 08:09

Больше похоже, что именно эта часть и занимает 4 секунды.
warchief писал(а):

Код: Выделить всё

    for (int y = 0; y < 25; y++)
    {
         for(int x = 0; x < 80; x++)
         {
               write (x, y, Display.clrchr[x][y].ch, Display.clrchr[x][y].clr);
         }
    }
Кстати, случайно внутри цикла не вызывается refresh() после каждого символа?

Аватара пользователя
СамСом
Сообщения: 60
Зарегистрирован: 05 окт 2007, 07:21
Контактная информация:

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение СамСом » 29 сен 2009, 09:16

100% такая трабла есть в FreePascal. Даже если тупо задать вывести 1999 раз один и тот же символ это будет явно заметно.

Насколько я понимаю там фичя в другом. В переключении страниц. Мы заполняем страницу, а потом её с текущей меняем местами. Но как это сделать я пока не знаю.

P.S. Если что сморозил сильно не пенать я честно говоря нубоват в программировании.
Тишина залог здоровья.
http://nastolka.info

Аватара пользователя
warchief
Сообщения: 300
Зарегистрирован: 11 янв 2008, 09:55
Откуда: Озеро снов

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение warchief » 29 сен 2009, 10:11

Кстати, случайно внутри цикла не вызывается refresh() после каждого символа?
Я не знаю на счет free pascal, но в turbo pascal write сразу выводит символ без вывоза какой-либо другой функции (в этом его проблема и именно от этого такая нагрузка на процессор). Я старался написать так чтобы было легко перенести в паскаль а там вроде нет функции refresh. Этот код условен и не привязан ни к какой библиотеке. Если бы я писал рогалик на c++ с использованием curse я бы вообще не парился по такой проблеме, в этой библиотеке все и так реализовано, от меня потребовали бы только заполнить внутренний буфер и потом вывести все функцией reflesh(). В паскале все сложнее.
Насколько я понимаю там фичя в другом. В переключении страниц. Мы заполняем страницу, а потом её с текущей меняем местами. Но как это сделать я пока не знаю.
Если это ко мне, то я имел ввиду сначала заполнять буфер, а заполнив его, вывести на экран. Двойная буферизация для сивольного рогалика в консоли не подойдет так как смысла в ней нет и она будет даже вредной.

Аватара пользователя
warchief
Сообщения: 300
Зарегистрирован: 11 янв 2008, 09:55
Откуда: Озеро снов

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение warchief » 29 сен 2009, 10:13

Aerton писал(а):Больше похоже, что именно эта часть и занимает 4 секунды.
Вы меня с автором темы не путаете? Или это не ко мне?

Аватара пользователя
Aerton
Сообщения: 503
Зарегистрирован: 11 авг 2007, 02:58
Откуда: Новосибирск
Контактная информация:

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Aerton » 29 сен 2009, 10:37

warchief писал(а):
Aerton писал(а):Больше похоже, что именно эта часть и занимает 4 секунды.
Вы меня с автором темы не путаете? Или это не ко мне?
Это я к тому, что буфер тут не поможет, если он сам будет выводиться 4 сек.

А curses можно и из паскаля использовать.
Автор не указал что он использует для вывода, но подозреваю, что это не write, раз речь идёт про цветной текст.

В общем, ждём от автора подробностей или кода, а то мы совсем в домыслах потонем.

Аватара пользователя
Эльф
Сообщения: 115
Зарегистрирован: 12 июл 2007, 16:39

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Эльф » 29 сен 2009, 10:42

Нет, судя по всему дело именно в полноэкранном режиме. Вот сейчас поэксперементировал с нижеследующей програмкой:
uses crt;

var i,j: integer;

begin;
while not keypressed do;
for j:=1 to 25 do
begin;
GotoXY(1,j);
for i:=1 to 80 do write ('#');
end;
end.
В полноэкранном режиме заполняет экран символом # за все те же 4-5 секунд. В оконном - почти мгновенно, меньше чем за полсекунды.
Автор DoomRL использует собственную библиотеку http://valkyrie.chaosforge.org/
Спасибо но... хм, в общем я там ничего не понял )
Рановато для меня, значиццо.

Аватара пользователя
warchief
Сообщения: 300
Зарегистрирован: 11 янв 2008, 09:55
Откуда: Озеро снов

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение warchief » 29 сен 2009, 10:47

что это не write, раз речь идёт про цветной текст
Как видим это все таки write:) и кстати он в отличие от printf из С может выводить цветной текст, а также текст в заданной координате.

Аватара пользователя
Sanja
Администратор
Сообщения: 791
Зарегистрирован: 24 ноя 2006, 12:25
Откуда: Новосибирск
Контактная информация:

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Sanja » 29 сен 2009, 10:51

Вроде уже пару раз перетирали эту тему. Ещё помнится когда Паша BreakMT свой проект делал. Использовали прямое обращение к видеобуферу (адрес 0B800:0000). Ускорение было в разы. Т.е. даже удвоенный экран 80х50 почти мгновенно перерисовывался.

Аватара пользователя
Эльф
Сообщения: 115
Зарегистрирован: 12 июл 2007, 16:39

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Эльф » 29 сен 2009, 10:55

Использовали прямое обращение к видеобуферу (адрес 0B800:0000).
А можно поподробней? Я натыкался на похожее обсуждение когда искал, не было ли уже похожей темы, но там речь ведь шла о досе?

Аватара пользователя
СамСом
Сообщения: 60
Зарегистрирован: 05 окт 2007, 07:21
Контактная информация:

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение СамСом » 29 сен 2009, 10:59

Sanja писал(а):Использовали прямое обращение к видеобуферу (адрес 0B800:0000).
Фичя хороша, даже очень. Гораздо удобней работать со цветами, но при моих экспериментах всё та же байда.

Вот если только массив адреса 0B800:0000 каким-то макаром мгновенно заполнить другим массивом то было самое то, а так те же задержки...

Щя буду экспериментировать с циклами, может какой за for быстрее работает.
Тишина залог здоровья.
http://nastolka.info

Аватара пользователя
warchief
Сообщения: 300
Зарегистрирован: 11 янв 2008, 09:55
Откуда: Озеро снов

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение warchief » 29 сен 2009, 11:13

В полноэкранном режиме заполняет экран символом # за все те же 4-5 секунд. В оконном - почти мгновенно, меньше чем за полсекунды.
Не знаю, у меня в turbo pascal данный код работает, экран заполняется мнговенно в обоих случаях. Наверное проблема в комплияторе?

Аватара пользователя
Эльф
Сообщения: 115
Зарегистрирован: 12 июл 2007, 16:39

Re: Вывод символов в полноэкранном режиме Free Pascal

Сообщение Эльф » 29 сен 2009, 11:41

Не знаю, у меня в turbo pascal данный код работает, экран заполняется мнговенно в обоих случаях. Наверное проблема в комплияторе?
Ох, да, помогло.

Только теперь винда, видимо, воспринимает программу как досовскую, и не дает выставить в ярлыке разрешение 80x25 )

Ответить

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 33 гостя