Введение
Сегодня, мы разберем код инвентаря представленного в Wad. Кастомный инвентарь (Custom Inventory). Для начала, пройдите по ссылке, и скачайте wad. Затем, откройте его код в Slade или Doom Builder. После этого, можно начинать.
Разбор кода.
#define ITEM_NUMBER 6
define — это комманда для создания константы.
Синтаксис у define, следующий:
#define название_константы значение
Таким образом, константе присваивается значение.
В нашем случае, ITEM_NUMBER, задает максимальное количество предметов в инвентаре.
str posible_items[ITEM_NUMBER] = {"SuperShotgun","RocketLauncher","BFG9000","Chaingun","PlasmaRifle","Shotgun"};
str item_icons[ITEM_NUMBER] = {"SGN2A0","LAUNA0","BFUGA0","MGUNA0","PLASA0","SHOTA0"};
Массив posible_items принимает названия акторов оружия, они в будущем будут использоваться в SetWeapon. Принимает возможные варианты оружия.
Массив item_icons принимает названия иконок, которые будут отображаться у оружий. Например у оружия «SuperShotgun«, будет показываться иконка «SGN2A0«. Массивы posible_items и item_icons, связаны меж собой, это значит что индекс (значение между квадратных скобок [ ]) должен совпадать у обоих массивов.
int img_size = 64.0;
img_size — задает разрешение картинки ячейки. В нашем случае разрешение = 64×64 пикселя. В будущем этот размер будет использоваться для правильного построения таблицы предметов инвентаря.
str your_items[ITEM_NUMBER];
int item_slots[ITEM_NUMBER]; //automaticly generated array
Массив your_items — хранит предметы вашего инвентаря. Его мы будем генерировать автоматически, проверяя наличие предметов в инвентаре, и добавляя их в your_items.
Массив item_slots — указывает есть ли предмет в инвентаре. Если есть предмет, то 1, если нет то 0. Массив item_slots связан с массивом your_items (индексы одинаковые).
Script 1
script 1 (void)
{
ACS_NamedExecuteWait("InvInit",0,0,0,0);
ACS_NamedExecute("DrawInventory",0,0,0,0);
}
Скрипт 1 — это стартовый скрипт (именно он вызывается в KEYCONF). В нем вызывается скрипт InvInit, который заполняет массивы значениями. Следующий за ним скрипт DrawInventory, рисует инвентарь, и просчитывает нахождение мышки в каждой из ячеек.
InvInit
Далее разберем скрипт InvInit
script "InvInit" (void)
{
int i=0;
//clear arrays
while(i<ITEM_NUMBER)
{
your_items[i] = "none";
item_slots[i] = 0;
i++;
}
Здесь, мы задаем пустые значения массивам your_items и item_slots.
i=0;
while(i<ITEM_NUMBER)
{
int has_items = CheckInventory(posible_items[i]);
if(has_items)
{
your_items[i] = posible_items[i];
item_slots[i] = 1;
}
i++;
}
А здесь, с помощью CheckInventory, проверяем наличие каждого из предметов posible_items, в нашем инвентаре. Если нашелся предмет, то добавляем его в массив your_items, и занимаем его слот item_slots[i] = 1;
DrawInventory.
Далее идет скрипт DrawInventory, он кстати, основан на коде мышки из урока ACS. Управляем мышкой.:
script "DrawInventory" (void)
{
SetPlayerProperty(0,1,PROP_TOTALLYFROZEN);
Здесь, мы заморозили игрока.
int MouseX = 200.0;
int MouseY = 200.0;
bool MouseDown = false;
Создали нужные переменные. Далее вошли в бесконечные цикл while.
SetHudSize(640, 400, false);
SetFont("DOOMFONT");
В SetHudSize указали разрешение экрана и указали SetFont(«DOOMFONT»); для дебага.
int DeltaX = -GetPlayerInput(-1, INPUT_YAW);
int DeltaY = -GetPlayerInput(-1, INPUT_PITCH);
Несмотря на то что, игрок заморожен, мы все еще можем получить yaw и pitch через GetPlayerInput. Получаем yaw и pitch игрока.
yaw / pitch / roll — это 3D углы, подробно о них узнать, можно в уроке DECORATE. Добавляем гильзы.
int buttons = GetPlayerInput(-1, INPUT_BUTTONS);
MouseDown = buttons & BT_ATTACK;
Получили код нажатых кнопок GetPlayerInput(-1, INPUT_BUTTONS), и среди всего этого месива, при помощи битовой маски «&» выцепляем кнопку выстрела.
MouseX += DeltaX*0.05;
MouseY += DeltaY*0.05;
Уменьшаем чувствительность мыши
SetCVar("mouseX",MouseX);
SetCVar("mouseY",MouseY);
SetCVar("leftClick",MouseDown);
И присваиваем информацию о мышке, нашим кварам.
createTable(50.0,50.0,5,5);
С помощью createTable, рисуем инвентарь. Синтаксис у него следующий:
createTable(начальное_значение_x, начальное_значение_y, количество_рядов, количество_столбцов);
Далее, остальной код «DrawInventory» я разбирать не буду, потому-что он полностью копирует код мышки из ACS. Управляем мышкой.
//Mouse
if(MouseX > 640.0)
MouseX = 640.0;
if(MouseX < 0.0)
MouseX = 0.0;
if(MouseY > 400.0)
MouseY = 400.0;
if(MouseY < 0.0)
MouseY = 0.0;
if(!MouseDown)
SetFont("BAL1A0");
else
SetFont("BAL2A0");
HudMessage(s:"a";HUDMSG_PLAIN,1,CR_BRICK,floor(MouseX),floor(MouseY),0.1);
Delay(1);
}
Функция createTable является самой важной, и самой сложной. По этой причине я сделал несколько дополнительных функций облегчающих жизнь. Разберем каждую из них.
drawImage.
function void drawImage(str image, int id, int x, int y)
{
SetFont(image);
HudMessage(s:"a";HUDMSG_PLAIN,id,CR_BRICK,x,y,0.1);
}
Функция drawImage — это более простой способ рисования изображений. Код, я думаю понятен, если нет то посмотрите урок ACS. Печатаем на экране (HudMessage)
Синтаксис у drawImage следующий:
drawImage("название_изображения", id, x, y)
findIconForItem.
function str findIconForItem(str item_name)
{
int i = 0;
while(i<ITEM_NUMBER)
{
if(posible_items[i] == item_name)
return item_icons[i];
i++;
}
return "none";
}
Функция findIconForItem ищет иконку, по названию предмета item_name. Для этого функция findIconForItem ищет предмет item_name в массиве posible_items. Если находит, то по индексу «i» возвращает иконку предмета. Опять же, подобные трюки работают, только потому-что posible_items и item_icons связаны индексом. Если такого предмета не нашлось, в качестве иконки возвращается «none«.
drawItem.
function void drawItem(int index,int block_size, int image_id, int x, int y)
{
int block_size_div_2 = block_size/2;
if(item_slots[index] != 0)
{
drawImage(findIconForItem(your_items[index]), image_id+500, x+block_size, y+block_size);
SetFont("DOOMFONT");
int number_of_items = CheckInventory(your_items[index]);
if(number_of_items)
{
HudMessage(i:number_of_items;HUDMSG_PLAIN,image_id,CR_WHITE,x+block_size_div_2-5.0,y+block_size_div_2-5.0,0.1);
}
}
}
Функция drawItem рисует иконку предмета, и его количество. Синтаксис у него следующий:
drawItem(индекс, размер_ячейки, id_изображения, x, y);
- индекс — так как, данная функция вызывается в цикле. Ему нужно передавать индекс, что-бы перебирать массив последовательно.
- размер_ячейки — нужен, для вычисления смещения картинки.
- id — задает id для HudMessage.
- x,y — координаты, на которых рисуется предмет.
int block_size_div_2 = block_size/2;
Вычисляю смещение картинки.
if(item_slots[index] != 0)
Если предмет, по заданному индексу — существует.
drawImage(findIconForItem(your_items[index]), image_id+500, x+block_size, y+block_size);
То мы рисуем его иконку «findIconForItem(your_items[index])«. Задаем необходимый image_id и смещение, чтобы предмет находился внутри ячейки (ячейка рисуется отдельно).
SetFont("DOOMFONT");
int number_of_items = CheckInventory(your_items[index]);
if(number_of_items)
{
HudMessage(i:number_of_items;HUDMSG_PLAIN,image_id,CR_WHITE,x+block_size_div_2-5.0,y+block_size_div_2-5.0,0.1);
}
Далее, задаем нужный шрифт. Получаем количество предмета «number_of_items«. И если количество предмета не 0, то рисуем это количество на экране.
HudMessage(i:number_of_items;HUDMSG_PLAIN,image_id,CR_WHITE,x+block_size_div_2-5.0,y+block_size_div_2-5.0,0.1);
Функцию drawItem разобрали, и честно говоря, мы уже много чего разобрали. Функцию createTable, та в которой рисуется инвентарь, я разберу во следующем уроке.