Но на самом деле, мне бы хотелось поговорить о том какая это «тяжкая» работа писать мобильные приложения на Qt… Разберём простой пример.
Итак. Имеем поздний апрель, 4 подряд пары какой-то практики, мобилка с симбой и несколько скучающих приколистов. И тут приходит в одну из голов гениальная в своей абсурдности идея! «Как быть если рядом оказались чоткие пацанчики и не оказалось семок? Не поймут ведь, если с ними не полузгаешь!». Тьфу, делов то… Ставим Qt SDK, быстренько запускаем Qt Creator и создаём новый проект (причём Desktop-приложение). Распараллеливаем работу, пока мы строгаем три панельки (меню, игра, результаты) чуваки за соседним компом рисуют кирпичную стену и изображение семечки — целую и разлузганную. А так же подбирают подходящий саундтрек…
Как это происходит… (Скрины я конечно делал только что)
По архитектуре приложение конечно же получается простейшее, но от этого не менее весёлое. Всего то три класса:
QSlidingStackedWidget - для красивого переключения между тремя панельками (теми самыми Меню. Игра, Результаты)
MainWgt - без мудрствования лукавого просто запихиваем всю логику в главный виджет.
SemkoItem - производная от QGraphicsPixmapItem, для отображения отдельно взятой семки, управления её полётом и прочее.
Рассказывать о реализации меню и результатов думаю не стоит, достаточно упомянуть что оно работает и вполне себе хранит количество слузганых семок тем или иным игроком.
А вот о самой игре, капельку упомянем. По сути, это QGraphicsView + QGraphicsScene, таймер динамически создающий новые семечки, класс отдельно летящей семечки следящий за своим падением, анимирующий сам себя. реагирующий на события и наконец следящий за своими координатами чтобы успеть самого себя уничтожить при уходе за границы видимости и великий рандом. Выглядит достаточно прозаично…
Начинаем игру:
void MainWgt::startGame()
{
if (isSound()){
moMainTheme->play();
}
placeSemkoTimer->stop();
placeTimerInterval = 1000;
placeSemkoTimer->setInterval(placeTimerInterval);
nextLevelCount = nextLevelIncrement;
semkoInterval = 30;
scene->setSceneRect(0, 0, 10, 10);
ui->lcdSluzgano->display(0);
ui->lcdUnluzged->display ( lives );
placeSemkoTimer->start();
}
Вбрасываем семечку по таймеру:
void MainWgt::placeSemko()
{
SemkoItem *semko = new SemkoItem(scene, semkoInterval);
connect(semko, SIGNAL(luzg()),this,SLOT(luzg()));
connect(semko, SIGNAL(unluzged()),this,SLOT(unluzged()));
connect(this, SIGNAL(nextLevel()),semko,SLOT(nextLevel()));
connect(this, SIGNAL(gameOver(bool)),semko,SLOT(gameOver(bool)));
scene->addItem(semko);
}
И обрабабатываем каждое попадание
void MainWgt::luzg()
{
int c = ui->lcdSluzgano->intValue() + 1;
if ( c >= nextLevelCount ){
nextLevelCount += nextLevelIncrement;
semkoInterval -= 3;
if (semkoInterval <= semkoIntervalMin){
semkoInterval = semkoIntervalMin;
}
int livesAdd = ui->lcdUnluzged->intValue() + 3;
ui->lcdUnluzged->display ( livesAdd );
placeTimerInterval = placeTimerInterval - placeTimerIntervalDecrement;
if (placeTimerInterval <= placeTimerIntervalMin){
placeTimerInterval = placeTimerIntervalMin;
}
placeSemkoTimer->stop();
placeSemkoTimer->setInterval(placeTimerInterval);
placeSemkoTimer->start();
emit nextLevel();
}
ui->lcdSluzgano->display ( c );
}
В этот момент как видно мы ещё и глядим на то сколько семок уже слузгано и не пора ли переходить на следущий уровень (а стало быть увеличить скорость сброса и падения).
Ну и что там ещё интересного есть… Да по сути ничего особенного… Итак, запускаем, тетстим, подправляем параметры, устраняем недочёты, прикручиваем музыку (группе Глом и Кураж-Бамбею кстати спасибо) и начинаем баловаться…
Менюшка…
Игрушка…
И не смотрите на такой некрасивый LCD снизу, в телефоне он каваен…
«Уууу б..!» — сказала толпа бездельников ближе к концу третьей пары, взглянув на то что получается. «Ага б..!» — заметил самый нетерпеливый, — «И как мне теперь сидеть на корточках и тыкать мышкой. смотря в монитор? Неудобно же!»
«Херня война, главное манёвры!» — промямлил главный девелопер (то бишь я) и решительно перешёл к портированию… Ох как это было сложно и долго… Аж минут 15 =).
Схема:
1) Втыкаем девайс в режиме PC Suite
2) Ставим на него Qt, пользуя для этого установленный на ПК Ovi Suite
3) Добавляем в креаторе новый вариант сборки нашего приложения
4) Выбираем Release версию и жмякаем запустить
Собственно всё, остаётся дождаться пока прогармма соберётся и на дисплее смартфона радостно появится менюшка запуска нашего приложения.
Итак. Что же в итоге? За каких то пару часов с помощью Qt можно быстро наклепать вполне играбельную фиговину, готовую для работы под всеми десктопными платформами и кроме того легко запускающейся из среды разработки на устройстве. Что примечательно, в Maemo и в Android-порте всё запускается аналогично симбиану, без лишних плясок с бубном. Легко? Думаю да. Изящно? Несомненно! =)
По самому проекту:
Страничка
Репозиторий
Версия для Symbian 9.4. Для установки коенчно же требуется предварительно поставить Qt.
Кстати да… Всё делалось на чистом C++, без использования QML. И тем не менее получилось быстро и прикольно. очень хотелось бы чтобы Qt таки стала более популярной платформой, вероятно после выхода 5.0 так и будет…
UPD:
Скажем дружное спасибо товарищу obramko за замечательный порт игрушки на Android…
Скриншот: