Тема: Разработка
анимированных изображений в программе.
Цель занятия:
·
познакомить
студентов с технологией создания анимированных изображений.
Задачи:
- обучающие – повторить,
закрепить и углубить знания студентов (работа в среда программирования C++Builder.)
- развивающие – сформировать
навыки по практическому решению поставленных задач;
- воспитывающие – развитие
внимательности, практичности.
Тип занятия:
комбинированное
Программное
обеспечение:
среда программирования C++Builder.
Формы организации
работы на занятие: работа в микро-группах.
Учащиеся должны
знать
основные понятия:
- инспектор объектов;
- компонент Timer;
- компонент PaintBox;
- расположение элементов на
форме;
- свойства объектов;
- классы;
- процедуры и функции;
Учащиеся должны
уметь:
- располагать элементы на форме ;
- задавать свойства для каждого
объекта ;
- создавать класс ;
- создавать и использовать
процедуры и функции;
- сохранять проект;
- выполнять компиляцию проекта;
Литература.
1. Шилдт
Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом
"Вильямс", 2010-330с.
|
2. Архангельский
А. Я. Програмирование в C++ Builder - М. : "Издательство Бином",
2003 – 1340 с.
|
3. Деннис
Ритчи. Язык программирования C. 2-е издание, переработанное и дополненное
Пер. с англ.-М. : Издательский дом "Вильямс", 2009 – 560 с.
|
4. Керниган
Б. Язык программирования Си - Питер. Невский Диалект, 2009 – 278 с.
5. Вильямс
А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер,
2003. - 624 с.: ил.
6. Юркин А.
Задачник по программированию. — СПб.: Питер, 2002. — 192 с.
|
Методы и
приёмы: пояснительно-иллюстративные,
практического обучения
Оборудование и
наглядные пособия: файлы-заготовки кода, проектор с выводом на экран
файла примера готовой програмы.
План занятия
№
|
Этап
|
Мин.
|
1
|
Организационный момент
|
3
|
2
|
Сообщение
темы и цели занятия.
|
2
|
3
|
Актуализация
опорных знаний и навыков.
|
10
|
4
|
Мотивация
учебной деятельности.
|
2
|
5.
|
Изучение нового материала
|
13
|
6.
|
Закрепление
нового материала. Выполнение практического
задания
“Разработка программного кода ”
|
40
|
7.
|
Подведение итогов занятия
|
10
|
Содержание
занятия
1.
Организационный
момент.
2.
Сообщение
темы и цели занятия.
Сегодня
на занятии познакомимся с технологией создания анимированного изображения
моделирующее физические процесы.
3.Актулизация
опорных знаний и навыков.
Пройдем небольшой тест. На выполнения задания
отводится 10 минут. За выполнение второго задания получаете 5 балов за все
остальные по балу.
9 балов – 5«отлично»
7 балов – 4 «хорошо»
5 балов – 3 «плохо»
Задание 1. Расставить в правильном порядке модификаторы
класса в соответствии с определением
|
1. protected
2. private
3. public
|
a.
обращения
к члену допускаются из любого кода
b.
обращения
к члену допускаются из методов того класса, в котором этот член определён, а
также из любых методов его классов-наследников.
c. обращения
к члену допускаются только из методов того класса, в котором этот член
определён
|
Ответ:
1 - ___; 2 - ___;3 - ___;
|
Задание
2. Определите название компонента по его изображению
|
___________________
___________________
___________________
___________________
___________________
|
Задание 3.Определите в каких строчках нет ошибки в
синтаксисе написания программы на С++
|
1.
Timer1
-> Enabled = true;
2.
Timer1
-> Enabled := true;
3.
Timer1.Enabled
:= true;
4.
Timer1
-> Enabled = true
|
Ответ:
|
Задание
4. Как создать новую форму.
|
1.
File
> New > Form
2.
Ctrl
+ Shift + N
3.
Нажать
на значок
4.
File
> New Form
|
Ответ:
|
Задание
5 Вставьте пропущенные слова.
|
По мере увеличения размера и
сложности ваших программ вам следует разделить их на небольшие легко
управляемые части, называемые (…..). Каждая (…….) в вашей программе должна
выполнять определенную задачу. Если программе необходимо выполнить
определенную задачу, то она вызывает соответствующую (……..), обеспечивая эту
(……..) информацией, которая ей понадобится в процессе обработки.
|
Задание 1. Расставить в правильном порядке модификаторы
класса в соответствии с определением
|
1.
Наследование
2.
Полиморфизм
3.
Инкапсуляция
|
a.
процесс
вызова и переопределение функций базового класса в дочерних
b.
пользователю
класса (программисту) доступен лишь определенный набор функций и переменных
для работы с классом.
c. механизм создания нового
класса на основе ранее созданного
|
Ответ:
1 - ___; 2 - ___;3 - ___;
|
Задание
2. Определите название компонента по его изображению
|
___________________
___________________
___________________
___________________
___________________
|
Задание 3.Определите в каких строчках нет ошибки в
синтаксисе написания программы на С++
|
1.
function
MaxNumber(a,b: integer): integer;
2.
function
MaxNumber(int a,b);
3.
int
MaxNumber(int a,b);
4.
int
MaxNumber(int a,b): int;
|
Ответ:
|
Задание
4. Как cохранить
все файлы проэкта.
|
1.
File
> Save
2.
Нажать
на значок
3.
Нажать
на значок
4.
Нажать
Shift+Ctrl+S
|
Ответ:
|
Задание
5 Вставьте пропущенные слова.
|
По мере увеличения размера и
сложности ваших программ вам следует разделить их на небольшие легко
управляемые части, называемые (…..). Каждая (…….) в вашей программе должна
выполнять определенную задачу. Если программе необходимо выполнить
определенную задачу, то она вызывает соответствующую (……..), обеспечивая эту
(……..) информацией, которая ей понадобится в процессе обработки.
|
|
|
|
4.
Мотивация учебной деятельности.
При
написании ряда программ мы столкнулись с тем что приходится создавать движение
определённого объекта. Очень часто данное действие приходится применяться для
написания игровых программ. Еще одна область применения анимации это
визуализация физических или химических законов. Сегодня мы и рассмотрим один из
эффектов, пламя из искр.
5. Изучение
нового материала
Анимация
- это демонстрирующаяся в быстром темпе последовательность кадров, каждый из
которых несколько отличается от предшествовавшего ему и следующего за ним
кадра. Каждый кадр отображается в течение определенного промежутка времени.
Если кадров достаточное количество и время их отображения невелико, то
создается иллюзия движения.
Процедурная анимация полностью
или частично рассчитывается компьютером. Сюда можно включить следующие её виды:
·
Симуляция
физического взаимодействия твёрдых тел.
·
Имитация
движения систем частиц, жидкостей и газов.
·
Имитация
взаимодействия мягких тел (ткани, волос).
·
Расчёт
движения иерархической структуры связей (скелета персонажа) под внешним
воздействием (Ragdoll).
·
Имитация
автономного (самостоятельного) движения персонажа. Примером такой системы
является программа Euphoria.
Рассмотрим
программы с использование анимации, которые разработали наши студенты.
Программа,
которую сегодня мы с вами будем разрабатывать, представляет интерес сразу с
двух точек зрения. Во-первых, это просто красивая программа, более или менее
достоверно рисующая эффект пламени. Во-вторых, она представляет собой хороший
пример двойной буферизации, наглядно демонстрируя - для чего эта двойная
буферизация нужна и насколько она эффективна. Рассмотрим каждый из аспектов
поподробнее
Итак,
прежде всего непосредственно про реализацию самого эффекта пламени. Чтобы
смоделировать его, представим себе пламя как объект, состоящий из отдельных
искр, которые зарождаясь где-то в нижней части объекта (там, где сгорает нечто
горючее), затем, будучи легче воздуха, поднимаются вверх, попутно прогорая и
постепенно теряя свою яркость. При этом считаем, что в момент своего зарождения
искра выбрасывается из точки своего образования с достаточно произвольной
скоростью как горизонтальной, так и вертикальной (впрочем, только вверх). Далее
в процессе ее движения на искру действуют силы: во-первых, подъемная сила, а
значит, она поднимается вверх ускоренно, во-вторых, сила сопротивления воздуха,
следовательно, горизонтальная составляющая ее скорости снижается, пока не
станет равной нулю. Допускаем, что яркость искры постоянно уменьшается, а когда
становится равной нулю - искра прогорела.
Исходя
из этих предположений, сделаем искры классом, создав массив искр, решив, что
пламя будет разгораться постепенно - при каждом срабатывании таймера число
горящих искр будет увеличиваться, пока не будут гореть сразу все. А когда искра
прогорает, она заново "зарождается" где-то внизу (при этом точное
место определяется достаточно произвольно).
Что
же касается, двойной буферизации, то ее идея проста: процесс построения
изображения происходит на обычно невидимом графическом объекте (буфере),
а по завершению этого построения содержимое буфера просто копируется туда, где
изображение должно выводиться. Делается это для борьбы с эффектом мерцания в ситуации,
когда за один проход изменяются цвета многих пикселей (много объектов меняют
свое положение). В случае с C++ Builder'ом это обычно выглядит так: имеется
объект типа TBitmap, в Canvas которого рисуется все изображение, а потом
готовое изображение рисуется в Canvas формы. В данном конкретном случае вместо
канвы невидимого битмапа и канвы формы используется канва двух объектов типа
TPaintBox. С принципиальной точки зрения это не имеет абсолютно никакого
значения, но позволяет воочию увидеть - что творится там, где изображение
строится в реальном времени (это буфер, его мучения мы обычно не видим), и как
все здорово и красиво в конечном изображении, куда копируется уже готовая
картинка из буфера.
Используются
следующие компоненты: Button, Edit, PaintBox, Timer.
6. Закрепление
нового материала. Выполнение практического задания “Разработка программного
кода ”
Расположим
необходимые компоненты на форме
Изменим свойства некоторых
компонентов
Button1:
Caption: "Старт"
PaintBox1:
Height: 345
Width: 193
PaintBox2:
Height: 345
Width: 193
Timer1:
Enabled: false
Interval: 10
Теперь рассмотрим код программы я разбил
код программы на смысловые блоки ваша задача собрать из данных блоков исходный
код.
7
|
1.
|
void
FirePointClass::Evolution()
|
2
|
2.
|
const
int N = 5000; //Число "искр"
|
5
|
3.
|
void
FirePointClass::Activate()
|
6
|
4.
|
{
Randomize();
//Обеспечиваем случайность "случайных чисел"
X = random(11) -
5; Y = 0;
//Задаем начальные координаты
Vx = 100.0
- random(200);
//Задаем начальную скорость
Vy = random(100);
FirePointColor = 0x000000FF;
//Вначале искра красного цвета
ColorChange = -0x00000001;
//Устанавливаем шаг изменения цвета
}
|
4
|
5.
|
{
public:
void
Activate(); //Функция, активирующая заново прогоревшую "искру"
void
Evolution(); //Изменения свойств при каждом срабатывании таймера
void
Drawing(); //Функция рисования "искры"
bool
IsBurning(); //Не прогорела ли еще "искра"
protect:
int
ColorChange; //Величина изменения цвета искры за один шаг
double
X, Y; //Координаты
double
Vx, Vy; //Компоненты скорости
int
FirePointColor; //Текущий цвет
}
|
8
|
6.
|
{
X
+= 0.01 * Vx; //Смещаем искру
Y
-= 0.01 * Vy;
if
(abs(Vx) >= 0.1) //Если горизонтальная скорость больше нуля
Vx
-= 1 * (Vx / fabs(Vx)); //Уменьшаем ее из-за "сопротивления
воздуха"
Vy
+= 0.5; //На искру действует "подъемная сила"
FirePointColor
+= ColorChange; //Уменьшаем яркость
}
|
10
|
7.
|
{
int
XX = (Form1 -> PaintBox1 -> Width) / 2; //Координаты точки отсчета
int YY = (Form1
-> PaintBox1 -> Height) - 20;
Form1
-> PaintBox1 -> Canvas -> Pixels[XX + XX][YY + YY] = TColor(FirePointColor);
//Рисуем
искру в виде точки
}
|
11
|
8.
|
bool
FirePointClass::IsBurning()
|
3
|
9.
|
class
FirePointClass //Класс "искр" (конструктор не требуется, т.к. при
каждой
//активации
"искры" свойствам заново присваиваются новые начальные значения)
|
16
|
10.
|
n
= 0; //Изначально нет ни одной горящей искры
Timer1
-> Enabled = false; //Запускаем таймер
}
|
9
|
11.
|
void
FirePointClass::Drawing()
|
13
|
12.
|
FirePointClass
FirePoint[N]; //Объявляем массив искр
|
17
|
13.
|
void
__fastcall TForm1::Timer1Timer(TObject *Sender)
|
1
|
14.
|
#include
<math> //Подключаем математическую библиотеку
|
14
|
15.
|
int
n; //Число уже горящих искр (для постепенного разгорания пламени)
|
18
|
16.
|
{
TRect Rect =
TRect(0, 0, PaintBox1 -> Width, PaintBox1 -> Height);
//Прямоугольник, закрывающий весь PaintBox
PaintBox1 ->
Canvas -> Brush -> Color = clBlack; //Устанавливаем цвет кисти
PaintBox1
-> Canvas -> FillRect(Rect); //И заливаем этим цветом изображение
for (int
i = 0; i <= n; i++) //Для всех уже горящих искр
if (FirePoint[i].IsBurning())
//Если не прогорела,...
FirePoint[i].Evolution();
//...изменяем ее свойства
else //Если прогорела
- активируем заново
FirePoint[i].
Evolution();
for (int i = 0;
i <= n; i++)
FirePoint[i].Drawing();
//Рисуем все горящие искры
PaintBox2 ->
Canvas -> CopyRect(Rect, PaintBox1 -> Canvas, Rect);
//Ключевой
момент двойной буферизации - копируем готовое изображение
//на
"основной экран" (здесь - второй PaintBox)
if (n
< N - 1) n++; //Если еще не все искры горят, увеличиваем их число
Edit1
-> Text = n; //Выводим количество уже горящих искр
}
|
15
|
17.
|
void
__fastcall TForm1::Button1Click(TObject *Sender)
|
12
|
18.
|
{
//Если цвет искры отличен от черного - значит, она еще горит
return(FirePointColor
> 0x00000000);
}
|
Проверим
правильно ли вы собрали все блоки. Вот так должен выглядеть ваш исходный код.
1. #include
<math> //Подключаем математическую библиотеку
2. const int N =
5000; //Число "искр"
3. class
FirePointClass //Класс "искр" (конструктор не требуется, т.к. при
каждой
4. //активации
"искры" свойствам заново присваиваются новые начальные значения)
5. {
6. public:
7. void
Activate(); //Функция, активирующая заново прогоревшую "искру"
8. void
Evolution(); //Изменения свойств при каждом срабатывании таймера
9. void
Drawing(); //Функция рисования "искры"
10. bool IsBurning();
//Не прогорела ли еще "искра"
11. protect:
12. int ColorChange;
//Величина изменения цвета искры за один шаг
13. double X, Y;
//Координаты
14. double Vx, Vy;
//Компоненты скорости
15. int
FirePointColor; //Текущий цвет
16. }
17. void
FirePointClass::Activate()
18. {
19. Randomize();
//Обеспечиваем случайность "случайных чисел"
20. X = random(11) -
5; Y = 0; //Задаем начальные координаты
21. Vx = 100.0 -
random(200); //Задаем начальную скорость
22. Vy = random(100);
23. FirePointColor =
0x000000FF; //Вначале искра красного цвета
24. ColorChange =
-0x00000001; //Устанавливаем шаг изменения цвета
25. }
26. void
FirePointClass::Evolution()
27. {
28. X += 0.01 * Vx; //Смещаем искру
29. Y -= 0.01 * Vy;
30. if (abs(Vx) >=
0.1) //Если горизонтальная скорость больше нуля
31. Vx -= 1 * (Vx /
fabs(Vx)); //Уменьшаем ее из-за "сопротивления воздуха"
32. Vy += 0.5; //На
искру действует "подъемная сила"
33. FirePointColor +=
ColorChange; //Уменьшаем яркость
34. }
35. void
FirePointClass::Drawing()
36. {
37. int XX = (Form1
-> PaintBox1 -> Width) / 2; //Координаты точки отсчета
38. int YY = (Form1
-> PaintBox1 -> Height) - 20;
39. Form1 ->
PaintBox1 -> Canvas -> Pixels[XX + XX][YY + YY] = TColor(FirePointColor);
40. //Рисуем искру в
виде точки
41. }
42. bool
FirePointClass::IsBurning()
43. { //Если цвет
искры отличен от черного - значит, она еще горит
44. return(FirePointColor
> 0x00000000);
45. }
46. FirePointClass
FirePoint[N]; //Объявляем массив искр
47. int n; //Число уже
горящих искр (для постепенного разгорания пламени)
48. //--------------------------------------------------------------------
49. void __fastcall
TForm1::Button1Click(TObject *Sender)
50. {
51. n = 0;
//Изначально нет ни одной горящей искры
52. Timer1 ->
Enabled = false; //Запускаем таймер
53. }
54. //--------------------------------------------------------------------
55. void __fastcall
TForm1::Timer1Timer(TObject *Sender)
56. {
57. TRect Rect =
TRect(0, 0, PaintBox1 -> Width, PaintBox1 -> Height);
58. //Прямоугольник, закрывающий весь PaintBox
59. PaintBox1 ->
Canvas -> Brush -> Color = clBlack; //Устанавливаем цвет кисти
60. PaintBox1 ->
Canvas -> FillRect(Rect); //И заливаем этим цветом изображение
61. for (int i = 0; i
<= n; i++) //Для всех уже горящих искр
62. if
(FirePoint[i].IsBurning()) //Если не прогорела,...
63. FirePoint[i].Evolution();
//...изменяем ее свойства
64. else //Если
прогорела - активируем заново
65. FirePoint[i]. Evolution();
66. for (int i = 0; i
<= n; i++)
67. FirePoint[i].Drawing();
//Рисуем все горящие искры
68. PaintBox2 ->
Canvas -> CopyRect(Rect, PaintBox1 -> Canvas, Rect);
69. //Ключевой момент
двойной буферизации - копируем готовое изображение
70. //на
"основной экран" (здесь - второй PaintBox)
71. if (n < N - 1)
n++; //Если еще не все искры горят, увеличиваем их число
72. Edit1 -> Text =
n; //Выводим количество уже горящих искр
73. }
Переносим
наш программный код в среду разработки и запускаем код на выполнение. Как вы
видите в коде намерено допущены ошибки ваша задача устранить 5 ошибок и
показать выполнение программы. Чтобы упростить вам задачу я зашифровал строки в
которых допущены ошибки.
ГАПТ
|
БУЦ
|
ПУТЕТ
|
ПТЬЕН
|
ПУЫЬТ
|
Расшифровка
11
|
16
|
39
|
52
|
65
|
1011
|
10000
|
100111
|
110100
|
1000001
|
ГАПТ
|
БУЦ
|
ПУТЕТ
|
ПТЬЕН
|
ПУЫЬТ
|
Проверим
правильно ли вы нашли ошибки.
11
– заменить protect на private;
16
– пропущена точка с запятой;
39
– увеличиваем не на ХХ и УУ а на Х и У
52 –
вместо false true;
65 –
используется Activate() вместо Evolution()
Исправляем
ошибки и запускаем программу на выполнение.
Как
вы видите, создание даже такой небольшой программы требует от программиста не
только углублённых знаний в области программирования, но и знаний по физике и
математике. Написание программ, которые моделируют какой то из физических или
химических процессов, позволит вам более детально рассмотреть большинство
методов которые вы сможете применить в будущем.
7.Подведение
итогов занятия.
Проверка
самостоятельной работы студентов, анализ работ. Выставление оценок.
8. Домашнее
задание.
Написать программу,
которая моделирует броуновское движение частиц в закрытом сосуде .
Оставьте свой комментарий
Авторизуйтесь, чтобы задавать вопросы.