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