Гоночка на JavaScript (30 строк кода)

    В продолжение недели ненормального программирования (как заметил phpcmsdev) решил написать игру в 30 строк кода. Так как тетрис, змейка и арканоид уже были сделаны, выбор пал на гоночки, которые входили в стандартный набор портативной игры.



    Ссылка на fiddle.

    (function(elid, width, height, speed, strength){
        var canvas = document.querySelector(elid),
                ctx = canvas.getContext("2d"),
                pos = 0, blocks = [];
        canvas.width = width; canvas.height = height;
        ctx.fillStyle = "black";
        var game = setInterval(function(){
            if( Math.random() < strength) blocks.push([Math.random()*(width-10),-10]);
            ctx.clearRect(0,0,width,height);
            ctx.fillRect(pos,height-50,10,40);
            for(var i = 0; i < blocks.length; i++){
                ctx.fillRect(blocks[i][0],blocks[i][1],10,10);
                if( blocks[i][1] > height - 60 && blocks[i][1] < height - 10 && Math.abs( pos - blocks[i][0]) < 10 ){
                    clearInterval(game);
                    alert("Game over. You have " + Math.floor(1000 * strength) + " points.");
                }
                if( blocks[i][1] > height - 5 ){
                    blocks.splice( i, 1);
                    i--;
                } else {
                    blocks[i][1] += 5;
                }
            }
            strength += 0.001;
        },speed);
        document.addEventListener('mousemove', function (e) {
            pos = (e.pageX > 0) ? ((e.pageX < width) ? e.pageX : width-10) : 0;
        }, false);
    })("#canvas",400,300,33,0.05);
    


    Особенности



    • По настоящему 30 строк кода: 1 строка HTML, 29 строк JavaScript. Правда без оборачивания в тег <script>, но думаю это допущение не такое страшное :).
    • Canvas. Я люблю Canvas! Рисовать на canvas простые фигуры однозначно проще, чем двигать div-ы. Получается не так красиво, зато не нужно лишний раз беспокоиться о смещениях элементов.
    • Возрастающая сложность и очки. На самом деле это одна переменная, но кому какая разницы как считаются очки? Главное же что бы побольше было!
    • setInterval. Отказаться от requestAnimationFrame было решено не столько из-за лишней строчки, сколько из-за того что логика игры описана вместе с отрисовкой.


    Заключение



    Спасибо jeston за информацию о Тетрисе, zag2art за перевод о Excel, DjComandos за Змейку и linoleum за Арканоид.

    Ребята, занимайтесь нормальным программированием.

    UPD


    Пользователь MinimaJack в свою очередь прислал вариант игры Ball, но не может запостить сам в силу объективных причин.

    Ссылка на fiddle.

    Поделиться публикацией

    Похожие публикации

    Комментарии 67
      +36
      Давай Doom уже!
      • НЛО прилетело и опубликовало эту надпись здесь
          +17
          Ну зачем Вы так?! Работа же встала…
          • НЛО прилетело и опубликовало эту надпись здесь
              +1
              6:67 — максимум, чего смог добиться… :)
              • НЛО прилетело и опубликовало эту надпись здесь
                • НЛО прилетело и опубликовало эту надпись здесь
                  • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    Тут из-за рандомной скорости попытка попытке рознь.
                    Вы продержались 6.88 секунд. Ох и зараза :)
                      0
                      7 с копейками! :)
                        –1
                        8.097!

                          –1
                          8.461 :)
                    +9
                    Боюсь рассказывать о Super Hexagon (упс, уже)
                    Кстати, у него есть ранняя бесплатная браузерная версия terrycavanaghgames.com/hexagon
                    Жаль, не на весь экран, как полноценный SH.
                      0
                      Нет вам прощенья! Пятиугольник не могу пройти… Кстати музыка забористая, особо после 40-ой секунды где-то начинается
                        +1
                        Советую заинтересовавшимся приобрести все таки полную версию, она стоит полтора бакса в Стиме. В браузерной версии, как мне показалось, присутствует небольшой лаг в управлении, да и по качеству она, понятное дело, уступает.
                          0
                          В браузерной версии ещё столкновение сбоку — смерть. Хотя полностью прошёл полноценный Super Hexagon, а флэшевый Hexagon разгоняется до гора-а-аздо меньших скоростей, привычка долбиться в стены меня добивала.
                            +1
                            Ахаха, в стиме:
                            Важные сведения о гексагонах (шестиугольниках):
                            Несмотря на то, что слово «гексагон» может показаться трудным для поиска рифмы к нему, на самом деле есть десятки слов, которые рифмуются с ним. Например: автобан, декагон, электрон, Кыргызстан, лепрекон и марафон.

                            Спасибо, добавил в список желаемого, куплю чуть позже (оказывается в стиме покупать из Китая за русские электронные деньги совсем не тривиально)
                              +1
                              Меня там больше всего порадовали уровни сложности. Самый простой уровень называется hard, потом открывается harder, hardest, hardester, hardestest и конечно же hardestestest. Лучших результатов достиг на планшете, на втором месте по удобности пк-версия с клавой, на последнем месте пк-версия с геймпадом.
                            +4
                            Работа, говорите, встала… Что ж, добьем.
                              0
                              Добили) Это вообще зараза :)
                                +1
                                ctrl+shift+I, esc, window.Game.Earn(10000000000000000);
                                  0
                                  Тогда вот ещё контрольный выстрел.
                                  0
                                  Еще есть drmeth.com/
                                0
                                7.7 сек. Больше не смог ))
                                  –6
                                  Пфффффф
                                  • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    Говорят 16 секунд это предел…

                                    Чёрт, тут ещё и направление рандомное. Когда я играл в первый раз, хоть траекторию можно было запомнить.
                                      0
                                      Проблема в том, что там мышиное управление, а это худший из возможных вариантов в таких играх. Неверующим предлагается провести десяток часов за игрой в Тохо.
                                      +8
                                      Пора уже тег заводить — «30 строк»
                                        +1
                                        А это хорошая мысль, сейчас добавлю.
                                          +3
                                          Надо уж тогда «ровными» числами пользоваться: 16, 32, 64, 128,…
                                          В данном случае и обёртка тегом
                                            0
                                            Это называется Code Golf. На SO, например, такой тег есть.
                                          0
                                          Ждем Diablo в 30 строчек
                                            0
                                            если у строки длина 2^64 то вполне и в одну поместится :)
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                +1
                                                Ой факт...)) В такую одну строку поместятся все игры в мире вместе взятые, и все библиотеки мира и вообще все, что только у нас есть :)
                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                    0
                                                    Увидев на почте уведомление о Вашем комментарии, так и думал что вспомните о Пи. Ну да — с ним сложно спорить, но ведь его можно тоже, как и игру — внести в строчку сам способ расчета числа, а не само число :)
                                            –2
                                            Хм, на Хабре объявлена неделя «30 строк кода»?
                                              +1
                                              подкидываю идею — Alien Invaders
                                                0
                                                blocks.splice( i, 1);
                                                i--;
                                                

                                                blocks.splice( --i, 1);
                                                

                                                же
                                                  +5
                                                  blocks.splice( i--, 1);
                                                    +2
                                                    Это уже не 30 строк будет :)
                                                      0
                                                      Ну здесь по коду все же нужен постфиксный оператор
                                                      blocks.splice( i--, 1);
                                                      

                                                      но да, верно. Привычка разделять действия в данном случае неуместна :)
                                                        0
                                                        Оу, пардон, точно)
                                                        Лучше бы тогда это разделили:
                                                        if( Math.random() < strength) blocks.push([Math.random()*(width-10),-10]);
                                                        
                                                          0
                                                          У меня первое желание было вот это
                                                          if( blocks[i][1] > height - 60 && blocks[i][1] < height - 10 && Math.abs( pos - blocks[i][0]) < 10 ){
                                                          
                                                          разнести на несколько строк.
                                                      +3
                                                      Даешь PacMan! Да чтоб со звуком, иначе не катит.
                                                        0
                                                        Вы забыли слово «крошечная» в названии
                                                          0
                                                          Небольшой баг: если подвести курсор близко к правой границе, «машинка» прячется за ней. Так можно ставить рекорды :-)
                                                            0
                                                            У меня один пиксель все равно остается и некоторые кубики его достают
                                                            +3
                                                            А ты, username, написал код в 30 строк?!
                                                              +5
                                                              фарш
                                                              var wrapper = document.getElementById('wrapper'), keyCode = 0, tank1 = document.getElementById('tank1'), tanks = [], step, fPoint = function(x, y) { return document.elementFromPoint(x + 20, y + 20); };
                                                              var addElem = function(elem, className, css, attrs) {
                                                              	var newD = document.createElement(elem);
                                                              	newD.className = className;
                                                              	newD.style.cssText = css;
                                                              	if(attrs != undefined) { newD.setAttribute(attrs, ''); }
                                                              	wrapper.appendChild(newD);
                                                              	return newD;
                                                              };
                                                              setInterval(function() {
                                                              	if(tanks.length < 2) {
                                                              		var n_el = addElem('div', 'tank2', '', 'tank2');
                                                              		n_el.style.left = 200;
                                                              		n_el.style.top = 80;
                                                              		tanks.push(n_el);
                                                              	}
                                                              	for(var i=0; i < tanks.length;i++) {
                                                              		var step = Math.round(Math.random()) == 0?40:-40;	
                                                              		if(fPoint(parseInt(tanks[i].style.left)+step + 20, parseInt(tanks[i].style.top) + 20) != null && fPoint(parseInt(tanks[i].style.left)+step + 20, parseInt(tanks[i].style.top) + 20).getAttribute('id') == 'wrapper') tanks[i].style.left = parseInt(tanks[i].style.left)+step, tanks[i].className = step < 0 ? 'to_left' : 'to_right';
                                                              		else if(fPoint(parseInt(tanks[i].style.left) + 20, parseInt(tanks[i].style.top)+step + 20) != null && fPoint(parseInt(tanks[i].style.left) + 20, parseInt(tanks[i].style.top)+step + 20).getAttribute('id') == 'wrapper') tanks[i].style.top = parseInt(tanks[i].style.top)+step, tanks[i].className = step < 0 ? 'to_top' : 'to_bottom';
                                                              	}
                                                              }, 500);
                                                              var to_left = 40, to_top = 40;
                                                              document.onkeydown = function (event) {
                                                              	to_left = (event.keyCode == 39)?(to_left >=420 ? to_left : (to_left + 40)):(event.keyCode == 37)?(to_left <= 0 ? 0 : to_left - 40):to_left;
                                                              	to_top = (event.keyCode == 38)?(to_top <= 0 ? 0 : to_top - 40):(event.keyCode == 40)?(to_top >=280 ? 280 : to_top + 40):to_top;
                                                              	console.log(to_left, to_top);
                                                              	if(document.elementFromPoint(to_left+20, to_top+20).getAttribute('id') == 'wrapper') tank1.style.left = to_left, tank1.style.top = to_top;
                                                              	else to_left = parseInt(tank1.style.left), to_top = parseInt(tank1.style.top);
                                                              }
                                                              


                                                              ТАНЧИКИИ!!!
                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                0
                                                                990 points
                                                                  +7
                                                                  Шок! Полноценный Javascript одной строкой!

                                                                  Это нужно видеть!
                                                                  eval()
                                                                    0
                                                                    1029 =)
                                                                      0
                                                                      Так, я в обязательном порядке требую Space Invaders! Можно и в 31 строку кода, но не больше 32.
                                                                        +1
                                                                        Внесу свои 5 копеек :) jsfiddle.net/SiDChik/2JEEH/18/embedded/result/
                                                                        JS
                                                                        (function(canvas, width, height, playersize, speed, acc){
                                                                            var ctx = canvas.getContext('2d');
                                                                            canvas.width = width; canvas.height = height; px=100; py=0; blocks_tick=0.2; p_acc=0;to_x=100;points=0;can_jump=0;
                                                                            var blocks=[];
                                                                            timer = setInterval(function(){
                                                                                ctx.clearRect(0,0,width,height);
                                                                                p_acc += 0.2; if (p_acc>10){p_acc=10;} py += p_acc;speed+=acc;points+=1;can_jump-=1;
                                                                                if (to_x<px){px-=6;}if (to_x>px){px+=6;}
                                                                                if (Math.random()<blocks_tick){
                                                                                    blocks.push({'x': width, 'y': Math.random()*height, 'size': Math.random()*40 + 20});
                                                                                }
                                                                                for (var i=0; i<blocks.length;i++){
                                                                                    blocks[i]['x'] -= speed;
                                                                                    ctx.fillStyle='#333'; ctx.fillRect(blocks[i]['x'], blocks[i]['y'], blocks[i]['size'], 10);
                                                                                    if ((blocks[i]['x'] + blocks[i]['size'] >= px) && (blocks[i]['x'] <= px + playersize) && (blocks[i]['y'] + 10 >= py) && (blocks[i]['y'] <= py + playersize)){
                                                                                        if ((p_acc>0) && (can_jump<0)){
                                                                                            p_acc=-8;can_jump = 30;py=blocks[i]['y']-playersize;
                                                                                        }
                                                                                        else{p_acc = -p_acc;py=blocks[i]['y']+10;}
                                                                                    }
                                                                                    if (blocks[i]['x']+blocks[i]['size']<0){blocks.splice(i--,1);}
                                                                                }
                                                                                ctx.fillStyle=(can_jump<0)?'#eeee00':'#aaa';ctx.fillRect(px,py,playersize, playersize);
                                                                                if (py>height){
                                                                                    clearInterval(timer);
                                                                                    if (confirm('GameOver! Your Points:'+points+' Restart?')){window.location.reload()}
                                                                                }
                                                                            }, 1000/24);
                                                                            document.addEventListener('mousemove', function (e) { to_x = e.pageX; }, false);
                                                                        })(document.getElementById('game'), 800, 600, 10, 6, 0.005);
                                                                        

                                                                          +1
                                                                          И версия с более ожесточенными правилами, нельзя вообще покидать экран.
                                                                          jsfiddle.net/SiDChik/2JEEH/19/embedded/result/
                                                                            0
                                                                            У меня не всегда успевает переключиться в другое состояние, поэтому ниндзя иногда проскакиват платформы.
                                                                              0
                                                                              Ну в том то и философия :) Пока мы серые мы не можем удержаться в пределах экрана. То есть если игрок серого цвета он проваливается сквозь платформы.
                                                                                0
                                                                                Но тогда он не должен же отталкиваться вниз, пока летит вверх. :)
                                                                                  0
                                                                                  Не всегда наши трудности бывают очевидны, так или иначе всегда есть препятствия на пути вверх. По факту я пытался сделать игру сложной и динамичной, еслиб в зависимости от состояния можно было пролетать и вверх и вниз это бы не усложняло, а упрощало бы ситуация, разве что менять состояния по таймеру, но мне это показалось не логичным.
                                                                                    0
                                                                                    Сделали, как сделали и правильно сделали. :) Просто мне сначала показалось странным поведение.
                                                                          0
                                                                            0
                                                                            Вот сколько за несколько дней понаписали статей на тему «30 строк js», но ваша гоночка всё же самая любимая, с удовольствием в неё теперь играю :)

                                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                            Самое читаемое