Итоги конкурса JS1k

    Подведены итоги конкурса скриптов размером 1024 байт или меньше. Ниже список победителей.

    1. Legend Of The Bouncing Beholder (автор: @marijnjh)
    2. Миниатюрные шахматы (Oscar Toledo G.)
    3. Тетрис со звуком (@sjoerd_visscher)
    4. WOLF1K и буквы в цветах радуги (@p01)
    5. Бинарные часы (tweetable) (@alexeym)
    6. Mother fucking lasers (@evilhackerdude)
    7. Схема графического движка (Lars Ronnback)
    8. Многопользовательский настольный теннис (@feiss)
    9. Генератор кода по азбуке Морзе (@chrissmoak)
    10. Пульсирующие 3D-провода (@unconed)

    Сайт с демками пока лежит, но некоторые из них можно найти на сайтах авторов.

    Например, вот первое место.

    c=document.body.children[0];h=t=150;L=w=c.width=800;u=D=50;H=[];R=Math.random;for($ in C=c.getContext('2d'))C[$[J=X=Y=0]+($[6]||'')]=C[$];setInterval("if(D)for(x=405,i=y=I=0;i<1e4;)L=\H[i++]=i<9|L<w&R()<.3?w:R()*u+80|0;$=++t%99-u;$=$*$/8+20;y+=Y;x+=y-H[(x+X)/u|0]>9?0:X;j=H[o=\x/u|0];Y=y<j|Y<0?Y+1:(y=j,J?-10:0);with(C){A=function(c,x,y,r){r&&a(x,y,r,0,7,0);fillStyle=c.P\?c:'#'+'ceff99ff78f86eeaaffffd45333'.substr(c*3,3);f();ba()};for(D=Z=0;Z<21;Z++){Z<7&&A(Z%6,w/\2,235,Z?250-15*Z:w);i=o-5+Z;S=x-i*u;B=S>9&S<41;ta(u-S,0);G=cL(0,T=H[i],0,T+9);T%6||(A(2,25,T-7\,5),y^j||B&&(H[i]-=.1,I++));G.P=G.addColorStop;G.P(0,i%7?'#7e3':(i^o||y^T||(y=H[i]+=$/99),\'#c7a'\));G.P(1,'#ca6');i%4&&A(6,t/2%200,9,i%2?27:33);m(-6,h);qt(-6,T,3,T);l(47,T);qt(56,T,56,\h);A(G);i%3?0:T<w?(A(G,33,T-15,10),fc(31,T-7,4,9)):(A(7,25,$,9),A(G,25,$,5),fc(24,$,2,h),D=B&y\>$-9?1:D);ta(S-u,0)}A(6,u,y-9,11);A(5,M=u+X*.7,Q=y-9+Y/5,8);A(8,M,Q,5);fx(I+'¢',5,15)}D=y>h?1:D",u);onkeydown=onkeyup=function(e){E=e.type[5]?4:0;e=e.keyCode;J=e^38?J:E;X=e^37?e^39?X:E:-E}


    Ниже он в отформатированном виде с комментариями.

    
    canvas=document.body.children[0];
    screen_height=time=150;
    last_height=screen_width=canvas.width=800;
    unit=dead=50;
    heights=[];
    
    // The abbreviation loop, initializing the variabled needed by the key-handlers on the side.
    for(prop in context=canvas.getContext('2d'))
      context[prop[jump=speed_x=speed_y=0]+(prop[6]||'')]=context[prop];
    
    setInterval(function(){
      if(dead)
        // initialize the player position, score, and heightmap
        for(x=405,i=y=score=0;i<1e4;)
          // (screen_width is reused as the off-the-screen height of gap blocks)
    
          // a block can be a gap if its index is <9, or if the last block was no gap. after this test,
          // a random number is compared to .3 to determine whether an actual gap is generated, or a
          // regular random height.
          last_height=heights[i++]=
            i<9|last_height<screen_width&Math.random()<.3?screen_width:Math.random()*unit+80|0;
    
      // silly formula to create parabolic movement based on the time
      plant_pos=++time%99-unit;plant_pos=plant_pos*plant_pos/8+20;
    
      
      y+=speed_y;
      // only move horizontally if that doesn't take us deep underground (x/unit|0 fetches the index of
      // the block below an x coordinate)
      x+=y-heights[(x+speed_x)/unit|0]>9?0:speed_x;
      // compute final player height index, and ground level under it
      ground=heights[player_index=x/unit|0];
      // adjust y and speed_y based on whether we are on the ground or not
      speed_y=y<ground|speed_y<0?speed_y+1:(y=ground,jump?-10:0);
    
      // we'll need the context a lot
      with(context){
        A=function(color,x,y,radius){
          // a is the abbreviated form of arc
          radius&&a(x,y,radius,0,7,0);
          // if color is not a gradient object (we set a P property in gradient objects), it is an index
          // into a set of colors
          fillStyle=color.P?color:'#'+'ceff99ff78f86eeaaffffd45333'.substr(color*3,3);
          // f for fill, ba for beginPath
          f(); ba();
        };
    
        // now loop over visible, or close to visible, blocks, and draw them and their clouds
        for(dead=i=0;i<21;i++){
          // this loop is reused for drawing the background/rainbow, which consists of seven concentric
          // circles. there's no good reason why interleaving clearing the screen with drawing the
          // screen's contents should work, but in this case it does
          i<7&&A(i%6,screen_width/2,235,i?250-15*i:screen_width);
          
          // we start drawing 5 units in front of the player (first four will be off-screen, needed just
          // for clouds)
          height_index=player_index-5+i;
    
          scroll_pos=x-height_index*unit;
          // since player screen position is fixed, we can use scroll position for collision detection.
          // this variable indicates whether the player is in the 'middle' of the current block
          player_in_middle=scroll_pos>9&scroll_pos<41;
    
          // ta for translate. move to start of block to make other drawing commands shorter
          ta(unit-scroll_pos,0);
          // cL for createLinearGradient, for the ground/grass gradient
          gradient=cL(0,height=heights[height_index],0,height+9);
          // if height is divisible by 6, there's a coin here. draw it. if the player is standing on the
          // ground, in the middle of this unit, pick up the coin
          height%6||(A(2,25,height-7,5),y^ground||player_in_middle&&(heights[height_index]-=.1,score++));
    
          // abbreviate, since we need this twice (and use it again to test whether a value passed to A
          // is a gradient)
          gradient.P=gradient.addColorStop;
          // this implements sinky terrain---when the index is divisible by 7, we use a different color,
          // and do the sinking if the player is standing here
          gradient.P(0,height_index%7?'#5e1':(height_index^player_index||y^height||
                                              (y=heights[height_index]+=plant_pos/99),'#a59'));
          // brown earth color for the bottom of the gradient
          gradient.P(1,'#b93');
    
          // this draws the clouds
          height_index%4&&A(6,time/2%200,9,height_index%2?27:33);
    
          // draws the terrain block. m is moveTo, qt is quadraticCurveTo, l is lineTo
          m(-6,screen_height);qt(-6,height,3,height);l(47,height);qt(56,height,56,screen_height);A(gradient);
    
          // draw deco trees or piranha plant (height==screen_width for gap blocks), check for collision
          // with plant
          height_index%3?0:height<screen_width
            ?(A(gradient,33,height-15,10),fc(31,height-7,4,9))
            :(A(7,25,plant_pos,9),A(3,25,plant_pos,5),fc(24,plant_pos,2,screen_height),
              dead=player_in_middle&y>plant_pos-9?1:dead);
    
          // undo block-local translation
          ta(scroll_pos-unit,0)
        }
    
        // draws the player, using the speed to adjust the position of the iris
        A(6,unit,y-9,11);
        A(5,iris_x=unit+speed_x*.7,iris_y=y-9+speed_y/5,8);
        A(8,iris_x,iris_y,5);
    
        // color is already dark from eye pupil, draw score with this color
        fx(score+'¢',5,15)
      }
    
      // check whether the player has fallen off the screen
      dead=y>screen_height?1:dead
    },unit);
    
    onkeydown=onkeyup=function(e){
      // if this is a keydown event, new_val gets the value 4, otherwise 0
      new_val=e.type[5]?4:0;
      e=e.keyCode;
    
      // give jump a truthy value if up was pressed, falsy if up was released
      jump=e^38?jump:new_val;
    
      // similar for speed_x, inverting new_val if left is pressed
      speed_x=e^37?e^39?speed_x:new_val:-new_val
    }

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 23

      +1
      Я ничего не понял, но результат мне нравится.
        +2
        я офигиваю, дорогая редакция.
          0
          впечатляет!
            0
            > Сайт с демками пока лежит, но некоторые из них можно найти на сайтах авторов.

            А можно в пост покидать ссылок на приложения на сайтах авторов?
              0
              > Например, вот первое место.

              в хроме завелось у кого-нибудь? :(
                +4
                да
                  0
                  у меня управление не работает. ничего не делает. вверх-вниз скроллит страницу
                    0
                    По самой демке сначала кликните — заработает.
                +6
                А давайте будем заходить на сайты по очереди :-) Чтобы они не падали :-)
                  0
                  В FF 3.6.10 первое место не работает
                  canvas.getContext is not a function
                    0
                    Kubutnu, FF 3.6.11pre — работает
                    +1
                    js1k.com/demo/750 — эта сволочь, однако, меня ещё и переигрывает.
                    Из минусов: нет рокировки
                      +1

                      Мда, алгоритм игры несколько странноват — куда и зачем пошёл король я так и не понял :)
                        +4
                        Король пошёл поднимать в атаку пешек.
                      0
                      однако на все ссылки
                      Service Temporarily Unavailable :)
                        +1
                        Очень впечатляет! Гораздо больше, чем победители недавнего конкурса 10k.
                          0
                          А есть обзор победителей на хабре?
                          Мне 10к конкурс нравился больше. И радует что двух победителей в нем (из 4), заняли хабралюди, которые писали про свои проекты.
                          0
                          Кто объяснит, откуда в примере берутся короткие имена методов context-а?
                          В спецификации canvas ничего не нашел такого.

                          // draws the terrain block. m is moveTo, qt is quadraticCurveTo, l is lineTo
                          m(-6,screen_height);qt(-6,height,3,height);l(47,height);qt(56,height,56,screen_height);A(gradient);
                            +1
                            вот отсюда
                            for(prop in context=canvas.getContext('2d'))
                              context[prop[jump=speed_x=speed_y=0]+(prop[6]||'')]=context[prop];
                            

                            или если убрать лишнее
                            for(prop in context=canvas.getContext('2d'))
                              context[prop[0]+(prop[6]||'')]=context[prop];
                            

                            то есть перебираем свойства контекста и делаем алиасы как первый символ имени + шестой (если он есть); видимо при этом они не пересекаются.
                            дальше идет with (context) {… } внутри которого доступны как длинные имена так и короткие.
                            вот такой замечательных ход для экономии байт :)
                              0
                              имелось ввиду нулевой и шестой, либо первый и седьмой
                              // для зануд :)
                                0
                                Плюс еще заодно проинициализировали начальные значения для переменных: jump=speed_x=speed_y=0

                                Красота… Спасибо!
                                  0
                                  Сам автор считает это самой полезной выдумкой для уменьшения размера :)

                                  Mechanized Abbreviation

                                  The coolest hack in this program is probably the mechanized abbreviation of the canvas context methods. Method names like quadraticCurveTo, createLinearGradient are nice and explicit, but those two taken together already eat 3.5% of the bytes available---when only referenced once! I needed to use them, but I wanted to avoid spelling them.

                                0
                                А мне эта дичайше понравилась.

                                Only users with full accounts can post comments. Log in, please.