Copter cruise
A simple Commanche-like that won the 20lines 'Terrain' contest at the OzoneAsylum in July 2004
Use the arrow keys to turn and go up or down. The lower and longer you fly the higher the score.
The heightmap is generated using the classic plasma fracal, with a twist: The heights are interpolated using a bilinear or bicubic interpolation with added midpoint.
The terrain is rendered using DOM elements in position absolute, to represent the perpspective view seen from the helicopter, including the fog. Only the top
property of each element move.
Source code
/* 1 */ mapSmall=[]
/* 2 */ mapBig=[]
/* 3 */ keyboardState = []
/* 4 */ for( x=y=z=p=angle=i=j=score=0*isNaN(bla=""); j<512?1:0*(document.getElementById('renderArea').innerHTML+=bla); mapSmall[j++&255]=Math.min(Math.random()*48,24) )
/* 5 */ bla += "<span style='position:absolute;left:"+ Math.round( 160+((j&31)-16)/(32-(j>>5))*318 ) +";top:0;width:"+ Math.round( 1+1.0/(32-(j>>5))*318 ) +";height:420px;background-color:rgb("+ Math.floor(204-(1+j>>5)*153/16) +","+ Math.floor(204-(1+j>>5)*( (((j&15)^((j>>5)&3))&0)+153)/16) +","+ Math.floor(204-(1+j>>5)*204/16+ 0*(keyboardState[j]=0)) +")'></span>\n"
/* 6 */ for( spanCollection=document.getElementsByTagName("span"); i<65536; mapBig[ i++ ]=(v1=Math.pow(((i>>8)&15)/15,1+(((i&255)^(i>>8))&255?1:0)))*(mapSmall[((i/16+1)&15)+(((i>>8)/16+1)&15)*16]*(u1=Math.pow((i&15)/15,1+(((i&255)^(i>>8))&240?1:0)))+mapSmall[((i/16)&15)+(((i>>8)/16+1)&15)*16]*(u0=1.0-u1))+(1.0-v1)*(mapSmall[((i/16+1)&15)+(((i>>8)/16)&15)*16]*u1+mapSmall[((i/16)&15)+(((i>>8)/16)&15)*16]*u0)+mapSmall[(i&15)+((i>>8)&15)*16]/48 )
/* .. */ {
/* .. */ }
/* .. */ document.onkeydown = function( evt )
/* .. */ {
/* 7 */ keyboardState[ evt?evt.keyCode:event.keyCode ] = 1
/* .. */ }
/* .. */ document.onkeyup = function( evt )
/* .. */ {
/* 8 */ keyboardState[ evt?evt.keyCode:event.keyCode ] = 0
/* .. */ }
/* .. */ function hop()
/* .. */ {
/* 9 */ for( k=0*(x+=Math.sin(angle+=(keyboardState[39]-keyboardState[37])/16)+ 0*(y-=Math.cos(angle)+0*(score+=8-z)))+0*(Z=z-8-0*mapBig[ (x&255)+(y&255)*256 ]/1) ;k<512; spanCollection[ k++ ].style.top=( Z+ mapBig[ ((x+(((k&31)-16)*(fovRatio=Math.cos( ((k&31)-16)/16*Math.PI/8 ))*Math.cos( angle )-((k>>5)-16)*fovRatio*Math.sin( angle )))&255)+((y+(((k&31)-16)*fovRatio*Math.sin( angle )+((k>>5)-16)*fovRatio*Math.cos( angle )))&255)*256 ] )*fovRatio*320/(32-(k>>5)) )
/* .. */ {
/* .. */ }
/* 10 */ document.getElementById('sprite').style.backgroundPosition = (-160*(1+keyboardState[39]-keyboardState[37])) +"px 0px"
/* 11 */ document.getElementById('power' ).style.left = 320-(p+=(hit=((z+mapBig[ (x&255)+(y&255)*256 ])<16))?32:0)
/* 12 */ p>=320?alert( "your score: "+ Math.round(score) ):z=Math.min( 8, z+(hit?2:0)-.5*(keyboardState[38]-keyboardState[40]) )
/* 13 */ clearInterval(intervalHandle+p-320)
/* .. */ }
/* 14 */ intervalHandle = setInterval( hop, 10 )