Changes between Initial Version and Version 1 of WorkingWithTilesets_v1


Ignore:
Timestamp:
Oct 5, 2008 3:32:37 AM (16 years ago)
Author:
sagrer
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • WorkingWithTilesets_v1

    v1 v1  
     1 = Принцип работы с наборами тайлов (тайлсетами) =
     2
     3Версия №1. '''В процессе проектирования'''.
     4
     5Более старые версии:
     6 * нет.
     7
     8Данный текст описывает только проект, т.е. относительно подробное, и в то же время достаточно абстрактное описание того как все должно быть устроено и как должно работать.
     9
     10----
     11
     12 == Организация файлов тайлсетов ==
     13
     14Все тайлсеты расположены в одном каталоге. Внутри этого каталога - по подкаталогу на каждый тайлсет, имя каталога является именем тайлсета. Внутри каждого каталога тайлсета содержатся следующие файлы:
     15
     16 * !TileSet.ini - настройки тайлсета. Формат файла описан [wiki:TileSetIniFormat_v1 тут].
     17 * Если набор не сжатый - то куча *.bmp-файлов с тайлами с именем вида {!TileName}.bmp, где {!TileName}=T_{Layer}_{Terrains}_{!VarNumber}, где {Layer} - двузначное число, номер слоя (любое число от единицы до 99, ибо номер слоя 00 зарезервирован); {!VarNumber} - двузначное число, номер варианта данного тайла; {Terrains}={Terr1}_{Terr2}_{Terr3}_{Terr4}, где {Terr1}-{Terr4} соотв названия террейнов в углах тайла - по строчкам, справа-налево, сверху-вниз, вот так:
     18||Terr1||Terr2||
     19||Terr3||Terr4||
     20 * Если набор сжатый - куча *.7z-файлов с bmp-хами с тайлами с именем вида {!TileName}.bmp, где {!TileName} - то же самое, что описано выше.
     21 * Пустые файлы с именами вида Deny_{Terr1}_{Terr2} где Terr1 и Terr2 - имена террейнов, между которыми запрещены переходы. Именем террейна может быть зарезервированное имя All что означает все террейны того же слоя что и второй террейн. По-умолчанию все переходы разрешены. Наличие такого файла запрещает переход. Порядок следования террейнов в имени значения не имеет. Смысловые дубли не должны мешать правильной работе реализации, но в то же время реализация должна стараться не допускать появления таких дублей, а также отслеживать их и при обнаружении вычищать. Имена Deny имеют более высокий приоритет над разрешением всех переходов по умолчанию и более низкий к  именам Allow, поэтому можно сначала запретить все переходы для какого-либо террейна, а затем уже разрешать определенные переходы через Allow. Писать Deny_All_All нельзя, такой файл если он появится - должен быть удален, ибо настройки переходов в реализации должны идти для каждого террейна отдельно.
     22 * Пустые файлы с именами вида Allow_{Terr1}_{Terr2} где Terr1 и Terr2 - имена террейнов, между которыми разрешены переходы. Использование имени All в данном случае бессмысленно, ибо по умолчанию все переходы уже разрешены. Отношение к дублям - такое же как для Deny.
     23
     24----
     25
     26 == Принцип реализации ==
     27
     28Работа с тайлами реализуется несколькими взаимозависимыми классами, связанными через их элементы-ссылки. Основным классом, связывающим все остальные является TTileSet, который реализует работу с содержимым одного набора тайлов. Есть более высокий уровень - TTileSetsCollection - фактически контейнер, содержащий ссылки на объекты типа TTileSet для всех доступных программе тайлсетов. '''TTileSetsCollection содержит''':
     29 * Массив ссылок на все объекты тайлсетов.
     30 * Путь по которому располагаются тайлсеты.
     31 * Путь к временному каталогу для временных файлов при работе с тайлсетами.
     32 * Ссылка на !CallBack-метод, для синхронизации при многопоточной работе, с учетом того что !CallBack будет иметь доступ к инфе объекта и всей вложенной инфе.
     33Также содержит методы:
     34 * Удалений, добавлений тайлсетов.
     35 * Методы, осуществляющие собственно чтение тайлсетов. Предусмотреть основной метод, выполняющий всю работу и своевременные вызовы !CallBack, а также открытые методы-обертки для вызова с и без использования !CallBack, при этом основной метод можно спрятать от простых смертных и оставить доступными только обертки.
     36 * Метод, возвращающий true если в каком-либо из тайлсетов есть "неправильные" (с нестандартной структурой) тайлы и false если таких нет.
     37
     38'''TTileSet содержит''':
     39 * Обратную ссылку на объект TTileSetsCollection.
     40 * Ссылку на объект, реализующий работу с файлом !TileSet.ini для этого тайлсета (TTileSetIni).
     41 * Массив ссылок на все тайлы, принадлежащие тайлсету - точнее на объекты класса TTile, реализующего работу с тайлом.
     42 * Массив ссылок на все тайлы, файлы которых реально существуют.
     43 * Массив ссылок на все тайлы, конфигурация которых неправильна (т.е. является одним из вариантов поворота для одной из стандартных конфигураций, а значит такой тайл требуется перевернуть в стандартную конфигурацию при нулевом повороте и переименовать).
     44 * Массив ссылок на все террейны, принадлежащие тайлсету - т.е. на объекты класса TTerrain, реализующего работу с террейном.
     45 * Массив ссылок на объекты класса TLayer, который по-сути является контейнером ссылок на объекты TTerrain и содержит ссылки на все террейны своего слоя.
     46 * Список строк Allow и Deny для информации из имен файлов разрешений-запретов переходов.
     47 * Дополнительная информация о тайлсете, например номер ревизии в случае если используется svn.
     48 * Объект класса TFlistFormat для списка тайлов в сжатом тайлсете.
     49 * Объект класса TFlistFormat для списка тайлов в временном каталоге с тайлами тайлсета. Последние 2 элемента - используются только если работаем со сжатым тайлсетом.
     50 * Список строк - имена всех террейнов тайлсета, мне выполнения методов должен быть в алфавитном порядке и соответствовать приоритету террейнов.
     51 * Булево значение - true если есть "неправильные" тайлы и false если таковых нет.
     52 * Булево значение - true если есть тайлы без реального файла с картинкой и false если таковых нет.
     53 * Ссылка на объект класса TMasksSet - описание класса смотри на [wiki:WorkingWithMasks странице] с описанием работы масок.
     54Также тут есть методы для:
     55 * Удалений, добавлений тайлов (по имени, влияющая на все три массива ссылок на тайлы).
     56 * Удалений, добавлений террейнов (по имени).
     57 * Удалений, добавлений слоев (по номеру слоя, с удалением принадлежащий слою террейнов).
     58 * Удалений, добавлений Allow и Deny, влияющее и на соответствующие объекты террейнов.
     59 * Метод для синхронизации временного распакованного варианта тайлсета со сжатым реальным тайлсетом.
     60 * Метод для обратной синхронизации содержимого временного каталога со сжатым реальным тайлсетом.
     61 * Метод, собственно выполняющий чтение информации о тайлсете.
     62 * Метод, ищущий неправильные тайлы, добавляющий их в соотв. списки, помечающий и выставляющий соотв. булево значение о их наличии в данном объекте.
     63 * Метод, генерящий на основе информации о слое и переходах террейна конфигурации всех возможных для террейна тайлов, проверяющий наличие каждого такого тайла, если его нету - добавляющий "несуществующий" (т.е. для него отсутствует файл с картинкой) тайл в систему и все нужные списки, помечающий правильным образом этот тайл и ставящий в нужную метку соотв. булево значение этого объекта о наличии "несуществующих" тайлов.
     64 * Метод, исправляющий тайлы с неправильной структурой (поворачивает и дает правильное имя).
     65 * Метод, осуществляющий генерацию конкретного переходного тайла (в аргументе линка на объект тайла).
     66 * Метод, осуществляющий генерацию всех переходных тайлов, для которых еще нету картинок.
     67
     68Удаление тайлов, разрешений\запретов переходов, если оно связано с реальным файлом набора - автоматически приводит к удалению соответствующих файлов из набора. Юзверь этой системы классов должен сам обеспечить предупреждение пользователя проги о возможном безвозвратном удалении файлов до вызова таких методов.
     69Кроме этого - следует организовать выделение и освобождение памяти так, чтобы памятью всех слоев, террейнов и тайлов заведовал именно класс TTileSet. Другие классы также могут иметь подобные ссылки, и даже выделять память под новые объекты - но в любом случае такой объект должен попасть в массив объекта TTileSet и в дальнейшем уничтожаться должен под управлением именно TTileSet, если же вложенные в него объекты сами новых объектов не создают, то использоваться может только копирование ссылки на уже созданный объект. Таким образом, в других классах может использоваться new, но delete всегда выполняется только классом TTileSet, причем гарантированно для всего, что могло быть создано по любому такому new.
     70
     71'''Класс TLayer''' весьма прост и содержит только номер слоя (в виде числового значения), массив ссылок на террейны и обратную ссылку на тайлсет, которому принадлежит слой.
     72
     73'''Класс TTileSetIni''' по сути также более чем прост, типичен для любого класса, работающего с конфигами в ini, содержит в себе структуры и переменные с данными секций !TileSet.ini, а также методы Load, Save, Clean для загрузки, чтения информации в\из файла и очистки (простановке значений по умолчанию) соответственно. Метод Load должен проверять соответствие номера версии формата в файле текущей реализации - если в файле версия новее - давать ошибку, если старее - конвертировать файл в новую версию (без записи на диск), если тот же - просто читать.
     74
     75На уровне террейна работа обеспечивается объектами '''класса TTerrain, который содержит''':
     76 * Имя террейна.
     77 * Число - приоритет террейна. Если приоритет неизвестен то значение = 0.
     78 * Ссылку на объект класса TLayer, которому принадлежит террейн. Если имеются проблемы с идентификацией единственного номера слоя - присваивается ссылка на слой с индексом 00 (ноль).
     79 * Численное значение слоя террейна. Если это 00 значит имеются проблемы с идентификацией номера слоя (например есть тайлы для одного террейна и разных слоев).
     80 * Массив чисел со всеми найденными для этого террейна значениями слоя.
     81 * Списки Allow и Deny содержащие имена террейнов, на которые, соответственно, разрешен или запрещен переход.
     82 * Массив ссылок на все тайлы террейна.
     83 * Обратная ссылка на тайлсет, которому принадлежит террейн.
     84Также тут есть методы для:
     85 * Удаления\добавления тайлов. Работают по имени или индексу. Убеждаются что такой тайл имеется в террейне, затем удаляется на уровне тайлсета.
     86 * Удаления\добавления элементов Allow и Deny - с синхронизацией с вовлеченными террейнами и списками реальных имен файлов в объекте тайлсета.
     87 * Смена слоя. Работает независимо от того, есть ли проблемы со слоями, меняет слой, переименовывает файлы тех тайлов, от которых есть какой-то смысл, остальные тайлы (т.е. те переходы, которые больше не нужны) либо удаляются, либо переименовываются как будто бы в них был смысл (в зависимости от аргументов метода) - второй вариант может использоваться при смене слоя сразу для нескольких террейнов без потери перехода между ними. При наличии проблемы со слоями, даже если работает с удалением
     88
     89На уровне тайла вся работа обеспечивается классом '''TTile, который содержит''':
     90 * Ссылку на свой тайлсет.
     91 * Ссылку на свой слой.
     92 * Путь к bmp-файлу, с именем файла (строка).
     93 * Путь к файлу в тайлсете, с именем файла (может не совпадать с bmp если оно например 7z).
     94 * Ссылка на объект типа TTileTerrs - содержит информацию о структуре тайла (территории) в удобном для быстрой программной обработки виде.
     95 * Номер варианта тайла с такой структурой.
     96 * Булевое значение Exists - true если тайл реально существует в тайлсете а не только должен наличествовать в теории исходя из структуры террейнов на слоях и возможных переходов.
     97 * Булевое значение !IsValid - true если структура тайла соответствует одной из стандартных, если соответствия нет - тайл является одним из вариантов поворота для одной из стандартных конфигураций, а значит такой тайл требуется перевернуть в стандартную конфигурацию при нулевом повороте и переименовать.
     98Также тут есть методы для:
     99 * Загрузки информации о тайле по его имени (смотрит свойства тайлсета и ищет нужные файлы).
     100 * Метод, возвращающий строку с именем тайла.
     101 * Метод, возвращающий повернутую нужное количество раз bmp-ху тайла.
     102 * Метод, возвращающий bmp-ху тайла без поворотов (вызывает предыдущий метод с нулевым поворотом).
     103
     104'''Класс TTileTerrs''' был бы простой структурой если бы не имел методы сравнения двух объектов этого типа, поэтому он класс. '''Содержит''':
     105 * Строки A,B,C,D с именами террейнов в соотв. углах (справа налево, по строкам сверху вниз, A соответствует {Terr1} а D соответствует {Terr4} в имени тайла). Вот табличка расположения углов:
     106||A||B||
     107||C||D||
     108 * Ссылка на родной тайл.
     109Также содержит методы:
     110 * Для чтения террейнов в углах (т.е. ABCD) из имени-строки тайла (и записи в инфу объекта).
     111 * Для генерации имени тайла по ABCD без той части где указывается вариант тайла.
     112 * Метод, возвращающий integer - если аргумент не совпадает по структуре с тайлом (аргумент также типа TTileTerrs) - вернет -1, иначе - вернет количество поворотов которое нужно применить к аргументу чтобы структура тайла совпадала со структурой аргумента. Таким образом если возвращает 0 значит структура тайла и аргумента метода идентичны.
     113 * Перегрузка оператора == - при сравнении двух объектов этого типа этим оператором - соотв. возвращает true если объекты идентичны и false если чем-либо различаются.
     114
     115----
     116
     117 == Как определяется правильна ли структура тайла ==
     118
     119Для начала определимся с приоритетом террейнов. Приоритет определяется по имени террейна, в алфавитном порядке (не только для первой, для всех букв имени террейна). Чем выше в списке по алфавиту идет имя террейна тем выше его приоритет. В дальнейшем буду считать что террейн с наивысшим приоритетом имеет номер 1, террейн с приоритетом ниже номер 2, ниже номер 3 и так далее. На основе этого допущения определим стандартные структуры террейнов:
     120
     121 * Из двух террейнов-1:
     122||2||2||
     123||1||2||
     124 * Из двух террейнов-2:
     125||1||1||
     126||2||2||
     127 * Из трех террейнов-1:
     128||1||1||
     129||2||3||
     130 * Из трех террейнов-2:
     131||1||1||
     132||3||2||
     133 * Из трех террейнов-3:
     134||1||2||
     135||3||1||
     136 * Из четырех террейнов-1:
     137||1||2||
     138||3||4||
     139 * Из четырех террейнов-2:
     140||1||2||
     141||4||3||
     142 * Из четырех террейнов-3:
     143||1||3||
     144||2||4||
     145 * Из четырех террейнов-4:
     146||1||3||
     147||4||2||
     148 * Из четырех террейнов-5:
     149||1||4||
     150||2||3||
     151 * Из четырех террейнов-6:
     152||1||4||
     153||3||2||
     154
     155----
     156
     157 == Как это все по идее должно работать ==
     158
     159В начале программа создает верхний уровень - объект класса '''TTileSetsCollection'''. Все остальные уровни создаются конструкторами и прочими методами этого объекта и его вложенными объектами. Освобождение памяти во избежание утечек - там же, деструкторами классов и их методами. Программа должна позаботиться только о правильном удалении объекта '''TTileSetsCollection''' когда он станет не нужен.
     160
     161После создания объекта класса '''TTileSetsCollection''' - программа пробивает в его опции все необходимые пути, если нужно - !CallBack-метод, а затем вызывает нужный метод чтения информации тайлсетов.
     162
     163Данный метод - читает имена тайлсетов, их количество - и создает нужное количество подобъектов класса '''TTileSet'''. Обращаю внимание, что все вложенные в '''TTileSetsCollection''' объекты имеют обратные ссылки на "родительский" объект, т.е. тот объект в который они вложены - что позволяет этим объектам использовать информацию своего владельца и даже своих соседей и вложенных в соседей объектов.
     164
     165Для каждого объекта '''TTileSet''' вызывается метод чтения информации тайлсета. Причем перед запуском чтения тайлсета при необходимости вызывается !CallBack что позволяет индицировать процесс загрузки, например, в окошко с прогрессбаром.
     166
     167Метод чтения информации тайлсетов - для начала читает свой конфиг, если используется svn - читает информацию о ревизии. Если тайлсет сжат - первым делом выполняет синхронизацию с временной, несжатой версией тайлсета. Затем - производит поиск всех файлов с тайлами, подсчитывает их количество, после чего (либо одновременно - смотря как будет реализовано и как оптимальнее работает) выделяет нужное количество объектов в массив с тайлами и загружает в эти объекты информацию по всем найденным тайлам. Обновременно со вбивкой информации в основной массив - создаются объекты террейнов, слоев, в них вбивается соответствующая информация, в т.ч. присваиваются ссылки на объекты тайлов. По завершению всего этого процесса - все объекты террейнов и слоев уже созданы, в них есть массивы со ссылками на тайлы. После этого становится возможным составление списка террейнов по алфавиту и установка приоритета для них.
     168
     169После того как приоритеты расставлены - становится возможным понять - какой тайл имеет правильную конфигурацию, а какой, увы, нет. Сканируется список тайлов, обнаруженные неправильные тайлы добавляются в соответствующие списки и помечаются. Автоматического исправления таких тайлов не происходит, это делает отдельный метод, вызываемый программой, например по команде пользователя.
     170
     171Затем осуществляется генерация всех возможных тайлов-переходов - если такой переходный тайл уже наличествует, хотя-бы в количестве 1 (адЫн) штука - ничего не происходит, если же ни одного такого тайла найдено не было - создается объект тайла, с пометкой что файла картинки у него нет, ссылка на него добавляется во все соответствующие массивы соответствующих объектов.
     172
     173Собсно это все что касается механизма чтения информации о тайлсете. После его завершения - в объекте класса '''TTileSetsCollection''' содержится вся необходимая информация о всех имеющихся тайлсетов, более чем достаточная для вывода любой информации в интерфейс программы, в т.ч. дерева террейнов и тайлов.
     174
     175Кроме этого у всех объектов системы имеются дополнительные методы, которые не вызываются при чтении тайлсетов, и предназначены для непосредственного их вызова программой - например методы удаления\добавления тайлов, генерации переходных тайлов, исправления "неправильных" тайлов и т.д. Подробно расписывать эти методы смысле нет, ибо механизм их действия понятен их простого их описания, а описания же для них наличествуют выше в данном тексте, в списках методов классов.
     176
     177Спасибо за то что прочитали весь этот бред :).