Я никогда прежде не занимался программированием игр, довольно простой вопрос.
Представьте, что я создаю игру «Тетрис», где основной цикл выглядит примерно так.
for every frame
handle input
if it's time to make the current block move down a row
if we can move the block
move the block
else
remove all complete rows
move rows down so there are no gaps
if we can spawn a new block
spawn a new current block
else
game over
Пока что все в игре происходит мгновенно - вещи порождаются мгновенно, строки удаляются мгновенно и т. Д. Но что, если я не хочу, чтобы что-то происходило мгновенно (то есть, анимация)?
for every frame
handle input
if it's time to make the current block move down a row
if we can move the block
move the block
else
?? animate complete rows disappearing (somehow, wait over multiple frames until the animation is done)
?? animate rows moving downwards (and again, wait over multiple frames)
if we can spawn a new block
spawn a new current block
else
game over
В моем клоне Понг это не было проблемой, поскольку каждый кадр я просто перемещал мяч и проверял наличие столкновений.
Как я могу обернуть голову вокруг этой проблемы? Конечно, большинство игр включает в себя некоторые действия, которые занимают больше кадра, а другие вещи останавливаются до тех пор, пока действие не будет выполнено.
Action
класс и очередь действий для выполнения. Когда действие завершено, удалите его из очереди и выполните следующее действие и т. Д. Более гибкий, чем конечный автомат.Я взял это из Game Coding Complete Майка МакШаффри.
Он говорит о «диспетчере процессов», который сводится к списку задач, которые необходимо выполнить. Например, процесс будет управлять анимацией рисования меча (AnimProcess), открытия двери или, в вашем случае, исчезновения ряда.
Процесс будет добавлен в список диспетчера процессов, который будет повторяться каждый кадр, и Update () вызывается для каждого. Так что очень похожие на сущности, но для действий. Там будет флаг уничтожения, чтобы удалить из списка, когда он закончил.
Другая приятная вещь о них - то, как они могут связать, имея указатель на следующий процесс. Таким образом, процесс анимации строки может состоять из:
(Поскольку процессы могут быть одноразовыми, условно там или там в течение X времени)
Если вы хотите больше подробностей, спросите об этом.
источник
Вы можете использовать приоритетную очередь действий. Вы продвигаете действие и время. В каждом кадре вы получаете время, и вы отключаете все действия, для которых указано время, как до этого времени, и выполняете их. Бонус: подход хорошо распараллеливается, и вы можете реализовать практически всю игровую логику таким образом.
источник
Вам всегда нужно знать разницу во времени между предыдущим и текущим кадром, тогда вам нужно сделать две вещи.
Решите, когда обновить вашу модель: например. в тетрисе, когда начинается удаление строки, вы больше не хотите, чтобы материал сталкивался со строкой, поэтому вы удаляете строку из «модели» вашего приложения.
Затем вам нужно обработать объект, который находится в переходном состоянии, в отдельный класс, который разрешает анимацию / событие в течение определенного периода времени. В примере с тетрисом строка будет постепенно исчезать (немного измените непрозрачность каждого кадра). После того, как непрозрачность станет равной 0, вы переместите все блоки сверху строки на один вниз.
Поначалу это может показаться немного сложным, но вы поймете, как это сделать, просто убедитесь, что абстрагируете много в разных классах, это облегчит задачу. Также убедитесь, что события, которые требуют времени, такие как удаление строки в тетрисе, относятся к типу «Огонь и забудь», просто создайте новый объект, который обрабатывает все, что необходимо сделать автоматически, и что, когда все будет сделано, удаляет себя из вашего сценографа.
источник
Вы должны думать об игре как о «конечном автомате». Игра может находиться в одном из нескольких состояний: в вашем случае, «ожидание ввода», «перемещение фигуры вниз», «взрывающаяся строка».
Вы делаете разные вещи в зависимости от состояния. Например, во время «перемещения фигуры» вы игнорируете ввод игрока и вместо этого анимируете фигуру из ее текущей строки в следующую. Что-то вроде этого:
источник