Сообщение от G.A.D
если можно то примеры частых способов реализации структуры пак файла.
|
Я дам не частый, а частНый способ реализации.
А заодно (если повезёт) услышу мнения по поводу кода.
В коде представлен класс "пакера" и функции, формирующей пак-файл.
Пример работы:
1. создаём пак-файл (с помощью функции, подобной той что приведена в коде после описания класса)
'пакуем все наши ресурсы в один файл
Global packer:TPacker = New TPacker
Local resFile:String = "data.res"
fnPackResAll(resFile)
2. читаем структуру пака
'подготовка данных о ресурсах, находящихся в паке
packer.fnUnpack(resFile)
3. грузим нужные ресурсы
Local imgLogo:TImage = LoadImage(packer.fnGet(RES_IMG_LOGO))
Номера ресурсов можно сделать константами, например:
Const RES_IMG_LOGO = 1
Const RES_IMG_BUTTON = 2
Эти константы РАВНЫ порядковому номеру соответствующего ресурса в паке.
Это может быть не очень удобно, но занимает мало места.
Опираясь на приведённый код довольно просто можно сделать вместо порядкового номера вводимые на этапе формирования пака идентификаторы, хоть числовые хоть строковые.
Лишь дописать проверку на их уникальность, и поиск в паке.
Напоминаю, что шрифты таким образом (сразу в память из потока) грузить оказалось невозможным.
Как вариант - распаковывать их в темп. Но тогда чё - после закрытия проги удалять их? А если не удалять, то эти лишний "мусор", и проще их сразу хранить в папке с данными и всё.
Вот код.
'класс TPacker - упаковщик/распаковщик игровых ресурсов
Type TPacker
Field list:TList = New TList
'Field listTmp:TList = New TList 'список распакованных в темп
Field resCount, size, k, path:String
Field file:TStream
Field bank:TBank
Field seekData, seek
Field masSizes[]
'добавление файла в список для последующей запаковки
Method fnAdd(ppath:String)
path = ppath.ToLower()
If(list.Contains(path) = True) Return
list.AddLast(path)
End Method
'запаковка всего что в списке в файл
Method fnPack(fileName:String)
If(list.IsEmpty()) Return
resCount = list.Count()
file = WriteFile(fileName)
WriteInt(file, resCount)
For path = EachIn list
If(FileType(path) <> 1)
RuntimeError("file not found: " + path)
Else
size = FileSize(path)
WriteInt(file, size)
'DebugLog "sz = " + size
EndIf
Next
For path = EachIn list
If(FileType(path) <> 1)
RuntimeError("file not found: " + path)
Else
bank = LoadBank(path)
WriteBank(bank, file, 0, bank.Size())
EndIf
Next
CloseFile(file)
End Method
'"распаковка". получение информации о содержимом файла ресурсов
Method fnUnpack(fileName:String)
If(FileType(fileName) <> 1) Return
file = ReadFile(fileName)
resCount = ReadInt(file)
masSizes = New Int[resCount]
For k = 0 Until resCount
size = ReadInt(file)
masSizes[k] = size
Next
seekData = StreamPos (file)
CloseFile(file)
path = fileName
End Method
'получение ресурса по индексу, т.е. по порядковому номеру в файле ресурсов
Method fnGet:TStream(id)
If(id < 0 Or id > resCount - 1) Return Null
seek = seekData
For k = 0 Until id
seek:+masSizes[k]
Next
file = ReadFile(path)
SeekStream(file, seek)
bank = CreateBank()
Local stream:TStream = OpenStream(bank)
For k = 0 Until masSizes[id]
WriteByte(stream, ReadByte(file))
Next
CloseFile(file)
FlushStream(stream)
SeekStream(stream, 0)
bank = Null
Return stream
End Method
'извлечение во временную папку ресурса по индексу
'возвращает путь к распакованному файлу
Method fnUnpackToTemp:String(id, fileName:String)
If(id < 0 Or id > resCount - 1) Return Null
seek = seekData
For k = 0 Until id
seek:+masSizes[k]
Next
file = ReadFile(path)
SeekStream(file, seek)
CreateDir("temp")
Local stream:TStream = WriteFile("temp\" + fileName)
For k = 0 Until masSizes[id]
WriteByte(stream, ReadByte(file))
Next
CloseFile(file)
CloseFile(stream)
Return "temp\" + fileName
End Method
'удаление файлов из временной папки
Method fnClearTemp()
Local files:String[] = LoadDir("temp")
Local fn:String
For fn = EachIn files
DebugLog "fn = " + fn
'DeleteFile("temp\" + fn)
'CloseFile(WriteFile("temp\" + fn))
Next
End Method
'очистка информации
Method fnClear()
list.Clear()
path = ""
masSizes = Null
End Method
End Type
'запаковываем наши ресурсы
Function fnPackResAll(packFile:String = "data.res")
packer.fnAdd("pointer.png") '0
packer.fnAdd("main.png") '1
packer.fnAdd("buttonUp.png") '2
packer.fnAdd("buttonDown.png") '3
packer.fnAdd("buttons\btnScreenShot1.png") '4
packer.fnAdd("buttons\btnScreenShot2.png") '5
packer.fnAdd("buttons\btnScreenShot3.png") '6
packer.fnAdd("buttons\btnStart1.png") '7
packer.fnAdd("buttons\btnStart2.png") '8
packer.fnAdd("buttons\btnStart3.png") '9
packer.fnAdd("fonts\usual.ttf") '10
packer.fnAdd("fonts\digit.ttf") '11
packer.fnAdd("fonts\xyz.ttf") '12
packer.fnAdd("fonts\bounds.ttf") '13
packer.fnAdd("buttonUpSmall.png") '14
packer.fnAdd("buttonDownSmall.png") '15
packer.fnAdd("logo.png") '16
packer.fnAdd("viewKrug.png") '17
packer.fnAdd("particles\serdce.png") '18
packer.fnAdd("particles\pentagon.png") '19
packer.fnAdd("particles\star.png") '20
packer.fnAdd("particles\star2.png") '21
packer.fnPack(packFile)
End Function