Challenge: 
Winner?: 
Yes
Code Snippet: 
set display mode 1024,768,32
sync on
sync rate 0


rem create image from data
datatoimage(1)

rem prepare game
gosub _game_setup


do

rem grab variables
k_left = leftkey()
k_right = rightkey()
k_up = upkey()
k_down = downkey()
k_ctrl = controlkey()
k_space = spacekey()
k_ret = returnkey()
displayscore#=curvevalue(truescore,displayscore#,2)

IF GAMEOVER=0

rem variable update
steptimer=steptimer+1 : if steptimer>2 then steptimer=0
count=count+18 : if count>360 then count=0
countb=countb+5 : if countb>360 then countb=0
nextleveldelay=nextleveldelay-1
if countc>0 then countc=countc-1

rem control level
if nextleveldelay=<0
nextleveldelay=2600
groundy=groundy-20
level=level+1
truescore=truescore+100
if fallrate#<2.0 then fallrate#=fallrate#+0.08
endif

rem control powerups
if currentpowtype=0
powspawncount=powspawncount+1
if powspawncount=>powspawnrate and powtype=0
   powspawncount=0
   temp=rnd(100)
   if temp=>85 and temp=<100 then powtype=1
   if temp=>55 and temp<85 then powtype=3+rnd(1)
   if temp=>30 and temp<55 then powtype=2
   if temp=>0 and temp<30 then powtype=5+rnd(2)
   powx=32+rnd(sw#-64)
   powy#=0
endif
if powtype>0
   powy#=powy#+2
   if powx=>x#-46 and powy#=>y#-46 and powx=<x#+46 and powy#=<y#+46
      currentpowtype=powtype
      if currentpowtype=1 then currentpowtime=1000
      if currentpowtype=2 then currentpowtime=200
      if currentpowtype=3 then currentpowtime=200
      if currentpowtype=4 then currentpowtime=1000
      if currentpowtype=5 then currentpowtime=0 : truescore=truescore+500
      if currentpowtype=6 then currentpowtime=0 : truescore=truescore+200
      if currentpowtype=7 then currentpowtime=0 : truescore=truescore+5000
      powtype=0
   endif
   if powy#>groundy then powtype=0
endif
else
   if currentpowtype=1
      if currentpowtime>900 then size#=curvevalue(5,size#,10)
      if currentpowtime=900 then size#=5
      if currentpowtime<101 then size#=curvevalue(1,size#,10)
      if currentpowtime=1 then size#=1
   endif
   if currentpowtype=2
      if currentpowtime=200 then yhold#=sh#
      yhold#=yhold#-6
      for n=1 to fallsnowlimit
         if fallsnow(n).y#=>yhold# then fallsnow(n).exist=0
      next n
      for n=0 to snownodes-1
         if snow(n)=>yhold# and snow(n)=<yhold#+50 then changesnowheight(0.2,n,n+1)
      next n
   endif
   if currentpowtype=3
      if currentpowtime=200 then yhold#=y#+32
      for n=0 to snownodes-1 step 2
         changesnowheight((yhold#-snow(n))/2000,n,n+1)
      next n
      countc=countc-10
      if countc=<0 then countc=400
   endif
   if currentpowtype=4
      if currentpowtime>750 then windrate#=windrate#+0.08
      if currentpowtime<250 then windrate#=windrate#-0.08
      if currentpowtime=1 then windrate#=0
   endif
   currentpowtime=currentpowtime-1
   if currentpowtime=<0 then currentpowtype=0
endif

rem movement
if k_left<>k_right
   if k_left=1
      if xvel#>-4.2 then xvel#=xvel#-0.06
   else
      if xvel#<0 then xvel#=xvel#+0.12
   endif
   if k_right=1
      if xvel#<4.2 then xvel#=xvel#+0.06
   else
      if xvel#>0 then xvel#=xvel#-0.12
   endif
else
   if xvel#<0 then xvel#=xvel#+0.12
   if xvel#>0 then xvel#=xvel#-0.12
   if xvel#=>-0.12 and xvel#=<0.12 then xvel#=0
endif

`xvel#=xvel#+(windrate#/100)
x#=x#+xvel#+(windrate#/5)
a#=a#+(xvel#*1.3/size#)+((windrate#*1.3)/5)

if x#-(8*(size#-1))=<0 then x#=1+(8*(size#-1)) : a#=a#-(xvel#*1.3/size#)-((windrate#*1.3)/5) : xvel#=0-(xvel#/2)
if x#+(8*(size#-1))=>sw#-0 then x#=sw#-1-(8*(size#-1)) : a#=a#-(xvel#*1.3/size#)-((windrate#*1.3)/5) : xvel#=0-(xvel#/2)

rem find the y position
   rem find which nodes the x position lies between
      leftnode=0
      rightnode=0
      for n=0 to snownodes-1
         if x#=>(sw#/100)*n then leftnode=n
      next n
      rightnode=leftnode+1
   rem indicate the nodes
      `ink rgb(255,0,0),0
      `circle (sw#/100)*leftnode,snow(leftnode)-2,2
      `circle (sw#/100)*rightnode,snow(rightnode)-2,2
      `ink rgb(255,255,255),0
   rem firstly, stick the sprite to the line
      `y#=snow(leftnode)-32
   rem the above method has an obvious flaw (snapping into place between node's). this way is smoother:
      m#=(snow(rightnode)-snow(leftnode))/(((sw#/100)*rightnode)-((sw#/100)*leftnode))     `find the gradient between nodes
      d#=x#-((sw#/100)*leftnode)                                                           `find distance between nearest node to the left and player's x position
      y#=snow(leftnode)+(m#*d#)-32                                                         `move the player to the final position ( leftmost node's y + gradient * distance )

rem control clouds
for n=1 to numclouds
   if clouds(n).exist=0
      if rnd(100)=0
         clouds(n).x#=rnd(sw#)
         clouds(n).xsize=200+rnd(200)
         clouds(n).speed#=-32+rnd(64) : clouds(n).speed#=clouds(n).speed#/32
         clouds(n).snowrate=4+rnd(8)
         clouds(n).ratecount=0
         clouds(n).exist=50+rnd(100)
      endif
   else
      clouds(n).x#=clouds(n).x#+clouds(n).speed#
      clouds(n).ratecount=clouds(n).ratecount+1
      if clouds(n).ratecount=>clouds(n).snowrate
         clouds(n).ratecount=0
         temp=findfreefallsnow()
         if temp>0
            fallsnow(temp).x#=clouds(n).x#-(clouds(n).xsize/2)+rnd(clouds(n).xsize)
            fallsnow(temp).y#=0
            fallsnow(temp).yvel#=60+rnd(40) : fallsnow(temp).yvel#=fallsnow(temp).yvel#/100
            if fallsnow(temp).x#>0 and fallsnow(temp).x#<sw# then fallsnow(temp).exist=1
         endif
         clouds(n).exist=clouds(n).exist-1
      endif
   endif
next n

rem control falling snow
for n=1 to fallsnowlimit
   if fallsnow(n).exist>0
      fallsnow(n).x#=fallsnow(n).x#+windrate#
      fallsnow(n).y#=fallsnow(n).y#+(fallsnow(n).yvel#*fallrate#)
      rem check for snow leaving screen boundaries
      if fallsnow(n).x#>sw# then fallsnow(n).x#=0-(fallsnow(n).x#-sw#)
      rem check for collision with player
      if fallsnow(n).x#=>x#-(32*size#) and fallsnow(n).x#=<x#+(32*size#)
         if fallsnow(n).y#=>y#-((size#-1)*30)-(32*size#) and fallsnow(n).y#=<y#-((size#-1)*30)+(32*size#)
            fallsnow(n).exist=0
            truescore=truescore+1
         endif
      endif
      rem check for hitting the snow
      templ=0
      tempr=0
      temp=0
      for o=0 to snownodes-1
         if fallsnow(n).y#=>snow(o)-1
            if fallsnow(n).x#=>(sw#/100)*o and fallsnow(n).x#=<(sw#/100)*(o+1)
               templ=o
               tempr=o+1
               temp=1
               fallsnow(n).exist=0
            endif
         endif
      next o
      if temp=1
         if windrate#=0 then changesnowheight(-0.2,templ,tempr)
         if windrate#>0 then changesnowheight(0.16,templ,tempr) : truescore=truescore+1
      endif
      if fallsnow(n).y#=>groundy then fallsnow(n).exist=0
   endif
next n

rem check contact between player and snow
if (xvel#>-1 and xvel#<1)=0
   changesnowheight(abs(xvel#/100)*size#,leftnode,rightnode)
   truescore=truescore+1
endif

rem snow debug/user-editing
if debug=1
if k_ctrl=0
   for n=0 to snownodes-1
   if n=<leftnode then p#=5-((leftnode-n)) else p#=5-((n-rightnode))
   if p#<0 then p#=0
   if k_up=1 then snow(n)=snow(n)-p#
   if k_down=1 then snow(n)=snow(n)+p#
   if k_space=1 then snow(n)=snow(leftnode)
   next n
else
   if steptimer=0
      if k_up=1 then groundy=groundy-1
      if k_down=1 then groundy=groundy+1
   endif
endif
endif

rem amend levels to boundaries
for n=0 to snownodes
if snow(n)<160 then snow(n)=160
if n<snownodes
   if snow(n)=<160 and snow(n+1)=<160 then gameover=1
endif
if snow(n)>groundy-20 then snow(n)=groundy-20
next n
if groundy<300 then groundy=300
if groundy>sh#-20 then groundy=sh#-20


ELSE

if k_ret=1 then gosub _game_setup

ENDIF


rem prepare pixel drawing
lock pixels

rem draw background
box 0,0,sw#,160,rgb(150,210,230),rgb(100,150,200),rgb(150,210,230),rgb(100,150,200)
box 0,160,sw#,220,rgb(40,200,220),rgb(150,210,230),rgb(40,200,220),rgb(150,210,230)
box 0,220,sw#,groundy,rgb(160,232,250),rgb(40,200,220),rgb(160,232,250),rgb(40,200,220)

rem draw upper boundary
ink rgb(160,220,240),0
line 0,160,sw#,160

rem update and draw sprite
rotate sprite 1,a#
scale sprite 1,100*size#
set sprite diffuse 1,255,255-(size#*20),255-(size#*20)
paste sprite 1,x#,y#-((size#-1)*30)

rem draw clouds
`for n=1 to numclouds
`   if clouds(n).exist>0 then line clouds(n).x#-(clouds(n).xsize/2),3,clouds(n).x#+(clouds(n).xsize/2),3
`next n

rem draw falling snow
for n=1 to fallsnowlimit
   if fallsnow(n).exist>0
      ink rgb(240+(cos(count)*14),240+(cos(count)*14),240+(cos(count)*14)),0
      `dot fallsnow(n).x#,fallsnow(n).y#
      box fallsnow(n).x#-2,fallsnow(n).y#-2,fallsnow(n).x#+2,fallsnow(n).y#+2
   endif
next n

rem draw powerups
if powtype>0
ink rgb(200+(cos(count)*54),200+(cos(count)*54),200+(cos(count)*54)),0` : box powx-10,powy#-10,powx+10,powy#+10
for n=1 to 360 step 30
box powx+(cos(n+countb)*14)-1,powy#+(sin(n+countb)*14)-1,powx+(cos(n+countb)*14)+1,powy#+(sin(n+countb)*14)+1
next n
if powtype=1
   for n=1 to 360 step 30
   box powx+(cos(n-countb)*8)-1,powy#+(sin(n-countb)*8)-1,powx+(cos(n-countb)*8)+1,powy#+(sin(n-countb)*8)+1
   next n
endif
if powtype=2
   box powx-6,powy#+2+(sin(countb)*1),powx+6,powy#+5+(sin(countb)*1)
   box powx-6,powy#-4-(sin(countb)*1),powx+6,powy#-1-(sin(countb)*1)
endif
if powtype=3
   line powx-8,powy#+4,powx+8,powy#+4
   line powx-8,powy#+4,powx,powy#-4+(cos(countb)*2)
   line powx+8,powy#+4,powx,powy#-4+(cos(countb)*2)
endif
if powtype=4
   line powx-8+(cos(countb+90)*2),powy#-8,powx-4+(cos(countb+90)*2),powy# : line powx-8+(cos(countb+90)*2),powy#+8,powx-4+(cos(countb+90)*2),powy#
   line powx-2+(cos(countb+180)*2),powy#-8,powx+2+(cos(countb+180)*2),powy# : line powx-2+(cos(countb+180)*2),powy#+8,powx+2+(cos(countb+180)*2),powy#
   line powx+4+(cos(countb+270)*2),powy#-8,powx+8+(cos(countb+270)*2),powy# : line powx+4+(cos(countb+270)*2),powy#+8,powx+8+(cos(countb+270)*2),powy#
endif
if powtype=5
   for n=1 to 360 step 30
   box powx+(cos(n+countb)*8)-1,powy#+(sin(n-countb)*8)-1,powx+(cos(n+countb)*8)+1,powy#+(sin(n-countb)*8)+1
   next n
   box powx-1,powy#-6+(sin(countb)*1),powx+1,powy#+6+(sin(countb)*1)
endif
if powtype=6
   for n=1 to 360 step 30
   box powx+(cos(n+countb)*8)-1,powy#+(sin(n-countb)*8)-1,powx+(cos(n+countb)*8)+1,powy#+(sin(n-countb)*8)+1
   next n
   box powx-3,powy#-6+(sin(countb)*1),powx-1,powy#+6+(sin(countb)*1)
   box powx+1,powy#-6+(sin(countb)*1),powx+3,powy#+6+(sin(countb)*1)
endif
if powtype=7
   for n=1 to 360 step 30
   box powx+(cos(n+countb)*8)-1,powy#+(sin(n-countb)*8)-1,powx+(cos(n+countb)*8)+1,powy#+(sin(n-countb)*8)+1
   next n
   box powx-1,powy#-6+(sin(countb)*1),powx+1,powy#+6+(sin(countb)*1)
   box powx-5,powy#-6+(sin(countb)*1),powx-3,powy#+6+(sin(countb)*1)
   box powx+3,powy#-6+(sin(countb)*1),powx+5,powy#+6+(sin(countb)*1)
endif
endif

rem fill the snow
n=0
progx#=0
topy#=0
ink rgb(255,255,255),0
repeat
m#=(snow(n+1)-snow(n))/(((sw#/100)*n+1)-((sw#/100)*n))
progx#=(sw#/100)*n
d#=progx#-((sw#/100)*n)
topy#=snow(n)+(m#*d#)+1
for progx#=(sw#/100)*n to (sw#/100)*(n+1) step 10
box progx#,topy#,progx#+10,groundy
next progx#
n=n+1
until n=>snownodes-1

rem powerup effects
if currentpowtype>0
   `if currentpowtype=1
   `endif
   if currentpowtype=2
   n=0
   o#=1
   p#=sw#/2
   ink rgb(220+(cos(count)*24),160+(cos(count)*49),160+(cos(count)*49)),0
      repeat
         line sw#/2-p#,yhold#+n,sw#/2+p#,yhold#+n
         o#=o#*1.1
         n=n+o#
         if o#=>10 then p#=p#/1.3
      until o#=>40
   endif
   if currentpowtype=3
   ink rgb(200+(cos(count)*44),140+(cos(count)*139),140+(cos(count)*139)),0
      for n=1 to 20
         line 0,yhold#-(countc/n),sw#,yhold#-(countc/n)
         line 0,yhold#+(countc/n),sw#,yhold#+(countc/n)
      next n
   endif
endif

rem draw the ground
box 0,groundy,sw#,sh#,rgb(100,90,60),rgb(80,70,40),rgb(100,90,60),rgb(80,70,40)

rem draw screen fps
ink rgb(255,255,255),0
text sw#-text width(str$(screen fps())),sh#-18,str$(screen fps())

rem draw stats
if gameover=0
   if level>1 then text 2,sh#-33,"Level "+str$(level)
   text 2,sh#-18,"Score "+str$(int(displayscore#))
else
   ink rgb(200,50,100),0
   center text sw#/2,(sh#/2)-34,"GAME OVER!"
   text (sw#/2)-100,(sh#/2),"Level" : text (sw#/2)+100-text width(str$(level)),(sh#/2),str$(level)
   text (sw#/2)-100,(sh#/2)+16,"Score" : text (sw#/2)+100-text width(str$(int(displayscore#))),(sh#/2)+16,str$(int(displayscore#))
   center text sw#/2,(sh#/2)+62,"press ENTER (RETURN) to start over"
endif

rem end pixel drawing
unlock pixels


sync
cls 0
loop



function findfreefallsnow()
returnint=0
   for n=1 to fallsnowlimit
      if fallsnow(n).exist=0
         returnint=n
         exit
      endif
   next n
endfunction returnint


function changesnowheight(value#,left,right)
   for n=0 to snownodes-1
   if n=<left then p#=5-((left-n)) else p#=5-((n-right))
   if p#<0 then p#=0
   snow(n)=snow(n)+(value#*p#)
   next n
endfunction



_game_setup:
rem create sprite
sprite 1,0,0,1
offset sprite 1,32,32
set sprite diffuse 1,255,255,255
scale sprite 1,100
hide sprite 1

rem prepare variables
sw#=screen width()                                     rem width of the screen
sh#=screen height()                                    rem height of the screen
x#=sw#/2.0                                             rem player's x position
y#=sh#/4.0                                             rem player's y position
xvel#=0                                                rem player's speed of movement along x axis
a#=0                                                   rem player's angle
size#=1                                                rem player's size effector (for "growth" powerup)
yhold#=0                                               rem remembers player's y pos (for "flatten" powerup) / position of wave ("heat" powerup)

rem prepare snow
global snownodes as integer
snownodes=sw#/10
dim snow(snownodes) as float
c#=0
for n=0 to snownodes
c#=c#+8
snow(n)=sh#-120+(cos(c#)*20)
next n

rem prepare clouds
type clouds                                            rem "clouds" spawn the falling snow, and aren't seen
   x# as float                                         rem cloud's x position
   xsize as integer                                    rem range of the cloud
   speed# as float                                     rem speed of cloud's movement
   snowrate as integer                                 rem time it takes for snow to spawn
   ratecount as integer                                rem increments each loop; snow spawns when equal to ratecount
   exist as integer                                    rem flag for checking if the cloud is in use
endtype
numclouds=10                                           rem max number of clouds allowed in play
dim clouds(numclouds) as clouds

rem prepare falling snow
type fallsnow
   x# as float                                         rem x position of falling snow
   y# as float                                         rem y position of falling snow
   yvel# as float                                      rem speed at which this one falls
   exist as integer                                    rem flag for checking if this fallsnow is in use
endtype
dim fallsnow(1000) as fallsnow

rem prepare ground
groundy=sh#-20                                         rem position of the line marking the lower boundary ("ground")

rem prepare powerups
powtype=0                                              rem type of powerup falling towards player
powx=0                                                 rem x position of the falling powerup
powy#=0                                                rem y position of the falling powerup
powspawnrate=1500                                      rem time it takes to spawn a new powerup
powspawncount=0                                        rem increments each loop; powerup spawns when equal to powspawnrate
currentpowtype=0                                       rem type of power currently in use by player
currentpowtime=0                                       rem time remaining for player's current power

rem info on powtype
rem powtype = 1                                            the "growth" powerup (player size increases)
rem powtype = 2                                            the "heat" powerup (wave of heat melts all falling snow)
rem powtype = 3                                            the "flatten" powerup (flattens snow to players level)
rem powtype = 4                                            the "wind" powerup (strong winds sends snow hurtling to the right)
rem powtype = 5                                            this powerup adds 500 pts
rem powtype = 6                                            this powerup adds 2000 pts
rem powtype = 7                                            this powerup adds 5000 pts

rem prepare other variables
fallrate#=1.2                                          rem "master" control of snow's falling speed
windrate#=0                                            rem wind strength (for "wind" powerup)
steptimer=0                                            rem simple timer for controlling the speed of ground height debug
count=0                                                rem wraps from 0-360 to change color of falling snow
countb=0                                               rem wraps from 0-360 to rotate powerup dots
countc=0                                               rem controls distance from yhold# for red lines ("flatten" powerup)
global fallsnowlimit as integer : fallsnowlimit=1000   rem max amount of falling snow to handle
nextleveldelay=2600                                    rem time until next level
level=1                                                rem the current level
global truescore as double integer : truescore=0       rem the correct score
global displayscore# as double float : displayscore#=0 rem the score to display
debug=0                                                rem enables/disables the extra debug controls
gameover=0                                             rem indicates whether or not the game is lost
temp=0
return




function datatoimage(image)
  memblock=1
  read size
  make memblock 1,size
  read sx `as dword
  read sy `as dword
  read depth `as dword
  write memblock dword 1,0,sx
  write memblock dword 1,4,sy
  write memblock dword 1,8,depth

  for x=0 to sx-1
    for y=0 to sy-1
      pos=(y*sx+x)*4+12
      read b `as byte
      read g `as byte
      read r `as byte
      read a `as byte

      write memblock byte 1,pos,b
      write memblock byte 1,pos+1,g
      write memblock byte 1,pos+2,r
      write memblock byte 1,pos+3,a
    next y
  next x
make image from memblock image,1
delete memblock 1
endfunction