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

>  "  x              = x  ",

>  "  x         o o    x  ",

>  "  x @      xxxxx   x  ",

>  "  xxxxx            x  ",

>  "      x!!!!!!!!!!!!x  ",

>  "      xxxxxxxxxxxxxx  ",

>  "                      "

>];

Фиксированная решётка и движущиеся элементы включены. Символы >x обозначают стены, пробелы – пустое место, а восклицательные знаки – фиксированная лава.

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

Мы будем поддерживать ещё два вида лавы: вертикальная черта >| — для кусочков, двигающихся по вертикали, и >v для капающей лавы. Она будет двигаться вниз, но не отскакивать обратно, а просто перепрыгивать на начальную позицию по достижению пола.

Игра состоит из нескольких уровней, которые надо закончить. Уровень закончен, когда собраны все монетки. Если игрок касается лавы, текущий уровень возвращается к исходному состоянию, и игрок начинает заново.

Чтение уровня

Следующий конструктор создаёт объект уровня. Аргументом должен быть массив строк, задающих уровень.

>function Level(plan) {

>  this.width = plan[0].length;

>  this.height = plan.length;

>  this.grid = [];

>  this.actors = [];


>  for (var y = 0; y < this.height; y++) {

>    var line = plan[y], gridLine = [];

>    for (var x = 0; x < this.width; x++) {

>      var ch = line[x], fieldType = null;

>      var Actor = actorChars[ch];

>      if (Actor)

>        this.actors.push(new Actor(new Vector(x, y), ch));

>      else if (ch == "x")

>        fieldType = "wall";

>      else if (ch == "!")

>        fieldType = "lava";

>      gridLine.push(fieldType);

>    }

>    this.grid.push(gridLine);

>  }


>  this.player = this.actors.filter(function(actor) {

>    return actor.type == "player";

>  })[0];

>  this.status = this.finishDelay = null;

>}

Для краткости код не проверяет входящие данные. Он предполагает, что план уровня допустимый, что там есть стартовая позиция игрока и другие необходимые вещи.

Уровень сохраняет свои ширину и высоту и ещё два массива – один для решётки, и один для движущихся частей. Решётку представляет массив массивов, где каждый вложенный массив представляет горизонтальную линию, а каждый квадрат содержит либо >null для пустых квадратов, либо строку, отражающую тип квадрата – >“wall” или >“lava”.

Массив >actors содержит объекты, отслеживающие положения и состояния динамических элементов. У каждого из них должно быть свойство