Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
21
Добавлен:
20.05.2015
Размер:
2.45 Mб
Скачать

Программирование на языке Си

Тема 13. Анимация

© К.Ю. Поляков, 2007

142

Анимация

Анимация (англ. animation) – оживление изображения на экране.

Задача: внутри синего квадрата 400 на 400 пикселей слева направо двигается желтый

квадрат 20 на 20 пикселей. Программа останавливается, если нажата клавиша Esc

или квадрат дошел до границы синей области.

Проблема: как изобразить перемещение объекта на экране? Привязка: состояние объекта задается координатами (x,y)

Принцип анимации:

1.рисуем объект в точке (x,y)

2.задержка на несколько миллисекунд

3.стираем объект

4.изменяем координаты (x,y)

5.переходим к шагу 1

143

Как "поймать" нажатие клавиши?

kbhit() – функция, определяет, было ли нажатие на (любую!) клавишу (0 – не было, не 0 – было).

if (

kbhit() )

if ( kbhit() != 0 )

 

 

printf("Нажата какая-то клавиша...");

else

printf("Нет нажатия...");

getch() – функция, которая определяет код нажатой клавиши: 27 = Esc, 13 = Enter, 32 = пробел, … int c;

if ( kbhit() ) {

printf("Нажата какая-то клавиша c = getch();

printf("Код клавиши %d", c);

}

144

Как выйти из цикла?

? Как не допустить выход за границу поля?

 

x + 20 < 400

для

kbhit() и getch()

 

 

#include <conio.h>

 

 

void main()

 

 

{

пока не вышли за границу синего квадрата

...

while ( x + 20 <

{

if ( kbhit() )

if ( getch() == 27

...

}

...

}

если нажата клавиша ...

) break;

если нажата клавиша с кодом 27 (Esc),

выйти из цикла

145

Процедура (рисование и стирание)

(x, y)

(x+20, y+20)

И деи

одна процедура рисует и стирает

стереть = нарисовать цветом фона

границу квадрата отключить (в основной программе)

цвет: желтым рисуем, синим стираем

void Draw( int x, int y, int color )

{

сплошная заливка

setfillstyle ( 1, color );

цветом color

bar(x, y, x+20, y+20);

}

залитый прямоугольник

146

Полная программа

void Draw ( int x, int y, int color )

{

 

процедура

...

 

 

}

 

включить

void main()

 

 

графический

{

 

 

режим

int d = DETECT, m;

 

 

 

initgraph ( &d, &m, "c:\\borlandc\\bgi" );

int x, y;

 

 

setfillstyle(1,

синий фон

начальные

bar(0, 0, 399,

 

координаты

x = 0; y = 240;

 

while ( x + 20 < 400 )

 

 

{

 

выход по

if ( kbhit() )

 

клавише Esc

if ( getch() == 27 ) break;

 

Draw ( x, y, YELLOW );

ждем 20 мс, нужно

delay ( 20 );

Draw ( x, y, 9

#include <dos.h>

x ++;

 

 

}

closegraph();

}

147

Задания

"4": Два квадрата двигаются в противоположных направлениях:

"5": Два квадрата двигаются

в противоположных направлениях и отталкиваются от стенок синего квадрата:

Управление клавишами

148

 

 

 

 

Задача: жёлтый квадрат внутри синего квадрата управляется

клавишами-стрелками. Коды клавиш:

 

 

влево – 75

вверх – 72

Esc – 27

вправо – 77

вниз – 80

 

 

Проблема: как изменять направление движения?

Решение:

if ( kbhit() )

если было нажатие на клавишу, …

code = getch();

if (code == 27) break;

switch ( code ) {

case 75: x --; break; case 77: x ++; break; case 72: y --; break; case 80: y ++;

}

}

получить ее код

выход по Esc

перемещение

149

Программа

void Draw (int x, int y, int color)

процедура

{

 

 

 

 

 

...

 

 

 

}

 

 

 

void main()

 

 

 

{

основной цикл

 

int x, y, code;

 

 

 

 

...

 

 

 

while ( 1 ) {

обработка

 

Draw(x, y, YELLOW);

 

нажатия на

 

delay(20);

клавишу

 

Draw(x, y, 9);

?

 

 

if ( kbhit() ) {

 

 

 

 

Что плохо?

...

 

 

}

?

 

 

}

 

 

 

Как убрать

}

 

 

 

 

мигание?

150

Задания

"4": Квадрат двигается при нажатии стрелок, однако не может выйти за границы синего квадрата:

"5": Квадрат непрерывно

двигается, при нажатии стрелок меняет направление и отталкивается от стенок синего квадрата:

151

Вращение

Задача: изобразить модель вращения Земли вокруг Солнца.

Проблема: движение по окружности, как изменять координаты?

Решение: использовать в качестве независимой переменной (менять в цикле) угол поворота α

 

 

(x, y)

 

L

α

x = x0 + L·cos(α)

 

y = y0

L·sin(α)

 

 

(x0, y0)

152

Процедура

цвет: желтый – рисуем, черный – стираем

void Draw( int x, int y, int color )

{

радиус Земли

const r = 10;

setcolor ( color ); circle ( x, y, r );

}

установили цвет линий

(x,y)

r

153

Константы и переменные

#include <math.h> // математические функции

void Draw ( int x, int y, int color )

{

...

}

void main()

{

const

rSun

= 60,

// радиус Солнца

 

L

=

150,

// радиус орбиты Земли

 

x0

=

200,

// координаты центра Солнца

 

y0

=

200;

 

int

x,

y,

 

// координаты Земли

 

code;

 

// код нажатой клавиши

float

a,

ha;

// угол поворота, шаг

int

d = DETECT, m;

initgraph ( &d, &m, "c:\\borlandc\\bgi" );

...

}

ждем 20 мс
новые
координаты

154

Основной цикл

circle ( x0, y0, rSun ); setfillstyle(1, YELLOW); floodfill ( x0, y0, WHITE

a = 0; // начальный угол ha = M_PI/180; // шаг 1o за 100 мс while(1) {

x = x0 + L*cos(a);

y = y0 - L*sin(a);

Draw ( x, y, LIGHTBLUE ); delay ( 20 );

Draw(x, y, 0);

if ( kbhit() )

if ( 27 == getch() ) break;

рисуем Солнце: белый контур, желтая заливка

const M_PI=3.1415926;

выход по Esc

a = a + ha;

поворот на ha

}

 

closegraph(); !

#include<math.h> // sin, cos, M_PI

155

Задания

"4": И зобразить модель Солнца с двумя планетами, которые вращаются в противоположные стороны:

"5": И зобразить модель

системы Солнце-Земля- Луна:

Соседние файлы в папке ПОЛЯКОВ_ПРЕЗЕНТАЦИИ_С++