COPTER CRUISE

329 words ~ 2-3 mins — Mathieu 'p01' Henri on July 29th, 2004

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 )