REM Challenge: Target Hitting
REM Author: Phaelax
 
set display mode 800,600,32
 
 
sync on
 
 
tilt# = 90
power# = 0.0
g# = 6.6
a# = 300
originX = 600
originY = 490
level = 1
 
 
repeat
   cls
 
   gosub Controls:
 
   drawScene()
 
   gosub drawMeter
 
   drawArcher(originX, originY+60, power#, tilt#)
   drawStupidGuy(725,570)
 
   gosub fireArrow
 
 
   gosub checkResults
 
   rem draw arrow
   ink rgb(0,0,255),0
   line originX+x, originY-y, originX+x+sin(a#)*20, originY-y+cos(a#)*20
 
 
   rem if player beats a level, pause for 2 seconds before continuing
   if win = 1
      if timer() - timestamp >= 2000
         originX = originX - 40
         x = x + 40
         inc level, 1
         win = 0
         appleHit = 0
      endif
   endif
 
 
   set cursor 20,20
   print "Power: ", power#*100
   print "Tilt: ", tilt#
   print
   print "Level: ", level
 
   sync
until returnkey()
end
 
 
checkResults:
   gameover = 0
   ink rgb(255,255,255),0
   if gameover = 0
      if appleHit = 1
         center text 400, 100, "You hit the apple!"
         if bodyHit = 1
            center text 400, 120, "Unfortunately, you also annihilated your buddy"
            ink rgb(255,0,0),0
            center text 400, 200, "GAME OVER"
            gameover = 1
         else
            center text 400, 120, "Congratulations, step back 10 paces and try 'his' luck again!"
            if win = 0 then timestamp = timer()
            win = 1
         endif
      else
         if bodyHit = 1
            center text 400, 120, "NO no no! The apple! Hit the apple!"
            ink rgb(255,0,0),0
            center text 400, 200, "GAME OVER"
            gameover = 1
         endif
      endif
   endif
 
 
 
   if gameover = 1
      center text 400, 240, "Would you like to try again? (Y/N)"
      if k = 21
         level = 1
         originX = 600
         appleHit = 0
         bodyHit = 0
      endif
      if k = 49 then end
   endif
 
RETURN
 
 
 
Controls:
   if gameover = 1 then k = scancode()
 
   if mouseclick() = 1 and mFlag = 0
      mFlag = 1
      oldX = originX
      oldY = originY
   endif
 
   if mouseclick() = 1 and mFlag = 1
      dx = (mousex() - oldX)
      dy = (mousey() - oldY)
      d2 = dx*dx + dy*dy
      if d2 > 16
         power# = d2 / 10000.0
         if power# > 1 then power# = 1
      else
         power# = 0
      endif
      tilt# = atanfull(dx, dy)*-1
      if tilt# < 0 then tilt# = 0
      if tilt# > 90 then tilt# = 90
   endif
 
   if mouseclick() = 0
      if mFlag = 1
         mFlag = 0
         if power# > 0
            fire = 1
            t# = 0
            v# = 120 * power#
            rem 750 is the x-axis we want to find the impact at
            impact_time# = (750-originX)/(sin(tilt#)*v#)
            preX = originX
            preY = originY
            appleHit = 0
            bodyHit = 0
         endif
      endif
   endif
RETURN
 
 
 
drawMeter:
   if mFlag = 1
      ink rgb(0,255,0),0
      circle originX, originY, 4
      circle originX, originY,100
      ink rgb(64,255,64),0
      d# = sqrt(d2)
      if d# > 100 then d# = 100
      line originX, originY, originX+sin(180+tilt#)*d#, originY-cos(180+tilt#)*d#
   endif
RETURN
 
 
fireArrow:
   if fire = 1
      t# = t# + 0.2
      if t# >= impact_time#
         t# = impact_time#
         fire = 0
      endif
      x = sin(tilt#)*v#*t#
      y = cos(tilt#)*v#*t# - 0.5*g#*t#^2
      feet = ((600-(originY-y)+20)/360.0)*180
      if originY-y > 600 then fire = 0
      ink rgb(0,0,255),0
      circle originX+x, originY-y, 2
      a# = wrapvalue(atanfull(x-preX, y-preY)+180)
      lx1 = originX + x
      ly1 = originY - y
      lx2 = lx1 + sin(a#)*20
      ly2 = ly1 + cos(a#)*20
      line lx1, ly1, lx2, ly2
      preX = x
      preY = y
 
      rem apple is: (circle 725, 476, 4)
      i = lx2 - lx1
      j = ly2 - ly1
      n# = ((725 - lx1)*i) + ((476 - ly1)*j)
      d# = i*i + j*j
      u# = n# / d#
      if u# >= 0 and u# <= 1
         ix# = lx1 + (lx2 - lx1)*u#
         iy# = ly1 + (ly2 - ly1)*u#
         e = 725 - ix#
         f = 476 - iy#
         dist = e*e + f*f
         if dist <= 36 then appleHit = 1 : r = dist
      endif
 
      rem bounding ellipse around target guy (ellipse x, y-45, 15,45), where [x,y] is stupidGuy position
      ex# = 725 / 15.0
      ey# = 525 / 45.0
      px# = (originX + x) / 15.0
      py# = (originY - y) / 45.0
      dist# = (ex# - px#)^2 + (ey# - py#)^2
      if dist# <= 1.0
         bodyHit = 1
      endif
   endif
RETURN
 
 
function drawScene()
   rem floor
   gradientVerticalBox(0,500,799,599,rgb(36,36,36),rgb(48,96,96))
   rem measuring wall
   for x = 0 to 40
      rem wall
      ink rgb(200,200,200),0
      box 730+x, 200+x, 730+x, 550+x
      rem shadow
      ink rgb(64,64,64),0
      box 730+x, 550+x, 799, 550+x
   next x
   rem wall top
   ink rgb(128,128,128),0
   for i = 1 to 10
      line 730+i, 200, 770+i, 240
   next i
   rem wall side
   box 770,240,780,590
 
   rem foot markings
   ink rgb(92,92,92),0
   for i = 0 to 17
      y = 240+i*20
      line 730, 200+i*20, 770, y
      line 770, y, 780, y
      feet$ = str$((18-i)*10)
      `if len(feet$) < 3 then feet$ = " "+feet$
      text 782,y-8, feet$
   next i
 
endfunction
 
 
function drawStupidGuy(x, y)
   ink rgb(255,203,179),0
   circle x, y-80, 10
   line x, y-70, x, y-30
   rem legs
   line x, y-30, x-20, y
   line x, y-30, x+20, y
   rem arms
   line x-15, y-35, x,y-55
   line x+15, y-35, x,y-55
   rem apple
   ink rgb(255,0,0),0
   circle x, y-94, 4
   circle x, y-94, 3
   circle x, y-94, 2
 
   ellipse x, y-45, 15,45
endfunction
 
 
function drawArcher(x, y, power#, tilt#)
   ink rgb(255,203,179),0
   circle x, y-80, 10
   line x, y-70, x, y-30
   rem legs
   line x, y-30, x-20, y
   line x, y-30, x+20, y
   rem point of hand on bow
   x2 = sin(tilt#)*30
   y2 = cos(tilt#)*30
 
   handX = x+x2
   handY = (y-60)-y2
   line x, y-60, handX, handY
 
   rem the ends of the bow
   bx1 = x+x2 + sin(tilt#-90)*20
   by1 = (y-60)-y2 + cos(tilt#-90)*20
   bx2 = x+x2 + sin(tilt#+90)*20
   by2 = (y-60)-y2 + cos(tilt#+90)*20
 
   rem arm pulling on bow string
   p = power#*20+4
   ax = 15-p
   ay = 5*power#
   bx = 30-p
   by = 0
 
   px = x + bx*sin(tilt#)
   py = (y-60) + -1*bx*cos(tilt#)
 
   elbowX = x + ax*sin(tilt#) + ay*cos(tilt#)
   elbowY = (y-58) + -1*ax*cos(tilt#) + ay*sin(tilt#)
 
   line x, y-58, elbowX, elbowY
   line elbowX, elbowY, px, py
 
   rem bow
   ink rgb(84,45,1),0
   line bx1, by1, bx2, by2
   ink rgb(255,255,255),0
 
   rem bow string
   for i = 20 to 36
      eAngle = i*10
      lx = sin(eAngle)*p
      ly = cos(eAngle)*20
      lx1 = handX + lx*sin(tilt#) + ly*cos(tilt#)
      ly1 = handY + -1*lx*cos(tilt#) + ly*sin(tilt#)
      line bx1, by1, lx1, ly1
      bx1 = lx1
      by1 = ly1
   next i
 
endfunction
 
 
 
 
 
REM **************************************************
REM Draws a box with a vertical gradient
REM **************************************************
function gradientVerticalBox(left,top,right,bottom,color1,color2)
   height#=bottom-top
   for y=top to bottom-1
      t# = (y-top) / height#
      ink getTransitionalColor(color1,color2,t#),0
      box left,y,right,y+1
   next y
endfunction
 
 
REM **************************************************
REM Returns a linear interpolated color between base
REM color and target color. Percent ranges from 0 to 1
REM **************************************************
function getTransitionalColor(base, target, percent#)
   br = rgbr(base)
   bg = rgbg(base)
   bb = rgbb(base)
   tr = rgbr(target)
   tg = rgbg(target)
   tb = rgbb(target)
   tr = br + (tr-br)*percent#
   tg = bg + (tg-bg)*percent#
   tb = bb + (tb-bb)*percent#
   color = rgb(tr,tg,tb)
endfunction color