Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ТРПО / Материалы по ТП / Гафаров_Metod_OOP_1.doc
Скачиваний:
120
Добавлен:
12.03.2015
Размер:
2.48 Mб
Скачать

2.3. Проектирование методов объектов

Методы TPoint достаточно простые: Constructor Init заполняет О-поля объекта; процедура Rotate вычисляет новые координаты точки по формулам геометрического поворота вокруг заданной оси на угол step, величина которого зависит от требуемой скорости вращения объекта и процедура Show скорее служит прототипом для дальнейшего наследования, чем для самостоятельного использования. Роль Destructora обсуждалась ранее.

В Constructore TLine обратите внимание, что объекты pn и pk инициализируются отдельно, поскольку каждый из них должен быть связан с таблицей VMT типа TPoint, а в методе Show значение входного параметра col определяет рисование или стирание линии.

Аналогично осуществляется инициализация сторон квадрата в TSquare и перекрытие виртуальных методов Show и Rotate собственными. После инициализации положение квадрата соответствует верхнему левому углу экрана.

(******** Методы TPoint ********************)

Constructor TPoint .Init ( xx, yy :Real; col :Byte );

Begin x:=xx; y:=yy; Pcolor := col; End;

Procedure TPoint .Rotate ( xOs,yOs :Integer );

Var xx, yy :Real;

Begin xx := (x - xOs)*Cos(step) - (y - yOs)*Sin(step) + xOs;

yy := (x - xOs)*Sin (step) + (y - yOs)*Cos(step) + yOs;

x :=xx; y:=yy;

End;

Procedure TPoint .Show ( col :Byte );

Begin PutPixel ( Round(x), Round(y), Pcolor ); End;

Destructor TPoint .Done;

Begin End;

(******** Методы TLine ********************)

Constructor TLine .Init ( x1,y1,x2,y2 :Real; col :Byte );

Begin pn.Init(x1,y1,col); pk.Init(x2,y2,col); Lcolor:=col; End;

Procedure TLine .Rotate ( xOs,yOs :Integer );

Begin pn.Rotate( xOs,yOs ); pk.Rotate( xOs,yOs ); End;

Procedure TLine .Show ( col :Byte );

Begin

If col=0 Then SetColor ( col ) Else SetColor ( Lcolor ) ;

Line(Round(pn.x),Round(pn.y),Round(pk.x),Round(pk.y));

End;

Destructor TLine .Done;

Begin End;

(***************** Методы TSquare ****************************)

Constructor TSquare .Init ( aa, colK :Byte );

Begin

as := aa; { установка размера стороны квадрата}

Sides[0]. Init ( as, as, 0, as, colK ); { инициализация сторон квадрата }

Sides[1]. Init ( 0, as, 0, 0, colK );

Sides[2]. Init ( 0, 0, as, 0, colK );

Sides[3]. Init ( as, 0, as, as, colK );

Scolor := colK;

End;

Procedure TSquare .Rotate ( xOs, yOs :Integer );

{ реализует вращение квадрата }

Var i :Byte;

Begin

For i:=0 To kv-1 Do Sides[i] .Rotate ( xOs,yOs );

End;

Procedure TSquare .Show( col :Byte );

{ рисует (стирает) изображение квадрата }

Var i :Byte;

Begin

For i := 0 To kv-1 Do Sides[i].Show ( col );

End;

Destructor TSquare .Done;

Begin End;

(***************** Методы TScreen ******************************)

Constructor TScreen .Init ( aa, colK, colG :Byte; dG :Integer );

Var i :Byte;

Begin

GraphInit; { инициализация графического режима VGAHi }

Inherited Init ( aa, colK ); { инициализация родителя }

Gdisp := dG; { задание Y-смещения поверхности качения }

For i := 0 To kv-1 Do With Sides[i] Do Begin

{перенос квадрата на поверхность}

pn.y := pn.y + Gdisp - as;

pk.y := pk.y + Gdisp - as;

End;

Gcolor := colG; { задание цвета поверхности качения }

OsX := as; OsY := Gdisp; { задание начальных координат оси вращения }

angle := 0; { задание начального значения угла поворота }

DrawGround; { рисование поверхности качения }

End;

Procedure TScreen .GraphInit; { инициализация графического режима VGAHi }

Var gd, gm, ErrorCode :Integer;

Begin

gd := Detect;

InitGraph ( gd, gm, ' ');

ErrorCode := GraphResult;

If ErrorCode <> grOk Then Begin

Writeln('Ошибка графики:', GraphErrorMsg ( ErrorCode ) );

Halt(1);

End;

End;

Procedure TScreen .DrawGround; { рисование поверхности качения }

Begin

SetColor ( Gcolor );

Line ( 0, Round( Gdisp + 1 ), GetMaxX, Round( Gdisp + 1 ) );

End;

Function TScreen .ShiftOsXY :Boolean;

{ реализует смещение оси вращения квадрата по оси X}

Begin

If angle > pi/2

Then Begin { если наступил момент переноса оси поворота, }

OsX := OsX + as; { то сместить ось по X на as}

ShiftOsXY := True;

End

Else ShiftOsXY := False;

End;

Procedure TScreen .Go;

{реализует движение квадрата и анимацию его изображения}

Begin

Repeat { цикл возобновления сцены }

Repeat { цикл качения по поверхности и анимации }

angle := angle + step; { накопление угла поворота}

If ShiftOsXY { если была смена оси вращения, }

Then Begin

angle:=0;

Continue; { то пропустить вращение и анимацию }

End;

Rotate ( OsX, OsY ); { вращение квадрата вокруг текущей оси }

Show(Scolor); { рисует изображение квадрата }

Delay( ms ); { задержка }

Show(0); { стирает изображение квадрата }

If KeyPressed Then Exit; { если клавиша нажата, то выход из процедуры}

Until OsX > GetMaxX; { если квадрат достиг правого края экрана, то }

Init ( as, Scolor, Gcolor, Gdisp ); { возобновление сцены }

DrawGround; { рисование поверхности качения }

Until False; { повторение работы до нажатия любой клавиши }

End;

Destructor TScreen .Done;

Begin CloseGraph; End; {закрытие графического режима }

Более сложные действия выполняются в Constructore TScreen. После перехода в графический режим осуществляется инициализация квадрата оператором Inherited Init (aa, colK); где ключевое слово Inherited означает – унаследованный, то есть происходит вызов Constructora типа TSquare. Отметим, что вызов унаследованного Constructor’a при проектировании Constructor’ов дочерних типов считается хорошим стилем в ООП-программировании. Далее квадрат «устанавливается» на поверхность качения путем коррекции координат Y его вершин на величину смещения этой поверхности на экране. Обратите внимание на оператор With, который, как и при обработке записей, позволяет вынести имя объекта в заголовок и избавляет от необходимости писать длинные составные имена. После этого назначаются координаты оси вращения OsX, OsY, совпадающие с координатами вершины 1 квадрата (см. рис. 2.1). Поскольку рисунок рельефа является статической частью сцены и, при движении квадрата остается неизменной, в конце процедуры следует прорисовка поверхности виртуальным методом DrawGround. Виртуальность метода обусловлена возможностью изменения формы (а значит и метода прорисовки) поверхности качения у потомков. По этой же причине виртуальны метод ShifOsXY ( контролирующий положение оси вращения по мере движения квадрата по поверхности) и метод Go. В последнем реализуются основные действия, происходящие на экране. Метод состоит из двух вложенных циклов: во внутреннем моделируется качение квадрата начиная с левого края до правого края экрана и анимация его изображения, во внешнем – обновление всей сцены и повторение указанных действий. Остальные подробности алгоритмов описанных методов даны в приведенных их текстах.