6.4.1 Монитор экрана.

   


Назад  |  Вперёд

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

Экран представлен как двумерный массив символов и управляется функциями put_point() и put_line(). В них для связи с экраном используется структура point:

           // файл screen.h

           const int XMAX=40;
           const int YMAX=24;

           struct point {
               int x, y;
               point() { }
               point(int a,int b) { x=; y=b; }
           };

           extern void put_point(int a, int b);
           inline void put_point(point p) { put_point(p.x,p.y); }

           extern void put_line(int, int, int, int);
           extern void put_line(point a, point b)
              { put_line(a.x,a.y,b.x,b.y); }

           extern void screen_init();
           extern void screen_destroy();
           extern void screen_refresh();
           extern void screen_clear();

           #include <iostream.h>

До вызова функций, выдающих изображение на экран (put_...), необходимо обратиться к функции инициализации экрана screen_init(). Изменения в структуре данных, описывающей экран, станут видимы на нем только после вызова функции обновления экрана screen_refresh(). Читатель может убедиться, что обновление экрана происходит просто с помощью копирования новых значений в массив, представляющий экран. Приведем функции и определения данных для управления экраном:

           #include "screen.h"
           #include <stream.h>

           enum color { black='*', white=' ' };

           char screen[XMAX] [YMAX];

           void screen_init()
           {
             for (int y=0; y<YMAX; y++)
                 for (int x=0; x<XMAX; x++)
                     screen[x] [y] = white;
           }

Функция

           void screen_destroy() { }

приведена просто для полноты картины. В реальных системах обычно нужны подобные функции уничтожения объекта.

Точки записываются, только если они попадают на экран:

           inline int on_screen(int a, int b)  // проверка попадания
           {
              return 0<=a && a <XMAX && 0<=b && b<YMAX;
           }

           void put_point(int a, int b)
           {
              if (on_screen(a,b)) screen[a] [b] = black;
           }

Для рисования прямых линий используется функция put_line():

           void put_line(int x0, int y0, int x1, int y1)
           /*
              Нарисовать отрезок прямой (x0,y0) - (x1,y1).
              Уравнение прямой: b(x-x0) + a(y-y0) = 0.
              Минимизируется величина abs(eps),
              где eps = 2*(b(x-x0)) + a(y-y0).
              См. Newman, Sproull
              ``Principles of interactive Computer Graphics''
              McGraw-Hill, New York, 1979. pp. 33-34.
            */
            {
              register int dx = 1;
              int a = x1 - x0;
              if (a < 0) dx = -1, a = -a;

              register int dy = 1;
              int b = y1 - y0;
              if (b < 0) dy = -1, b = -b;

              int two_a = 2*a;
              int two_b = 2*b;
              int xcrit = -b + two_a;
              register int eps = 0;

              for (;;) {
                put_point(x0,y0);
                if (x0==x1 && y0==y1) break;
                if (eps <= xcrit) x0 +=dx, eps +=two_b;
                if (eps>=a || a<b) y0 +=dy, eps -=two_a;
              }
           }

Имеются функции для очистки и обновления экрана:

           void screen_clear() { screen_init(); }

           void screen_refresh()
           {
             for (int y=YMAX-1; 0<=y; y--) { // с верхней строки до нижней
               for (int x=0; x<XMAX; x++)   // от левого столбца до правого
                   cout << screen[x] [y];
               cout << '\n';
             }
           }

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


Назад  |  Вперёд


OtDiatlovaOU
К началу книги

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.