Some tweetable #js1k demos


JS1k is consuming me at the moment. I saw this entry by strager and it inspired me to push for a tweetable (<=140 byte) demo based on his.

By dropping the save/restore and alpha blending features, I was able to come up with a few candidates which I think look fairly pretty.

Unlike my previous allRGB and rot13 entries, where I had a definite goal in mind, here I’m really just playing with parameters until something cool appears on the screen. Which is kinda neat, it recaptures that innocent experimental spirit which was what first attracted me to programming when I was a kid.

Stained Glass (140b). A stained glass window, ever expanding and becoming more intricate. There’s a nice ‘grayscale’ effect due to anti-aliasing and the fact that we’re drawing over some lines at slight offsets, making them thicker and so appearing darker. I started off using ‘with’ in the code like @strager, but actually found I saved bytes without it, because setInterval code is executed in the global scope but we need to do the translate outside setInterval- it’s more succinct to just say ‘d.’ everywhere.

h=60,d=document.body.children[0];d.height*=h;d=d.getContext('2d');d.translate(h,h),setInterval("d.strokeRect(9,9,h/2,h++/2),d.rotate(90)",9)

Exploding Web (139b). This one starts as a spirograph then quickly destablises into a sunburst. But as soon as you think you know the pattern, a new one emerges – after running for a few seconds, you can suddenly see hints of beams of light seen through a forest. Or is it just a mess of lines? ;)

h=99,d=document.body.children[0];d.height*=h;d=d.getContext('2d');d.translate(h,h);setInterval("d.strokeRect(9,9,h/2+--h,h);d.rotate(h)",1)

Moonrise (140b). The interesting thing about all these demos is the way they evolve the longer they’re run. To me, this one really has depth. First it’s a new dawn with the sun shining, then the moon takes over and its light reflects over the waters of a rippling lake. As you scroll down the page, the lake transforms into an abstract network of shapes which have an inscrutible pattern.

h=99,d=document.body.children[0];d.height*=h;d=d.getContext('2d');d.translate(h,h),setInterval("d.strokeRect(10,9,h/3,h++/3),d.rotate(9)",2)

rot13 (138b). An entry which actually does something useful in under 140 bytes! Performs the rot13 substitution cipher on user input. Loops until you press cancel, at which point it quits with an error. Don’t think I can fix that in the 2 remaining bytes :( I’ve also written a ‘full’ version in 1000ish bytes, which I’ll tidy and submit later. Slap “javascript:” on the front and you’ve got a very handy bookmarklet :)

for(r=o='rot13';o=prompt(r,o).replace(/[a-z]/gi,function(c){return String.fromCharCode((n=c.charCodeAt()+13)>122||n<104&&n>90?n-26:n)}););

Blocks of colour (140b). This one I’d entered a few days ago as my first twitter sized entry. It’s 140 bytes including the #js1k hashtag, which is pretty funky. It’s similar to ‘s ‘fence’ entry, and uses the colour randomising code from his entry. The “|0″ part performs type conversion, and seems to be required for Chrome.

r=Math.random;setInterval('with(document.body.children[0].getContext("2d"))fillStyle="#"+(1E6*r()|0),fillRect(r()*290,r()*99,9,9)',2)//#js1k

Cave of Evil (136b). Showing off three new features here, firstly a new way to access the canvas – most people so far are using document.body.children[0], but document.body.children.c is one byte shorter, which helps. Also, this demo sets the width and the height in one move: height=width*=h=9, which is pretty cool, and finally I’m using canvas’s globalAlpha property to create a really nice greyscale effect. Damn, this is addictive!
with(document.body.children.c)height=width*=h=9,c=getContext('2d'), c.globalAlpha=.008,setInterval("c.fillRect(0,0,h,h),c.rotate(h++)",1)

Update: Chrome doesn’t like globalAlpha’s <0.01, and Opera doesn't like <0.1, so I've updated the code.

with(document.body.children.c)height=width*=h=9,c=getContext(’2d’), c.globalAlpha=.1,setInterval(“c.fillRect(0,0,h,h),c.rotate(h++)”,5)

It’s almost as pretty :)


Related Posts:

, , , , ,

  1. #1 by strager on September 1, 2010 - 9:29 pm

    Nice entries you have there. =] Although they’re less pretty than jazzyb (IMO), they fit in a tweet.

    I looked at “Stained Glass” and noticed the code can be shrunk a bit more. You write “h=60;d.height*=h;” where you could write “d.height*=h=60;”. Also, rotate takes its angle in radians, not degrees; 90 can be mod’d out to approximately 2.

    “Exploding Web” and “Moonrise” can also take advantage of the first optimization I mentioned.

    Hope this helps squeeze some more magic into a tweet!

    • #2 by Howard Yeend on September 2, 2010 - 12:34 am

      Thanks! Useful to know about rotate, that’s handy. Yeah I realised I could do d.height*=h=60 when I did the cave, but I’d already submitted the other demos so I left it in :)

  2. #3 by r4z0rw0lf on September 1, 2010 - 10:39 pm

    The cave of evil wont work in Webkit based browsers, or Opera. also, setting the delay for setInterval to 1 froze Firefox on my computer.

    • #4 by Howard Yeend on September 2, 2010 - 12:31 am

      Yep, a fix has been submitted. It actually does work (no errors) but setting globalAlpha to <0.01 in chrome results in things being drawn in white, and the same in Opera for <0.1, which is disappointing.

      I can't reproduce the firefox hang, but I've set the timeout to 5 instead. Hopefully that should fix it.

      Thanks for the feedback.

  3. #5 by Ph0X on September 1, 2010 - 11:39 pm

    Hey, I was also inspired by you and strager, and although I just started learning JS and Canvas 2days ago, I decided to give this a try.

    Here’s what I finally got (140b):
    http://www.ehsankia.com/cjs/6

    I was going for something a little bit more artistic, but sadly, couldn’t get it any lower than 155b
    http://www.ehsankia.com/cjs/5

    Cheers.

    • #6 by Howard Yeend on September 2, 2010 - 12:46 am

      Cool stuff!

      Here’s a version of the 2nd which fits into 136b:

      C=document.body.children[a=0].getContext(’2d’);setInterval(“with(Math)C.stroke(C.lineTo(140+90*cos(a+=.1)-35*cos(3.1*a),150*sin(a)))”,1)

      It’s not quite the same, but maybe you can use some of the optimisations to make it better.

      i.e. .1 instead of 0.1 and c.stroke(c.lineto(…)) instead of c.lineto(…),c.stroke()

      only tested in firefox, so the 2nd optimisation might not work.

  4. #7 by anon on September 6, 2010 - 4:25 am

    PLEASE make a version of your lovely demo where older tiles disappear. Beautiful stuff :)
    http://js1k.com/demo/578

    • #8 by Howard Yeend on September 6, 2010 - 11:14 am

      that’s no problem, but I doubt it’ll fit in a tweet ;) I’ll write a new one with disappearing blocks later.

  5. #9 by Mathieu 'p01' Henri on September 9, 2010 - 8:54 pm

    While taking a little break from WOLF1K I made this tweet-sized Embossed Mandelbrot: http://js1k.com/demo/624

    • #10 by Howard Yeend on September 11, 2010 - 7:41 am

      yeah I saw that, very impressive work! Now you just need to add a scroll-to-zoom interface in the remaining byte…

  6. #11 by Kate on April 30, 2012 - 4:34 pm

    Very impressed :)

Comments are closed.