3 января 2015 3.01.15 9 3389

Разработка игры. Бродилка. [Лог#1]

+14

Собираюсь разрабатывать игру, ничего сверх крутого, просто небольшая бродилка.
Процессом создания хотел бы поделиться с публикой данного сайта.
В первую очередь данный текст ориентирован на любителей игростроя — тех, кто хочет разрабатывать свои игрули или же просто интересуется как сие делается, возможно, процесс заинтересует и геймеров.

Не могу конкретно определить к чему относится данный пост — лог, обсуждение или же статья.

Не хочется обещать чего-то масштабного (в плане контента) так как боюсь, что по каким-то причинам не смогу это реализовать. Подобные логи планирую писать каждую неделю или около того.

Будут встречаться куски кода, преимущественно на Си\Си++ языке, возможно, будут различные WIP(working in progress) скриншоты моделей, самой игры (на поздней стадии).

Кому уже интересно могут узнать больше вот некое подобие дизайн-документа.

Теперь к теме:
Весьма странно начинать лог разработки не рассказав об игре хотя бы двух слов, связанно это с сегодняшней темой — предметы и инвентарь.
Будет затронута только программная часть т.е. без графики, а всю информацию будем выводить в консоль. В конце лог-статьи будет приведён код на языке С++. Тег code работал не так как я думал, а простой текст «ест» табуляцию, поэтому рекомендую скачать файл с исходным кодом.

А теперь приступим :)

Для начала определить структуру предмета необходимо… или же нет?
На самом деле, следует знать зачем эти всякие предметы нужны и на что они влияют, но тут ответ более-менее ясен — характеристики персонажа, но вот что это за характеристики? Это и следует обозначить.

// Характеристики
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 — перечисления.

Код, возможно, кого-то испугает, но на самом деле всё очень просто.
Мы имеем структуру описания предмета — это означает, что используя этот «бланк» можно будет обозначить любой предмет в игре.
Вот пример такого определения:

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;
};

Таким образом, можно манипулируя тремя параметрами получить различные предметы.
Должен заметить, что с названием предметов есть неприятный момент, например такой — «ЭПИЧНЫЙ труба»… такое можно исправить, но это уже на будущее :)

Вот скриншот с консоли программы, демонстрирующие генератор предметов:

Можно скачать код или посмотреть.

Это первая статья из цикла, поэтому принимаю различные предложения по улучшению подачи контента )
Хотелось бы разрабатывать игру не просто для себя, а совместно с сообществом т.е. пользователями данного ресурса ( по большей части игроками ).


Лучшие комментарии

Не забывай писать Первый Комментарий.
Такой вот вопрос: почему структуры? Почему не классы?
Для меня структуры — это что-то лёгкое, а вот классы уже более тяжёлые( много полей, функций-членов ), конечно с программной точки зрения разницы нет практически :)
использовал одинаковый функционал

Вот за это слово у нас в универе тебя бы четвертовали
3Д от 2Д сильно отличается? Вообще, анимация с точки зрения программирования сложная?
Есть подобие дизайн-документа(в статье есть ссылка), сейчас рисуются концепты.
Да, программировал графику как 2Д, так и 3Д, хоть и без крутых шейдеров.
Делал модельки, текстуры рисовал)
Бывает и я ленюсь, а иногда понимаю, что надо ещё где-то раздобыть кучу знаний по графике, программированию и т.д. — это тоже стопорит процесс.
Сильных отличий не заметил (использовал одинаковый функционал).
Делал классическую спрайтовую анимацию когда-то — показалось очень просто, а вот скелетную анимацию для 3Д так и не осилил (принцип понятен, только вот до кода дело не дошло).
Однажды хотел даже написать простую программку для спрайтовой анимации, хотя знал, что в интернете 100% есть подобная, но я же для себя )
Что-то кроме этого уже сделано?
С 3Д графикой или 2Д уже работал?
Спрашиваю потому что интересно и вообще я когда-то тоже хотел, но лень она такая(
Читай также