, она отпрыгнет назад на стартовую позицию (капающая). Если нет, она инвертирует скорость и продолжает двигаться в обратном направлении (отскакивает). Конструктор задаёт только необходимые свойства. Позже мы напишем метод, который занимается самим движением.
>function Lava(pos, ch) {
> this.pos = pos;
> this.size = new Vector(1, 1);
> if (ch == "=") {
> this.speed = new Vector(2, 0);
> } else if (ch == "|") {
> this.speed = new Vector(0, 2);
> } else if (ch == "v") {
> this.speed = new Vector(0, 3);
> this.repeatPos = pos;
> }
>}
>Lava.prototype.type = "lava";
Монеты просты в реализации. Они просто сидят на месте. Но для оживления игры они будут подрагивать, слегка двигаясь по вертикали туда-сюда. Для отслеживания этого, объект >coin
хранит основную позицию вместе со свойством >wobble
, которое отслеживает фазу движения. Вместе они определяют положение монеты (хранящееся в свойстве >pos
).
>function Coin(pos) {
> this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1));
> this.size = new Vector(0.6, 0.6);
> this.wobble = Math.random() * Math.PI * 2;
>}
>Coin.prototype.type = "coin";
В главе 13 мы видели, что >Math.sin
даёт координату y точки на круге. Она движется туда и обратно в виде плавной волны, пока мы движемся по кругу, что делает функцию синуса пригодной для моделирования волнового движения.
Чтобы избежать случая, когда все монетки двигаются синхронно, начальная фаза каждой будет случайной. Фаза волны >Math.sin
и ширина волны — 2π. Мы умножаем значение, возвращаемое >Math.random
, на этот номер, чтобы задать монете случайное начальное положение в волне.
Теперь мы написали всё, что необходимо для представления состояния уровня.
>var simpleLevel = new Level(simpleLevelPlan);
>console.log(simpleLevel.width, "by", simpleLevel.height);
>// → 22 by 9
Нам предстоит выводить эти уровни на экран и моделировать время и движение внутри них.
В большинстве случаев код данной главы не заботится об инкапсуляции. Во-первых, инкапсуляция требует дополнительных усилий. Программы становятся больше, требуют больше концепций и интерфейсов. А так как от слишком большого объёма кода глаза читателя стекленеют, я постарался сохранить программу небольшой.
Во-вторых, различные элементы игры так связаны вместе, что если бы менялось поведение одного из них, вряд ли оставшийся код оставался бы неизменным. Создание интерфейсов между элементами привело бы к использованию слишком большого количества предположений по поводу того, как работает игра. И тогда они были бы неэффективными – меняя одну часть системы, вам приходилось бы думать, как это влияет на другие части, потому что их интерфейсы не охватывали бы новую ситуацию.