-
Обеспечьте вывод различных простых графических элементов.
Для вывода простых графических элементов использовались стандартные функции библиотеки GRX, для удобства они представлены в виде таблицы:
Таблица 1 – Некоторые стандартные функции библиотеки GRX:
|
Функция |
Описание |
|
GrTextXY(int x, int y, char *str, GrColor fg, GrColor bg) |
Вывод строки текста str, начиная с точки (x,y), с цветом символов fg и цветом фона bg |
|
GrPlot(int x, int y, GrColor c) |
Точка с координатами (x,y) и цветом c |
|
GrLine(int x1, int y1, int x2,int y2, GrColor c) |
Линия из точки (x1,y1) до точки (x2,y2) с цветом c |
|
GrBox(int x1, int y1, int x2, int y2, GrColor c) |
Прямоугольник с цветом c, верхний левый угол которого имеет координаты (x1,y1), а нижний правый угол имеет координаты (x2,y2) |
|
GrCircle(int x, int y, int r, GrColor c) |
Окружность с центром в точке (x,y), радиусом r и цветом c |
|
GrEllipse(int x, int y, int xa, int ya, GrColor c) |
Эллипс с центром в точке (x,y), радиусом по горизонтали xa, радиусом по вертикали ya и цветом c |
|
GrEllipseArc(int x, int y, int xa, int ya, int start, int end, int style, GrColor c), где style - это одна из 3-x констант: GR ARC STYLE OPEN, GR ARC STYLE CLOSE 1, GR_ARC_STYLE_CLOSE2 |
Дуга эллипса с центром в точке (x,y), радиусом по горизонтали xa, радиусом по вертикали ya и цветом c, при этом start определяет начальный угол, end определяет конечный угол, углы задаются в градусах, умноженных на 10, например, для установки угла в 90 градусов надо указать 900. |
|
GrFilledBox(int x1, int y1, int x2, int y2, GrColor c) |
Аналогична GrBox, только прямоугольник заполняется цветом c |
|
GrFilledCircle(int x, int y, int r, GrColor c) |
Аналогична GrCircle, только окружность заполняется цветом c |
|
GrFilledEllipse(int x, int y, int xa, int ya, GrColor c) |
Аналогична GrEllipse, только эллипс заполняется цветом c |
#include <grx20.h>
#include <grxkeys.h>
#include <time.h>
#include <stdlib.h>
main()
{
srand(time(0));
GrSetMode(GR_width_height_graphics,800,600);
GrFilledBox(0,0,GrMaxX(),GrMaxY(),0);
GrKeyType K;
int i,c;
int x,y,dl,vs,r;
while(K != GrKey_Escape)
{
K=GrKeyRead();
c=1+rand()%15;
x=rand()%GrMaxX();
y=rand()%GrMaxY();
if(GrKey_Space==K)
{i=1+rand()%3;}
if(2==i)
{dl=rand()%140;
vs=rand()%100;
GrBox(x, y, x+dl, y+vs,c);}
if(1==i)
{r=rand()%140;
GrCircle(x, y, r,c);}
if(3==i)
{GrPlot(x,y,c);}
}}
Данная программа выводит, окружности, прямоугольники или точки по нажатию клавиши Space. После компиляции и запуска видим на экране вот такую картину:

Рисунок 2 – Пример вывода простых графических элементов.
Рассмотрим более подробно функции и принципы используемые на данном этапе. Функции srand(time(0)) и rand()% позволяют получать случайные величины координат и размеров графических объектов. В дальнейшем эта же функция используется для получения случайных перемещений, изменения направления движения и изменения цвета графических элементов. Для использования этих функции были подключены стандартные библиотеки языка С++. Для чтения клавиши, была использована функция GrKeyRead(). Организация случайного вывода различных элементов осуществляется на основе цикла if, в дальнейшем для упрощения кода, будет использоваться цикл связка switch - case.
-
Обеспечить более удобную работу с графическими объектами на основе объектно-ориентированного подхода и реализовать случайное перемещение.
Для выполнения данного этапа необходимо реализовать перемещение графических объектов, в частности на первом этапе необходимо реализовать перемещение точек. Перемещение любого объекта будет состоять из трех шагов:
1) удаление имеющегося изображения объекта;
2) задание новых координат объекта;
3) отображение объекта согласно его новым координатам.
Но для такого перемещения надо запоминать координаты имеющегося изображения, чтобы его можно было удалить на первом шаге. Поэтому с каждым графическим объектом надо связать его координаты, то есть переменные x и y. Если имеется десять объектов, то всего необходимо десять пар таких переменных, каждая из которых должна быть связана с одним из объектов.
Удобный способ реализации такой связи между изображением графического объекта и его координатами предоставляет объектно-ориентированный подход.
Согласно этому подходу с каждым изображением графического объекта сопоставляется экземпляр программного объекта. Все объекты одного вида объединяются в класс.
Сначала необходимо определить основный класс «Точка», от которого потом могут быть порождены более сложные классы, реализующие более сложные графические объекты.
Для этого добавляется описание нового типа TPoint (класс «Точка»). Объект подобно структуре может содержать в себе различные компоненты. Объект класса «Точка» содержит поля: координаты и цвет объекта. Но кроме этого объект может «содержать» в себе методы (функции). Частным случаем этих методов можно считать конструктор и деструктор объекта. Конструктор вызывается при создании объекта, а деструктор вызывается при удалении объекта. Остальные методы нужны для того, что обеспечить «поведение» объекта. В частности для объекта «Точка» необходимы методы, связанные с его отображением (Draw, Show, Hide). Кроме того, будет реализован метод MoveXY для обеспечения перемещения объекта в пределах окна.
Описание класса «Точка» (TPoint) содержит в себе набор данных и методов, составляющих этот объект. Это описание размещается после строк, определяющих подключение заголовочных файлов, и перед функцией main. Описание класса TPoint формируется следующим образом:
struct TPoint{ int x,y; int color;
TPoint(int ix,int iy,int icolor);
virtual ~TPoint();
virtual void Draw(int icolor);
void Show();
void Hide();
void MoveXY(int ix, int iy);
};
Описание класса объектов похоже на описание структуры. Сначала идет ключевое слово struct, затем наименование класса. В качестве наименования класса «Точка» используется TPoint. Внутри фигурных скобок описываются поля и методы объектов этого класса.
Объект «Точка» имеет три поля: координаты x и y, а также цвет color.
После описания полей объекта указан конструктор объекта (метод вызываемый при создании объекта). Объявление конструктора похоже на объявление функции, только имя конструктора обязательно должно соответствовать имени класса (в данном случае TPoint). Кроме того, конструктор не имеет возвращаемого значения, поэтому тип возвращаемого значения не указывается. Класс может иметь несколько различных конструкторов. В этом случае их имена будут одинаковыми, так как они совпадают с именем класса, но они должны отличаться своими аргументами. В данном примере имеется только один конструктор с тремя аргументами: координатами ix, iy, а также цветом icolor. Эти аргументы нужны для инициализации объекта «Точка» при его создании.
В следующей строке идет объявление деструктора (метода вызываемого при удалении объекта). Деструктор не имеет аргументов и всегда может быть только один в составе объекта. Имя деструктора - это имя класса, предваряемое символом '~' (в данном случае ~TPoint). Перед именем деструктора поставлено ключевое слово virtual. Это означает, что деструктор является виртуальным.
После деструктора указана функция Draw, которая обеспечивает рисование объекта заданным цветом icolor. При этом предполагается, что объект рисуется с текущими параметрами. В случае объекта «Точка» предполагается, что рисуется точка с координатами x, y и цветом icolor. Перед именем данной функции поставлено ключевое слово virtual. Это означает, что функция является виртуальной. Смысл и необходимость этого будут объяснены в дальнейшем.
Затем объявляются две функции: Show и Hide. Функция Show отображает объект с текущими параметрами. В случае объекта «Точка» предполагается, что отображается точка с координатами x, y и цветом color. Функция Hide скрывает изображение объекта.
Последней функцией (методом) объекта является функция MoveXY, которая обеспечивает перемещение объекта в новые координаты ix, iy.
После закрывающей фигурной скобки описания класса должна ставиться точка с запятой, как и в случае описания структуры.
Но функции (методы) класса в свою очередь необходимо определять, то есть необходимо раскрыть содержимое этих методов. Поэтому после описания класса необходимо разместить определение методов этого класса.
В конструкторе TPoint задаются изначальные координаты и цвет объекта (x, y, color) согласно значениям аргументов конструктора (ix, iy, icolor). Получается, что после описания класса TPoint необходимо раскрыть содержимое конструктора TPoint следующим образом.
TPoint::TPoint(int ix,int iy,int icolor)
{
x=ix;
y=iy;
color=icolor;
}
Функция Draw обеспечивает рисование точки заданным цветом (значение которого передается через аргумент icolor) согласно имеющимся координатам экземпляра объекта, сохраненным в переменных x и y. Чтобы точки были лучше заметны, для их отображения используется четыре пикселя, то есть используется четыре вызова функции GrPlot для рисования этих пикселей.
Функция Show обеспечивает отображение объекта имеющимся цветом (color) с помощью вызова метода Draw. Эта функция полезна для обеспечения универсальности, так как она может использоваться не только для рисования точки, а вообще для рисования любого объекта, если для него определен метод Draw.
Функция Hide обеспечивает скрытие изображения объекта с помощью вызова его метода Draw с цветом фона. В данном примере в качестве цвета фона будет использоваться черный цвет, который имеет код, равный 0. Эта функция также обеспечивает универсальность.
Функция MoveXY обеспечивает перемещение объекта согласно указанным ранее шагам. Для этого сначала убирается изображение объекта (Hide), затем координаты объекта (x и y) изменяются на заданные координаты (ix и iy), после этого объект отображается уже на новом месте (Show). Метод MoveXY может использоваться для перемещения любого объекта, если для него определен метод Draw, так как методы Hide и Show являются универсальными и основаны на методе Draw.
Для каждой точки должны быть определены случайные приращения по горизонтали и по вертикали. Эти случайные приращения могут быть получены на основе значения rand()%7-3, что соответствует случайному числу от -3 до 3. Тогда новое значение x для i-го объекта будет равно obj[i]->x+ rand()%7-3, а значение у будет равно obj [i] ->y+ rand()%7-3. Если вызвать obj[i]->MoveXY с этими параметрами, то i-й объект совершит случайное перемещение. Перемещения точек должны выполняться до тех пор, пока не будет нажата клавиша, поэтому перебор всех N объектов и их перемещение необходимо осуществлять внутри цикла ожидания нажатия клавиши. Чтобы можно было настраивать скорость перемещения объектов, перед перебором N объектов надо формировать задержку на основе вызова функции GrSleep. Изменяя значение аргумента этой процедуры (значение задержки в миллисекундах, например, равное 20) можно настроить удобную скорость перемещения объектов по экрану. Таким образом:
while (!GrKeyPressed()); надо поместить следующий фрагмент.
while (!GrKeyPressed()){
GrSleep(20); for(i=0;i<N;i++){ obj[i]->MoveXY(obj[i]->x+rand()%7-3,obj[i]->y+rand()%7-3);
}
}
