I imagine Spring to be a beautiful season that you don't mind spending your time in the hills, enjoying the beautiful blue skies and clouds.
for(_='fill(R),QMath.PPrandom()O*O,Nba(Z[0]Y0;XXm=Wa.VQVon+=h(in485*(i%3=X--;));;for()iify("#fff")+a[g3216=mouse*Ps(g/V 9 stroke(=f?.5:.15functi(Pmax(0,z.addColorStop((-6380g){c.widthc.height=XB=f=Wn=10Xp=q=6S=O*1Xh=return 40220+S)-60)}i a)(Y+(g[6]||"")]=(""+])[27]?]:C){]=C}})(iu=Xd=VcI(0e=new UtArray(d.datVbuffer ld(2setInterval(Vceu=m-6W[2*m-n,n=m]Y;p=[2*p-q+.4,q=p]Y;s=mXt=m+1Xif(p<s){f&&(p2B.06;A=""i=~~B;iA"✓",m.004;V)}else 0<=t-s?(V#0f0"Qm+):(Vred"Qm-,p.5QA="",B=Wm,n-4p=Pm(mp)kk{v=k+u;w=v70l=Xlj=0*l+k,x=0*((l-w)/(0-w)Qy=1-x/y=255*y*y,.7Qe[j]=(l<w?0:255)<<24|(~~((v+x)/60)%2?y:0)<<|y<<8|y}r=.3*60-p,0 save( ta(r pg(d,0+r gC("destati-over" Z arc(m-u,p+61 R fx(A,370 ZVl(i,i+u22i%9||Vfc(0N0N1,1gA(.3Zarc(12*i-.1*u%72N20+Q9RgA(1z=VcL1,"#8DF""#04B" fy(z fc re()},30keydowndown=f=1};keyupup=f=0}';g=/[-V-ZN-R]/.exec(_);)with(_.split(g))_=join(shift());eval(_)
Zm9yKF89J2ZpbGwoUiksUU1hdGguUFByYW5kb20oKU8qTyxOYmEoWlswXVkwO1hYbT1XYS5WUVYfb24eKz0daCgcaW4bNDgaNSooaSUzGT0aWBgtLTspFyk7Fjtmb3IoFSkVaRhpFxRmeSgiExMjZmZmIhIpKxFhW2cQMzIPMTYOPR5tb3VzZQwqUHMbKGcvCxZWCTkJc3Ryb2tlKAg9Zj8uNTouMTUHZnVuY3RpHigGUG1heCgFMCwEFnouYWRkQ29sb3JTdG9wKAMoBC02BBoEMzgwAgZnKXsBYy53aWR0aBhjLmhlaWdodD0PWEI9Zj1Xbj0xMFhwPXE9NgRTPU8qMVhoPQFyZXR1cm4gNDALMjIwK1MpLQ8LNjApfRVpIBsgYSkoARBZKyhnWzZdfHwiIildPSgiIisQXSlbMjddPxBdOgZDKXsQXT1DfX0pKGkWdT1YZD1WY0koGgQOMBZlPW5ldyBVG3QPQXJyYXkoZC5kYXRWYnVmZmVyCWxkKDIWc2V0SW50ZXJ2YWwoAVZjZQIWdT1tLTZXWzIqbS1uLG49bV1ZO3A9WzIqcC1xKy40LHE9cF1ZO3M9HG0RDlh0PRxtKzERDlhpZihwPHMpe2YmJihwHTIWQh0uMDY7QT0iIhVpPX5+QjtpF0EdIuKckyIsbR0uMDA0O1YSKX1lbHNlIDA8PXQtcz8oVhMjMGYwIlFtKwcpOihWE3JlZCJRbS0HLHAdLjVRQT0iIixCPVcFbSxuLTQWcD1QbRsoHG0RDgRwKRVrGGsXe3Y9ayt1O3c9HHYRNzAVbD0OWGwXaj0aMCpsK2sseD0PMCooKGwtdykvKA8wLXcpUXk9MS14Lw8EeT0yNTUqBXkqeSwuN1FlW2pdPShsPHc/MDoyNTUpPDwyNHwofn4oKHYreCkvNjApJTI/eTowKTw8Dnx5PDw4fHl9cj0uMyoFNjAtcCwwCXNhdmUoCXRhKARyCXBnKGQsBA4wK3IJZ0MoImRlc3QbYXRpHi1vdmVyIglaCWFyYyhtLXUscCs2BDEEBAgJUgkSCWZ4KEEsMwQ3MAlaFFZsKGksHGkrdREyMggUaSU5fHxWZmMoGjBODzBOMSwxH2dBKC4zH1ofYXJjKDEyKmktLjEqdSU3BBkRMk4yMCsZUQQ5H1IfZ0EoMRZ6PVZjTAIDMSwiIzhERiIDBCIjMDRCIglmeSh6CWZjAglyZSgpfSwzMBYea2V5ZG93bgxkb3duPQFmPTF9Ox5rZXl1cAx1cD0BZj0wfSc7Zz0vWwEtH1YtWk4tUl0vLmV4ZWMoXyk7KXdpdGgoXy5zcGxpdChnKSlfPWpvaW4oc2hpZnQoKSk7ZXZhbChfKQ==
// zz85 / twitter.com/blurspline
// More details to come on my blog
// @ http://www.lab4games.net/zz85/blog/
//
// Minified by Closure, Packed with @Siorki's RegPack
// which improves @aivopaas's JSCrush compression
//
// After going using a node script for my workflow,
// I tweaking some values in the minified form before submitting
// Therefore, this is probably not the final version,
// but probably you might find what you want if you
// have bothered to look in here..
var w, h // width, height
var image, data32; // data image stuff
var s; // section width
var down; // is button pressed
var f; // terrian function
var i, j; // loop counters
var u, v; // inner loop
var ballx, ballx2, bally, bally2; // ball positions
var ballay; // acceleration
var pany; // scrolling
var q, q2; // terrian height differences
var th; // base terrain height
var offx; // offfset
var u2, offy, v2, k; // variables in loops
var gbg; // gradient background
var score, airtime, comments; // some game play stuff..
// ball variables
c.width = w = 480;
c.height = h = 320;
s = 60;
airtime = down = 0
ballx = ballx2 = 100
bally = bally2 = s
// terrain function
f=function(a,b,c) {
return Math.sin(a / 220 + seed) * 40 - Math.sin(a / s) * 32;
}
// different terrain when you refresh
var seed= Math.random() * 10;
// tweet i saw from @aivopaas on shortening canvas properties and functions
for(i in a)(function(i){a[i[0]+(i[6]||'')]=(''+a[i])[27]?a[i]:function(_){a[i]=_}})(i)
offx = 0; // offsetx
th = h / 2; // terrain height
// Use typed arrays for performance boost
image = a.createImageData(w, h / 2);
data32 = new Uint32Array(image.data.buffer);
a.ld(2)
// comments = ['yeah','great','awesome','wow!','moo', 'fantastic']
// comments = '♪♫❤☼';
setInterval(function() {
a.clearRect(0, -s, w, h + s);
offx = ballx - s;
// BALL PHYSICS
ballay = 0.4; // gravity
// Position Verlet Swapping via Array trick !
ballx = [2 * ballx - ballx2, ballx2=ballx][0]
bally = [2 * bally - bally2 + ballay, bally2 = bally][0]
// TERRIAN HEIGHTS
q = f(ballx) + th;
q2 = f(ballx + 1) + th;
if (bally < q) { // is ball on the ground?
// in the air
down&&(bally+=2)
airtime+=0.05
score = ''
for (i=~~airtime;i--;) score += '✓', ballx += 0.004;
a.fy('#fff');
// if (bally > bally2) score += comments[~~airtime];
} else {
// on the hills
if (q2 - q >= 0) {
// is the slope going down?
a.fy('#0f0');
ballx += down ? 0.5 : 0.15;
// score = down ? '☺' : '.'
// score = 'ouch!' + airtime
} else {
// upwards
a.fy('red');
ballx -= down ? 0.5 : 0.15;
bally += 0.5;
}
airtime = 0
score = ''
}
ballx = Math.max(ballx, ballx2 - 4);
bally = Math.min(f(ballx) + th, bally);
// Generate the stripe pattern based on the terrian using a pixel approach
for (u = w; u--;) {
u2 = u + offx
offy = f(u2) + 70
for (v = h/2; v--;) {
j = v * w + u;
v2 = (v - offy) / (h - offy) * h; // h = th * 2 multiplier for slant (0..4)
k = 1 - v2 / h;
k = Math.max(k * k, 0.7) * 255;
data32[j] =
((v < offy ? 0 : 255) << 24) | // alpha
((~~((u2 + v2) / s) % 2 // stripe?
? k : 0) << 16) | // blue
(k << 8) | // green
k; // red
}
}
// Start to paint stuff
pany = Math.max(s - bally, 0) * 0.3;
a.save();
a.translate(0, pany);
a.putImageData(image, 0, 160 + pany);
a.gC('destination-over') // thanks to this, we are painting things backwards
// Draw ball
a.beginPath();
a.arc(ballx - offx, bally + s, 10, 0, 9);
a.stroke();
a.fill();
a.fy('#fff');
// Paint score ~~
a.fillText(score, 30, 70);
// Outline Terrian
a.beginPath();
for (i = w; i--;) a.lineTo(i, f(i + offx) + 229);
a.stroke();
// CLOUDS
for (i = w; i--;) {
// a.beginPath();
i%9 || a.fillRect(Math.random()*w, Math.random()*h, 1, 1);
a.gA(0.3)
a.beginPath();
a.arc(i * 12 - offx * 0.1 % 70 , (i%3)*5 + Math.random()*2, 20 + (i% 3)*5, 0, 9);
a.fill();
a.gA(1)
}
// We paint the background last
gbg = a.createLinearGradient(0, -s, w, h + s)
gbg.addColorStop(1, '#8DF')
gbg.addColorStop(0, '#04B');
a.fy(gbg);
a.fillRect(0, -s, w, h + s);
a.restore();
}, 30); // target 25 fps
onkeydown = onmousedown = function (a,b,c) {
down = 1
}
onkeyup = onmouseup = function (a,b,c) {
down = 0
}