Динамическая загрузка спрайтов

Материал из DRKB


Динамическая загрузка спрайтов

Если делать игру с большим количеством графических изображений, то неразумно будет загружать их все сразу, например зачем в основном меню игры графика босса с последнего уровня? А вот памяти его "фото" будет жрать! Чтобы этого не происходило, необходимо разделить всю игру на сцены, и просто при загрузке конкретной сцены удалять из памяти ненужные картинки и загружать туда только те которые в этой сцене используются. Делаем это так: При загрузке сцены пишем:

LoadPicData(DxImagelist1, 'Menu');
  • Вместо DxImagelist1 имя вашего TdxImageLista
  • 'Menu' - Тут название файла со списком используемых картинок данной сцены


Формат файла со списком такой:

[название] (название одинаково с именем файла, только без расширения)
PictureHeight=800 (Высота картинки)
PictureWidth=600 (Ширина картинки)
PatternHeight=0 (Высота кадра (если в картинке несколько кадров)) 
PatternWidth=0 (Ширина кадра)
SkipHeight=0 (Пропуск высоты, пусть останеться 0)
SkipWidth=0 (Пропуск ширины, пусть останеться 0)
SystemMemory=0 (Пока не надо, пусть останеться 0)
Transparent=0 (Прозрачен или нет)
TransparentColor=clBlack (Цвет прозрачности)

Например кусочек файла "game.dat":

[enemy]
PictureHeight=96
PictureWidth=192
PatternHeight=0
PatternWidth=48
SkipHeight=0
SkipWidth=0
SystemMemory=0
Transparent=1
TransparentColor=$00FF8040


При этом файлы должны лежать в папке Pictures\Bmp (если они Bitmapы) или Pictures\Jpg (если они в Jpeg). Ещё файлы со списком должны лежать в Pictures\Data

А вот и сама процедура загрузки:

PS. В USES надо дописать DIB, Jpeg, iniFiles

procedure TForm1.LoadPicData(var DXImageList: TDXImageList; FileName: string);
var
  i: Integer;
  Item: TPictureCollectionItem;
  SectionName: string;
  Ident: string;
  NewGraphic: TDIB;
  BitMap: TBitMap;
  PicFileName: string;
  SectionList: TStringList;
  JpgImg: TJPEGImage;
  Ext: string;

  function GetName(InDir, InFileName: string): string;
  begin
    Result := ExtractFilePath(Application.ExeName) + InDir + '\' + InFileName;
  end;

begin
  DXImageList.Items.Clear; // Очищаем память от картинок
  FileName := ChangeFileExt(FileName, '.dat');
  NewGraphic := TDIB.Create;
  BitMap := TBitMap.Create;
  SectionList := TStringList.Create;
  try
    // Читаем файл со списком изображений
    with TIniFile.Create(GetName('Pictures\data', FileName)) do
    try
      ReadSections(SectionList);
      for i := 0 to SectionList.Count-1 do
      begin
        SectionName := SectionList[i];
        // Пытаемся определить формат картинки
        Ext := 'bmp';
        PicFileName := GetName('Pictures', Ext + '\' + SectionName + '.' + Ext);
        if FileExists(PicFileName) then
          NewGraphic.LoadFromFile(PicFileName);
        else
        if not (FileExists(PicFileName)) then
        begin
          Ext := 'jpg';
          PicFileName := GetName('Pictures\Jpg\', SectionName + '.' + Ext);
          JpgImg := TJPEGImage.Create;
          try
            JpgImg.LoadFromFile(PicFileName);
            NewGraphic.Assign(JpgImg);
          finally
            JpgImg.Free;
          end;
        end;
        // Добавляем картинку в память
        Item := TPictureCollectionItem.Create(DXImageList.Items);
        Item.Picture.Graphic := NewGraphic;
        Item.Name := SectionName;
        Item.PatternHeight := ReadInteger(SectionName, 'PatternHeight', 0);
        Item.PatternWidth := ReadInteger(SectionName, 'PatternWidth', 0);
        Item.SkipHeight := ReadInteger(SectionName, 'SkipHeight', 0);
        Item.SkipWidth := ReadInteger(SectionName, 'SkipWidth', 0);
        Item.SystemMemory := ReadBool(SectionName, 'SystemMemory', False);
        Item.Transparent := ReadBool(SectionName, 'Transparent', False);
        Item.TransparentColor := StringToColor(ReadString(SectionName, 'TransparentColor', 'clBlack'));
        Item.Restore;
      end;
    finally
      Free;
    end;
  finally
    NewGraphic.Free;
    BitMap.Free;
    SectionList.Free;
  end;
end;


Author: Spose
Source: http://www.mirgames.ru
ID: 03922