Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 18.10.2018, 18:36
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 11  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Tails, у меня к тебе вопрос по поводу используемой тобой реляционной модели. Вот смотри, я загоняю справочные данные в реляционные таблицы. Например, там могут быть профили каких-нибудь атак, как в примере, который ты приводил ранее в другой ветке. Так вот, этих самых атак может быть условно пяток видов по качеству (урон огнём, водой и т.п., в т.ч сочетания), при этом цифры по каждому виду имеют какой-то разброс. Таким образом, возможных уникальных комбинаций с ходу может за сотню зашкалить.

Каким образом ты создаёшь и систематизируешь идентификаторы подобных записей, чтобы потом ориентироваться в них и не сойти с ума?
__________________
Не сломано - не чини!

Старый 18.10.2018, 19:37
Tails вне форума Посмотреть профиль Отправить личное сообщение для Tails Найти все сообщения от Tails
  № 12  
Ответить с цитированием
Tails
 
Аватар для Tails

блогер
Регистрация: Dec 2008
Адрес: г. Чебоксары
Сообщений: 2,259
Записей в блоге: 6
Например так: (Сущности и их свойства)
Тип атаки: id.
Атака: id, тип, damage, cooldown
Юнит: id, name, attack1, attack2

Код AS3:
// Заполняем таблички.
// Типы атак:
attackTypes.add(1); // Физическая.
attackTypes.add(2); // Огненная.
attackTypes.add(3); // Ледяная.
 
// Атаки:
attacks.add(1, 1, 100, 2); // Физическая атака, 100 урона, 2 сек кд.
attacks.add(2, 1, 500, 10); // Физическая атака, 500 урона, 10 сек кд.
attacks.add(3, 2, 2000, 100); // Огненная атака, 2000 урона, 100 сек кд.
 
// Юниты:
units.add(1, "Goblin", 1, 0); // Гоблин, может лупить физ уроном.
units.add(2, "Mage", 3, 0); // Маг, может лупить фаерболами.
units.add(3, "Paladin", 2, 3); // Паладин, может лупить сильным физ уроном и ещё параллельно кастовать фаерболы.
units.add(4, "Rabbit", 0, 0); // Безобидный кролик.
Обрати внимание, что из этих данных мы всё обо всех знаем. В коде нам не надо пилить никаких дополнительный условий сравнения типов, наследников и т.п.

Примерно такая структура в игре Warcraft 3. У них один юнит может иметь не более 2 атак. Ещё, id типа атаки можно захардкодить, так-как он не будет меняться от проекта к проекту. Это очень удобно:
Код AS3:
attackTypes.add(AttackType.PHYSICS); // Физическая.
attackTypes.add(AttackType.FIRE); // Огненная.
attackTypes.add(AttackType.ICE); // Ледяная.
Потом, в коде движка оперировать константами, а не волшебными числами, в формулах расчёта урона и т.п. Хороший пример, как некоторые данные зашиты в движок (ID Типа атаки). Движок просто берёт эту структуру и просчитывает её. Всё что ему нужно знать есть в табличках. Структуру данных ты можешь взять откуда угодно, захардкодить, загрузить с диска или из сети. Юниты другие, игра другая, а код тот-же.
__________________
Дети не должны знать о своих родителях

Старый 19.10.2018, 10:07
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 13  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Угу, более-менее ясно. Скажи, пожалуйста, какого типа переменные attackTypes, attacks и units и что делает метод add()? Здесь интерфейс используется?

Мне представлялось, что классы-парсеры - это "статики".

Добавлено через 4 часа 51 минуту
...да, и если взять твой блок кода с атаками, то там теоретические может быть та самая сотня записей. Как удержать в голове, что "1" - это физическая на 100, "3" - это магическая на 2000, а "103" - это холодом на 40? В этом собственно и был исходный вопрос.
__________________
Не сломано - не чини!

Старый 19.10.2018, 22:45
Tails вне форума Посмотреть профиль Отправить личное сообщение для Tails Найти все сообщения от Tails
  № 14  
Ответить с цитированием
Tails
 
Аватар для Tails

блогер
Регистрация: Dec 2008
Адрес: г. Чебоксары
Сообщений: 2,259
Записей в блоге: 6
Цитата:
Какого типа переменные attackTypes, attacks и units
Списки с доступом данных по id или перечислением. Хранят соответствующие записи сущностей: AttackType, Attack и Unit соответственно.

Цитата:
Что делает метод add()
Метод списка, добавляет новую запись.

Цитата:
Здесь интерфейс используется?
Интерфейс, который Intarface? (Конструкция языка AS3) Нет, список - это просто обёртка над Object или Vector, с некоторыми публичными методами для удобной работы с данными. (Доступ записи по ID, как минимум)

Цитата:
Мне представлялось, что классы-парсеры - это "статики".
Это отдельный вопрос, я его тут никак не освещал. Парсер будет отдельным классом. Статики - плохо, лучше использовать обычный экземпляр класса, если нет конкретных причин для статики. Из соображений невозможности наследования статиков.

Цитата:
...да, и если взять твой блок кода с атаками, то там теоретические может быть та самая сотня записей. Как удержать в голове, что "1" - это физическая на 100, "3" - это магическая на 2000, а "103" - это холодом на 40?
Никак. Это структура данных, она предназначена не для запоминания людьми, а для удобного представления данных в памяти приложения, возможности расширения и т.д. Это данные для машины. Если работать с голыми данными становится сложно - пишется редактор, который будет отображать их для человека в удобном виде, с выпадающими списочками, подсветкой зависимостей и т.д. Если структура данных слишком сложная, то такая админка будет обязательно нужна.

Добавлено через 1 час 29 минут
пс. Обычно, каждый юнит имеет собственную, уникальную запись атаки. То есть, 2 юнита не могут ссылаться на одну и ту-же запись.

Если запись атаки уникальная для каждого юнита:
Отношение "1 к 1", можно редактировать атаку у каждого юнита отдельно.

Если запись атаки может быть общей для многих юнитов:
Отношение "1 к многим", редактируя одну запись, атака меняется у всех владельцев.

Это вопрос к проектированию бд, что конкретно требуется. Я привел пример "1 к многим" чисто для понимания связывания данных.
__________________
Дети не должны знать о своих родителях

Старый 20.10.2018, 00:22
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 15  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Прости мне моё занудство. Я на принципиальном уровне идею прекрасно понимаю (и имею опыт работы с реляционными СУБД как пользователь), но чего-то никак в голову не укладывается практическая реализация в создаваемой программе.

Цитата:
Сообщение от Tails Посмотреть сообщение
Списки с доступом данных по id или перечислением. Хранят соответствующие записи сущностей: AttackType, Attack и Unit соответственно.
Не совсем понимаю, что ты подразумеваешь под списками. Или это и есть те самые классы, которые непосредственно взаимодействуют с json-таблицами?

Я себе как представлял твой пример. Класс атаки примерно такой:

Код AS3:
public class Attack
{
private var _id: uint;
private var _type: uint;
private var _damage: int;
private var _cooldown: uint;
 
public function Attack (id: uint)
{
_id = id;
var jsonData: Object = JsonAttackData.getData(_id);
_type = jsonData[type];
_damage = jsonData[damage];
_cooldown = jsonData[cooldown];
}
То есть в момент, когда нам требуется данная атака, программа создаёт экземпляр приведённого мной класса,
который получает в конструктор требуемый id, по нему ломится в класс-парсер, обслуживающий соответствующую json-таблицу, и получает от статического метода все остальные данные из таблицы.

Цитата:
Метод списка, добавляет новую запись.
Добавляет куда? В json-таблицу?

Цитата:
Интерфейс, который Intarface? (Конструкция языка AS3) Нет, список - это просто обёртка над Object или Vector, с некоторыми публичными методами для удобной работы с данными. (Доступ записи по ID, как минимум)
Ну да, который конструкция. Если у разных классов одинаковый публичный метод add(), то это похоже на использование интерфейса. Или это всё-таки не разные классы, а наследники?

Цитата:
Это отдельный вопрос, я его тут никак не освещал. Парсер будет отдельным классом. Статики - плохо, лучше использовать обычный экземпляр класса, если нет конкретных причин для статики. Из соображений невозможности наследования статиков.
Не понимаю, как этого можно добиться. Если у наших таблиц разное число полей и данные в них могут быть разного типа, то как ещё сделать можно? Один базовый класс и пачку наследников - по одному на каждый вид таблицы? Они же должны ещё "знать" и названия полей таблиц.
__________________
Не сломано - не чини!

Старый 20.10.2018, 02:07
Tails вне форума Посмотреть профиль Отправить личное сообщение для Tails Найти все сообщения от Tails
  № 16  
Ответить с цитированием
Tails
 
Аватар для Tails

блогер
Регистрация: Dec 2008
Адрес: г. Чебоксары
Сообщений: 2,259
Записей в блоге: 6
Вот, я набросал небольшой пример. Есть реализация данных в отдельном JSON, парсинг.
Вложения
Тип файла: zip HumansZoo.zip (23.3 Кб, 35 просмотров)
__________________
Дети не должны знать о своих родителях

Старый 20.10.2018, 16:13
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 17  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Tails, огромное спасибо, тронут твоей заботой. Пример разобрал, теперь всё встало на места. Поясни ряд мелких моментов, плиз:

Я верно понял, что объявление переменных в классах AttackData, AttackTypeData и UnitData публичными - это такой коммунистичный вариант реализации дата-класса, чтобы не запариваться с приватными переменными и комплектом сеттеров-геттеров? Меня смущает, что раз данные всё-таки из таблицы переписываются в поля класса для дальнейшего использования, нет риска, что они в процессе будут изменены и тем самым поломаны? Почему всё-таки не используешь приватные? Чтобы парсер передавал значения прямо в конструктор создаваемого дата-класса, а забирать геттерами?

У тебя в момент запуска приложения все данные из json-таблиц читаются, парсятся и перегоняются в объекты-списки. Больше в рантайме исходные json-таблицы не используются, все классы Модели обращаются к классам-спискам, зная id нужных им вещей. Так?

Формат json-таблицы тоже весьма нестандартный у тебя. Так как это не классическая 2-мерная таблица "ключ: значение", а наборы "ключ: массив значений". Чем ты создашь их? Только самописный редактор или есть какие-то варианты заполнять комфортно вручную и потом экспортировать в подобный формат?
Я пока нашёл плагин для Гугл.докс, но он по-моему так не умеет

Твой вариант 100% отлично подходит для хранения справочных данных. А что ты делаешь с данными, которые меняются в рантайме? Тоже их по подобным спискам распихиваешь?

Добавлено через 2 минуты
P.S. Забыл... Почему обжекты хэшами называют?
__________________
Не сломано - не чини!

Старый 20.10.2018, 16:51
Tails вне форума Посмотреть профиль Отправить личное сообщение для Tails Найти все сообщения от Tails
  № 18  
Ответить с цитированием
Tails
 
Аватар для Tails

блогер
Регистрация: Dec 2008
Адрес: г. Чебоксары
Сообщений: 2,259
Записей в блоге: 6
Цитата:
Я верно понял, что объявление переменных в классах AttackData, AttackTypeData и UnitData публичными - это такой коммунистичный вариант реализации дата-класса, чтобы не запариваться с приватными переменными и комплектом сеттеров-геттеров? Меня смущает, что раз данные всё-таки из таблицы переписываются в поля класса для дальнейшего использования, нет риска, что они в процессе будут изменены и тем самым поломаны? Почему всё-таки не используешь приватные? Чтобы парсер передавал значения прямо в конструктор создаваемого дата-класса, а забирать геттерами?
В конструктор передаю только id, иначе потом не очень удобно работать. В парсере, например. Лучше обращаться по имени свойства. Сами свойства открывать/закрывать для прямого редактирования геттер/сеттерами - дело автора. Я вот решил для простоты не усложнять.

Цитата:
У тебя в момент запуска приложения все данные из json-таблиц читаются, парсятся и перегоняются в объекты-списки. Больше в рантайме исходные json-таблицы не используются, все классы Модели обращаются к классам-спискам, зная id нужных им вещей. Так?
Да, всё верно. Зачем каждый раз парсить JSON? Это будет очень накладно, неудобно и можно легко ошибиться из-за отсутствия типизации.

Цитата:
Формат json-таблицы тоже весьма нестандартный у тебя. Так как это не классическая 2-мерная таблица "ключ: значение", а наборы "ключ: массив значений". Чем ты создашь их? Только самописный редактор или есть какие-то варианты заполнять комфортно вручную и потом экспортировать в подобный формат?
Ключ - имя таблицы, массив - её записи. Этот json написал вручную. Для небольших структур данных это не сложно. На больших проектах я использую админку или редактор.

Цитата:
Твой вариант 100% отлично подходит для хранения справочных данных. А что ты делаешь с данными, которые меняются в рантайме? Тоже их по подобным спискам распихиваешь?
Данные в рантайме будут находиться в объекте World из этого примера. Там тоже будут аналогичные списки, только, они ещё будут пулять события (Унаследованы от EventDispatcher) при добавлении/удалении из списка, изменения их свойств и т.д. События нужны для тех, кому интересно что происходит в игровом мире. (Вьюшке, например)
Например, если класс UnitData описывает юнит, то представление конкретного юнита в рантайме будет что-то вроде:
Unit:
id - ID Юнита. (Не путать с UnitData.id)
unitID - ID Описания юнита. (Ссылка на UnitData)
life - Текущее здоровье этого юнита.
...

Например, если на карте будет 10 гоблинов, у нас будет 10 записей Unit:
{ id:1, unitID:2, life:55 }
{ id:2, unitID:2, life:45 }
{ id:3, unitID:2, life:100 }
...

Цитата:
P.S. Забыл... Почему обжекты хэшами называют?
Я называю. Потому что Object реализует интерфейс хеш-таблицы. (Ассоциативный массив)
https://ru.wikipedia.org/wiki/%D0%A5...B8%D1%86%D0%B0
__________________
Дети не должны знать о своих родителях

Старый 20.10.2018, 17:05
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 19  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Цитата:
Сообщение от Tails Посмотреть сообщение
Данные в рантайме будут находиться в объекте World из этого примера. Там тоже будут аналогичные списки, только, они ещё будут пулять события (Унаследованы от EventDispatcher) при добавлении/удалении из списка, изменения их свойств и т.д. События нужны для тех, кому интересно что происходит в игровом мире. (Вьюшке, например)

Например, если на карте будет 10 гоблинов, у нас будет 10 записей Unit:
{ id:1, unitID:2, life:55 }
{ id:2, unitID:2, life:45 }
{ id:3, unitID:2, life:100 }
...
Да, очень круто! То есть если в процессе игры гоблину прилетело от мага, то его life в списке будет отминусован, о чём список ещё и уведомит всех желающих.
__________________
Не сломано - не чини!


Последний раз редактировалось Appleman; 20.10.2018 в 17:21.
Старый 20.10.2018, 17:31
Tails вне форума Посмотреть профиль Отправить личное сообщение для Tails Найти все сообщения от Tails
  № 20  
Ответить с цитированием
Tails
 
Аватар для Tails

блогер
Регистрация: Dec 2008
Адрес: г. Чебоксары
Сообщений: 2,259
Записей в блоге: 6
UnitData.life - Максимальное здоровье этого типа юнита.
Unit.life - Текущее здоровье конкретного юнита.
Это разные переменные. Можно написать UnitData.lifeMax, если это вводит в заблуждение.

UnitData - Описывает класс юнитов. Unit - Описывает конкретного юнита. Конкретным юнитом может быть кто угодно, Маг, Гоблин и т.д., смотря на кого он ссылается через unitID.

Цитата:
В классах юнитов у тебя только методы реализованы?
Какие методы? Обычно нет, обычно всё взаимодействие с миром происходит через апи объекта World. Например, для добавления юнита в мир, нужно вызывать не world.units.add() (Хотя этот метод есть у списка юнитов), а world.unitAdd(). Дело в том, что там бывает нужно не просто добавить юнит, а ещё выполнить некоторые другие действия, в том числе с другими списками. Кд обнулить, цену заплатить и т.д. Объект world содержит публичное апи для взаимодействия с игровым миром.
world.unitAdd()
world.unitKill()
world.buyUnit()

Ну, я тут уже не знаю. Тут уже зависит от проекта, что кому и как нужно.
__________________
Дети не должны знать о своих родителях

Создать новую тему Ответ Часовой пояс GMT +4, время: 21:06.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 21:06.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.