Программный модуль
К файлу модуля Unit1.h (Листинг 1.1) добавлено описание структуры FigureType, включающей позицию (X,Y), смещение (DX,DY) фигуры и номер объекта спрайта (SD); а в секцииpublic класса формы объявлены четыре переменные размеров изображений, две фигуры Fig [2] и соответствующие им две пары спрайтов Sprite [4]. Класс SpriteClass и его методы определены в файлах Sprite.h и Sprite.cpp, соответственно.
ttifndef UnitlH
#define UnitlH
#include <vcl\Classes.hpp> ttinclude <vcl\Controls.hpp> ftinclude <vcl\StdCtrls.hpp>
#include <vc1\Forms.hpp> ttinclude "sprite.h"
#include <vcl\Buttons.hpp> ftinclude "sampreg.h" ftinclude <vcl\Dialogs.hpp>
typedef struct { int X, Y, DX, DY, SD; } FigureType;
class TFormI: public TForm (
_published: // IDE-managed Components TPaintBox *PaintBox;
TImage *DrawBox;
TImage *Background;
TImage *Figures;
TTimer *Timerl;
TPanel * Panel 1;
TSpeedButton *SpeedButtonl;
TSpeedButton *SpeedButton2;
TSpeedButton *SpeedButton3;
TSpinEdit *SpinEditl;
TOpenDialog *OpenDialog;
void _fastcall TimerlTimer(TObject * Sender);
void _fastcall SpinEditlKeyUp(TObject *Sender, WORD &Key, TShiftState Shift);
void _fastcall SpinEditlKeyDown(TObject * Sender,
WORD &Key, TShiftState Shifts-void_fastcall SpeedButtonlClick(TObject *Sender) ;
void_fastcall SpeedButton2Click(TObject * Sender);
void_fastcall SpeedButton3Click(TObject * Sender);
private: // User declarations public: // User declarations _fastcall TFormI(TComponent* Owner);
int W, H, w, h;
FigureType Fig[2];
SpriteClass Sprite[4];
};
extern TFormI *Forml;
#endif
Листинг 1.1. Содержание файла Unii1.h.
Файл модуля Unit1.cpp (Листинг 1.2) содержит 5 обработчиков событий от нажатия кнопок управления и обработчик события таймера.
//-_---------_____________-___-_-----__-____________________-
^include <vcl\vcl.h>
#pragma hdrstop
#include "Unitl.h"
#pragma link "sampreg"
#pragma resource "*.dfm" TFormI *Forml;
//----------------——--——--—------———------—-----------
_fastcall TFormI::TFormI(TComponent* Owner) : TForm(Owner) ( // Конструктор формы устанавливает размеры по умолчанию W = Н = 400; w = h =61;
} //----------------------------------------------------------
void_fastcall TFormI::SpeedButtonlClick(TObject *Sender)
{ if (OpenDialog->Execute())
{ // Открыть файл изображения фона
Background->Picture->LoadFromFile(OpenDialog->FileName) ;
W = Background->Picture->Width;
H = Background->Picture->Height;
}
} //----—----------——-------—-——---—-—-—-------------
void_fastcall TFormI::SpeedButton2Click(TObject *Sender) { if (OpenDialog->Execute())
{ // Открыть файл изображения фигур
Figures->Picture->LoadFromFile(OpenDialog->FileName);
w = (Figures->Picture->Width)/6;
h = Figures->Picture->Height;
//______---------------------------------------------------
void_fastcall TFormI::SpeedButton3Click(TObject *Sender)
{ // Инициализировать поля структуры обеих фигур Fig[0].X = W/4; Fig[l].X = 3*W/4;
Fig[0].Y = H/4; Fig[l].Y = 3*H/4;
Fig[0].DX = 1; Fig[l].DX = -1;
Fig[0].DY = 1; Fig[l].DY = -1;
Fig[0].SD = 0; Fig[l].SD = 0;
// Подготовить экземпляры спрайта
Sprite[0].SetSprite(Figures->Canvas, 0,0, 4*w,0, w,h);
Sprite[1].SetSprite(Figures->Canvas, 2*w,0, 4*w,0, w,h);
Sprite[2].SetSprite(Figures->Canvas, w,0, 5*w,0, w,h);
Sprite[3].SetSprite(Figures->Canvas, 3*w,0, 5*w,0, w,h) ;
Timerl->Enabled = true;
}
void _fastcall TFormI::SpinEditlKeyUp(TObject *Sender,
WORD &Key, TShiftState Shift) { Timerl->Interval++; } void _fastcall TFormI::SpinEditlKeyDown(TObject *Sender,
WORD &Key, TShiftState Shift) { Timerl->Interval--; } //-.____-_-_-_-_.....____.__________________________________
int Shift = 0; // переменная прокрутки фона void _fastcall TFormI::TimerlTimer(TObject *Sender) ( // Сместить фигуры в пределах периметра
Fig[0].X += Fig[0].DX; Fig[0].Y += Fig[0].DY;
if (Fig[0].X > (W/2-w)) Fig[0].DX = -1;
if (Fig[0].X < 20) Fig[0].DX = 1;
if (Fig[0].Y > (H-2*h)) Fig[0].DY = -1;
if (Fig[0].Y < 20) Fig[0].DY = 1 ;
Fig[l].X += Fig[l].DX; Fig[l].Y += Pig[l].DY;
if (Fig[l].X > (W-w)) Fig[l].DX = -1;
if (Fig[l].X < (W/2+w)) Fig[l].DX = 1;
if (Fig[l].Y > (H-h)) Fig[l].DY = -1;
if (Fig[l].Y < 30) Fig[l].DY = 1 ;
// Оживить фигуры, переключая экземпляр спрайта
Fig[0].SD = (Fig[0].SD == 0) ? 2 : 0;
Fig[l].SD = (Fig[l].SD == 1) ? 3 : 1 ;
// Нарисовать фон и сдвинуть его влево
if (Shift == 0)
{ DrawBox->Canvas->CopyMode = cmSrcCopy;
DrawBox->Canvas->CopyRect(Rect(О, О, W, H),
Background->Canvas, Rect(0, 0, W, H));
}
else
{ DrawBox->Canvas->CopyMod^s = cmSrcCopy;
DrawBox->Canvas->CopyRect(Rect(0, 0, W-Shift, H),
Background->Canvas, Rect(Shift, 0, W, H) ) ;
DrawBox->Canvas->CopyRect(Rect(W-Shift, 0, W, H),
Background->Canvas, Rect(0, 0, Shift, H)) ;
}
Shift += 2;
if (Shift >= W) Shift -= W;
// Нарисовать фигуры на канве внеэкранного битового образа
Sprite[Fig[0].SD].Draw(DrawBox->Canvas,Fig[0].X, Fig[0].Y) ;
Sprite[Fig[l].SD].Draw(DrawBox->Canvas,Fig[1].X, Fig[l].Y) ;
// Скопировать изображение на экран
PaintBox->Canvas->CopyMode = cmSrcCopy;
PaintBox->Canvas->CopyRect(Rect(0, 0, W, H),
DrawBox->Canvas, Rect(0, 0, W, H)) ;
}
Листинг 1.2. Содержание файла Unit1 cpp.
Быстрые кнопки компонент TSpeedButton служат для управления программой. Первая кнопка открывает и загружает объект Background класса TImage из файла с изображением фона (размером w на H). Вторая кнопка открывает и загружает объект Figures класса TImage из файла с изображениями фигур (размером w на h каждая).
Третья кнопка устанавливает фигуры в начальные позиции и подготавливает объекты спрайта посредством обращении к методу SetSprite., а затем запускает таймер.
Нажатие кнопок компоненты редактирования TSpinEdit вызывает увеличение или уменьшение на единицу значения интервала таймера (по умолчанию устанавливается значение 40, соответствующее кадровой частоте 1/25 сек).
Ядром приложения является обработчик события OnTimer объекта Timerl. Первый блок кода реакции на прерывание от таймера отвечает за перемещение фигур, изменяя направление движения всякий раз, когда они "утыкаются" в фиксированные границы отведенного периметра. Рис. 1.2 изображает структуру канвы объектов DrawBox и PaintBox.
Рис.1.2. Структура канвы для рисования движущихся фигур.
Следующий блок реализует прокрутку фона справа-налево, делая анимацию более реальной (можете называть этот процесс" виртуальной реальностью, если хотите). Фигуры могут сходиться и расходиться, но общее впечатление их движения слева-направо сохраняется. Для начала надо скопировать изображение фона целиком в буфер внеэкранного изображения, а затем организовать циклический сдвиг влево данных буфера на величину, установленную переменной Shift. Заключительный блок рисует, при помощи метода Draw, фигуры на канве невидимого объекта DrawBox, а затем копирует изображение канвы на экран, в видимый объект PaintBox.