Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Перевод SDL Game Framework Series. Часть 5 — SDL Animation

Anna | 24.06.2014 | нет комментариев
Каждому здравствуй! Прошло достаточно много времени с момента перевода 4 части серии начальств по разработке игрового фрэймворка с поддержкой обширно знаменитой библиотеки SDL. Сейчас мой график немножко разгрузился и я готов продолжить (не последнее дело в этом сыграл Андрей Фирсов aka Vorobeez, тот, что дословно выдернул меня из делового потока своими вопросами «А когда же продолжение?!»). К тому же незадолго меня перевели в read-only, а так хочется восстановить вероятность комментирования постов…

В прошлом уроке мы попытались сделать знаменитую игру Крестики-Нолики. Верю, у большинства из вас попытки запуска игры были удачными, допустимо у кого-то даже получилось модифицировать и усовершенствовать написанный код (а кому-то это всё покажется детским лепетом). Даже если это не так, усердствуйте, пытайтесь, и в финальном выводе у вас всё получится.В этом уроке мы попытаемся проапгрейдить наши навыки, добавив в копилку реализацию анимации с поддержкой SDL. Как и раньше, мы будем базироваться на предыдущих уроках (но не на TicTacToe, это был обособленный резкий план). Думаю, пора начинать.

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

Создаем 2 новых файла CAnimation.h и CAnimation.cpp соответствено. В финальном выводе, когда мы будем создавать CEntity класс, он будет наследоваться от CAnimation, но теперь мы будем тестировать только один объект, тот, что мы сотворим чуть позднее. И раньше чем начать давайте добавим директиву включения#include «CAnimation.h» в CApp.h (желанно до #include «CEvent.h»).

Let’s make some code!

Открываем CAnimation.h, и добавляем следующие строки:

CAnimation.h

#ifndef _CANIMATION_H_
    #define _CANIMATION_H_

#include <SDL.h>

class CAnimation {
    private:
        int    CurrentFrame;

        int     FrameInc;

    private:
        int     FrameRate; //Milliseconds

        long    OldTime;

    public:
        int    MaxFrames;

        bool    Oscillate;

    public:
        CAnimation();

        void OnAnimate();

    public:
        void SetFrameRate(int Rate);

        void SetCurrentFrame(int Frame);

        int GetCurrentFrame();
};

#endif

А в CAnimation.cpp вписываем это:

CAnimation.cpp

#include "CAnimation.h"

CAnimation::CAnimation() {
    CurrentFrame    = 0;
    MaxFrames       = 0;
    FrameInc        = 1;

    FrameRate       = 100; //Milliseconds
    OldTime         = 0;

    Oscillate       = false;
}

void CAnimation::OnAnimate() {
    if(OldTime   FrameRate > SDL_GetTicks()) {
        return;
    }

    OldTime = SDL_GetTicks();

    CurrentFrame  = FrameInc;

    if(Oscillate) {
        if(FrameInc > 0) {
            if(CurrentFrame >= MaxFrames) {
                FrameInc = -FrameInc;
            }
        }else{
            if(CurrentFrame <= 0) {
                FrameInc = -FrameInc;
            }
        }
    }else{
        if(CurrentFrame >= MaxFrames) {
            CurrentFrame = 0;
        }
    }
}

void CAnimation::SetFrameRate(int Rate) {
    FrameRate = Rate;
}

void CAnimation::SetCurrentFrame(int Frame) {
    if(Frame < 0 || Frame >= MaxFrames) return;

    CurrentFrame = Frame;
}

int CAnimation::GetCurrentFrame() {
    return CurrentFrame;
}

Думаю стоит немножко рассказать о том что же всё-таки делает данный код. В геймдеве существует один стержневой элемент анимации, тот, что нам необходимо обрабатывать — нынешний кадр анимации. Посмотрите на изображение, которое мы будем применять в этом уроке. Как видите, у нас есть 8 кадров дракончика на одном изображении. Обращаться к нынешнему кадру мы будем по его порядковому номеру 1,2,… и отрисовывать его.

Помните, во втором уроке, мы сотворили функцию, Дабы отрисовывать часть изображения? Осталось применить её вкупе с нашим кадром анимации, и вуаля!

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

CSurface::OnDraw(Surf_Display, Surf_Image, 0, 0, Ezhik.GetCurrentFrame() * 64, 0, 64, 64);

Когда CurrentFrame возрастает на 1, мы каждого лишь смещаемся на 64 пикселя вправо по изображению (размер кадра), и рисуем данный кадр.

Как вы теснее додумались, MaxFrames уведомляет нам о том, сколько каждого кадров анимации у нас имеется. Ну и напоследок нам необходимо знать, сколько кадров в секунду у нас отрисовывается, а вернее, как стремительно эта анимация будет отображаться (да, да, тот самый знаменитый FPS). Определение частоты отрисовки запрограммировано в способе OnAnimate:

if(OldTime   FrameRate > SDL_GetTicks()) {
    return;
}

Складывая ветхое значение времени прошедшего с момента работы SDL и желаемой частоты кадров, мы можем сравнить его с тем временем, которое определяет сколько времени теснее работает SDL (нынешнее). Разжую: возможен, мы только запустили нашу программу. SDL_GetTicks возвращает 0, и OldTime безусловно тоже равен 0. Примем как данность что желаемая частота кадров составляет 1 кадр в секунду. Т.о. FrameRate = 1000 (миллисекунды). Выходит, 0 1000 огромнее 0? Да, т.е. нам нужно пропустить данный такт и ожидать дальнейшего. Но на дальнейшем такте 0 1000 поменьше SDL_GetTicks, это должно обозначать, что 1 секунда прошла. Таким образом, мы увеличиваем значение кадра, а после этого сбрасываем значение OldTime на нынешнее временя, и запускаем проверку вначале. Думаю сейчас больше ясно как это всё работает.

А вот сейчас расскажу про Oscillate и FrameInc. Не то, Дабы я хотел вас запутать, добавив всё это, скорее напротив, следственно покажу, для чего это нужно. В всеобщем и целом, когда Oscillate выставлено в true, класс анимации будет увеличить кадры до достижения максимального числа кадров, а после этого сокращать. Если бы у нас было 10 кадров, к примеру, то мы отслеживали бы что-то как бы этого: 0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1 2… (CurrentFrame). Мы проходим каждый путь от 0 до 9 а после этого спускаемся в обратном порядке. Всё предельно легко! В дальнейшем уроке я покажу увлекательный метод применения каждого этого. Как же это работает? Давайте взглянем на OnAnimate чуть пристальнее.

Про OldTime и его призвание мы в курсе, а что с остальными кусками кода? Приглядимся к проверке значенияOscillate. Внутри мы легко проверяем достигло ли CurrentFrame максимального числа кадров. Если да, сбрасываем CurrentFrame обратно в 0.

Думаю что задав Oscillate значение true у нас будет больше плавное отображение анимации! А вы как считаете? Давайте разглядим призвание FrameInc. Значение FrameInc задаётся равным либо 1 либо -1, в зависимости от того необходимо ли нам идти по кадрам в ту либо другую сторону (сокращать либо увеличивать). То есть если FrameInc огромнее 0, мы начинаем инкрементировать кадры, в отвратном случае применяем декремент. Таким образом мы попеременно достигаем либо 0 либо значения MaxFrames, что, как мне кажется, гораздо больше прекрасно (по крайней мере нет жёсткого сброса CurrentFrame в 0).

Финишная черта

Сейчас соберем всё вместе! Необходимо сделать оъект класса CAnimation в CApp.h:

CAnimation      Anim_Yoshi;

Зададим значение MaxFrames, внутри CApp_OnInit:

Anim_Yoshi.MaxFrames = 8;

Если вам необходима анимация от 0 кадра до 7 и обратно, задаем:

Anim_Yoshi.Oscillate = true;

Заставим анимироваться Йожи внутри CApp_OnLoop:

Anim_Yoshi.OnAnimate();

И безусловно, Дабы насладиться анимацией, необходимо её посмотреть, добавив в CApp_OnRender:

CSurface::OnDraw(Surf_Display, Surf_Test, 290, 220, Anim_Yoshi.GetCurrentFrame() * 64, 0, 64, 64);

Ну вот и всё! Скомпилируйте наш обновлённый план и запустите! Не позабудьте скачать картинку из этой статьи, потому что в подлинной кадры в столбик, что, ИМХО, уродливо смотрится. И ещё пара моментов. От того что картинка .PNG, необходимо применять IMG_Load (в предыдущих статьях я писал про эту функцию) и подключить к плану библиотеку ключом -lSDL_image. Также, испробуйте отключить у Йожи данный нервирующий розовый цвет (как это сделать тоже дозволено посмотреть в прошлых статьях). Фуроров вам, в нелегком труде GameDeveloper’a! Верю эти статьи помогают…

Ссылки на начальный код:

Ссылки на все уроки:

 

Источник: programmingmaster.ru

 

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB