Жарков В.А. - Visual C++ 2005, DirectX 9.0c и Microsoft Agent в компьютерной графике, мультимедиа и играх (Листинги книги) - 2005
.pdfГлава 50. Управляемый мигающий текст
Листинг 50.1. Метод для элемента управления TrackBar.
private:
System::Void trackBar1_Scroll(System::Object^ sender, System::EventArgs^ e)
{
//Включаем таймер Timer (задаем Enabled равным true): timer1->Enabled = true;
//Устанавливаем свойство Interval таймера Timer //в зависимости от перемещения ползунка Value: timer1->Interval = trackBar1->Value;
}
Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer (ниже формы в режиме проектирования). Появляется файл Form13.h с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 50.2. Метод для компонента Timer.
//Объявляем булеву переменную myText со значением false: bool static myText = false;
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Программируем анимацию: if (myText == false)
{
//Задаем чередование черного Black //и белого White цветов текста //внутри элемента label1: label1->ForeColor = Color::Black;
//Изменяем значение myText на противоположное: myText = true;
}
else
{
label1->ForeColor = Color::White;
//Изменяем значение myText на противоположное: myText = false;
}
}
Глава 51. Методика изображения летающих предметов
Листинг 51.1. Объявление объекта и глобальных переменных.
//Задаем ширину и высоту прямоугольника, //внутри которого будет летать мяч:
int static width_of_rectangle = 1000; int static height_of_rectangle = 500;
//Верхняя горизонтальная линия прямоугольника отстоит
//от оси 'x' на расстоянии boundary_of_rectangle_у: int static boundary_of_rectangle_y = 15;
//Левая вертикальная линия прямоугольника отстоит
//от оси 'y' на расстоянии boundary_of_rectangle_x: int static boundary_of_rectangle_x = 15;
//Размер мяча size_of_ball, как часть (доля) //от размеров прямоугольника:
int static size_of_ball = 20;
//Величина перемещения мяча size_of_move_of_ball, //как часть (доля) от размеров мяча:
int static size_of_move_of_ball = 5;
//Объявляем объект myBitmap класса Bitmap: private: Bitmap^ myBitmap;
//Объявляем целочисленные переменные:
int static position_of_ball_x, position_of_ball_y, radius_of_ball_x, radius_of_ball_y, move_of_ball_x, move_of_ball_y, width_of_bitmap_of_ball, height_of_bitmap_of_ball,
width_of_margin_of_bitmap, height_of_margin_of_bitmap;
Дважды щелкаем по форме Form1 в режиме проектирования. Появляется файл Form1.h с шаблоном (метода Form1_Load), который после записи нашего кода принимает такой вид.
Листинг 51.2. Метод Form1_Load.
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
//Создаем объект myGraphih класса Graphics
252 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
//и стираем другие изображения:
Graphics^ myGraphics = this->CreateGraphics(); myGraphics->Clear(BackColor);
//Задаем радиус мяча как дробь (часть) //от ширины или высоты прямоугольника,
//в зависимости от того, какая дробь меньше: double radius_of_ball =
Math::Min(width_of_rectangle / myGraphics->DpiX, height_of_rectangle / myGraphics->DpiY) / size_of_ball;
//Задаем ширину и высоту мяча в DPI (ТОЧКИ НА ДЮЙМ) //для единиц разрешения изображения //по горизонтали и вертикали, что идентично значениям //в направлении осей 'x' и 'y':
radius_of_ball_x = Convert::ToInt32(radius_of_ball *
myGraphics->DpiX); radius_of_ball_y =
Convert::ToInt32(radius_of_ball * myGraphics->DpiY);
//Высвобождаем ресурсы, //выделенные объекту myGraphics: myGraphics->Dispose();
//Задаем шаг перемещения мяча или в 1 пиксель, //или как часть (дробь, доля) от размера шара, //в зависимости от того, какая величина больше.
//Это означает, что на каждом шаге перемещение мяча //пропорционально его размеру, //а размер мяча, в свою очередь,
//пропорционален размеру прямоугольника. //Таким образом, при прочих равных условиях, //когда размеры прямоугольника уменьшаются, //перемещение мяча замедляется, //и когда увеличиваются, //перемещение мяча ускоряется:
move_of_ball_x = Convert::ToInt32(Math::Max(1, radius_of_ball_x / size_of_move_of_ball));
move_of_ball_y = Convert::ToInt32(Math::Max(1, radius_of_ball_y / size_of_move_of_ball));
//Значение перемещения мяча также определяет //поле изображения вокруг мяча.
//На каждом шаге перемещение мяча //равно перемещению поля изображения,
Глава 51. Методика изображения летающих предметов |
253 |
//что позволяет стирать предыдущее изображение мяча //перед каждым последующим изображением мяча //без мерцания:
width_of_margin_of_bitmap = move_of_ball_x; height_of_margin_of_bitmap = move_of_ball_y;
//Определяем фактический размер изображения, //где нарисован мяч, //прибавляя поля к размерам мяча:
width_of_bitmap_of_ball = 2 * (radius_of_ball_x + width_of_margin_of_bitmap);
height_of_bitmap_of_ball = 2 * (radius_of_ball_y + height_of_margin_of_bitmap);
//Создаем новый рисунок мяча //соответствующей ширины и высоты:
myBitmap = gcnew Bitmap(width_of_bitmap_of_ball, height_of_bitmap_of_ball);
//Получаем объект класса Graphics //для изображения мяча,
//удаляем существующий мяч и рисуем новый мяч. //Задаем черный цвет Black для мяча,
//чтобы он был лучше виден в книге: myGraphics = Graphics::FromImage(myBitmap); myGraphics->Clear(BackColor);
myGraphics->FillEllipse(Brushes::Black, move_of_ball_x, move_of_ball_y,
2 * radius_of_ball_x, 2 * radius_of_ball_y);
//Высвобождаем ресурсы, //выделенные объекту myGraphics: myGraphics->Dispose();
//Задаем расположение мяча в центре прямоугольника: position_of_ball_x =
Convert::ToInt32(width_of_rectangle / 2); position_of_ball_y =
Convert::ToInt32(height_of_rectangle / 2);
}
Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer (ниже формы в режиме проектирования). Появляется файл Form1.h с шаблоном, который после записи нашего кода принимает следующий вид.
254 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
Листинг 51.3. Метод для компонента Timer.
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Создаем объект myGraphics класса Graphics: Graphics^ myGraphics = this->CreateGraphics();
//Рисуем четыре граничные линии прямоугольника, //от которых будет отскакивать летающий мяч
//при помощи пера Pen(Color::Red, 3): Pen^ myPen = gcnew Pen(Color::Red, 3); myGraphics->DrawLine(myPen,
boundary_of_rectangle_x, boundary_of_rectangle_y, width_of_rectangle, boundary_of_rectangle_y);
//Другой вариант задания пера Pen: myGraphics->DrawLine(gcnew Pen(Color::Red, 3),
boundary_of_rectangle_x, boundary_of_rectangle_y, boundary_of_rectangle_x, height_of_rectangle);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), boundary_of_rectangle_x, height_of_rectangle, width_of_rectangle, height_of_rectangle);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), width_of_rectangle, boundary_of_rectangle_y, width_of_rectangle, height_of_rectangle);
//Рисуем изображение мяча на форме Form1 //при помощи метода DrawImage: myGraphics->DrawImage(myBitmap,
Convert::ToInt32(position_of_ball_x - width_of_bitmap_of_ball / 2), Convert::ToInt32(position_of_ball_y - height_of_bitmap_of_ball / 2), width_of_bitmap_of_ball, height_of_bitmap_of_ball);
//Высвобождаем ресурсы, //выделенные объекту myGraphics: myGraphics->Dispose();
//После изображения мяча с текущими координатами //увеличиваем координаты мяча
//на шаг перемещения в направлении осей 'x' и 'y': position_of_ball_x = position_of_ball_x +
move_of_ball_x;
position_of_ball_y = position_of_ball_y +
Глава 51. Методика изображения летающих предметов |
255 |
move_of_ball_y;
//Изменяем направление перемещения мяча по оси 'x', //когда мяч ударяется о какую-либо из двух //граничных вертикальных линий прямоугольника:
if (position_of_ball_x + radius_of_ball_x >= width_of_rectangle)
{
move_of_ball_x = -move_of_ball_x;
//В момент удара подаем звуковой сигнал Beep: Microsoft::VisualBasic::Interaction::Beep();
}
if (position_of_ball_x - radius_of_ball_x <= boundary_of_rectangle_x)
{
move_of_ball_x = -move_of_ball_x;
//В момент удара подаем звуковой сигнал Beep: Microsoft::VisualBasic::Interaction::Beep();
}
//Изменяем направление перемещения мяча по оси 'y', //когда мяч ударяется о какую-либо из двух //граничных горизонтальных линий прямоугольника:
if (position_of_ball_y + radius_of_ball_y >= height_of_rectangle)
{
move_of_ball_y = -move_of_ball_y;
//В момент удара подаем звуковой сигнал Beep: Microsoft::VisualBasic::Interaction::Beep();
}
if (position_of_ball_y - radius_of_ball_y <= boundary_of_rectangle_y)
{
move_of_ball_y = -move_of_ball_y;
//В момент удара подаем звуковой сигнал Beep: Microsoft::VisualBasic::Interaction::Beep();
}
}
В этом коде главным является вызов перегруженного метода DrawImage, который в VC++ имеет много видов перегрузки. Здесь использован вид перегрузки с та-
кой сигнатурой: DrawImage(Image, Integer, Integer, Integer, Integer). Этот метод мы уже объясняли в предыдущей главе. Чтобы установить значение свойства Interval компонента Timer в зависимости от свойства Value ползунка элемента управления TrackBar, дважды щелкаем элемент TrackBar в режиме проектирования. Появляется файл Form1.h с шаблоном, который после записи нашего кода принимает такой вид.
256 Жарков В.А. Компьютерная графика, мультимедиа и игры на Visual C++ 2005
Листинг 51.4. Метод для элемента управления TrackBar.
private:
System::Void trackBar1_Scroll(System::Object^ sender, System::EventArgs^ e)
{
//Включаем таймер Timer (задаем Enabled равным true): timer1->Enabled = true;
//Устанавливаем свойство Interval таймера Timer //в зависимости от перемещения ползунка Value: timer1->Interval = trackBar1->Value;
}
Согласно разработанной выше методике, чтобы иметь возможность приостановить (и запустить вновь) процесс анимации на любом рисунке при помощи кнопки Stop Animation, дважды щелкаем эту кнопку в режиме проектирования (рис. 51.1). Появляется файл Form1.h с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 51.5. Метод для кнопки Stop Animation.
//Объявляем булеву переменную OffOn
//и задаем ей значение, например, false: bool static OffOn = false;
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
//Задаем чередование остановки //и возобновления анимации
//после каждого щелчка кнопки Button: if (OffOn == false)
{
//Приостанавливаем анимацию: timer1->Enabled = false;
//Изменяем значение OffOn на противоположное: OffOn = true;
}
else
{
//Возобновляем анимацию: timer1->Enabled = true;
//Изменяем значение OffOn на противоположное: OffOn = false;
}
}
Глава 51. Методика изображения летающих предметов |
257 |
Листинг 51.6. Метод для компонента PrintDocument.
private: System::Void printDocument1_PrintPage( System::Object^ sender, System::Drawing::Printing::PrintPageEventArgs^ e)
{
//Создаем объект myGraphics класса Graphics: Graphics^ myGraphics = this->CreateGraphics();
//Связываем объект myGraphics с текущим принтером: myGraphics = e->Graphics;
//Рисуем четыре граничные линии прямоугольника, //от которых будет отскакивать летающий мяч
//при помощи пера Pen(Color::Red, 3): Pen^ myPen = gcnew Pen(Color::Red, 3); myGraphics->DrawLine(myPen,
boundary_of_rectangle_x, boundary_of_rectangle_y, width_of_rectangle, boundary_of_rectangle_y);
//Другой вариант задания пера Pen: myGraphics->DrawLine(gcnew Pen(Color::Red, 3),
boundary_of_rectangle_x, boundary_of_rectangle_y, boundary_of_rectangle_x, height_of_rectangle);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), boundary_of_rectangle_x, height_of_rectangle, width_of_rectangle, height_of_rectangle);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), width_of_rectangle, boundary_of_rectangle_y, width_of_rectangle, height_of_rectangle);
//Рисуем изображение мяча на форме Form1 //при помощи метода DrawImage: myGraphics->DrawImage(myBitmap,
Convert::ToInt32(position_of_ball_x - width_of_bitmap_of_ball / 2),
Convert::ToInt32(position_of_ball_y - height_of_bitmap_of_ball / 2), width_of_bitmap_of_ball, height_of_bitmap_of_ball);
//Высвобождаем ресурсы от объекта myGraphics: myGraphics->Dispose();
}
Глава 52. Методика анимации градиентного заполнения текста цветом
Листинг 52.1. Объявление и инициализация глобальных переменных.
//Задаем ширину и высоту прямоугольника, //внутри которого будет размещаться текст: int static width_of_rectangle = 700;
int static height_of_rectangle = 300;
//Верхняя горизонтальная линия прямоугольника отстоит
//от оси 'x' на расстоянии boundary_of_rectangle_y: int static boundary_of_rectangle_y = 15;
//Левая вертикальная линия прямоугольника отстоит
//от оси 'y' на расстоянии boundary_of_rectangle_x: int static boundary_of_rectangle_x = 15; //Объявляем целочисленные переменные //и задаем значения:
float static Shift_of_Gradient = 10; int static Step_of_Gradient = 5;
Дважды щелкаем по форме Form1 в режиме проектирования и в появившийся шаблон записываем наш код, после чего метод принимает такой вид.
Листинг 52.2. Метод Form1_Load.
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
//Создаем объект myGraphics класса Graphics //и стираем (Clear) другие изображения: Graphics^ myGraphics = this->CreateGraphics(); myGraphics->Clear(BackColor);
}
Чтобы подключить к работе таймер, дважды щелкаем значок для компонента Timer (ниже формы в режиме проектирования). Появляется файл Form1.h с шаблоном, который после записи нашего кода принимает следующий вид.
Листинг 52.3. Метод для компонента Timer.
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)
{
//Создаем объект myGraphics класса Graphics: Graphics^ myGraphics = this->CreateGraphics();
Глава 52. Методика анимации градиентного заполнения текста цветом |
259 |
//Рисуем четыре граничные линии прямоугольника, //внутри которого будет размещаться текст: myGraphics->DrawLine(gcnew Pen(Color::Red, 3),
boundary_of_rectangle_x, boundary_of_rectangle_y, width_of_rectangle, boundary_of_rectangle_y);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), boundary_of_rectangle_x, boundary_of_rectangle_y, boundary_of_rectangle_x, height_of_rectangle);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), boundary_of_rectangle_x, height_of_rectangle, width_of_rectangle, height_of_rectangle);
myGraphics->DrawLine(gcnew Pen(Color::Red, 3), width_of_rectangle, boundary_of_rectangle_y, width_of_rectangle, height_of_rectangle);
//Задаем тип шрифта, размер текста и стиль шрифта: Drawing::Font^ myFont =
gcnew Drawing::Font("Times New Roman", 100, FontStyle::Bold, GraphicsUnit::Point);
//Записываем текст, цвет которого будет изменяться: String^ drawText = "Visual";
//Задаем меру строки текста
//при помощи метода MeasureString: SizeF^ SizeF_of_Text =
gcnew SizeF(myGraphics->MeasureString( drawText, myFont));
//Задаем точку, от которой будет рисоваться текст, //сцентрированный внутри прямоугольника:
PointF^ Start_of_drawPointF =
gcnew PointF(Convert::ToSingle( (width_of_rectangle - SizeF_of_Text->Width) / 2),
Convert::ToSingle(
(height_of_rectangle - SizeF_of_Text->Height) / 2));
//Создаем объект myBrush класса LinearGradientBrush //и задаем его параметры //для градиентной заливки текста
//двумя цветами (Color::Red, BackColor) //от начальной точки PointF(0.0f, 0.0f) //до конечной точки
//PointF(Shift_of_Gradient, 200.0f);