'Butterfinger Builder 'pal#0 bottle, nice 'pal#1 rope, landing pad 'pal#2 ground 'pal#3 city, bottle reflect 'pal#4 hud 'bg#0 text 'bg#1 rope only, one column scrolled per scanline 'bg#2 landing pad only 'bg#3 rope holder, groud, city 'spr#90+3 nice text 'spr#100 bottle reflect 'spr#101 bottle 'spr#101 rope tip 'pram$e000 2bytes high score 'pram$e002 16bytes seed 'file#3 rope holder 'file#4 landing pads 'file#5 hud 'file#6 city 'file#7 alternative palette 'the whole playfield area is bounded to 23x36 'all physics computation are 0x0 based coords, then the whole drawing operation are shifted using 'SCROLL' to center it 'the rope is drawn with the raster interrupt by shifting it's pixel using 'SCROLL' '''DATA difficulty_data: 'r max score 'w pad width in cells 'x,y pad bg copy params 'i,a pad min and max height offset from play field in pixel 'm rope amplitude 's rope swing force 'l rope length from pivot in pixel 'o pad max x offset from center in pixel 'u score multiplier 'd force side ' r w x y i a m s l o u d data 00100 ,8 ,0,00 ,100,100 ,0.06,0.00044,50 ,00 ,1 ,0 data 00400 ,6 ,0,04 ,150,180 ,0.08,0.00044,50 ,30 ,1.11 ,0 data 00800 ,8 ,0,00 ,170,200 ,0.10,0.00066,99 ,30 ,1.11 ,30 data 01000 ,4 ,0,12 ,230,270 ,0.12,0.00066,25 ,40 ,1.22 ,0 data 01500 ,8 ,0,00 ,190,240 ,0.14,0.00088,50 ,50 ,1.22 ,50 data 02000 ,6 ,0,04 ,190,240 ,0.14,0.00088,50 ,100 ,1.22 ,0 data 02500 ,5 ,0,08 ,170,220 ,0.14,0.00066,50 ,60 ,1.33 ,0 data 03000 ,4 ,0,12 ,190,240 ,0.14,0.00044,50 ,60 ,1.66 ,0 data 04000 ,2 ,0,20 ,150,270 ,0.18,0.00022,50 ,60 ,1.88 ,0 data 05000 ,3 ,0,16 ,60,60 ,0.18,0.00188,50 ,50 ,1.88 ,40 data 99999 ,2 ,0,20 ,270,270 ,0.10,0.00022,150,40 ,1.88 ,0 bottle_frames: 'list of characters for bottle spinning animation data 16,19,22,25,28 data 64,67,70,73,76 'additionnal frame for when the bottle land on the pad data 112,115,118,121,124 'cache it for quick access dim bfs(14) restore bottle_frames for bf=0 to 14 :read bfs(bf) :next bf reflect_frames: 'follow the bottle orientation data 192,194,196,198,200 data 202,204,206,224,224 data 192,192,192,192,192 'same but flipped data 192,204,202,198,226 data 196,194,228,230,230 data 192,192,192,192,192 dim rfs(29) restore reflect_frames for bf=0 to 29 :read rfs(bf) :next bf '''ROPE global rnx,rsl,winy 'rnx= layer 1 scroll value at scanline 0 rnx=0 'rsl= pixels the rope gains on every scanline rsl=0 sub r scroll 1,rnx-(raster-winy+1)*rsl, end sub '''SETUP 'to detect layout changes shownw=0 :shownh=0 'to center the 23x36cells window in the center according shown.w and shown.h winx=0 :winy=0 'center rope pivot point inside the window pivx=23*8/2 'bottle frame bf=0 'reflect flip frame offset rf=0 'landing pad width in cell padw=0 'bg copy coord padxc=0 :padyc=0 'landing pad position: left, right and top boundaries in pixels padl=0 :padr=0 :padt=0 'distance from top of playing field and landing pad in pixel distmin=0 :distmax=0 'ground position in pixel groundy=34*8 'fall acceleration in pixels per frame grav=0.34 'part of the slide speed kept every frame fric=0.72 'the slide stops below this speed slowv=0.08 'random seed if peekl($e002)=0 then randomize 123,$e002 'state '0= swinging '1= falling '2= sliding '3= landed '4= missed st=0 'hold during a number of frame hld=0 'score reducer per swing reduce=20 rdc=0 'nice state '0= no message '1= follow sliding right '2= follow sliding left '3= oups ns=0 'initial score inits=0 score=inits best=peekw($E000) 'initial difficulty gosub difficulty sw=amp :av=0 'initial palette gosub colorize '''MAIN sub title copy rom(8),size(8) to $ff00 copy rom(9),$1000 to $8000 bg source rom(10) bg copy 0,0,22,22 to 0,0 bg fill 22,11 to 63,21 char 97 bg fill 0,22 to 63,50 char 97 for i=0 to 7 sprite 30+i,,,208+i*2 sprite 30+i size 1 pal 2 sprite 40+i,,,208+i*2 sprite 40+i size 1 pal 3 next i dim bx(6) bx(0)=0 bx(1)=14 bx(2)=29 bx(3)=37 bx(4)=49 bx(5)=63 bx(6)=77 for i=0 to 6 sprite 20+i,bx(i),0,176+i*2 sprite 20+i size 1 pal 4 next i do 'draw title ty=cos(timer/80)*3+shown.h/2-114 tx=(shown.w-(8*16))/2+cos(timer/200)*2 for i=0 to 7 sprite 30+i,tx+i*16,ty, sprite 40+i,tx+i*16,ty+2, next i 'draw title 2 tx=shown.w/2-44 ty=shown.h/2-87 for i=0 to 6 sprite 20+i,bx(i)+tx+cos(timer/(140+(i*30)))*2,ty+cos(timer/(120+(i*30)))*2,176+i*2 next i 'draw image ix=(shown.w-8*22)/2 iy=(shown.h-8*22)/2 scroll 0,-ix,-iy if touch.tap then cx=(touch.x-ix)\8 cy=(touch.y-iy)\8 if cx>=1 and cx<=7 and cy>=19 and cy<=20 then poke $d999,123 else exit sub end if end if wait vbl loop end sub call title wait vbl cls 0 sprite off copy rom(1),32 to $ff00 copy rom(2),$1000 to $8000 music 0 font 160 on raster call r 'setup sprite size and palette sprite 100 pal 3 size 1 sprite 101 pal 0 size 2 sprite 102 pal 1 do 'detect layout changes if shownw<>shown.w or shownh<>shown.h then shownw=shown.w :shownh=shown.h gosub layout gosub hud gosub redraw 'rope tip tipx=pivx+rlen*cos(0.75+sw) :tipy=rlen*sin(0.75+sw) otipx=tipx :otipy=tipy end if 'swing the rope otipx=tipx :otipy=tipy oav=av add sw,av add av,swkc*sin(sw) 'compute rope tip position tipx=pivx+rlen*cos(0.75+sw) tipy=rlen*sin(0.75+sw) 'reduce score at each swing if oav<>0 and sgn(av)<>sgn(oav) and score>0 then score=max(100,score-rdc) gosub hud end if 'compute rope line linear parameters rsl=(tipx-pivx)/(tipy) rnx=1-pivx-winx 'compute and draw rope cy1=int(tipy)\8 bg 1 :pal 1 bg fill 0,0 to 0,63 char 0 if cy1>0 then bg fill 0,0 to 0,cy1-1 char 15 cell 0,cy1,8+(int(tipy) mod 8) 'update according to the state on st gosub s_swing, s_fall, s_slide, s_over, s_over 'draw bottle and rope tip sprite 100,bx-4+winx,by+4+winy,rfs(bf+rf) sprite 101,bx-8+winx,by+winy,bfs(bf) sprite 102,tipx-4+winx,tipy-4+winy,3 'update nice message on ns gosub n_none, n_right, n_left, n_oups, n_none wait vbl loop '''STATES s_swing: 'the bottle is attached to the rope tip 'compute rope tip position bx=tipx-4 :by=tipy-4 vx=tipx-otipx :vy=tipy-otipy sprite 101 flip abs(vx>0),0 rf=abs(vx>0)*15 if tap then st=1 volume 3,15, play 3,41,0 sound 4 haptic 6 end if return s_fall: 'the bottle falling free after being detached from the rope oby=by 'compute gravity add vy,grav add bx,vx add by,vy if bf<9 then add bf,1/2 'check if bottle land on the pad if vy>0 and oby+20<=padt and by+20>=padt then if bx+7>=padl and bx+1=groundy then by=groundy-20 st=4 bf=0 hld=55 score=inits music 32 haptic 1 rdc=0 end if return 'sliding on the platform s_slide: 'compute slide and friction add bx,vx if bf<14 then add bf,1/2 vx=vx*fric 'left the pad and fall again if bx+7=padr then st=1 vy=0 ns=3 'bottle stop sliding else if abs(vx)0) then gosub difficulty 'new round: fresh swing, new platform sw=amp :av=0 :oav=0 st=0 ns=0 if score=0 then gosub colorize gosub hud gosub redraw if score=0 then music 0 end if return '''NICE n_none: sprite off 90 to 93 return n_right: sprite 90,bx+12+winx,by+4+winy,4 sprite 91,bx+20+winx,by+4+winy,5 sprite 92,bx+28+winx,by+4+winy,6 sprite 93,bx+36+winx,by+4+winy,7 return n_left: sprite 90,bx-36+winx,by+4+winy,7 sprite 91,bx-28+winx,by+4+winy,4 sprite 92,bx-20+winx,by+4+winy,5 sprite 93,bx-12+winx,by+4+winy,6 return n_oups: sprite 90,,,31 sprite 91,,,47 sprite 92,,,63 sprite 93,,,79 return '''ROUTINES layout: 'recompute and draw layout 'center the window winx=(shownw-23*8)/2 winy=(shownh-36*8)/2 'center hud scroll 0,-winx,-winy bg 3 :cls 3 'draw the background city bg source rom(6) bg copy 0,0,14,27 to 64-14+1,15 bg copy 14,0,14,27 to 1,15 'draw rope holder bg source rom(3) bg copy 0,0,2,8 to 0,0 'draw ground pal 2 bg fill 0,34+8 to 63,34+8 char 1 bg fill 0,35+8 to 63,63 char 2 'center rope holder and ground scroll 3,-winx-22\2*8+4,-winy+8*8 'center the pivot scroll 1,,-winy 'debug playfield pal 2 :bg 0 'bg fill 23,0 to 63,63 char 2 'bg fill 0,36 to 63,63 char 2 return hud: 'redraw hud bg 0 bg source rom(5) bg copy 0,0,23,2 to 0,1 pal 4 number 3,2,score,5 number 15,2,best,5 return difficulty: 'update difficulty according the score 'update difficuly restore difficulty_data read threshold while score>=threshold and threshold<99999 skip 11 :read threshold wend read padw, padxc, padyc, distmin, distmax, amp, swkc, rlen, padoff, multiplier, sidew padt=rnd(distmax-distmin,$e002)+distmin side=(rnd(1,$e002)*2)-1 dist=sidew+padoff*(rnd $e002) padl=(23-padw)*8\2+dist*side padr=padl+padw*8 return redraw: 'redraw pad 'draw the pad bg 2 :cls 2 bg source rom(4) bg copy padxc,padyc,8,4 to 0,0 scroll 2,-padl-winx,-padt-winy 'draw below the pad until it reach the floor t=padt+4*8 :y=4 while t