210
Байт-код (Bytecode) —
Паттерны программирования игр
базовыми операциями игрового движка были бы опре-
делены заклинания? Большинство заклинаний будут из-
менять один из показателей колдуна, начнем с этого:
void setHealth(int wizard, int amount);
void setWisdom(int wizard, int amount);
void setAgility(int wizard, int amount);
Первый параметр указывает того колдуна, на чьи по-
казатели влияет заклинание, например 0 для игрока и
1
для его соперника. Таким образом, лечащие заклинания
колдун может применить сам на себя, а атакующие —
на врагов. Этими тремя простыми методами можно вы-
разить огромное разнообразие магических заклинаний.
Если заклинание будет просто тихо изменять состоя-
ния, то с точки зрения логики игры все останется нор-
мально, а вот пользователю станет скучно. Исправим
положение:
void playSound(int soundId);
void spawnParticles(int particleType);
На игровом процессе изменения не отразятся, а
вос-
приятие
будет совсем другим. Мы могли бы добавить
анимацию и сотрясающуюся камеру, но для начала
и так сойдет.
Волшебный набор инструкций
А теперь посмотрим, как превратить этот
программный
API в нечто, управляемое данными. Начнем с простого
и постепенно осветим все тонкости. Сейчас просто при-
вяжем параметры к методам. Методы
set___()
всегда
влияют на состояние колдуна, улучшая его показатели.
Точно так же операции спецэффектов всегда воспроиз-
водят один и тот же звук и визуальный эффект, жестко
прописанные в коде.
Теперь заклинание стало просто серией инструкций,
каждая из которых определяет, какую операцию вы хо-
тите выполнить. Мы можем их перечислить:
Паттерны программирования игр
— Паттерны поведения
211
enum Instruction
{
INST_SET_HEALTH = 0x00,
INST_SET_WISDOM = 0x01,
INST_SET_AGILITY = 0x02,
INST_PLAY_SOUND = 0x03,
INST_SPAWN_PARTICLES = 0x04
};
Чтобы закодировать заклинание в данные, нам по-
надобится хранить массив значений
enum
. У нас не так
много элементов, поэтому все значения
enum
лег-
ко поместятся в один байт. А значит, код заклинаний,
по сути, — просто список байтов, то есть байт-код.
Чтобы выполнить инструкцию, мы смотрим, какому
элементу она соответствует, и ссылаемся на нужный ме-
тод API:
switch (instruction)
{
case INST_SET_HEALTH:
setHealth(0, 100);
break;
case INST_SET_WISDOM:
setWisdom(0, 100);
break;
case INST_SET_AGILITY:
setAgility(0, 100);
break;
case INST_PLAY_SOUND:
playSound(SOUND_BANG);
break;
case INST_SPAWN_PARTICLES:
spawnParticles(PARTICLE_FLAME);
break;
}
Таким образом, наш интерпретатор становится мо-
стом между миром кода и миром данных. Мы можем
Иногда байт-код для ВМ
использует более од-
ного байта для инструк-
ции, да и правила интер-
претации более
сложные. Настоящий
машинный код для
обычного чипа с архи-
тектурой x86 на поря-
док сложнее.
Но использование
единственного байта
вполне приемлемо для
виртуальной машины
Java и Common Language
Runtime компании
Microsoft, который яв-
ляется основой плат-
формы .NET, а значит —
нам подходит.
Do'stlaringiz bilan baham: |