| Вывод текста в режиме 256 цветов |
Сергей Андрианов
|
17.12.2001 | |
|
14k | ||
|
Мир ПК, #12/2001
Вывод текста в режиме 256 цветовСергей Андрианов17.12.2001
В статье «Палитра VGA: управление цветом» было рассказано о том, как правильно вывести спрайт на экран. Теперь настала очередь разобраться с текстом. Нетрудно догадаться, что единственный способ его вывода на экран — прорисовка каждой буквы по точкам, т. е. здесь применяется та же самая технология, которая уже была рассмотрена на примере отображения спрайтов. Самый универсальный вариант — выводить каждую букву как спрайт, тем более что при этом можно применить красивые многоцветные буквы различного размера. Однако, во-первых, на экране с разрешением 320x200 точек не очень-то развернешься с крупными шрифтами, а при использовании мелких трудно получить что-нибудь более удачное, чем стандартный шрифт. Во-вторых, даже при размере символа 8x8 точек для хранения одного шрифта придется отвести 16 Кбайт оперативной памяти. И в-третьих, такие шрифты нужно самостоятельно рисовать, что при 256 символах нелегкий труд, да и довольно бессмысленный для небольшой игрушки. Поэтому в качестве альтернативы пойдем по самому простому и наименее ресурсоемкому пути и выберем стандартный шрифт, который ничто не мешает сочетать со спрайтовыми. В VideoBIOS компьютера помещена таблица со шрифтами разных размеров: 8x8, 8x14 и 8x16 точек. В России они, как правило, хранятся в теле резидентной программы, проводящей русификацию. Будем работать с самым «экономичным» из них — 8x8 точек, но для этого нужно знать адрес той ячейки памяти, с которой начинается его размещение. Этот адрес можно получить с помощью функции VideoBIOS (см. листинг 1). Для его хранения предусмотрена переменная FontTable. Ее значение ставится в блоке инициализации модуля, и тогда не требуется вызывать никаких дополнительных процедур, а шрифты станут доступны, начиная с первой строки основной программы. Надо сказать, что память при этом не расходуется (не считая 4 байт на указатель), поскольку используются шрифты, загруженные в ОЗУ. Итак, приступим к выбору цветов для символов и фона. Вопрос не такой уж простой, каким кажется на первый взгляд. Дело в том, что после установки палитры в первых 16 регистрах уже не будет тех цветов, к которым все привыкли: 0 — черный, 1 — синий, 2 — зеленый и т. д. Конечно, можно смириться с этим и просмотреть большую простыню1 с описанием всех 256 цветов, чтобы отобрать самый подходящий. Правда, для работы все равно придется ограничиться таблицей с номерами все тех же хорошо знакомых 16 цветов, а раз так, не проще ли поручить компьютеру конвертировать привычные для нас номера в номера рабочей палитры. Однако тогда мы уже не сможем применять для отображения текста остальные 240 цветов, но так ли уж велика эта потеря? Мне, например, более симпатичен именно такой вариант. У редактора Paint, с помощью которого рисовались спрайты для нашей программы, есть своя любимая палитра. Если создавать картинку с нуля или преобразовать полноцветное (24-разрядное с 16 млн. цветов) изображение в палитровое (8-разрядное 256-цветное), то этот редактор будет работать с одной и той же палитрой. Хотя ее цвета могут оказаться не самыми оптимальными для решения нашей задачи, есть уверенность, что все выполненные изображения будут воспроизводиться на экране в правильных цветах. Номера цветов палитры Paint, наиболее близкие к стандартным 16, хранятся в массиве Colors нашей программы. Если 16 цветов все-таки будет не хватать, длину этого массива можно увеличить. На нулевом месте записан номер черного цвета, на первом — синего и т. д. Если вы выберете какую-либо другую палитру, то цифры придется подкорректировать. Можно, конечно, подбор цветов поручить и компьютеру, но тогда такую процедуру придется вызывать только после установки палитры. Впрочем, этот блок позволяется разместить и в модуле программы, устанавливающем палитру, однако мне хотелось сделать так, чтобы все модули были независимы друг от друга. Модуль вывода изображения на экран в режиме 256 цветов содержит следующее:
Как уже было сказано, буквы выводятся по одной точке, каждой из которых на экране отводится 1 байт, а вот в шрифтах они лежат гораздо компактнее: на одну точку приходится один бит. Весь горизонтальный ряд точек помещается в одном байте, а вся буква — в восьми. При отрисовке буквы перед записью байта в видеопамять проверяется, что находится в нужном бите таблицы шрифтов: 0 или 1. В нашем примере будем выводить надписи в каждом кадре, что более наглядно. Чтобы посмотреть, как работает описанный модуль, следует включить его имя в директиву uses, описать дополнительную типизированную константу TextColor : byte = 0 и вставить фрагмент, приведенный в листинге 2, между вызовами процедуры отрисовки спрайта PutSprite и процедуры ожидания луча обратного хода WaitVerticalRetrace. На экране должна появиться переливающаяся разными цветами надпись, одна половина которой отображается на непрозрачном фоне, а другая — на прозрачном. Однако за простоту и нетребовательность к ресурсам приходится платить: предлагаемый способ вывода текста не обладает свойствами спрайта и портит под ним фон. Так что если текст требуется часто перерисовывать, то следует либо самому заботиться о сохранении фона, либо задать его непрозрачным. листинг 1
interface
{ установка параметров вывода текста }
procedure SetTextParm(color,bkcolor,typetext:byte);
{ color - цвет текста }
{ bkcolor - цвет фона }
{ typetext = 0 - прозрачный фон }
{ typetext = 1 - непрозрачный фон }
{ запрос текущих параметров }
procedure GetTextParm(var color,bkcolor,typetext:byte);
{вывод текста по координатам x,y (верхний левый угол)}
procedure PutText(x,y:word;text:string);
{вывод символа по координатам x,y (верхний левый угол)}
procedure PutChar(x,y:word;chr:char);
implementation
uses dos;
type
FTType = array[0..255,0..7]of byte; {для шрифта}
const
Colors : array[0..15]of byte =
( 0, 2, 20, 22,160,162,172,182,
109,111,125,127,237,239,253,255);
{цвета, соответствующие номерам 0-15}
var
FontTable : ^FTType; {таблица шрифта}
Color1,bkColor1 : byte;
{номера <стандартных> цветов текста и фона}
Color2,bkColor2 : byte;
{номера цветов текста и фона в выбранной палитре}
TextType : byte; {способ вывода (прозрачно или нет)}
procedure SetTextParm(color,bkcolor,typetext:byte);
begin
Color1 := color;
bkColor1 := bkcolor;
TextType := typetext;
Color2 := Colors[Color1];
bkColor2 := Colors[bkColor1];
end;
procedure GetTextParm(var color,bkcolor,typetext:byte);
begin
color := Color1;
bkcolor := bkColor1;
typetext := TextType;
end;
procedure PutText(x,y:word;text:string);
var
i:word;
begin
if(byte(text[0])>0)then
for i := 1 to byte(text[0]) do
putchar(x+8*(i-1),y,text[i])
end;
procedure PutPixel(x,y:word;c:byte); {вывод точки}
begin
mem[SegA000:x+y*320] := c;
end;
function getpixel(x,y:word):byte; {запрос цвета точки}
begin
getpixel := mem[SegA000:x+y*320];
end;
procedure putchar(x,y:word;chr:char);
var
i,j,k,l : word;
cc,bb : byte;
begin
l := byte(chr);
case TextType of
0: for i := 0 to 7 do { прозрачный фон }
for j := 0 to 7 do
if (FontTable^[l,i] and
(1 shl (7-j)) <> 0) then
putpixel(x+j,y+i,Color2);
1: for i := 0 to 7 do { непрозрачный фон }
for j := 0 to 7 do
if (FontTable^[l,i] and
(1 shl (7-j)) <> 0) then
putpixel(x+j,y+i,Color2)
else putpixel(x+j,y+i,bkColor2);
end;
end;
var r : registers;
begin {инициализация - получаем адрес таблицы шрифтов}
r.ax := $1130;
r.bh := 3;
intr($10,r);
FontTable := ptr(r.es,r.bp);
Color1 := 15; {заносим величины по умолчанию}
bkColor1 := 0;
TextType := 1;
Color2 := Colors[Color1];
bkColor2 := Colors[bkColor1];
end.
листинг 2inc(TextColor); SetTextParm(TextColor div 16, (TextColor + 48) div 16,1); PutText(56,16,'Демонстрационная'); SetTextParm(TextColor and $F,0,0); PutText(192,16,'программа'); Мир ПК, #12/2001 Постоянный адрес статьи: http://www.osp.ru/pcworld/2001/12/098.htm |
|||