Статьи

Модернизируйте свою HTML5 Canvas Game

Современные браузеры, как Internet Explorer 10 реализует стабильные версии некоторых интересных функций HTML5, в том числе интерфейсы прикладного программирования (API), перетаскивание и файловый API . Эти функции переносят нас в новую эру веб-приложений и новых, быстро развивающихся игровых сценариев.

В этой статье, состоящей из двух частей, я покажу, как я использовал эти новые функции для модернизации моей последней игры на HTML5 , HTML5 Platformer . Надеюсь, вы получите отличные новые идеи для своих игр!

Часть 1. Аппаратное масштабирование и CSS3
Часть 2. Автономный, файловый и API-интерфейс перетаскивания (следующая статья)

Примечание. Демо-версия URL приведена в конце этой статьи. Не стесняйтесь играть, используя ваш любимый браузер, и посмотрите видео геймплея IE10. Исходный код будет доступен для скачивания в части 2.

Масштабирование между устройствами

Если вы создаете игру HTML5, вам, вероятно, интересна кроссплатформенная природа этого стандартного языка программирования. Но совместимость с широким спектром устройств означает, что вам нужно учитывать огромное количество разрешений. По сравнению с SVG, на первый взгляд Canvas плохо подготовлен к этому.

Однако для казуальной игры, основанной на спрайтах, существует простое решение для реализации. Дэвид Катухе проделал огромную работу, описав это в своем блоге. Раскройте возможности HTML 5 Canvas для игр — часть 1 (подробности см. В разделе «Использование функции аппаратного масштабирования»).

Идея так же проста, как и умна . Вы работаете внутри холста с фиксированным, предсказуемым разрешением и растягиваете его до текущего отображаемого разрешения, используя свойства canvas.style.

Шаг 1: растянуть

В моей маленькой игре на HTML5 Platformer ресурсы и логика уровней были установлены на 800 × 480. Поэтому, если я хочу заполнить экран 1080p или планшет 1366 × 768, мне нужно создать активы с более высоким разрешением, чтобы соответствовать этим спецификациям.

Прежде чем создавать все эти ресурсы, я могу попробовать операцию масштабирования — вместе с правильным сглаживанием — чтобы повысить качество изображения. Давайте попробуем.
Операция масштабирования просто требует этот код:

 window.addEventListener ("resize", OnResizeCalled, false);

 function OnResizeCalled () {
     canvas.style.width = window.innerWidth + 'px';
     canvas.style.height = window.innerHeight + 'px';
 }

Вот и все!

В браузерах с аппаратным ускорением эта операция будет выполняться вашим графическим процессором бесплатно. Сглаживание может быть даже включено. Вот почему Дэвид Катухе подумал, что стоит упомянуть об этом в своей статье о производительности Canvas .

Кстати, этот трюк не относится к HTML5. Большинство современных консольных игр не рассчитаны внутренне в 720p или 1080p; почти все они визуализируются в более низких разрешениях (например, 1024 × 600) и позволяют графическому процессору обрабатывать процесс масштабирования / сглаживания. В большинстве случаев описанный здесь метод может помочь вам увеличить количество кадров в секунду (FPS).

Но это действие само по себе вызывает проблему отношения. Действительно, когда холст имел фиксированный размер 800 × 480, соотношение контролировалось. Теперь я получаю странный результат при изменении размера окна браузера:

Игра все еще играбельна, но также явно далека от оптимальной.

Шаг 2: Контролируйте свое соотношение

Идея в том, чтобы контролировать заполнение экрана при изменении размера окна браузера. Вместо того, чтобы растягивать что-либо дальше, я собираюсь добавить некоторое пустое пространство справа, если окно слишком большое, или внизу, если окно слишком высокое. Вот этот код:

 var gameWidth = window.innerWidth;
 var gameHeight = window.innerHeight;
 var scaleToFitX = gameWidth / 800;
 var scaleToFitY = gameHeight / 480;

 var currentScreenRatio = gameWidth / gameHeight;
 var optimRatio = Math.min (scaleToFitX, scaleToFitY);

 if (currentScreenRatio> = 1,77 && currentScreenRatio 

Оператор «if» создает исключение: если вы нажали F11 в своем браузере, чтобы переключиться на полноэкранный просмотр, и у вас появился экран 16: 9 (например, мой экран Sony VAIO Z 1920x1080 или планшет Samsung BUILD 1366x768), игра будет полностью растянута. Этот опыт был довольно удивительным.

Без этого исключения вы увидите тип вывода:

Обратите внимание на черные области ниже и справа от игры, контролируя соотношение.
Было бы еще лучше, если бы игра была в центре, придавая ей эффект широкоэкранного фильма, верно? Давай сделаем это.

Шаг 3: Сосредоточьте игру с помощью CSS3 Grid Layout

Центрирование HTML-элемента иногда может быть болезненным. Есть несколько способов сделать это - и есть много ресурсов в сети, чтобы помочь.

Мне нравится использовать новую спецификацию под названием CSS Grid Layout (в настоящее время поддерживается только IE10), которая является основой нашего макета в стиле Metro в Windows 8.

Центрирование элемента с помощью CSS Grid Layout очень просто:

  • Переключить отображение контейнера для отображения: сетка.
  • Определите 1 столбец и 1 строку.
  • Центрируйте внутренний элемент с помощью свойств выравнивания столбца и выравнивания строки.

Вот CSS, используемый в моем случае:

 .canvasHolder {
     ширина: 100%;
     высота: 100%;
     дисплей: -ms-grid;
     -ms-grid-колонки: 1fr;
     -ms-grid-rows: 1fr;
 }

 #platformerCanvas {
     -ms-grid-column: 1;
     -ms-grid-row: 1;
     -ms-grid-column-align: центр;
     -ms-grid-row-align: центр;
 }

Вы заметите префикс «-ms» для IE10. Mozilla недавно объявила, что они также будут поддерживать спецификацию CSS Grid Layout для Firefox в 2012 году, что является отличной новостью. В то же время этот фокус работает только с IE10. Вот как это выглядит:


Окна IE10 будут отображать вертикальные или горизонтальные черные полосы, похожие на то, что вы можете увидеть на экране телевизора. В других браузерах результаты будут совпадать с шагами 2, поскольку спецификация CSS3 Grid Layout будет игнорироваться.

Использование плавной анимации

Теперь, когда мы обрабатываем несколько разрешений с помощью простой операции масштабирования, было бы неплохо воспроизвести плавный переход, когда пользователь изменяет размер окна. Также было бы здорово сыграть классную анимацию, пока загружается каждый уровень. Для этого мы будем использовать инструменты CSS3 Transitions и CSS3 3D Transforms. На большинстве платформ аппаратное ускорение обеспечивается графическим процессором.

Анимация каждого изменения, внесенного в свойства стиля Canvas

CSS3 Transitions прост в использовании и обеспечивает плавную, эффективную анимацию. Чтобы узнать, как их использовать, вы можете прочитать отличную статью моего коллеги, Введение в переходы CSS3 , или поиграть на нашем сайте тест-драйва в Internet Explorer, Hands On: переходы .

 #platformerCanvas {
     -ms-grid-column: 1;
     -ms-grid-row: 1;
     -ms-grid-column-align: центр;
     -ms-grid-row-align: центр;

     -ms-transition-property: all;
     -ms-transition-duration: 1 с;
     -ms-transition-timer-function: легкость;
 }

Холст с идентификатором « platformerCanvas » теперь будет автоматически отражать любые изменения, внесенные в его свойства стиля в анимации за одну секунду, созданной функцией замедления. Благодаря этому новому правилу изменение размера окна браузера уменьшает / увеличивает размер холста с плавной анимацией. Мне нравится эффект, который он производит — все только с 3 линиями CSS.
Примечание: я также добавляю различные префиксы (-moz, -webkit и -o для Mozilla, WebKit и Opera соответственно) для совместимости. Вы захотите не забыть сделать то же самое.

Создание крутой анимации между каждым уровнем

Теперь я хотел бы использовать CSS3 3D-преобразования, чтобы временно пропустить холст. Это будет сделано с анимированным поворотом на 90 градусов по оси Y. Я загружу следующий уровень, как только анимация повернется на 90 градусов и вернется в исходное положение (повернутый на ноль градусов). Чтобы лучше понять эффект, вы можете поиграть с нашими Hands On: 3D Transforms на сайте тест-драйва в Internet Explorer:

Мы также собираемся поиграть со свойствами scale и rotateY, чтобы создать забавную анимацию. Для этого я добавляю два правила CSS и нацеливаюсь на два класса:

 .moveRotation
 {
     -ms-transform: перспектива (500px) масштаб поворота Y (-90 градусов) (0,1);
     -webkit-transform: перспективный (500px) масштаб (0);
     -moz-transform: перспективный (500px) масштаб rotateY (-90deg) (0,1);
 }

 .initialRotation
 {
     -ms-transform: перспектива (500px) масштаб rotateY (0deg) (1);
     -webkit-transform: перспективный (500px) масштаб (1);
     -moz-transform: перспектива (500 пикселей) rotateY (0 градусов) масштаб (1);
 }

Во-первых, мой холст имеет установленный класс initialRotation:

  <canvas id = "platformerCanvas" width = "800" height = "480" class = "initialRotation"> </ canvas> 

Теперь идея состоит в том, чтобы подождать, пока игрок не побьет текущий уровень. Как только это будет сделано, мы изменим класс холста с initialRotation на moveRotation . Это автоматически вызовет CSS3-переходы, которые мы установили ранее, для создания анимации.

Чтобы узнать, когда закончится анимация, возникает событие. Он называется по-разному в каждом браузере. Вот код, который я использую для регистрации события и нацеливания на IE10, Firefox, WebKit и Opera:

 // Регистрация в разных браузерах поставщиков end end события
 PlatformerGame.prototype.registerTransitionEndEvents = function () {
     // IE10, Firefox, Chrome & Safari, Opera
     this.platformerGameStage.canvas.addEventListener ("MSTransitionEnd", onTransitionEnd (this));
     this.platformerGameStage.canvas.addEventListener ("transitionend", onTransitionEnd (this));
     this.platformerGameStage.canvas.addEventListener ("webkitTransitionEnd", onTransitionEnd (this));
     this.platformerGameStage.canvas.addEventListener ("OTransitionEnd", onTransitionEnd (this));
 };
 И вот код, который будет перезвонить:
 // Функция вызывается после завершения перехода
 // Затем загружаем следующий уровень
 function onTransitionEnd (instance) {
     return function () {
         if (instance.loadNextLevel === true) {
             instance.LoadNextLevel ();
         }
     }
 };

Наконец, вот код для моей игры, который устанавливает класс moveRotation на холсте:

 // Выполнить соответствующее действие для продвижения игры и
 // чтобы вернуть игрока к игре.
 PlatformerGame.prototype.HandleInput = function () {
     if (! this.wasContinuePressed && this.continuePressed) {
         if (! this.level.Hero.IsAlive) {
             this.level.StartNewLife ();
         }
         иначе если (this.level.TimeRemaining == 0) {
             if (this.level.ReachedExit) {
                 // Если поддерживается переходы CSS3
                 // Мы используем плавные и приятные эффекты между уровнями
                 if (Modernizr.csstransitions) {
                     this.loadNextLevel = true;
                     // Установка класса moveRotation вызовет переход css
                     this.platformerGameStage.canvas.className = "moveRotation";
                 }
                 // Если переход CSS3 не поддерживается, мы переходим напрямую
                 // на следующий уровень
                 еще {
                     this.LoadNextLevel ();
                 }
             }
             еще
                 this.ReloadCurrentLevel ();
         }
         this.platformerGameStage.removeChild (statusBitmap);
         overlayDisplayed = false;
     }

     this.wasContinuePressed = this.continuePressed;
 };

Обратите внимание, что я использую Modernizr для определения функций переходов CSS. Наконец мы возвращаем класс initialRotation внутри функции LoadNextLevel:

  // Загрузка следующего уровня 
 PlatformerGame.prototype.LoadNextLevel = function () {
     this.loadNextLevel = false;
     // Сброс класса initialRotation вызовет переход
     this.platformerGameStage.canvas.className = "initialRotation";
     // ... loadNextLevel логика ...
 }; 

Примечание. Возможно, вы заметили, что я не устанавливаю те же преобразования (и анимацию) для WebKit, что и для IE10 и Firefox в моем предыдущем блоке CSS. Это связано с тем, что в моем случае Chrome не будет вести себя так же, как IE10 и Firefox 11. Я установил простой случай воспроизведения на jsFiddle .

Демо-видео и URL

Вот короткое видео, демонстрирующее функции IE10, описанные в этой статье:

Вы также можете поиграть с этой демонстрацией в IE10 или в вашем любимом браузере здесь: Современный HTML5 Platformer .

В следующей части этой статьи я покажу, как реализовать автономный API, чтобы моя игра работала без сетевых подключений, и как перетаскивание API может создать еще одну интересную функцию.