Добавлен DarkDes,
опубликован
Извиняюсь за не столь содержательный заголовок
ТЕМА: КОД
Генерация предметов
Весьма странно начинать лог разработки не рассказав об игре хотя бы двух слов, да ещё и издалека — предметы и инвентарь.
Будет затронута только программная часть т.е. без графики, а всю информацию будем выводить в консоль. В конце лог-статьи будет приведён код на языке С++.
Будет затронута только программная часть т.е. без графики, а всю информацию будем выводить в консоль. В конце лог-статьи будет приведён код на языке С++.
А теперь приступим :)
Характеристики
Для начала определить структуру предмета необходимо… или же нет?
На самом деле, следует знать зачем эти всякие предметы нужны и на что они влияют, но тут ответ более-менее ясен — характеристики персонажа, но вот что это за характеристики? Это и следует обозначить.
На самом деле, следует знать зачем эти всякие предметы нужны и на что они влияют, но тут ответ более-менее ясен — характеристики персонажа, но вот что это за характеристики? Это и следует обозначить.
// Характеристики
struct sAttributes
{
short health; // Здоровье
short shield; // Щит
short defence; // Оборона (глушитель урона)
short damage; // Урон
};
Если Вам знаком синтаксис языка Cи, то вопросов возникнуть не должно, а для тех кто «не в теме», следует пояснить кое-что, но не углубляться в подробности: (лучше найти информацию в интернете, а то я плохо объясняю)
struct название_структуры
{
тип переменная; // комментарий
};
Теперь у нас есть структура определяющая характеристики.
Можно завести структуру и для персонажа, затем для предмета, но лучше не спешить и немного подумать.
Можно завести структуру и для персонажа, затем для предмета, но лучше не спешить и немного подумать.
Описание предмета
Каждый предмет в игре лучше «зарегистрировать» т.е. записать их в особый список, который будет хранить всю «статичную» информацию о предметах ( характеристики, например ).
А оперировать в инвентаре будем с более простой структурой предмета, которая будет ссылаться на информацию предмета в списке.
А оперировать в инвентаре будем с более простой структурой предмета, которая будет ссылаться на информацию предмета в списке.
// Качество
enum eQuality
{
EQ_COMMON =0, // Обычный
EQ_STANDARD =1, // Стандартный (в чём отличие от обычного?)
EQ_HANDMADE, // Самопальный
EQ_LEGENDARY, // Легендарный
EQ_EPIC, // Эпичный
Count_Quiality // так узнаем кол-во
};
// Тип предмета, если установлен в OTHER, то может быть произвольный
enum eKind // TYPE
{
Kind_WEAPON = 0, // Оружие
Kind_ARMOR, // Броня
//Kind_POTION,
Kind_OTHER
};
// Бит-флаги предмета
enum eItemFlag
{
IF_CLEAR = 0x0000,
IF_EQUIP = 0x0001, // Можно экипировать
IF_COLLECTABLE = 0x0002, // Занимает один слот, записывая кол-во
IF_USABLE = 0x0004, // Можно использовать
IF_QUEST = 0x0008 // Предмет, необходимый по сюжету\квесту (нельзя выбросить, слот не учитывается)
};
// Описание предмета для глобального списка
struct sItemDescription
{
// Уникальный ID
unsigned long ID;
string name; // название предмета для отображения
string desc; // описание
sAttributes attrib;
eQuality qual; // качество
eKind kind; // тип
long falgs; // бит-флаги
// Визуальная информация
int modelID; // номер 3Д модели
int textureID; // номер текстуры для 3Д модели
int pictureID; // номер картинки\текстуры\иконки для отображения в инвентаре
// Цена предмета, можно задать вручную или же воспользоваться специальной функцией
int cost;
};
- Эй! Что такое unsigned long, string и eQuality ?
unsigned означает, что наша переменная имеет исключительно положительное значение (для целочисленных типов).
long - аналогично как и short, однако, занимает больше памяти и следовательно может иметь больше значений.
string - тип описывающий строку текста (из стандартной C++ библиотеки).
eQuality и eKind - перечисления.
unsigned означает, что наша переменная имеет исключительно положительное значение (для целочисленных типов).
long - аналогично как и short, однако, занимает больше памяти и следовательно может иметь больше значений.
string - тип описывающий строку текста (из стандартной C++ библиотеки).
eQuality и eKind - перечисления.
Код, возможно, кого-то испугает, но на самом деле всё очень просто.
Мы имеем структуру описания предмета - это означает, что используя этот "бланк" можно будет обозначить любой предмет в игре.
Вот пример такого определения:
Мы имеем структуру описания предмета - это означает, что используя этот "бланк" можно будет обозначить любой предмет в игре.
Вот пример такого определения:
sItemDescription SuperSword;
SuperSword.ID = CurID++; // Для каждого предмета считается свой ID
SuperSword.name = "Супер меч";
SuperSword.desc = "Лишь избранный может нести его";
SuperSword.attrib.health = 0;
SuperSword.attrib.shield = 0;
SuperSword.attrib.defence = 0;
SuperSword.attrib.damage = 20;
SuperSword.kind = Kind_WEAPON; // Тип "оружие"
SuperSword.qual = EQ_LEGENDARY; // Качество предмета как "Легендарный"
SuperSword.falgs = IF_EQUIP; // можно экипировать
SuperSword.cost = ItemCost( SuperSword ); // Вычислим стоимость предмета
И это очень простой предмет, а представьте если их, скажем, 20 .. это же жуть их так все описывать, поэтому напрашивается идея генерации этих самых предметов. Разумеется представленный мой способ не очень, но надо же начать с чего-то :)
Генератор
Это функция, принимающая в качестве аргумента требования к процедурному предмету (смотри ниже).
sItemDescription GenerateItem( const sItemGenerationDesc &gendesc )
{
sItemDescription desc;
desc.ID = CurID++;
desc.kind = gendesc.kind;
desc.qual = gendesc.quality;
desc.attrib.health = 0;
desc.attrib.defence = 0;
desc.attrib.damage = 0;
desc.attrib.shield = 0;
if( desc.kind == Kind_WEAPON )
{
desc.name = QualityToString(desc.qual) + " " + weapons_names[ RandomRange(0,weapons_names_count) ];
// Лихо рассчитываем параметр используя качество, начальное значение и великий рандом
desc.attrib.damage = gendesc.attribs_ranges.damage + ((int)desc.qual) * RandomRange( 0, 4 );
desc.falgs = IF_EQUIP;
}else
if( desc.kind == Kind_ARMOR )
{
desc.name = QualityToString(desc.qual) + " " + armor_names[ RandomRange(0,armor_names_count) ];
desc.attrib.shield = gendesc.attribs_ranges.shield + ((int)desc.qual) * RandomRange( 0, 2 );
desc.attrib.defence = gendesc.attribs_ranges.defence + RandomRange( 0, 2 );
desc.falgs = IF_EQUIP;
}
desc.cost = ItemCost( desc ); // Вычисляем цену
desc.desc = "Этот предмет сгенерирован программой"; // описание описания, извините за тавтологию
return desc;
}
А что-то за структура sItemGenerationDesc ?
struct sItemGenerationDesc
{
eQuality quality; // Качество, которое мы хотим дать предмету
eKind kind; // Тип предмета - оружие, броня или может ещё что
sAttributes attribs_ranges; // Разброс по атрибутам или их начальное значение
};
Таким образом, можно манипулируя тремя параметрами получить различные предметы.
Должен заметить, что с названием предметов есть неприятный момент, например, такой - "ЭПИЧНЫЙ труба" ... такое можно исправить, но это уже на будущее :)
Должен заметить, что с названием предметов есть неприятный момент, например, такой - "ЭПИЧНЫЙ труба" ... такое можно исправить, но это уже на будущее :)
Вот скриншот с консоли программы, демонстрирующие генератор предметов:
Можно скачать код или посмотреть.
Безусловно этот код изменится, ведь данная программа больше написана для тестирования.
Это первая статья из цикла, поэтому принимаю различные предложения по улучшению подачи контента )
Хотелось бы разрабатывать игру не просто для себя, а совместно с сообществом.
Хотелось бы разрабатывать игру не просто для себя, а совместно с сообществом.
Что дальше?
На радаре концепт арты врагов! Если не терпится посмотреть на них, то можете разыскать их на сайте стопгейм.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Я не предлагаю сидеть на всем готовом. Нормальный движок не будет сажать тебя в свою песочницу, закидывать игрушками и говорить "сиди тут и не дергайся", нормальный движок дает ящик с инструментами и выкидывает на улицу. Нужно грамотно использовать реюзаемые части кода и инструменты, чтобы создать энвайронмент под себя.
Отредактирован nvc123
но только при условии что накопилось достаточно кода который можно использовать повторно
и сборка велосипеда помогает узнать как он устроен
Собственный движок нужен только для высоко-производительных вещей или для реализации каких-то необычных технологий, которые к уже готовым движкам стыкуются чуть более чем никак.
Заказчику искренне пофиг на твою нелюбовь к готовым движкам, ему важен результат и за приемлимое время. Проще говоря, заказ явно выполнит быстрее человек, не побрезговавший воспользоваться тем же Unity, чем тот, кто из принципа будет писать велосипеды.
Долгострои редко нормально окупаются...
Инди разработчик делает игру так, как ему хочется, поэтому для него это не так критично.
Если делать игру ради процесса написания движка - вперед. Дальше 95% людей не уйдут. Я слишком много сидел на ресурсах по геймдеву чтобы этого не знать. Две типичные новичковские ошибки - брать и пытаться делать на ВСЁМ готовом и делать ВСЁ с нуля. Грамотно совмещайте и все будет оки.
Отредактирован Doc
Вон кстати enhaton дело говорит.
Отредактирован Kozinaka