Выбрать главу

Следующий кусок кода:

 else begin

  Vector[12] := BrushIndex*16;

  for i := 0 to 24 do begin

   BaseIndex := GetBaseIndex(Vector[i]);

   AdditionalIndex := GetAdditionalIndex(Vector[i]);

   if BaseIndex = BrushIndex then begin

    if EqualTable[i,AdditionalIndex] 16 then Vector[i] := BaseIndex*16 + EqualTable[i,AdditionalIndex];

   end else begin

    if NotEqualTable[i,AdditionalIndex] else if NotEqualTable[i,AdditionalIndex]> 16 then Vector[i] := BrushIndex*16+ NotEqualTable[i,AdditionalIndex] – 16;

   end;

  end;

 end;

end;

Делает все то же самое, для двух оставшихся случаев. Голубым выделены те строчки, которые по моему мнению можно удалить, но при этом исправить в таблице NotEqualTable числа больше 16 на эти же числа минус 16. Все, с технологией покончено!!!

Следующие страницы я посвящу некоторым особенностям вывода карты на экран в моем примере. Кого интересовала только технология расчета плавных перетеканий текстур, дальше, если нет желания, могут не читать.

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

Конкретно для вывода карты на экран использовались компоненты TDXDraw, TDXImageList и TDXTimer.

TDXDraw — в основном используется для переключения страниц видеопамяти. Что это такое объяснять не буду.

TDXImageList — хранит в качестве элементов файлы со спрайтами выстроенными в одну цепочку. Соответственно к конкретному спрайту можно обратится по имени файла и номеру спрайта в нем. Также в этом компоненте есть две переменные PatternWidth, PatternHeight для указания ширины и высоты спрайтов, и переменная TransparentColor для указание прозрачного цвета.

TDXTimer — используется для генерации события DXTimerTimer с частотой заданной или рассчитанной в ходе выполнения программы.

Итак, текстуры выполнены в виде одного файла внутри которого выстроены в цепочку в соответствии с принципами изложенными выше и помещены в TDXImageList под именем "West". ( TDXImageList позволяет находить файлы внутри себя по их имени)

Нам нужно вывести на экран некоторую часть карты, причем карта наша состоит из кусочков и нам нужно вывести только те кусочки, которые видны в данный момент.

Можно сделать окно вывода кратным размеру текстур, а скроллинг организовать потекстурно с шагом равным ширине/высоте текстуры, тогда нет проблем, но это смотрится не очень красиво. Наша задача состоит в том, чтобы организовать скроллинг попиксельно и дать возможность задать окно вывода любого размера. Для того, чтобы это сделать нужно рассчитать сколько текстур по горизонтали и сколько текстур по вертикали мы должны отрисовать в окне вывода, включая и те текстуры которые в данный момент времени видны только частично.

Рисунок 9

На рисунке 9 клеточками изображена карта. Черным контуром показано окно вывода. Как видно – не все ячейки карты целиком влезли в окно, но их тоже надо отрисовать. Положение окна вывода на карте определяется координатами его левого верхнего угла относительно карты.( TopLeftCorner.x, TopLeftCorner.y) Их величины в пикселях(Нам же надо сделать попиксельный скроллинг) При создании новой карты они приравниваются нулям, и в дальнейшем определяются положением полос прокрутки. Вот часть кода:

procedure TMainForm.RedrawMap;

Var

 OffsPoint : TPoint;

 TopLeftElem : TPoint;

 ElemCount : TPoint;

 HelpVar1 : Integer;

 HelpVar2 : Integer;

 i,j : Integer;

 x,y : Integer;

 Index : Integer;

begin

 OffsPoint.x := TopLeftCorner.x mod ElemWidth;

 OffsPoint.y := TopLeftCorner.y mod ElemHeight;

Данные две строчки позволяют получить смешение левого верхнего угла экрана внутри левой верхней ячейки(См. рисунок 9). Глобальные переменные ElemWidth,ElemHeight это высота и ширина ячейки(текстуры). Теперь нам необходимо получить номер строки и столбца ячейки где находится левый верхний угол окна вывода:

TopLeftElem.x := TopLeftCorner.x div ElemWidth;

TopLeftElem.y := TopLeftCorner.y div ElemHeight;

Далее необходимо рассчитать сколько у нас целых текстур влезает в окно вывода по вертикали и горизонтали:

HelpVar1 := DXDraw.Width – (ElemWidth – OffsPoint.x );

HelpVar2 := DXDraw.Height – (ElemHeight – OffsPoint.y );

ElemCount.x := HelpVar1 div ElemWidth;

ElemCount.y := HelpVar2 div Elemheight;

Где DXDraw.Width, DXDraw.Height – это ширина и высота окна вывода. Если у нас есть нецелые текстуры снизу и справа окна вывода, то добавляем к ElemCount.x, ElemCount.y по единице:

if (HelpVar1 mod ElemWidth)> 0 Then Inc( ElemCount.x );

if (HelpVar2 mod ElemHeight)> 0 Then Inc( ElemCount.y );

Далее следует вывод на экран:

For j := 0 to ElemCount.y do  For i := 0 to ElemCount.x do Begin // Вычислить координаты куда выводить

 X := i * ElemWidth – OffsPoint.x;

 Y := j * ElemHeight – OffsPoint.y;

 // Вычислить номер текстуры

 Index := GetElement(TopLeftElem.X + i,TopLeftElem.Y + j);

 // Вывести текстуру на экран

 // Учтите что LandType это не тип земли, а тип мира

 // Snow,West и т.д.

 ImageList.Items.Find(LandType).Draw(DXDraw.Surface,x,y,Index);

end;

Строка: Index := GetElement(TopLeftElem.X + i,TopLeftElem.Y + j); обращается к матрице карты и считывает оттуда номер текстуры, следующая строка выводит ее на экран.

Возможно вы спросите: А как же нецелые текстуры слева и сверху окна вывода? Их-то ты не учел? Посмотрите на кусок кода отвечающий за вывод на экран. Циклическая переменная инициализируется от 0 до ElemCount.(x,y). Это значит, что всегда выводится на одну текстуру больше, чем в ElemCount, а если слева и сверху нет нецелых текстур, то переменная OffsPoint.(x,y) будет равна размерам ячейки. Переменные HelpVar(1,2) станут на размер ячейки меньше, и следовательно переменные ElemCount.(x,y) станут на единицу меньше. Все. Смотрите исходники в модуле Main.pas.

В программе не отловлены все баги. Например определен только один тип мира "West", да и текстуры нарисованы чисто схематически.

Исходные тексты Вы можете скачать тут , а библиотеку DelphiX найдете на сайте DelphiGFX в разделе Libs.

Шпаргалка по ресурсам Windows-32 (для Delphi)

Этот текст — попытка сжатого ответа на большинство заданных в конференции вопросов по ресурсам Windows. Возможно, Вы найдете здесь (в неявном виде) объяснение части связанных с ресурсами сложностей в Delphi.

Стандартная технология доступа к ресурсам

Для компиляции примера надо создать на диске перечисленные исходные файлы (все в текстовом формате). Я не привел примеров для ресурсов типа BitMap`ов, Icon`ов и курсоров, поскольку обращения к ним достаточно тривиальны и не содержат каких-либо неоднозначностей, и, во-вторых, они (декларации ресурсов) недостаточно компактно записываются в виде текста.