Паттерны программирования игр
— Паттерны поведения
217
break;
}
case INST_GET_WISDOM:
case INST_GET_AGILITY:
// …
Работа со стеком идет в обоих направлениях. Ин-
струкции забирают параметр из стека, чтобы опреде-
лить, для какого из колдунов необходимо изменить по-
казатели, а затем считывают значение выбранного
показателя и снова помещают его в стек.
Таким образом можно копировать значения показа-
телей друг для друга. Мы могли бы создать заклинание,
уравняющее ловкость колдуна с его мудростью, или дру-
гое, немного странное заклинание, которое позволит
уравнять показатели здоровья двух противников.
Уже интереснее, но пока весьма ограниченно. Нам
нужна арифметика. Время научить нашу маленькую
виртуальную машину складывать 1+1. Добавим еще не-
сколько инструкций. К этому моменту вы уже понима-
ете принцип и сможете сами догадаться, как инструк-
ции будут выглядеть. Я покажу сложение:
case INST_ADD:
{
int b = pop();
int a = pop();
push(a + b);
break;
}
Видите, инструкция снова извлекает из стека два зна-
чения, обрабатывает их, а затем помещает результат об-
ратно в стек. Раньше каждая добавленная инструкция
немного увеличивала функциональность языка, но эта —
настоящий прорыв. Может, вам не очевидно, но на самом
деле сейчас мы можем обрабатывать все виды сложных
многократно вложенных арифметических выражений.
218
Байт-код (Bytecode) —
Паттерны программирования игр
Рассмотрим чуть более сложный пример. Допустим,
нам нужно заклинание, которое увеличивает значение
показателя здоровья колдуна на среднее арифметиче-
ское от его ловкости и мудрости. Код такой:
setHealth(0, getHealth(0) +
(getAgility(0) + getWisdom(0)) / 2);
Вы можете подумать, что нам понадобятся инструк-
ции для обработки группировки, которая создается
из-за вложенности. Но она уже подразумевается в стеке.
Вот как вы могли бы вычислить это значение вручную.
1. Получим текущее значение показателя здоровья
колдуна и запомним его.
2. Получим значение показателя ловкости и запом-
ним его.
3. То же самое для мудрости.
4. Берем два последних значения, складываем их
и запоминаем результат.
5. Разделим его на 2 и запомним результат.
6. Вспомним значение показателя здоровья и доба-
вим его к результату.
7. Возьмем результат и установим его в показатель
здоровья.
Видите все эти «запомним» и «вспомним»? Каждое
«запомним» эквивалентно помещению в стек, а каждое
«вспомним» — извлечению из него. Следовательно, мы
легко переведем наши задания в байт-код. Первая стро-
ка будет выглядеть так:
LITERAL 0
GET_HEALTH
Это фрагмент байт-кода помещает текущее значение
показателя здоровья в стек. Если мы продолжим так же
механически переводить каждую строку, в итоге мы
Do'stlaringiz bilan baham: |