19. Фазовая анимация

Занятие 19


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

На прошлом занятии мы создали движущиеся изображения зайца, солнышка и привидения. Но, увы, мы получили изображения зайца. который не ходит по полянке, а "тянется", так как у него не двигаются ноги, уши и так далее. Хотелось бы сделать движение более реалистичным. Вспомним, каким образом мы выводили на экран изображение зайца:

txTransparentBlt (txDC(), hero.x, hero.y, hero.sizeX, hero.sizeY, hero.image, 0, 0, RGB (3, 79, 42));

hero.x, hero.y                 - координаты зайца
hero.sizeX, hero.sizeY   - размер картинки с зайцем по ширине и высоте
hero.image                     - картинка с изображением зайца
RGB (3, 79, 42)             - цвет фона, который должен быть убран

Что же означали числа 0, 0? Это отступ по горизонтали и вертикали, если мы хоти указать только часть картинки, например, если мы укажем:

txTransparentBlt (txDC(), hero.x, hero.y, hero.sizeX - 20, hero.sizeY - 20, hero.image, 20, 20, RGB (3, 79, 42));


то получим следующий эффект:



На экран выводится не вся картинка, а только ее часть, которая обрезает ее по горизонтали и вертикали на 20 пикселей.


Как же это можно использовать в нашей программе?

Введем параметр, который отвечает за время:

int t = 0;

Будем передавать его в функцию рисования героев:

DrawHero (Hare, t);
DrawHero (Sun, t);
DrawHero (Ghost, t);

Время будем увеличивать:

t++;

Запишем команду рисования героя, которая зависит от переменной t, причем изменять картинку будем только по горизонтали, изменяя ее размер от sizeX до 0:

txTransparentBlt (txDC(), hero.x, hero.y, hero.sizeX - t % hero.sizeX , hero.sizeY, hero.image, t % hero.sizeX,  0, RGB (3, 79, 42));

Получим:


Как видим, получили эффект "стирания" картинки.

Как же используя данный эффект, создать анимированного героя?

В графическом редакторе (например, Photoshop) откроем картинку с нашим героем:


Размер нашей картинки 120 на 175, создадим анимацию из шести различных положений зайца, для этого увеличим холст по горизонтали в шесть раз: 

Изображение - Размер холста


Скопируем изображение зайца (Ctrl + C) и вставим 5 раз (Ctrl + V), распределим все копии на холсте. Внесем в каждое изображение изменения, имитируя движение зайца:


А теперь, в зависимости от времени будем показывать все 6 картинок по очереди, для этого при изменении t будем изменять область показа картинки на ее размер по горизонтали: hero.sizeX.

txTransparentBlt (txDC(), hero.x, hero.y, hero.sizeX, hero.sizeY, hero.image, t % 6 * hero.sizeX ,  0, RGB (3, 79, 42));

В результате:



В данном случае у нас заяц движется вправо, для того, чтобы заяц двигался влево, добавим еще один ряд картинок. Для этого увеличим холст по вертикали на 350, скопируем все наши картинки, вставим и отразим нижний ряд по горизонтали (Редактирование - Транспонирование - Отразить по горизонтали).

Получим:


Получается, если мы нажимаем клавишу вправо или герой движется вправо, то скорость vx > 0, если игрок движется влево, то vx < 0. И, если vx > 0, то показываем верхний ряд (сдвиг по у =  0), если vx < 0, то показываем второй ряд (сдвиг по у равен sizeY).

Функция рисования героя будет выглядеть так:

void DrawHero (Character hero, int t)
    {
    int shift = 0; // показываем верхний ряд
    if  (hero.vx <  0) shift =  1;  // показываем нижний  ряд
    txTransparentBlt (txDC(), hero.x, hero.y, hero.sizeX, hero.sizeY, hero.image, t % 6 * hero.sizeX, shift * hero.sizeY, RGB (3, 79, 42));
    }

Аналогично создадим картинки для привидения и солнца.



Как видим, у привидения и солнца четыре картинки по горизонтали и один ряд по вертикали.
Добавим в структуру героя параметры, которые отвечают за количество фаз движения по горизонтали и вертикали:

struct Character
    {
    double  x,  y;
    double vx, vy;
    double ax, ay;
    int sizeX, sizeY;
    int phasesX;
    int phasesY;
    HDC image;
    };

Рисование героя:


void DrawHero (Character hero, int t)
    {
    int shift = 0;
    if (hero.phasesY == 2)
       shift = (hero.vx <= 0) ? 0 : 1;
    txTransparentBlt (txDC(), hero.x, hero.y, hero.sizeX, hero.sizeY, hero.image, t % (hero.phasesX) * hero.sizeX, shift * hero.sizeY, RGB (3, 79, 42));
    }


Пример

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

Файлы изображений

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

Результат работы программы


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

Внести изменения в вашу предыдущую программу, реализовав для всех героев фазовую анимацию.