Выразительный JavaScript (Хавербеке) - страница 158

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

Одну вещь мы всё-таки инкапсулируем – подсистему рисования. Это сделано специально для того, чтобы в следующей главе мы могли выводить на экран ту же игру другим способом. Спрятав рисование за интерфейс, мы можем просто загрузить ту же программу и подключить к ней новый модуль вывода на экран.

Рисование

Инкапсулировать код для рисования мы будем, введя объект >display, который выводит уровень на экран. Тип экрана, который мы определяем, зовётся >DOMDisplay, потому что он использует элементы DOM для показа уровня.

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

Следующая вспомогательная функция даёт простой способ создания элемента с назначением класса.

>function elt(name, className) {

>  var elt = document.createElement(name);

>  if (className) elt.className = className;

>  return elt;

>}

Экран создаём, передавая ему родительский элемент, к которому необходимо подсоединиться, и объект уровня.

>function DOMDisplay(parent, level) {

>  this.wrap = parent.appendChild(elt("div", "game"));

>  this.level = level;


>  this.wrap.appendChild(this.drawBackground());

>  this.actorLayer = null;

>  this.drawFrame();

>}

Используя тот факт, что >appendChild возвращает добавленный элемент, мы создаём окружающий элемент >wrapper и сохраняем его в свойстве >wrap.

Неизменный фон уровня рисуется единожды. Актёры перерисовываются каждый раз при обновлении экрана. Свойство >actorLayer используется в >drawFrame для отслеживания элемента, содержащего актёра – чтобы их было легко удалять и заменять.

Координаты и размеры измеряются в единицах, относительных к размеру решётки так, что дистанция в единицу означает один элемент решётки. Когда мы задаём размеры в пикселях, нам нужно будет масштабировать координаты – игра была бы очень мелкой, если б один квадратик задавался одним пикселем. Переменная >scale даёт количество пикселей, которое занимает один элемент решётки.

>var scale = 20;


>DOMDisplay.prototype.drawBackground = function() {

>  var table = elt("table", "background");