Вторник, 01.07.2025, 05:30Приветствую Вас Гость | RSS
Game masterS
Главная | Советы и секреты - Форум | Регистрация | Вход
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Советы и секреты
PikaTeach(удаленный)Дата: Понедельник, 16.06.2008, 08:51 | Сообщение # 1
PRO ИмбА
Группа: Ответственный за работу сайта
Сообщений: 114
Репутация: 6
Статус: Нет на сайте
Аналог оператора With

В разных языках есть оператор With, смысл которого в том, что к полям объекта подставленному к оператору, производится быстрый доступ и в тексте и в скомпилированном коде (за счет занесения объекта в регистр процессора). Данного оператора в Blitzmax нету. Но его можно частично заменить с помощью новой локальной переменной. Поскольку объявлять переменную можно в любом месте, и новая переменная, скорее всего (не гарантированно), помещается в регистр, то объявив локально и коротким именем переменную с нужным нам объектом, в большинстве случаев, можно добиться аналогичного результатата. Это можно назвать решением недостатка языка 1.7 .
Пример:
Method Abc( argument1:TMyType, argument2%, ... )
...
Local a:TMyType = argument1
a.Field1 = New Type2
a.Method1( ... )
...
End Method

Использование GCCollect

Не рекомендую использовать GCCollect в главном цикле - это снижает производительность. Автоматическая уборка мусора вполне справляется с большинством задач. Лучше использовать эту команду в случаях, когда было резервирование очень больших объемов памяти и память лучше освободить, чтобы поскорее уменьшить нагрузку на ресурсы системы.

Инициализация новых переменных и объектов

Blitzmax автоматически инициализирует новые переменные, поэтому отпадает необходимость инициализировать пустые переменные объектов значением NULL.
Можно писать просто: Local obj:TMyType;
Вместо: Local obj:TMyType = NULL;
То же относится и к полям типов/классов. Также все значения нового массива будут проинициализированы нулями.

Определение состояния списка

Чтобы определить, пуст список или нет, не надо использовать TList.Count() - это медленый метод, надо использовать TList.IsEmpty().

Проход по многомерному массиву

Если мы объявили многомерный массив как массив значений (Local a[n,m]), а не массив массива (a[n][m]), то пройти весь массив можно не стандартным способом с вложенными циклами, а одним foreach:Local a[2,2]
a[0,0]=1; a[0,1]=2; a[1,0]=3; a[1,1]=4
For Local i:Int = EachIn a; Print i; Next;

Из примера видно, что проход выполняется сначала по последним индексам.
Но, как всегда, есть и неприятный момент: если вы заметили я инициализировал каждый элемент массива отдельно. И сделал это потому, что при подобном объявлении Blitzmax не поддерживает инициализацию массива. И красивой записи, как для массива массивов: Local b[][] = [[1,2],[3,4]] сделать не даст.

Запись в строку по индексам : string[2]=78

Нормального доступа к элементам строки в Blitzmax'e нет. Марк типо сильно боится дураков-программистов и сильно о них заботится. Он, наверное, пропитался духом псевдо-любви к умалишенным в ущерб неумалишенных. Объяснение, почему он не делает нормальный индексный доступ к строкам, а только чтение, меня просто развеселило: он заботится о том, что, если мы передаем строку в функцию, ее там кто-то может изменить. А типа чтобы ее не изменили стопроцентно надо ее копировать, а не передавать через ссылку. А это целых 7 лишних символов каждый раз набирать: ".Copy()". Вопрос а нафик нам вообще надо сохранять строку? Или мы настолько тупы, что не знаем, что пишем? И нам ни за что не известно будет ли функция менять строку или нет? Ппц просто. Я уже молчу про то, что это решается на уровне языка элементарно, и не в одном языке делалось: аргумент функции объявляется как ссылка или как значение. Если ссылка - передаем ссылку на строку и она может быть изменена после работы функции. Если значение - то строка копируется и что там функция будет с ней делать, нас не волнует: у нас оригинал, а там - копия. Все давно известно, ничего не надо изобретать и писать лишних 7 символов тоже не надо. Но зато придется изобретать нам. Итак, решение:

Local str$ = "Hello"
Print str

Local p:IntPtr = IntPtr(Varptr(str))
Local pchar:ShortPtr = ShortPtr(p[0])
pchar :+ 6'this offset depends on the String structure

pchar[0]=Asc("H")
pchar[1]=Asc("e")
pchar[2]=Asc(" ")
pchar[3]=Asc("h")
pchar[4]=Asc("e")

Print str

Или вот так одной строкой:
Local pchar:Short Ptr = Short Ptr(Int Ptr(Varptr(str))[0]) + 6

Переопределение полей в наследниках

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

Рисуем кусок изображения

Используем SetViewport

Function DrawImageRect(img:TImage, x#, y#, rx#, ry#, rw#, rh#)
SetViewport x, y, rw, rh
DrawImage img, x - rx, x - ry
SetViewport(0, 0, GFX_WIDTH, GFX_HEIGHT)
End Function

Особенности: надо знать абсолютные координаты.
Недостатки: SetViewport не всеми картами поддерживается.

материал взят с http://blitzmax.3dn.ru


 
  • Страница 1 из 1
  • 1
Поиск:


Copyright MyCorp © 2025