А.А.Семенов , А.Г.Юдина
Господа программисты,
Теперь Вам не надо изобретать свой велосипед!
Просто наследуйте наш.
(Из рекламного буклета фирмы Borland)
Эта статья адресована тем преподавателям информатики, которые хотели бы познакомить своих учеников с ООП на примерах, по возможности наглядных и не очень сложных.Попробуем разработать на Паскале программу — хранитель экрана (screen saver)с фигурками различной формы, гуляющими по экрану.
Для работы потребуется Турбо Паскаль версии не меньше 6. Никаких особенных требований к технике (от 286-го). Достаточно поставить только turbo.exe (интегрированную среду), turbo.tph (файл помощи) и turbo.tpl (библиотеки system и crt). Все вместе занимает 1,3 Мбайта и умещается на дискету. Необходимый уровень подготовки — умение использовать основные конструкции языка (ветвления и циклы), а также описывать и применять процедуры и функции для решения несложных задач вычислительного характера (включая работу с массивами).
По ходу работы над нашим проектом будут затронуты также такие темы, как работа с графикой, использование встроенного ассемблера, устройство видеопамяти, создание модулей — самодельных библиотек процедур и функций. Возможно, вы сочтете это удобным поводом для расширения кругозора ваших учеников.
Занятие 1
Итак, мы решили познакомиться с ООП на примере графических объектов.Стандартная VGA-графика Паскаля (640x480 точек, 16 цветов) не очень годится для анимации — в ней маловато цветов. Поэтому попробуем использовать для работы графический режим VGA с шестнадцатеричным номером 13h (320x200 точек, 256 цветов). Доступ к видеопамяти в этом режиме очень простой, а перевести монитор в данный режим можно вызовом 10h прерывания BIOS. И никакого модуля Graph!
Пишем текст:
begin
{установить видеорежим 13h — всего 2
строчки на встроенном ассемблере}
asm
mov ax, 13h {пересылка номера
видеорежима в регистр}
int 10h {вызов прерывания с
шестнадцатеричным номером 10h}
end;
Readln
end.
Теперь попытаемся зажечь на экране какой-нибудь пиксель. Для этого достаточно вывести в оперативную память видеокарты (она начинается с адреса $A000:0000 байт, значение которого равно номеру цвета в палитре (0
ЈномерЈ255). Для доступа к памяти используем стандартный массив Паскаля Mem. (Об адресации оперативной памяти см. примечание.)Итак,
beginprocedure PutPixel(x,y: integer; color: byte); {0
ЈxЈ319;0ЈyЈ199;0ЈcolorЈ255}Палитра устанавливается 10h прерыванием BIOS во время инициализации видеорежима. Если она нас не устроит, ее нетрудно будет сменить.
Почему в процедуре PutPixel вспомогательная переменная a описана как word, а не как integer?
В нашем графическом режиме экран разбит на 320x200=64 000 точек, а максимальное значение для integer 32 767. Для типа word максимальное значение 65 535.
Домашнее задание
Написать следующие процедуры:
FillScreen(color: byte)
— заливает экран цветом color;HLine(x1,x2,y: integer; color: byte)
— рисует горизонтальную линию цвета color;VLine(x,y1,y2: integer; color: byte)
— рисует вертикальную линию цвета color.Примечание. Почему адрес ячейки оперативной памяти (например,
$A000:16) записывается так странно?Восьмиразрядные микропроцессоры (8080, 8085) имели 16-битовую адресную шину и как следствие объем адресуемой памяти 64 Кбайт. Первый 16-разрядный процессор Intel 8086 имел уже 20-битовую шину адреса и мог обращаться к 1 мегабайту оперативной памяти. Для программной совместимости с предшествующими моделями было решено организовать адресацию памяти с помощью двух 16-битовых регистров. Первый из них задает так называемый сегмент памяти, а второй — смещение в пределах данного сегмента. Физический адрес ячейки памяти процессор находит по формуле
А=16*адрес сегмента + смещение. Таким образом, к одной ячейке памяти можно обратиться несколькими способами!Довольно-таки странно, зато в пределах одного сегмента памяти поддерживается совместимость по адресации с 8-разрядными процессорами.
Обычно адрес записывают так:
(адрес сегмента) :(смещение). Если адрес представлен в шестнадцатеричном формате, то вначале ставят знак $ (в Паскале это признак шестнадцатеричного числа).Например, адрес
$A000:16 можно записать как $A000:$10, или, если учесть, что 10•163= =40960, как 40960:16. Физический адрес будет равен 40960•16+16=655376.Занятие 2
Теперь можно перенести все процедуры в самодельную библиотеку (файл сохранить как Graph13h.pas):
Unit Graph13h;
interface
procedure Screen13h;
procedure PutPixel(x,y: integer; color: byte);
procedure FillScreen(color: byte);
procedure FillRect(x1,y1,x2,y2:integer;color:byte);
procedure HLine(x1,y,x2: integer; color: byte);
procedure VLine(x,y1,y2: integer; color: byte);
implementation
procedure Screen13h; assembler;
procedure PutPixel(x,y: integer; color: byte);
var a:word;
begin
a:=320*y+x;
mem[$a000:a]:=color
end;
procedure FillScreen(color: byte);
var m,n: integer;
begin
for m:=0 to 199 do
for n:=0 to 319 do PutPixel(n,m,color)
end;
{Заливка прямоугольника}
procedure FillRect(x1,y1,x2,y2:integer;color:byte);
var m,n:integer;
begin
for m:=x1 to x2 do
for n:=y1 to y2 do
PutPixel(m,n,color)
end;
procedure HLine(x1,y,x2: integer; color: byte);
var m,n,k: integer;
begin
if x1<x2 then begin n:=x1;k:=x2 end else begin
n:=x2;k:=x1 end;
for m:=n to k do PutPixel(m,y,color)
end;
procedure VLine(x,y1,y2: integer; color: byte);
var m,n,k: integer;
begin
if y1<y2 then begin n:=y1;k:=y2 end else begin n:=y2;k:=y1
end;
for m:=n to k do PutPixel(x,m,color)
end;
end.
Откомпилируем файл Graph13h.pas. Будет создан файл библиотеки Graph13h.tpu с объектным кодом процедур.
Программа проверки созданных инструментов существенно упростится: uses Graph13h;и можно будет приступить к созданию объектов.
Создание и использование модулей —
очень удобный прием, так как они разгружают текст
проекта от рутинных процедур. К тому же они дают
возможность одолеть
64-килобайтный предел размера кода программы.
Дополнить модуль
Screen13h процедурой FillRect(x1,y1,x2,y2:word;color:byte), которая заливает прямоугольник с заданными вершинами цветом color.Дополнительное задание “со звездочкой” — дополнить библиотеку процедурой
Line(x1,y1,x2,y2:word;color:byte) для рисования произвольного отрезка, заданного двумя точками.