Игра про уничтожение блоков с использованием HTML5 canvas
В детстве очень любил простую игру, где нужно уничтожать блоки одного цвета, чтобы очистить экран. Как начал заниматься изучением HTML5 canvas, решил реализовать её.
Поиграть можно тут: демка.
Суть игры
Смысл игры был прост: есть поле, на котором разбросаны разноцветные блоки. Эти блоки гравитацией тянет вниз. Игрок может уничтожать блоки, выбирая один из группы одноцветных рядом по горизонтали и вертикали. Игра очень похожа “на три в ряд”, разница только в том, что блоки уничтожаются все по близлежащему цвету, не только в ряд.
Задача игрока — убрать все блоки, или оставить как можно меньше. За уничтоженный блок начисляется очко. Всегда максимальное количество возможных очков равно площади поля. Поэтому даже если убраны не все блоки, можно соревноваться набирая большее количество очков.
Начало реализации игры, знакомство с html5 canvas
Первым делом стал заполнять экран блоками. Создал двумерный массив, рандомно назначил цвета.
Далее нужно было написать логику уничтожения блоков одного цвета. Вроде бы алгоритм простой, но столкнулся с трудностью обхода прилежащих блоков. Некоторое время экспериментируя, решил создать дополнительный массив, в котором хранил информацию об обойдённых блоках. Сама функция рекурсивно обходила их по всем четырём сторонам, назначала блоки, подлежащие уничтожению.
Мало сделать уничтожение блоков, предстояло сымулировать гравитацию. Сделать было легко, просто обходим столбцы и смещаем все блоки вниз. В игре есть ещё момент: когда столбец становится пуст, для уничтожения смежных блоков нужно удалить пустой столбец, или сместить оставшиеся блоки так, чтобы получились новые цветовые группы.
Оптимизация отрисовки html5 canvas
Ладно, блоки уничтожаются. Процесс обхода оптимизирован. Но всё же игра на html5 canvas тормозила при уничтожении большого количества блоков. Причина была в том, что на перерисовку html5 canvas нужно время. Если блоков достаточно много (ведь играть на поле маленького размера не интересно), перерисовка занимала порой более 1 секунды.
Нужно было срочно с этим разбираться. Стал искать решения в интернетах.
Самое простое, что можно было сделать — это заливать области только после обозначения зон заливки. Но такое решение не особо помогло, нужно было применять более эффективный способ оптимизации.
В итоге я решил использовать информацию об обновившихся блоках, чтобы рисовать только в тех местах, где действительно произошли изменения. Так же создал CanvasBuffer для рисования в фоне и быстрой перерисовки участков.
После этих оптимизаций, игра по уничтожению блоков на html5 canvas получилась настолько быстрой, что при большом количестве блоков и небольшом количестве цветов было ощущение, будто песок осыпается под собственной тяжестью.
Код первоначальной версии игры можно посмотреть на github: block-destruction-game.