Наверх

Урок 7. Добавляем весь набор фигур. Передача объекта по ссылке

В тетрисе не так много фигур. Для их обозначения обычно используются латинские буквы I, J, L, O, S, T, Z — из-за схожести формы фигур и букв.

Добавим в конфиг тетриса набор начальных координат для всех этих фигур:
var Tetris = {
  config: {
    // ...
    figureTypes: {
      I: [
          [[-3,5]],
          [[-2,5]],
          [[-1,5]],
          [[ 0,5]]
      	],
      J: [
               [[-2,6]],
               [[-1,6]],
          [[0,5],[0,6]]
      ],
      L: [
          [[-2,5]],
          [[-1,5]],
          [[0,5],[0,6]]
      ],
      O: [
        [[-1,5],[-1,5]],
        [[ 0,5], [0,6]]
      ],
      S: [
              [[-1,6],[-1,7]],
        [[0,5], [0,6]]
      ],
      T: [
        [[-1,5],[-1,6],[-1,7]],
               [[0,6]]
      ],
      Z: [
        [[-1,4],[-1,5]],
                [[0,5], [0,6]]
      ]
    }
  },
  // ...
}
В методе создания фигуры будем брать случайную фигуру из набора
figure: {
  // ...
  create: function() {
    this.coords = this.getRandomFigure();
  },
  // ...
}
Метод getRandomFigure будет возвращать координаты случайно выбранной фигуры
figure: {
  // ...
  getRandomFigure: function() {
    var keys = Object.keys(Tetris.config.figureTypes);
    var randKey = Math.floor(Math.random() * keys.length);
    return Tetris.config.figureTypes[keys[randKey]];
  },
  // ...
}
Так как у нас есть высокие фигуры и отрицательные координаты могут продержаться дольше одного тика, могут возникнуть ошибки при попытке проверить блок с отрицательной координатой на пустоту.

Чтобы избежать этой ошибки, допишем проверку в методе touched
touched: function() {
  var contact = false;
  Tetris.each(this.coords, function(i,j){
    var figureRow = Tetris.figure.coords[i][j][0];
    // Здесь (figureRow >= 0)
    if (figureRow >= 0 && Tetris.pitch.bricks[figureRow + 1]  == undefined) {
      contact = true;
    }
  });
  if (contact) {
    return contact;
  }
  Tetris.each(this.coords, function(i,j){
    var figureRow = Tetris.figure.coords[i][j][0];
    var figureCol = Tetris.figure.coords[i][j][1];
    // И здесь (figureRow >= 0)
    if (figureRow >= 0 && Tetris.pitch.bricks[figureRow + 1][figureCol]) {
      contact = true;
    }
  });
  if (contact) {
    return contact;
  }
  return false;
}

Когда я запустил этот код, сначала обрадовался — фигурки начали падать, появлялись разные фигурки, их соприкосновения обрабатывались корректно, но где-то на середине процесс останавливался (хотя тики продолжали идти).

И тут я вспомнил, что в JavaScript объекты, в отличие от остальных типов (строк, чисел и пр.) передаются в функцию по ссылке. Соответственно, меняя координаты фигуры, мы меняли их в объекте Tetris.config.figureTypes. И при создании новой фигуры координаты ей присваивались не из конфига, а новые, изменённые. В итоге, фигура появлялась поверх предыдущей с таким же типом.

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

Я выбрал второй вариант. Получилось немного монструозно — из-за того, что я хотел сохранить силуэт фигур в конфиге, но работает исправно.
// ...
    figureTypes: {
      I: function() {
        return [
          [[-3,5]],
          [[-2,5]],
          [[-1,5]],
          [[ 0,5]]
      	];
      },
      J: function() {
        return [
               [[-2,6]],
               [[-1,6]],
          [[0,5],[0,6]]
      ];
      },
      L: function() {
        return [
          [[-2,5]],
          [[-1,5]],
          [[0,5],[0,6]]
      ];
      },
      O: function() {
        return [
        [[-1,5],[-1,6]],
        [[ 0,5], [0,6]]
      ];
      },
      S: function() {
        return [
              [[-1,6],[-1,7]],
        [[0,5], [0,6]]
      ];
      },
      T: function() {
        return [
        [[-1,5],[-1,6],[-1,7]],
               [[0,6]]
      ];
      },
      Z: function() {
        return [
            [[-1,4],[-1,5]],
                    [[0,5], [0,6]]
          ];
      }
    }
  // ...

Вот итоговый код этого урока: http://jsfiddle.net/ilyautkin/aavju3jd/13/

0 комментариев

    Авторизация

    через сервис Loginza:

    Подписка или RSS

    Буду присылать новые статьи — никакого спама



    Шаблоны MODX

    1 2 Дальше »

    Объектная
    модель
    MODX