Паттерны программирования игр
— Паттерны уменьшения связанности
307
if (channel == –1) return;
startSound(resource, channel,
pending_[i].volume);
}
numPending_ = 0;
}
// 6 …
};
Сейчас нам нужно просто вызвать код из какого-ни-
будь удобного места. Где оно — целиком и полностью
зависит от вашей игры. Это может быть главный цикл
игры или выделенный аудиопоток.
Такая реализация работает неплохо, но не подра-
зумевает обработки
каждого
запроса на воспроизве-
дение звука с помощью единственного вызова метода
update()
. Если вы делаете что-то наподобие асинхрон-
ной обработки запроса после загрузки ресурса, это
не сработает. Чтобы
update()
мог обрабатывать за-
просы по одному, у него должна быть возможность из-
влекать один из них из буфера, оставляя там остальные.
То есть нам нужна настоящая очередь.
Циклический буфер
Есть множество способов реализовать очередь, но мне
симпатичнее всего
циклический
буфер
. В нем сохраняет-
ся все, что выходит за границы буфера путем постепен-
ного вытеснения элементов из начала очереди.
Да, я знаю, о чем вы думаете. Если удалять элементы
из начала буфера, не надо ли нам смещать все остальные
элементы? Не замедлится ли игра?
Вот почему иногда мы вынуждены пользоваться свя-
занными списками: они позволяют нам исключать эле-
менты без необходимости смещать все остальные. Ока-
зывается, и массив можно реализовать таким образом,
что ничего смещать не придется. Я вам покажу как,
но сначала позвольте ввести несколько терминов.
308
Очередь событий (Event Queue) —
Паттерны программирования игр
• Голова
очереди — то место, откуда начинают
счи-
тываться
запросы. Головой является самый ста-
рый из ожидающих обработки запросов.
• Хвост
— другой конец. В эту ячейку массива
запи-
сывается
следующий полученный запрос. Обрати-
те внимание: он указывает на первую пустую ячей-
ку справа от очереди. Можете представлять его как
полуоткрытый интервал, если вам так будет проще.
Поскольку метод
playSound()
помещает запрос
в конец массива, голова начинается на нулевом элемен-
те, а хвост растет вправо (рис. 15.3).
Рис. 15.3.
Заполнение массива запросами
Опишем это в коде. Для начала немного изменим
поля, чтобы обозначить маркеры в классе:
class Audio
{
public:
static void init()
{
head_ = 0;
tail_ = 0;
}
// @ …
private:
static int head_;
static int tail_;
// @ …
};
В такой реализации метода
playSound()
поле
numPending
_ было заменено на
tail_
. Но в остальном
он остался прежним:
Do'stlaringiz bilan baham: |