7. Движение героев. Циклы

Занятие 7


Это надо знать


Использование цикла для изображения нескольких одинаковых героев

Если мы хотим изобразить 7 елок в ряд, как нам поступить? Мы можем 7 раз вызвать функцию tree, для этого записать команды:

    tree (100,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
    tree (200,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
    tree (300,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
    tree (400,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
    tree (500,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
    tree (600,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
    tree (700,  50,  1,  1,  0,  0,  RGB (145,  210,  80));

Результат выполнения программы:


А если мы хотим нарисовать 20 елок; 50 елок; 100 елок? Как-то не очень рационально писать 100 раз вызов функции tree. Как поступают в этом случае?
Посмотрим, какой параметр функции tree изменяется при вызове. Это параметр х
Как  изменяется х? От 100 до 700.
На какую величину х изменяется каждый раз? На 100.

Для решения нашей задачи воспользуемся оператором цикла.


Циклом в программировании называют повторение одних и тех же действий. Последовательность действий, которые повторяются в цикле, называют телом цикла.

Общий вид цикла while:

while (условие)
   {
   последовательность действий
   }

Условие - это выражение, которое может принимать значения true (истина)  false (ложь).
Простое условие - это сравнение двух выражений по величине.

Операции сравнения:
<      меньше
>      больше
<=    меньше или равно
>=    больше или равно
=      равно
!=     не равно

Составное условие состоится из простых условий с помощью логических операций:
&&    и
||        или

Составное условие с && (и) истинно, когда все входящие в него простые условия истинны. В остальных случаях - ложно.
Составное условие с || (или) ложно, когда все входящие в него простые условия ложны. В остальных случаях - истинно.


Запишем оператор цикла while следующим образом:

int x = 100;
while ( x <= 700)
       {
        tree (x,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
        x +=100;
        }

Где

int x = 100;              - начальное значение
 x <= 700;                - условие продолжения цикла
 x += 100                 - шаг изменения переменной х

Последовательность выполнения оператора цикла:

1. Переменной х будет присвоено значение 100;
2. Проверится условие: x <= 700 (да, т.к. 100 <= 700);
3. Будет нарисована елка в координатах (100, 50);
4. Переменная х будет увеличена на 100 (х = 100 + 100 = 200);
5. Проверится условие: x <= 700 (да, т.к. 200 <= 700);
6. Будет нарисована елка в координатах (200, 50);
7. Переменная х будет увеличена на 100 (х = 200 + 100 = 300);
И так далее, пока x не станет больше числа 700, тогда оператор цикла while закончит свою работу и мы получим рисунок, аналогичный выполнению предыдущей программы.

Использование цикла для осуществления движения героя

Изменим программу, чтобы  на экране появлялись самокаты справа налево, как будто самокат катится:

int x  =  635;
while ( x  >=  50)
       {
        scooter (x,  510,  0.8,  0.8, TX_BLUE,  TX_RED); 
        x  -=  10;
        }

int x  =  635;      - начальное значение
x  >=  50;           - двигаемся вправо, пока х больше или равно числу 50
x  -=  10;            - уменьшаем х на 10

Результат выполнения программы будет следующим:


Для того, чтобы показать, что самокат движется, необходимо в теле цикла стирать предыдущий рисунок самоката. Для этого будем использовать команду txClear();
Команду txSleep (50); будем использовать для задержки перерисовки изображения.

Фрагмент программы:

int main()
    {
    txCreateWindow (800, 600);

    tree (300, 50, 1, 1, 0, 0, RGB (145, 210, 80));
    frog (700, 485, 0.6, 0.6, 0, 0, RGB ( 30, 190, 50));

    int x  =  635;
    while ( x  >=  50)
        {
        txSetFillColor (TX_WHITE);
        txClear();

        scooter (x,  510,  0.8,  0.8,  TX_BLUE,  TX_RED);
        x  -=  10;
        txSleep (50);
        }

    return 0;
    }

Результат выполнения:



Почему  не рисуются елки и лягушка? 

Посмотрим на последовательность выполнения команд:

1. Рисуется елка.
2. Рисуется лягушка.
3. В теле  цикла while выбирается белый цвет, стирается все с экрана, рисуется самокат.

Т.е. все изображения, которые были на экране до выполнения этого цикла, будут стерты. Как же этого избежать? Поместим рисование всех  героев в наш цикл:

int main()
    {
    txCreateWindow (800,  600);
  
    int x = 635;
    while ( x >= 50)
        {
        txSetFillColor (TX_WHITE);
        txClear();

        tree (300,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
        frog (700,  485,  0.6,  0.6,  0,  0,  RGB ( 30,  190,  50));

        scooter (x,  510,  0.8,  0.8,  TX_BLUE,  TX_RED);
        
        x -= 10;
        txSleep (50);
        }

    return 0;
    }



Создадим функцию MoveScooterFrog, в которую поместим цикл, отвечающий за движение самоката. Изменим координату х = 700 в вызове функции frog на х + 60, лягушка будет ехать на самокате.

int main()
    {
    txCreateWindow (800,  600);

    MoveScooterFrog();

    return 0;
    }

void MoveScooterFrog()
    {
    int x = 635;
    while (x  >=  50)
        {
        txSetFillColor (TX_WHITE);
        txClear();

        tree (300,  50,  1,  1,  0,  0,  RGB (145,  210,  80));
       
        frog  (x + 60,  485,  0.6,  0.6,  0,  0,  RGB ( 30,  190,  50));
        scooter (x,   510,  0.8,  0.8,  TX_BLUE,  TX_RED);

        x -= 10;

        txSleep (50);
        }
    }


Одновременно с координатой х можно изменять и координату у, тогда герои будут двигаться по диагонали.

void MoveScooterFrog()
    {
    int x = 635,  y = 510;
    while (x >= 50)
        {
        txSetFillColor (TX_WHITE);
        txClear();

        tree (300, 50, 1, 1, 0, 0, RGB (145, 210, 80));
        
        frog    (x + 60,  y - 25,  0.6,  0.6,  0,  0,  RGB ( 30,  190,  50));
        scooter (x,  y,   0.8,  0.8,  TX_BLUE,  TX_RED);

        x  -=  10;
        y  -=   5;

        txSleep (50);
        }
    }


Движение героя в зависимости от времени

Каждый герой нашей программы проходит какой-то путь. Из математики мы знаем, что для расчета пути необходимо скорость умножить на время.
Обозначим время t.
Будем изменять наш цикл в зависимости от времени, тогда 
координата х будет вычисляться по формуле: начальное значение х + скорость*t;
координата y будет вычисляться по формуле: начальное значение y + скорость*t.

void MoveScooterFrog()
    {
     int t = 0;
     while (t <= 100)
          {
          txSetFillColor (TX_WHITE);
          txClear(); 


          tree (300, 50, 1, 1, 0, 0, RGB (145, 210, 80));

          frog      (695 + 10*t, 485 - 5*t, 0.6, 0.6, 0, 0, RGB ( 30, 190, 50));
          scooter (635 + 10*t, 510 - 5*t, 0.8, 0.8, TX_BLUE, TX_RED);

          t++;

          txSleep (50);
          }
    }


t = 0;                      - начальное значение времени
695 + 10*t - 695    - начальная координата х лягушки, 10 - скорость по х
635 + 10*t - 635    - начальная координата х самоката, 10 - скорость по х
485 - 5*t - 485       - начальная координата у лягушки, 5 - скорость по у
510 - 5*t - 510       - начальная координата у самоката, 5 - скорость по у
t++;                       - увеличиваем переменную t на 1.



    



Пример

Создадим мультфильм со следующими сценами:

Фон всех сцен:  елки.
Сцена 1 (MoveMosquito): Слева направо пролетает комар.
Сцена 2 (MoveFrog): Слева направо по диагонали проходит лягушка.
Сцена 3 (MoveFrogScooterMosquito): Лягушка справа налево по диагонали проезжает на самокате. За ней летит комар.
Сцена 4 (MoveFrogMosquito): Слева направо пролетает  красный комар и идет худая лягушка/

Посмотреть текст программы


Результат выполнения программы



Домашнее задание

Придумать сценарий мультфильма.
Разработать и написать не менее трех функций, каждая из которых реализует сцену с одновременным движением нескольких героев.