Крошечный арканоид на JavaScript (30 строк кода)

от автора

Наблюдая за тем, как люди в 30 строк джаваскрипта умещают excel и змейку, я решил не отставать от прогресса, и создать что-нибудь подобное.
Итак, дамы и господа — 30ти строчный арканоид на чистом JS.



Ссылка на fiddle.
Также продублирую на codepen, а то фиддл всю ночь 500кой отвечал.

JavaScript:

(function (fld, pF, px, py, dx, dy, lifes, score) {   var cycle = setInterval(function () {     var bx = pF(ball.style.left = pF(ball.style.left) + dx + 'px'),       by = pF(ball.style.top = pF(ball.style.top) + dy + 'px'),       row = ((by - 30) / 14) | 0, col = (bx / 32) | 0;      if (bx < 0 && dx < 0 || bx >= 314 && dx > 0) dx *= -1;     if (bx + 6 >= px && bx + 6 <= px + 64 && by >= 259 && by <= 264) {       dy *= -1;       if (bx + 6 <= px + 21) dx = -6;       else if (bx + 6 >= px + 43) dx = 6;       else if (Math.abs(dx) == 6) dx = (dx * 2 / 3) | 0;     }     if (by < 0) dy *= -1;     if (by >= 288 && !--lifes) clearInterval(cycle), alert('Game over!');     if (by >= 288 && lifes) dy *= -1, lifesNode.innerHTML = lifes;     if (by >= 18 && by <= 100 && fld[row * 10 + col].className != 'removed') {       dy *= -1, fld[row * 10 + col].className = 'removed';       if (dx < 0 && ((bx | 0) % 32 < 10 || (bx | 0) % 32 > 22)) dx *= -1;       if (dx > 0 && (((bx + 12) | 0) % 32 < 10 || ((bx + 12) | 0) % 32 > 22)) dx *= -1;       scoreNode.innerHTML = ++score;       if (score == 50) clearInterval(cycle), alert('Victory!');     }   }, 1000 / 60);    document.addEventListener('mousemove', function (e) {     px = (e.pageX > 40) ? ((e.pageX < 290) ? e.pageX - 40 : 256) : 0;     paddle.style.left = px + 'px';   }, false); }(field.children, parseFloat, 129, 270, -4, -4, 3, 0)); 

В целом я старался добиться максимальной аутентичности:

  • угол отражения шарика зависит (немножко) от того, на какую сторону ракетки он упал: при падении на левую треть мячик отлетает влево, при попадании на правую треть — вправо (в обоих случаях снаряд отражается под немного бо́льшим углом, чем при ударе о середину), при попадании в центр шарик отлетает под 45° а его направление по оси икс не меняется.
  • Подсчет очков (а как же без этого).
  • Дается три жизни. Правда, при попадании шарика на нижнюю грань игра не ресетится, а шарик просто отскакивает и отнимается одна жизнь.

Из недостатков: шарик иногда неадекватно себя ведет и ломает слишком много кирпичей.

Под капотом

С версткой все просто. Кирпичики — инлайн-блоки, ракетка и снаряд — position: absolute.

А вот с collision detection чуть интереснее. Область, где расположены кирпичи ограничена сверху и снизу, а значит проверять соударения есть смысл только тогда, когда снаряд в этой области. Высота и ширина кирпичей определена. Поэтому, взяв координаты шарика, мы точно сможем определить номер кирпича, в который он попал. Если его координаты X и Y, а ширина и высота кирпичей width и height, то взяв целую часть от частного X / width и Y / height мы получим в точности номер столбца и строки col и row текущей цели. Зная это мы можем вычислить номер этого элемента:
number = row * rowLength + col.
Благо, querySelectorAll возвращает элементы именно в том порядке, в котором они расположены в html. И мы легко можем удалить текущий кирпич:
elements[number].className = 'removed'.

setInterval

Не смотря на то, что нативный requestAnimationFrame уже реализован во всех десктопных браузерах, было решено отказаться от него в пользу setInterval. Во-первых, это позволяет охватить также старые версии, а во-вторых это экономит одну (драгоценную!) строчку кода:

requestAnimationFrame(function () frame {   requestAnimationFrame(frame); }); // против var cycle = setInterval(function () { }, delay); 

Итого

Код, на мой взгляд, получился довольно компактный. Самая длинная строчка — 88 символов (с учетом индентации). Сама игра немного кривенькая, ну, а чего ещё ожидать от 30ти строчек?)
Сейчас видимо, как кто-то заметил в комментариях к предыдущим постам, стоит ждать ‘Крошечную Windows’ в 30 строк.

ссылка на оригинал статьи http://habrahabr.ru/post/202530/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *