Войти
Playground SDKСтатьи

Настройки и рисование

Часть вторая, в которой мы сохраняем настройки, грузим текстуры и занимаемся анимацией.

Сохранение настроек
У нас периодически возникает необходимость не только запустить игру, но и продолжить с того-же места. Или сохранить текущие настройки. Для этого в движке предусмотрен специальный класс – TPrefs.
Этот класс сохраняет где надо (под Windows – в common appdata) файл с настройками. Файл сохраняется зашифрованным. Шифрование вроде бы не сложное, код указывает в настройках TPlatform. TPlatform::SetConfig, параметр TPlatform::kEncryptionKey, ключ должен иметь длину 12 символов, последние 3 должны быть AAA.
Настройки состоят из разных таблиц, указываемых в аргументах  методов как userIndex. По умолчанию есть только глобальный юзер, называемый TPrefs::kGlobalIndex. Сюда идут настройки, общие для всех юзеров. Каждый новый юзер добавляется путем установки ему любого параметра. Удаляется методом DeleteUser.
Настройки юзерам можно хранить любые, для чего существуют многочисленные Set и Get методы. Все параметры идут как пары «имя-значение».
Рисование
Рисование осуществляется в методе TWindow::Draw. Движок поддерживает как трехмерную, так и двухмерную графику. С 3Д я не работаю, да и не очень оно рекомендуется для казуальных игр, поэтому буду рассматривать 2Д.
Рисование осуществляется «как-есть», т.е. в какой последовательности мы рисуем – в такой оно и будет на экране. Все координаты задаются относительно текущего окна. Отвечает за рисование класс TRenderer, опять-таки синглетон. Но нам практически не придется его использовать, разве что для рисования всякой экзотики.
Большая часть графики рисуется посредством спрайтов, которыми мы сейчас и займемся.
Текстуры
Для начала нам нужно загрузить текстуры, на которых находятся наши спрайты. Базовый класс для текстуры - TTexture. Это просто текстура без наворотов. Почти любой подобный объект в движке имеет статический метод Get, возвращающий новую ссылку на объект. Менеджмент ресурсов встроенный, с подсчетом ссылок. Реализовано оно посредством boost::shared_ptr. У этого есть свои достоинства и недостатки. Достоинства – не надо думать о том, чтобы все освободить - оно само освободится. Недостатки – мы не можем казать «загрузи мне эти текстуры и держи их в памяти», такие вещи придется делать руками (вы же не хотите, чтобы на каждом чихе игры туда-сюда гонялся жесткий диск?).
В имени текстуры не обязательно даже задавать расширение – движок сам найдет нужный файл.
Текстуры бывают обычные и анимированные. Обычные – это одна картинка на кадр. Анимированные генерируются в специальном инструменте, filmstrip/sidewalk, и имеют раскладку по кадрам и одну или несколько анимаций. Анимированне текстуры – это класс TAnimatedTexture. На диске такая текстура хранится в виде xml-файла с описанием и png-файла с изображением.
Filmstip – визуальный инструмент для создания анимированных текстур. Все кадры будущей анимации должны быть помещены в одну папку, крайне желательно, чтобы имена были цифровыми – так гарантируется правильный порядок кадров. Затем указывается, куда сохранить готовую анимацию. В визуальном редакторе можно настроить разные вещи (параметры анимации, расставить по кадрам разные точки).
С помощью sidewalk мы можем перегенерировать текстуру при изменении исходных данных или сделать новую. Вообще, filmstrip для генерации текстур использует sidewalk. При использовании его из командной строки мы имеем доступ к несколько большим возможностям, вроде раскладывания готового изображения по 2-м файлам – цветовой канал в jpg, альфа – в png, недоступных из GUI.
Спрайты
Спрайты наследуются от базового спрайта – TSprite. Каждый спрайт – это собственно он и несколько подчиненных-child. Спрайты раскладываются по слоям и отрисовываются в подобающем порядке.
Спрайты создаются статическим методом TSprite::Create. В качестве аргументов указывается слой (по умолчанию – 0) и текстура (по умолчанию – пустая ссылка). Если спрайт не содержит текстуры – он не рисуется, но рисует child'ов. Этим можно пользоваться для создания нужной иерархии. Спрайт добавляется в отрисовку методом AddChild, убирается оттуда методом RemoveChild. Нельзя забывать удалить спрайт при удалении объекта – иначе «родитель» будет держать ссылку на него и на экране будет изображен уже давно убитый объект.
По идее, у нас на одно окно достаточно одного корневого спрайта, к которому цепляются все подчиненные. При этом в методе TWindow::Draw достаточно 2-х строк – переход в режим двухмерного рисования (создать на блок экземпляр TBegin2d) и вызвать метод Draw корневого спрайта. Все объекты будут нарисованы.
Само собой, что от спрайта можно наследовать свои классы для рисования чего-нибудь изначально непредусмотренного. Пример (не очень хороший, но достаточный, чтобы понять суть) есть в документации.
Так-же есть анимированные спрайты (TAnimatedSprite). Это те спрайты, которые были созданы инструментами. Отличия в том, что мы можем играть нужную анимацию или использовать их в качестве текстурного атласа, выставляя при отрисовке нужные кадры.
Параметры отрисовки
Теперь самое сложное в спрайтах – параметры отрисовки. У нас нет методов типа «подвинуть спрайт», «повернуть спрайт». Вместо этого есть класс TDrawSpec. В нем хранятся все параметры, влияющие на то, как и где будет происходить рисование. Самые используемые – mMatrix и mBlendMode,
Каждый спрайт имеет матрицу трансформации (3x3). Каждая строчка – TVec3. Предусмотрена нужгая вещь – у TVec3 есть конструктор, принимающий TVec2 и один свободный параметр. Чтобы переместить спрайт на какую-либо позицию, следует указать mMatrix[2] = TVec3(mPosition, 1.0f), где mPosition – TVec2.
Так-же мы должны указать способ блендинга. Это параметр mBlendMode, конкретные параметры – TRenderer::EBlendMode, В последней версии движка по умолчанию используется kBlendOpaque.
Есть еще разные флажки и параметры, но с ними можно уже без проблем разобраться самостоятельно.
Для передачи параметров в спрайт у последнего есть метод GetDrawSpec, возвращающий ссылку на TDrawSpec спрайта. С одной стороны может показаться странным, что нет ничего похожего на SetDrawSpec, но через некоторое время все становится понятно – это сделано, чтоб не плодить много строчек.
Анимируем окно.
Теперь нам нужно не просто нарисовать что-либо в окне, но и анимировать это. У нас нет методов типа «обновление по кадру» и «обновление 100 раз в секунду». мы можем сказать, что хотим, чтобы данное окно обновлялось не чаще, чем через N миллисекунд. Метод зовется TWindow:StartWindowAnimation. После этого начинаются вызовы OnTaskAnimate (который надо перегрузить) не чаще, чем через заданное время. Метод должен возвращать true, если надо обновит еще кадр и false, если более обновлять не надо.
Так-же при изменении на экране чего-либо нужно указать, что требуется перерисовка. Делается это для всего экрана метрдом TWindowManager::InvalidateScreen.

#tanimatedtexture, #tprefs, #tsprite, #ttexture

7 ноября 2007 (Обновление: 8 ноя. 2007)

Комментарии [4]