Использование HTML5 и Typescript в разработке

HTML5 хорош работой «из коробки», из окна браузера. Но со стороны разработки чистый JavaScript мне всегда не нравился. Хотелось иметь все те преимущества, которые дают те же C# и Visual Studio. Если вам интересен процесс обустройства рабочего пространства для создания HTML5-игр с использованием классов, полноценной отладки и внятного автодополнения — прошу под кат!

Рабочей средой станет редактор Visual Studio Code и браузер Chrome, который будет использоваться для отладки. Классами, строгой типизацией и абстракцией нас обеспечит Typescript — транспилируемый (т.е. преобразующийся в Javascript) язык от Microsoft. В качестве игрового HTML5-фреймворка выступает Phaser.

Начнём обустраиваться. Процесс первоначальной настройки не быстрый и не совсем легкий, но его нужно сделать только один раз. Все, что написано далее, я проверял на Windows 7 x64.

1. Устанавливаем необходимые программы.

Chrome
Visual Studio Code
NodeJS (подойдет как последняя, так и LTS версия)

2. Устанавливаем пакеты для NodeJS.

VS Code изначально готов к работе с NodeJS, так что нам остаётся только установить нужные пакеты. Включаем консоль (через Пуск — «Стандартные» -> «Командная строка»; я предпочитаю клавиши Win+R -> cmd). Возможно потребуется запустить консоль от имени администратора. Вводим следующие команды:

npm install -g typescript
npm install -g http-server

C Typescript всё ясно, а http-server нужен для запуска локального сервера, на котором мы и будем тестировать своё творение.

Дальнейшие действия я буду производить внутри VS Code на примере движка Phaser, но аналогично можно сделать для любого другого (или вообще не использовать готовый движок, но всё равно иметь преимущества перед чистым JS, которые я указал в начале статьи).

3. Для начала создадим костяк проекта

А. Создаём папку проекта, и внутри следующую структуру

bin/ — папка, которую впоследствии и будем выкладывать в интернет
bin/assets/ — ресурсы игры (звуки, картинки)
bin/js/ — в эту папку typescript будет транспилироваться в javascript
src/ — исходный код нашего проекта (на Typescript)
tsDefinitions/ — файлы аннотаций типов, нужны для автодополнения (см. далее)

Б. Интеграция движка Phaser в проект

Скачиваем Phaser. Теперь переносим соответствующие файлы в проект (файл phaser ---> файл проекта):

  • phaser/build/phaser.js ---> bin/js/phaser.js
  • phaser/typescript/box2d.d.ts ---> tsDefinitions/box2d.d.ts
  • phaser/typescript/p2.d.ts ---> tsDefinitions/p2.d.ts
  • phaser/typescript/pixi.d.ts ---> tsDefinitions/pixi.d.ts
  • phaser/typescript/phaser.d.ts ---> tsDefinitions/phaser.d.ts

Первый файл — сам движок. Когда игра будет закончена, его можно заменить на phaser.min.js, для меньшего размера. Пока нам нужен именно этот файл, так как его удобнее использовать при отладке.

Далее четыре файла — это аннотации типов для phaser, который будет использовать typescript.

Аналогичные действия можно использовать для любого другого движка.

В. Создаём файл стартовую страницу игры (bin/index.html)

<!DOCTYPE html>
<html>
<head>
<title>Simple game</title>
<script src=«js/phaser.js»></script>
<script src=«js/game.js»></script>
</head>
<body>
<h1>Simple game</h1>
<div id=«content»></div>
</body>
</html>

Обратите внимание на теги script, включающие движок phaser.js и код нашей игры game.js, который уже скоро появится. :) Элемент div с идентификатором content будет при написании кода (пункт 6) использоваться как игровая область.

4. Конфигурация для Typescript

Теперь нам нужно указать редактору, как образом мы хотим преобразовывать Typescript-код в JS-код. Для этого создадим файл tsconfig.json:

{
«compilerOptions»: {
«target»: «es5»,
«sourceMap»: true,
«outFile»: «bin/js/game.js»
}
}

Здесь мы указываем, что все *.ts файлы в проекте нужно транспилировать в javascript версии ES5, и собрать в один файл, располагающийся в bin/js/game.js. Опция «sourceMap» нужна для создания карты исходных файлов, что позволит нам осуществлять отладку через файлы Typescript. Как непосредственно запустить транспиляцию мы узнаем позже.

5. Запуск локального сервера

Теперь нужно запустить локальный сервер из папки bin/. Для этого создадим «задачу» в VS Code, выполняющую простую команду в консоли. Выбираем из меню «Задачи» -> «Настроить задачи». В дереве проекта создастся файл .vscode/tasks.json, содержимое которого меняем на:

{
«version»: «2.0.0»,
«tasks»: [
{
«label»: «Run Server At \bin»,
«type»: «shell»,
«command»: «http-server ${workspaceFolder}\\bin»,
«problemMatcher»: []
}
]
}

Мы хотим, чтобы при выполнении задачи «Run Server At \bin», редактор запускал команду http-server в консоли, из папки bin/ нашего проекта. Запустить эту задачу (т.е. сервер) можно через «Задачи» -> «Запустить задачу» -> «Run Server At \bin». Зайти на сервер можно через браузер по ссылке «localhost:8080».

6. Наконец-таки код игры!

Напишем простую заглушку — код нашей игры. Программа будет выводить изображение в центре игровой области, на цветном фоне. Создадим файл src/Game.ts.

Не забудьте закинуть cat.jpg в bin/assets, так как код использует данный ресурс.

class SimpleGame
{
game: Phaser.Game;

constructor()
{
this.game = new Phaser.Game( 800, 600, Phaser.AUTO, 'content', { preload:this.preload, create:this.create} );
}

preload()
{
this.game.load.image( 'cat', «assets/cat.jpg» );
}

create()
{
this.game.stage.backgroundColor = 0xaa22ff;
let logo = this.game.add.sprite( this.game.world.centerX, this.game.world.centerY, 'cat' );
logo.anchor.setTo( 0.5, 0.5 );
}
}

// when the page has finished loading, create our game
window.onload = () => {
let game = new SimpleGame();
}

В Game.ts создаём класс SimpleGame для нашей игры, который при создании (constructor()) запускает движок в div элементе с идентификатором «content», устанавливает размер 800х600 пикселей, и указывает, какие функции выполнять при предзагрузке и первоначальном старте игры (preload() и create()).

В preload() мы загружаем ресурсы и производим первоначальную настройку. Загружаем файл «assets/cat.jpg» в движок под ключом «cat».

Create() вызывается один раз при запуске игры. Устанавливаем цвет фона. Выводим спрайт, загруженный под ключом «cat», в центре экрана.

В последних строках (window.onload) указываем, что делать при загрузке веб-страницы (она происходит ДО загрузки самой игры). В данном случае создаём экземпляр класса SimpleGame.


Теперь узнаем, как производить js-код и отладку.

7. Транспиляция кода

Время создать javascript — код! Для этого нажимаем Ctrl+Shift+B (в меню это «Задачи» -> «Запустить задачу сборки»). На основе нашего файла конфигурации tsconfig.json редактор предлагает нам два варианта — «сборка» и «отслеживание». Первый — единоразовая транспиляция. Все *.ts файлы будут переведены в js и собраны в один файл game.js, согласно файлу конфигурации. Второй вариант — такой же, только теперь при любом изменении и сохранении исходного кода сборка будет запускаться автоматически.

Теперь, запустив сервер, и перейдя в браузере по ссылке «localhost:8080» мы можем увидеть картинку и надпись «Simple game». :)

8. Отладка

Устанавливаем расширение — отладчик. Нажимаем Ctrl+Shift+X, что откроет менеджер расширений, ищем и ставим Chrome Debugger. Перезапускаем редактор.

По нажатию F5 в редакторе запускается отладка. В первый раз редактор не знает, какой именно инструмент для отладки использовать, поэтому мы должны сами указать ему. При первом нажатии F5 в проекте будет создан файл конфигурации .vscode/launch.json, содержимое которого меняем на:

{
«version»: «0.2.0»,
«configurations»: [
{
«name»: «Debug localhost»,
«type»: «chrome»,
«request»: «launch»,
«url»: «http://localhost:8080/»,
«webRoot»: «${workspaceRoot}\\bin»
}
]
}

Мы указываем, что будем использовать Chrome debugger, который запустит Chrome по адресу http://localhost:8080/, и подключится к браузеру. WebRoot указывает на корневую папку сервера и нужен для разрешения ссылок.

Теперь нам доступен весь функционал стандартного дебаггера! Можем устанавливать точки останова, использовать watch-выражения и тд из typescript-кода.

Пара советов

Если после транспиляции игра на странице сервера не обновилась, зажмите Shift и в браузере «Перезагрузить страницу», чтобы он не использовал кэшированную версию страницы.

Иногда при отладке не срабатывают точки останова, особенно если они находятся в начале выполнения кода (например, сразу после загрузки страницы) нужно обновить страницу в открывшемся браузере, так как дебаггер ещё не успел запуститься.

Используйте флаг «strict»: true в файле tsconfig.json. Строгий режим проверки кода спасет от незаметных ошибок.

Ctrl + Пробел в редакторе предлагает варианты автодополнения. Можно использовать при редактировании как файлов с исходным кодом, так и файлов конфигураций.


Вот так, с помощью нехитрых приспособлений...

После настройки типичный рабочий процесс будет выглядеть так:

  • Создание typescript кода в папке src. Можно создавать несколько файлов, транспилятор преобразует все файлы в один — game.js.
  • Спрайты, аудиофайлы и тд перемещаем в bin/assets.
  • Запуск локального сервера через «Запуск задачи» -> «Run Server At \bin». За состоянием сервера можно следить в окне «Terminal» редактора.
  • Транспиляция Typescript через Ctrl+Shift+B.
  • Открытие страницы с игрой и подключение отладчика через нажатие F5.
  • После завершения работы над проектом — публикация папки bin/.

Спасибо за внимание!

На основе этой статьи.

Проект

chrome — 63.0
vs code — 1.18
nodejs — 8.9.3
phaser — 2.9.3
typescript — 2.6.2

windows 7 x64

Документация Phaser
Руководство по Typescript