Search
Write a publication
Pull to refresh

Первый опыт или создание приложения с помощью MIDletPascal

Преамбула



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

Фабула



Опыта написания программ для телефона у меня не было, как и вопроса «чем писать?» — уже давно хотелось попробовать в деле MIDLet Pascal. Сказано — сделано, но тут меня поджидало несколько подводных камней.

Версии MIDlet Pascal


На данный момент существует две версии IDE: оригинальная 2.02 и полностью свободная 3.2 (далее буду именовать как 2-я и 3-я ветки).
Для написания программ для меня удобнее оказалась 3-я ветка: нормальная настраиваемая подсветка синтаксиса и внешнего вида IDE, поддержка переводов интерфейса, человеческая история файлов и т.д. Но, если быть честным, писать код в Notepad++ ничуть не хуже, чем в обеих ветках, потому что ни там ни тут нет автодополнения.
Зато есть простейшие редакторы ресурсов. Причем во второй ветке простой и удобный редактор картинок (я все иконки для проекта нарисовал в нем), но нет HEX-редактора, а в 3-й ветке — неплохой HEX-редактор при отвратительном графическом.
От 3-й ветки мне всё равно пришлось отказаться по нескольким причинам. Первая и главная — абсолютно не работают сторонние библиотеки, которые работают во 2-й ветке. Вторая — компилятор 3-й ветки падает при сборке проекта, если в проекте используются строки на русском языке.
Сначала я пробовал писать программу в 3-й версии, а собирать во 2-й, но мне это быстро надоело и я полностью перебрался на 2-ю ветку.

Для сравнения приложу скриншоты обеих версий:



Написание программы


Так как я ни разу не брался за j2me и даже не интересовался что это и с чем едят, то и работа с MIDlet Pascal для меня началась с разбора азов. Примитивные примеры из серии «Hello, World!» быстро дали понять — будет не слишком просто. Для меня стало открытием, что любая программа так или иначе выполняется исключительно в циклах, внутри которых происходит обработка прерываний, вызванных событиями, нажатиями кнопок и т.д.

Простейший пример программы в цикле:

  1.  
  2.  program Test;
  3.  
  4.  { объявляем переменные}
  5.  var
  6.    k: integer;
  7.    s: string;
  8.  
  9.  { основное тело программы }
  10.  begin
  11.    { задаем цвет в формате RGB }
  12.    SetColor(255, 0, 0);
  13.    s := 'Hello, Word!';
  14.    { рисуем текст в середине экрана в буфере! }
  15.    DrawText(s, GetWidth/2 - GetStringWidth(s)/2, GetHeight/2 - GetStringHeight(s)/2);
  16.    { отрисовываем на экране }
  17.    Repaint;
  18.    repeat
  19.      k := GetKeyClicked; // ловим нажатие клавиши
  20.      Delay(100);         // задержка
  21.    until KeyToAction(k) = GA_FIRE; // ждем нажатия на ОК
  22.  end.
  23.  


Если заменить блок repeat на Delay (1000), то программа закроется сама через одну секунду работы.

Язык MIDlet Pascal напоминает усеченный pascal.

Поддерживаемые типы данных:

* boolean
* char
* integer
* real
* string
* image
* command
* recordStore
* http
* resource

Комплексные типы:

* records
* arrays

Объекты не поддерживаются. Можно писать свои процедуры и функции. Нет привычных по Delphi конструкций with, case и прочих. По спартански, но и этого достаточно. Как написал кто-то на форуме по мидлетпаскалю: «В мидлетпаскале базово реализовано всё что нужно для написания программ» и я с этим полностью согласен.

Принципы работы


Любая программа может работать в 2-х режимах — графическом и «режиме формы“. В первом случае мы всё рисуем сами в буфере телефона, а потом выводим на экран, во втором мы указываем компоненты формы, их последовательность, но внешний вид формы уже будет зависеть от конкретной модели телефона. У меня Fly MC300, а у друга — Nokia 3720. Приложения в режиме формы выглядят различно. Субъективно, у Nokia гораздо удобнее и качественнее.
Чтобы избежать непредсказуемости внешнего вида, надо использовать графический режим (который в MIDlet Pascal по умолчанию), но следует помнить, что простейшие вещи проще реализовать в режиме формы, чем в графическом режиме. В графическом режиме необходимо всё рисовать самому, а в режиме формы это делает за вас телефон.
Переключение между режимами производится командами:

ShowCanvas
ShowForm

Библиотеки


Для упрощения реализации различных типовых задач энтузиастами было написано много подключаемых библиотек. Со списком и инструкциями к применению можно ознакомиться тут.
В моем проекте были использованы библиотеки menu32 и font32. Первая служит для организации простого меню, а вторая — для вывода рисованного текста. Menu32 использует для своей работы font32 (и такое бывает). Font32 работает со шрифтом, описание которого содержится в 2-х файлах, один из которых представляет из себя картинку формата png со всеми символами, выведенными в строку, и dat файл со смещениями по оси Х, обозначающими границы букв. Подобную связку файлов можно получить с помощью специальной программы-генератора, которую можно взять в ветке форума, посвященного font32. Хорошо читаемые шрифты получаются только из растровых шрифтов, результат преобразования векторных шрифтов требует обязательной правки обоих файлов, потому что буквы наползают друг на друга, а dat файл содержит неверные смещения.
Мне было лень заниматься правкой, поэтому я использовал растровые шрифты: MS Sans Serif и Small Fonts.

Проблемы и их решения


Проблем было не много, но они были. Первой, поставившей в тупик, стала задача нахождения координат точки пересечения двух прямых. Задача крайне тривиальная и успешно решается еще в средней школе, но оказалось, что я полностью забыл элементарную геометрию — даже уравнение прямой вспомнилось с большим трудом. Пришлось немного погуглить и найти решение.
Вторая проблема возникла при обработке нажатий клавиш. Дело в том, что для определения нажатой клавиши есть две функции: GetKeyClicked и GetKeyPressed, которые возвращают код клавиши, а так же существует функция KeyToAction, возвращающая код действия клавиши. Я не знаю является ли это особенностью именно MIDlet Pascal или всей jme платформы в целом, но реализация работы с клавиатурой реализована следующим образом: первые две функции возвращают коды клавиш, соответствующие цифровой клавиатуре, а третья функция возвращает коды, соответствующие нажатию джойстика.

  1.  
  2. program KeyBoardTest;
  3.  
  4. var
  5.   k, ka: integer;
  6.  
  7. begin
  8.   repeat  
  9.     k  := GetKeyClicked;
  10.     ka := KeyToAction(k);
  11.     Delay(100);
  12.   until ka = GA_FIRE;  
  13. end.  
  14.  


Данная маленькая программа проверяет нажатие клавиатуры и если была нажата клавиша ОК (обычно это середина джойстика) — закрывается. Подводный камень кроется в том, что на различных телефонах нажатие клавиш может отрабатываться по разному. Например, на моем Fly нажатия на кнопки 2, 4, 6, 8 и 5 генерят еще и коды действия джойстика, чего не делает протестированная Nokia. А так как обработка нажатий происходит в цикле когда обрабатываются коды клавиш и действия, то может возникнуть вариант, когда произойдет лишняя обработка события, связанного с действием. Лечится cия беда двумя способами: при отлове срабатывания клавиши присваивать значение переменой k несуществующий код клавиши (KE_NONE) и/или обрабатывать нажатия клавиш по кодам. Например для телефонов Nokia и SonyEricsson нажатие джойстика соответсвует коду "-5», но есть и обратная сторона медали — коды, возвращаемые при нажатии, могут отличаться у телефонов различных марок. К счастью, у Nokia и SonyEricsson коды совпадают.
Приведенные выше функции возвращают коды, соответствующие псевдонимам клавиш/действий, но список этот неполный и не содержит софт клавиш, кнопки стирания и т.д. Коды подобных клавиш были получены энтузиастами опытным путем, но не для не всех производителей телефонов.

Программа


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

Несколько скриншотов:



Особенности работы

Перемещение по пуле происходит последовательно, начиная с игрока запад, против часовой стрелки, путем нажатия джойстика вверх или вниз. Ввод значений происходит по нажатию клавиши ОК. Результаты начинают выводиться только тогда, когда у всех игроков введено хотя-бы по одному значению. Функцию левой софт клавиши так же выполняет звездочка.
Программа не поддерживает сенсорные экраны, потому что у меня нет возможности протестировать работу с сенсором, да и не представляю я как производить ввод цифр без кнопок.

Скачать исходники и саму программу
Исходники предназначены для изучения и их можно подвергать любой переработке, какая вам заблагорассудится. Так как писалось всё для себя, то код далеко не идеален. Наверняка можно всё подшерстить и кое-что переделать, оптимизировать и т.д., но мне лень.

Послесловие


В качестве эмулятора использовался Sun Java Wireless Toolkit 2.5.2 for CLDC.
На полное написание программы в свободное от работы-жены-ребенка время понадобилось три дня. Сам процесс написания крайне занимателен, потому что средств отладки нет, всё приходится лепить самому на коленке. Кривули IDE тоже ставят палки в колеса, но всё равно интересно. Программировал я в свое удовольствие, поставленную задачу благополучно решил, заработал +5 к опыту.
Очень хотелось бы увидеть в будущем MIDlet Pacal 3-й, а может уже и 4-й ветки, но с нормально работающим компилятором, поддержкой уже существующих библиотек и всех положительных моментов 2-й ветки. Долгой жизни проекту, если в общем, ведь где еще можно найти среду разработки jme программ объемом в 2 мегабайта?
Отдельная благодарность всем обитателям форума forum.boolean.name за примеры и информацию.
Благодарю за внимание!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.