Утилитка для восстановления русского текста, который портят IDE Blitzmax.

Сегодня случилось страшное: мои коменты на русском попортило стандартное ИДЕ. Я обычно его не пользую, но вот решил написать пару небольших тестов, чтобы определиться с методами. И когда я открыл файлы снова, то был сильно огорчен подменой руссокого текста в комментариях со статистикой по быстродействию, несуразным набором символов. Ситуацию пришлось исправлять и писать преобразователь полученных в ИДЕ кракозябров обратно в русский текст. Тому, кто столкнулся с подобной проблемой, эта утилитка пригодится: http://blitzmax.3dn.ru/load/6-1-0-1

Новости 25-06-2006

Я таки решил не откладывать переход к сайту и сегодня попытался поработать с юкозом. Кое-что получилось. Правда с утра все жутко тормозило. Сначала админка, потом сам сайт. Так что пол дня я просто тупо провтыкал, наблюдая разные ошибки 505 и прочие и ожидая сообщений сервера. Правда после обеда вроде все наладилось. И я передумал забить на него сразу. Я добавил первую статью про главный игровой цикл, как обещал в предыдущем посте. Подправил недостатки в связи с комментом к предыдущему посту.
Теперь про новый сайт. Адрес: http://blitzmax.3dn.ru
Я сделал опрос, чтобы не занимать много вашего времени. Просто проголосуйте насколько хорошо работает юкоз. Если все нормально, то я продолжу на нем. Поскольку там возможностей и удобностей больше. От рейтинга и пользовательских аккаутнов, до новостей, файлов и форума. Если нет - буду продолжать здесь. Но, наверное, изменю формат постов или еще как-то извернусь. Я заметил, некоторые добавили блог в РСС, на юкозе не спешите - я подумаю как это лучше организовать. Скорее через ленту новостей - я постараюсь в ней отражать все изменения. Поскольку там несколько лент для каждой категории. Если есть еще какие пожелания - прошу высказываться. Также если не сильно лень - прошу зарегистрироваться на сайте, посмотреть возможности и отписаться с комментами и пожеланиями.
зы: если с юкозом все будет норм, то в течении недели я туда перенесу материалы.
ззы: тут пара людей спрашивала насчет партиклов. Я несколько морозился, сейчас скажу поточнее: старая система сильно интегрирована в двиг, вырезать ее оттуда нет ни времени, ни желания. Новая еще в стадии проектирования. Когда я ее допишу до приемлимого вида, то скажу как ее можно получить.

Изменения и дополнения

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

Неприятное в BlitzMax, ч.3 - разработка игр

3.1. Нет поддержки шрифтов с произвольной шириной и утилит для работы с ними. Моноширинные - это вчерашний день.

3.2. Нет зачатков даже движка как в Blitz3D. Есть просто набор либ для работы с сетью, звуком графикой и устройствами ввода (мышь, клавиатура, джойстик). Джентльменский набор, но "ни цента больше".

3.3. Нет и намека на партиклы. О редакторе молчу, хотя бы классы или либы для работы с ними были какие-то. А современный уровень игростроения их требует. Все надо делать самому - опять время/деньги. Хотя есть пара сторонних убогих движков частиц. И даже с редакторами.

3.4. ГУИ. Игровое конечно. Опять полное отсутствие. Хотя тут проще - есть сторонние библиотеки. И даже бесплатные.

3.5. Нет поддержки треккерных форматов звука. Но можно использовать сторонние библиотеки.

3.6. Нет физики. Есть сторонние модули.

Неприятное в BlitzMax, ч.2 - библиотеки

2.1. Нет списка со значениями, не являющимися объектами. Например, целыми - Int.

2.2. Списки не очень удобно реализованы. Было бы хорошо наличие у элементов списка TLink поля Parent, для ссылки на родительский список (И поля Child для многоуровневых древовидных списков). Это связано с менеджером памяти языка, который не в состоянии корректно удалять объекты с кросслинками.

2.3. Утечка памяти в функции LoadImage при загрузке *.png. Ее практически не заметно, т.к. вылазит она при особых случаях, например при перегрузке картинок, что обычно не требуется - они загружаются один раз обычно. Но, например, при отсутствии менеджера ресурсов, когда нам нужно перезагружать изображение (при обработке скриптов, например), то утечка становится заметной. Причем внутренний меденжер памяти утечку не показывает.
Прим.: при загрузке *.jpg утечки нет.

2.4. При создании нового pixmap, он не инициализируется. Т.е. мы создали новый pixmap, а там мешанина из пикселов, а не черный или белый или заданный программистом фон. Надо писать функции заполнения новообразованных пиксмапов, а это - время/деньги.

2.5. Неясности со шрифтами: LoadImageFont("Arial.ttf"…) не приводит к ожидаемому результату, а с полным путем LoadImageFont("C:\Windows\Fonts\Arial.ttf"…) все работает. Хотелось бы без указания путей. Хоть и есть фонт по умолчанию.

2.6. Отсутствие такого хорошего понятия как контекст устройства. Есть в вынь и в пурике ( StartDrawing(OutputID) ). На CreateGraphics(…) его заменить нельзя - если разрешение не поддерживается, контекст не создается. Это очень-очень плохо. Нельзя рисовать нормально в оффскрин окно. Другими словами рисовать в текстуру (спрайт) можно только ручками через массив пикселей, что медленно. Сторонние библиотеки для этого - платные.

2.7. Метод pixmap. Paste(…) не проверяет размеры - это приводит к глюкам с затиранием памяти и необходимостью писать много чего своими ручками. Это unsafe (при том, что полезные вещи в страхе этого самого unsafe не делаются), и время/деньги на дополнительный код.

2.8. Глючность идиотическая, надеялся, что такого не встречу. Пример: когда работа с пиксмапами формата PF_RGBA8888 проходит отлично, а смена формата на PF_BGRA8888 приводит к непонятным глюкам в официальных библиотечных функциях.

2.9. Глюки при работе с созданием пиксмапов, если их делаешь много, то возникает глюк. Этот глюк как-то связан с форматом картинки. При формате PF_BGRA8888 он возникает раньше. GCCollect() не помогает, дело не в переполнении, а хз в чем.

2.10. Звук: Полная распаковка/загрузка в память, потом проигрывание. Это приводит к тому, что мы в программе уже запустили звук на проигрывание, а оно начинается позже - после полной распаковки. Это заметно даже на не сильно больших звуках, не треках. Сначала было совсем жестко - распаковка была не в отдельном процессе и можно было нарваться на притормаживания при попытках проиграть звук. Сейчас сделали распаковку в фоне (отдельным процессом). Этим убрались притормаживания всего приложения при проигрывании. Но остались паузы между желаемым началом проигрывания (вызовом в коде) и реальным началом, когда уже слышен звук.
При этом фоновая распаковка породила другую проблему. Тормоза при не фоновой распаковке можно было обойти правильной организацией ресурсов. Загрузкой и распаковкой звуков в начале игры или уровня, когда можно и подождать. Таким образом, при самой игре звуки проигрывались уже распакованные из памяти, не вызывая никаких нареканий. Теперь при такой организации, если приложение загрузилось достаточно быстро, а звуки в фоне не распаковались, то опять есть паузы в начале работы, между тем, когда звук должен проиграться и когда он звучит на самом деле. Вылез теперь немного иной недостаток - невозможность узнать, когда звук распакован, чтобы дождаться полной загрузки ресурсов.
Правильнее бы делать блочную распаковку/загрузку и проигрывание. Как в винампе, например. Когда подгружается кусок и распаковывается быстро и играется сразу, незаметно для слуха. А потом в фоне догружаются остальные части.

Неприятное в BlitzMax, ч.1 - язык

1.1. Отсутствие перегрузки функций. Это большое зло. Это надо, это сокращает время для написания кода. Плюс этот недостаток порождает целый ряд других.
Пример:
Нужен менеджер ресурсов. Там нужен такой метод LoadRes(target:TypeOfResource var, url$). Вот при перегрузке функций, нужная функция в зависимости от типа нужного ресурса будет подставляться на этапе сборки. А без перегрузки я должен: первое - писать свой обработчик по типу ресурса (если сделать одну функцию с параметром типа общего объекта - Object) - тратить свое время на лишний код! И второе - этот код будет выполняться во время работы процесса, что будет снижать быстродействие! Уже два ОГРОМЕННЫХ МИНУСА!
Можно обойти это немного, конкретизировав методы загрузки ( LoadImage(url$), LoadSound(url$) ), но это немного снизит удобство. Т.к. для каждого ресурса надо будет помнить свою функцию.

1.2. Отсутствие конструкторов с параметрами. Писать функции для создания классов - не очень то и удобно с точки зрения поддержки и развития кода. - Их ведь нельзя наследовать и п1 - нельзя перегружать. Делать для инициализации статические методы (тоже что и функции по сути) при наличии потомков - тоже неудачно и упирается в отсутствие перегрузки функций и методов - см.сл.п.

1.3. Неправильная или глючная поддержка в потомках возвращаемых значений методов. Т.е. в потомке нельзя переопределить тип возвращаемого значения. Оно логично со второго раза, а с третьего - видно, что не менее логично, если тип возвращаемого значения - объект, то в методе потомка можно возвращать потомка от исходного значения-объекта. Чем плохо конкретно - тем, что нельзя писать одноименные методы-конструкторы для потомков и предков красиво и без извратов (приведения типов, что делает код громоздким и невыразительным). А так же методы копирования. Т.е., по сути, нет перегрузки методов (и функций), что неудобно.

1.4. Невозможность создания указателей на типы пользователя. Например я сделал тип TRGBA_Color с полями R, G, В, и А соответсвенно для цветов и прозрачности. Сделать так я не могу:
Local p:TRGBA_Color Ptr = TRGBA_Color Ptr(bmp.PixelPtr(0,0))
Т.е. получить указатель на пикселы и работать с ним красиво - p.R = 100. Приходится делать это указателем на байты, что с ЯП высокого уровня не очень то и ассоциируется. Похоже, это связано с тем, что каждый тип является объектом и переменная этого типа уже и есть указатель на объект и заботой о защите памяти (только safe - функционал). Приведение типов или индексный доступ, конечно, не защищены от "дурака" - прогламмера (unsafe - функционал), но позволяют "не дураку" нормально и удобно работать.

1.5. Нет команды SinCos, которая поддерживается новыми процессорами и позволяет быстрее производить операции просчета вращения и т.п., т.к. обычно надо и синус и косинус угла, а одной командой это явно сделать быстрее, чем двумя.

1.6. Статический step в циклах. Иногда надо, чтобы при проходе по массиву приращение индекса менялось. Приходится делать через while/wend.

1.7. Нет оператора With. Можно сделать аналог, но это увеличивает громоздкость кода.

1.8. Система слежения за освободившейся памятью (менеджер памяти языка) и автоматическим удалением не нужных уже объектов, хоть и хороша и удобна, но не совершенна. И порой возникали утечки из-за перекрестных ссылок (кросслинков). Т.е. все равно приходится следить за корректной очисткой памяти, что отвлекает от основного процесса написания кода, увеличивает объем текста программы и в сумме эти два фактора приводят к увеличению времени написания программы. Плюс это не характерно для ЯП высокого уровня - менеджер памяти должен быть на высоте. Так что это получается что-то среднее между ЯП высокого и среднего уровней.
Утечки возникают даже не при кросс-линках а и в ситуациях, когда возникать не должны. Например: объект-контейнер, содержит в себе список других объектов. Объекты содержат поле с линком на элемент списка типа TLink, - не на сам контейнер. На этот контейнер ссылается глобальная переменная, поэтому он и "живет". Глюк: если в методе объекта из списка контейнера глобальная переменная переопределяется (в "пусто" или другой контейнер), то память не очищается! Контейнер не удаляется! При освобождении объекта в другом месте - все нормально и память освобождается. Глюк лечится, если объект из контейнера при переопределении глобальной переменной выбрасывается из списка - Tlink.Remove(). Но вообще-то такого быть не должно.

1.9. Нет указателей на методы типов. Указатели на функции - есть, а на методы - нет. А это облегчило бы написание кода в некоторых случаях.

1.10. Нет нормальной полноценной совместимости (приведения) типов. Неоднократно сталкивался с тем, что надо было массив TObject[] преобразовать к моему типу (например для возврата из функции, для конвертирования из TList к массиву). Приходилось писать свои функции для преобразования вроде ObjArrayToTMytypeArray: TMytype[]( Object[] ). Можно в принципе и без этого - приводить типы уже во время работы с массивом, но наглядность и легкость чтения кода теряются. А это надо для реюзабельности кода.
П.с.: Таки сделали приведение типов для массивов - хорошо хоть развивается язык, а не стоит на месте.
П.п.с.: Млин. Криво работает. Нулевые массивы на выходе часто.

1.11. Нет директивы inline. Нужна она! И не только для ускорения работы кода.

1.12. Глюк с продолжением строки: если второй строкой идет комментарий, то выдается ошибка:
Field pms:TPixmap[] = [ ..
'LoadImage("images/gem_1_rotate.png") ..
- это нужно для комментирования при экспериментах с различными значениями в массиве.

1.13. Оптимизация кода очень плохая. Нет оптимизации по использованию методов - методы, которые ни разу не использовались в коде, все равно компилируются. Тот код, который пишется, буквально переводится один в один.

1.14. Нет инкапсуляции, т.е. защищенных и открытых методов и полей класса. Есть ее какое-то подобие на уровне модуля, но не в классе. А отсутствие инкапсуляции - это есть unsafe.

1.15. Нет автоматического приведения типов. Т.е. если в функции объявлен один тип, а передается другой, причем совместимый (общий класс Object), возникает ошибка.

1.16. Игры с типами не доделаны. Вот начал я привыкать к этим играм с типизацией и ощутил необходимость ссылки на тип. То, что в С++ шаблонами можно сделать. Такая переменная в которой нужный тип обозначен - очень нужно для наследования и для различных фабрик объектов, чтоб кода писать меньше. А то можно и приустать конструкторы под каждый новый тип переписывать, раз уж нет их с параметрами и перегрузки функций тоже нет.
П.с.: !!! Я придумал, как это обойти. В нужных нам классах метод Copy(), создающий копию класса. Неужели сделали перегрузку хоть на уровне преобразования возвращаемого результата с учетом наследования. Но - нужно самому писать весь код по копированию.

1.17. Нет автоматических конструкторов копирования объектов. Приходится писать самому - а это время. А время - деньги.

1.18. Несколько глупо реализовано конструирование объектов при наследовании. Переопределенный конструктор предка вызывается по любому, даже если мы его не вызываем и его вызов нам не нужен, т.к. мы переопределяем конструктор в наследнике. Практический пример: нужно НЕЗНАЧИТЕЛЬНОЕ изменение предка. Предок использует поле объекта одного типа, в наследнике нужно это же поле, но другого типа. В конструкторе этот объект создается. В наследнике значит надо переопределить создание этого объекта на нужный нам тип. Но в конструкторе предка этот объект тоже создается, а потом пересоздается в наследнике. Конечно, менеджер памяти лишний объект потом удалит, но вообще получается очень глупое и неразумное использование ресурсов. Хорошо если этот объект маленький, а если требует серьезных расчетов, подгрузки ресурсов и т.д. - получится заметное снижение производительности. Поэтому предок надо писать заново либо с нуля, либо с предка предка, еще не имеющего нужных нам полей объектов. Вывод: Язык не очень дружелюбен к наследованию и, следовательно, к хорошей поддержке крупных и долгосрочных проектов.

Неприятное в BlitzMax

Теперь о плохом.
Сначала то, что относится к языку как таковому:

1) Отсутствие перегрузки функций. Это большое зло. Это надо, это сокращает время для написания кода. Плюс этот недостаток порождает целый ряд других.
Пример:
Нужен менеджер ресурсов. Там нужен такой метод LoadRes(target:TypeOfResource var, url$). Вот при перегрузке функций, нужная функция в зависимости от типа нужного ресурса будет подставляться на этапе сборки. А без перегрузки я должен: первое - писать свой обработчик по типу ресурса (если сделать одну функцию с параметром типа общего объекта - Object) - тратить свое время на лишний код! И второе - этот код будет выполняться во время работы процесса, что будет снижать быстродействие! Уже два ОГРОМЕННЫХ МИНУСА!
Можно обойти это немного, конкретизировав методы загрузки ( LoadImage(url$), LoadSound(url$) ), но это немного снизит удобство. Т.к. для каждого ресурса надо будет помнить свою функцию.

2) Отсутствие конструкторов с параметрами. Писать функции для создания классов - не очень то и удобно с точки зрения поддержки и развития кода. - Их ведь нельзя наследовать и п1 - нельзя перегружать. Делать для инициализации статические методы (тоже что и функции по сути) при наличии потомков - тоже неудачно и упирается в отсутствие перегрузки функций и методов - см.сл.п.

3) Неправильная или глючная поддержка в потомках возвращаемых значений методов. Т.е. в потомке нельзя переопределить тип возвращаемого значения. Оно логично со второго раза, а с третьего - видно, что не менее логично, если тип возвращаемого значения - объект, то в методе потомка можно возвращать потомка от исходного значения-объекта. Чем плохо конкретно - тем, что нельзя писать одноименные методы-конструкторы для потомков и предков красиво и без извратов (приведения типов, что делает код громоздким и невыразительным). А так же методы копирования. Т.е., по сути, нет перегрузки методов (и функций), что неудобно.

4) Невозможность создания указателей на типы пользователя. Например я сделал тип TRGBA_Color с полями R, G, В, и А соответсвенно для цветов и прозрачности. Сделать так я не могу:
Local p:TRGBA_Color Ptr = TRGBA_Color Ptr(bmp.PixelPtr(0,0))
Т.е. получить указатель на пикселы и работать с ним красиво - p.R = 100. Приходится делать это указателем на байты, что с ЯП высокого уровня не очень то и ассоциируется. Похоже, это связано с тем, что каждый тип является объектом и переменная этого типа уже и есть указатель на объект и заботой о защите памяти (только safe - функционал). Приведение типов или индексный доступ, конечно, не защищены от "дурака" - прогламмера (unsafe - функционал), но позволяют "не дураку" нормально и удобно работать.

5) Нет команды SinCos, которая поддерживается новыми процессорами и позволяет быстрее производить операции просчета вращения и т.п., т.к. обычно надо и синус и косинус угла, а одной командой это явно сделать быстрее, чем двумя.

6) Статический step в циклах. Иногда надо, чтобы при проходе по массиву приращение индекса менялось. Приходится делать через while/wend.

7) Нет оператора With. Можно сделать аналог, но это увеличивает громоздкость кода.

8) Система слежения за освободившейся памятью (менеджер памяти языка) и автоматическим удалением не нужных уже объектов, хоть и хороша и удобна, но не совершенна. И порой возникали утечки из-за перекрестных ссылок (кросслинков). Т.е. все равно приходится следить за корректной очисткой памяти, что отвлекает от основного процесса написания кода, увеличивает объем текста программы и в сумме эти два фактора приводят к увеличению времени написания программы. Плюс это не характерно для ЯП высокого уровня - менеджер памяти должен быть на высоте. Так что это получается что-то среднее между ЯП высокого и среднего уровней.
Утечки возникают даже не при кросс-линках а и в ситуациях, когда возникать не должны. Например: объект-контейнер, содержит в себе список других объектов. Объекты содержат поле с линком на элемент списка типа TLink, - не на сам контейнер. На этот контейнер ссылается глобальная переменная, поэтому он и "живет". Глюк: если в методе объекта из списка контейнера глобальная переменная переопределяется (в "пусто" или другой контейнер), то память не очищается! Контейнер не удаляется! При освобождении объекта в другом месте - все нормально и память освобождается. Глюк лечится, если объект из контейнера при переопределении глобальной переменной выбрасывается из списка - Tlink.Remove(). Но вообще-то такого быть не должно.

9) Нет указателей на методы типов. Указатели на функции - есть, а на методы - нет. А это облегчило бы написание кода в некоторых случаях.

10) Нет нормальной полноценной совместимости (приведения) типов. Неоднократно сталкивался с тем, что надо было массив TObject[] преобразовать к моему типу (например для возврата из функции, для конвертирования из TList к массиву). Приходилось писать свои функции для преобразования вроде ObjArrayToTMytypeArray: TMytype[]( Object[] ). Можно в принципе и без этого - приводить типы уже во время работы с массивом, но наглядность и легкость чтения кода теряются. А это надо для реюзабельности кода.
П.с.: Таки сделали приведение типов для массивов - хорошо хоть развивается язык, а не стоит на месте.
П.п.с.: Млин. Криво работает. Нулевые массивы на выходе часто.

11) Нет директивы inline. Нужна она! И не только для ускорения работы кода.

12) Глюк с продолжением строки: если второй строкой идет комментарий, то выдается ошибка:
Field pms:TPixmap[] = [ ..
'LoadImage("images/gem_1_rotate.png") ..
- это нужно для комментирования при экспериментах с различными значениями в массиве.

13) Оптимизация кода очень плохая. Нет оптимизации по использованию методов - методы, которые ни разу не использовались в коде, все равно компилируются. Тот код, который пишется, буквально переводится один в один.

14) Нет инкапсуляции, т.е. защищенных и открытых методов и полей класса. Есть ее какое-то подобие на уровне модуля, но не в классе. А отсутствие инкапсуляции - это есть unsafe.

15) Нет автоматического приведения типов. Т.е. если в функции объявлен один тип, а передается другой, причем совместимый (общий класс Object), возникает ошибка.

16) Игры с типами не доделаны. Вот начал я привыкать к этим играм с типизацией и ощутил необходимость ссылки на тип. То, что в С++ шаблонами можно сделать. Такая переменная в которой нужный тип обозначен - очень нужно для наследования и для различных фабрик объектов, чтоб кода писать меньше. А то можно и приустать конструкторы под каждый новый тип переписывать, раз уж нет их с параметрами и перегрузки функций тоже нет.
П.с.: !!! Я придумал, как это обойти. В нужных нам классах метод Copy(), создающий копию класса. Неужели сделали перегрузку хоть на уровне преобразования возвращаемого результата с учетом наследования. Но - нужно самому писать весь код по копированию.

17) Нет автоматических конструкторов копирования объектов. Приходится писать самому - а это время. А время - деньги.

18) Несколько глупо реализовано конструирование объектов при наследовании. Переопределенный конструктор предка вызывается по любому, даже если мы его не вызываем и его вызов нам не нужен, т.к. мы переопределяем конструктор в наследнике. Практический пример: нужно НЕЗНАЧИТЕЛЬНОЕ изменение предка. Предок использует поле объекта одного типа, в наследнике нужно это же поле, но другого типа. В конструкторе этот объект создается. В наследнике значит надо переопределить создание этого объекта на нужный нам тип. Но в конструкторе предка этот объект тоже создается, а потом пересоздается в наследнике. Конечно, менеджер памяти лишний объект потом удалит, но вообще получается очень глупое и неразумное использование ресурсов. Хорошо если этот объект маленький, а если требует серьезных расчетов, подгрузки ресурсов и т.д. - получится заметное снижение производительности. Поэтому предок надо писать заново либо с нуля, либо с предка предка, еще не имеющего нужных нам полей объектов. Вывод: Язык не очень дружелюбен к наследованию и, следовательно, к хорошей поддержке крупных и долгосрочных проектов.

Теперь то, что можно отнести к недостаткам библиотек:

19) Нет списка со значениями, не являющимися объектами. Например, целыми - Int.

20) Списки не очень удобно реализованы. Было бы хорошо наличие у элементов списка TLink поля Parent, для ссылки на родительский список (И поля Child для многоуровневых древовидных списков). Это связано с менеджером памяти языка, который не в состоянии корректно удалять объекты с кросслинками.

21) Утечка памяти в функции LoadImage при загрузке *.png. Ее практически не заметно, т.к. вылазит она при особых случаях, например при перегрузке картинок, что обычно не требуется - они загружаются один раз обычно. Но, например, при отсутствии менеджера ресурсов, когда нам нужно перезагружать изображение (при обработке скриптов, например), то утечка становится заметной. Причем внутренний меденжер памяти утечку не показывает.
Прим.: при загрузке *.jpg утечки нет.

22) При создании нового pixmap, он не инициализируется. Т.е. мы создали новый pixmap, а там мешанина из пикселов, а не черный или белый или заданный программистом фон. Надо писать функции заполнения новообразованных пиксмапов, а это - время/деньги.

23) Неясности со шрифтами: LoadImageFont("Arial.ttf"…) не приводит к ожидаемому результату, а с полным путем LoadImageFont("C:\Windows\Fonts\Arial.ttf"…) все работает. Хотелось бы без указания путей. Хоть и есть фонт по умолчанию.

24) Отсутствие такого хорошего понятия как контекст устройства. Есть в вынь и в пурике ( StartDrawing(OutputID) ). На CreateGraphics(…) его заменить нельзя - если разрешение не поддерживается, контекст не создается. Это очень-очень плохо. Нельзя рисовать нормально в оффскрин окно. Другими словами рисовать в текстуру (спрайт) можно только ручками через массив пикселей, что медленно. Сторонние библиотеки для этого - платные.

25) Метод pixmap. Paste(…) не проверяет размеры - это приводит к глюкам с затиранием памяти и необходимостью писать много чего своими ручками. Это unsafe (при том, что полезные вещи в страхе этого самого unsafe не делаются), и время/деньги на дополнительный код.

26) Глючность идиотическая, надеялся, что такого не встречу. Пример: когда работа с пиксмапами формата PF_RGBA8888 проходит отлично, а смена формата на PF_BGRA8888 приводит к непонятным глюкам в официальных библиотечных функциях.

27) Глюки при работе с созданием пиксмапов, если их делаешь много, то возникает глюк. Этот глюк как-то связан с форматом картинки. При формате PF_BGRA8888 он возникает раньше. GCCollect() не помогает, дело не в переполнении, а хз в чем.

Теперь то, что больше относится к написанию игр собственно:

28) Нет поддержки шрифтов с произвольной шириной и утилит для работы с ними. Моноширинные - это вчерашний день.

29) Нет зачатков даже движка как в Blitz3D. Есть просто набор либ для работы с сетью, звуком графикой и устройствами ввода (мышь, клавиатура, джойстик). Джентльменский набор, но "ни цента больше".

30) Нет и намека на партиклы. О редакторе молчу, хотя бы классы или либы для работы с ними были какие-то. А современный уровень игростроения их требует. Все надо делать самому - опять время/деньги. Хотя есть пара сторонних убогих движков частиц. И даже с редакторами.

31) ГУИ. Игровое конечно. Опять полное отсутствие. Хотя тут проще - есть сторонние библиотеки. И даже бесплатные.

32) Нет поддержки треккерных форматов звука. Но можно использовать сторонние библиотеки.

33) Нет физики. Есть сторонние модули.

А в дальнейшем, по мере моего желания, будет рассказываться о путях обхода описанных препятствий и просто полезных вещах при программировании на BlitzMax. Я планирую делать по посту в неделю, а как получится - увидим.

Приятное в BlitzMax

Поскольку опять возникли некоторые споры по языку на форуме, то я решил немного ускорится и выложить плюсы и минусы BlitzMax, которые обнаружились при работе с ним. Для начала плюсы (или просто вещи, которые мне в нем понравились), потому что их меньше:
  • Можно сразу делать инициализацию локальных переменных, в том числе и массивов:
    Local a%[] = [1,2,3]
  • Инициализация при объявлении полей класса - уменьшается количество текста, которое нужно писать программисту, т.к. часто отпадает необходимость писать конструктор:
    Field mObj:Object = new TMyType
  • Обращение к каждому элементу строки через индекс:
    a$ = "blablabla"; print a[3];
    но нельзя сделать присвоение вида:
    a[3]=46; - это только для проверки символов строки.
  • Строка является объектом. Можно записать:
    a$ = "blablabla"; a.length()
  • Указатели с индексным доступом:
    p: Byte Ptr; p[3] = 0;
  • Цикл for/until - в отличие от for/to, переменная увеличивается до величины, не включая ее. Что удобно для работы с массивами, начинающимися с 0.
  • Довольно таки просто реальзовать переключение оконного и полнооконного графических режимов. И, впрочем, множество других нужных мелочей.
  • Звук 3Д - есть позиционирование и глубина: SetChannelPan и SetChannelDepth, соответственно.

Немного о самом BlitzMax

BlitzMax - это объектно-ориентированный язык программирования высокого уровня, предназначенный для разработки 2Д игр. Растет из BlitzBasic'а от компании Blitz Research LTD, основателем которой является Mark Sibly. Язык платный, стоит немного - 80 долларов. Есть свое ИДЕ. Есть отладка. Компиляция в машинный код, что хорошо сказывается на быстродействии написанных на нем программ.
О самом языке: Поддерживает абстракцию, и наследование. С полиморфизмом и инкапсуляцией - хуже. Точнее с полиморфизмом - хуже, инкапсуляции - нет. Так что лично я считаю, что его правильнее отнести к объектным языкам, а не к объектно-ориентированным. Мне много в нем не хватает, после работы на С++ и Объектном Паскале (Делфи). Что еще хорошего: указатели на функции, встроенный менеджер памяти, динамические массивы с переменной длинной, указатели на примитивные типы, расширяемость за счет работы с внешними библиотеками (DLL), открытость - все библиотеки даны в исходниках, мультиплатформенность (MacOS, Windows, Linux).
О его ориентированности на разработку игр: прямая работа с OpenGL; библиотеки для работы с графикой (OpenGL и Direct-X), загрузка/выгрузка изображений (форматы *.png, *.jpg, *.jp2000, *.bmp), отрисовка с поддержкой альфа-канала и различных способов наложения, достаточно хорошая библиотека обработки коллизий с попиксельной точностью; библиотеки для работы со звуком (форматы *.wav, *.ogg) и сетью.