Advertisement
Guest User

Celeste CLASSIC code

a guest
Dec 12th, 2018
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 46.03 KB | None | 0 0
  1. -- ~celeste~
  2. -- matt thorson + noel berry
  3.  
  4. -- globals --
  5. -------------
  6.  
  7. room = { x=0, y=0 }
  8. objects = {}
  9. types = {}
  10. freeze=0
  11. shake=0
  12. will_restart=false
  13. delay_restart=0
  14. got_fruit={}
  15. has_dashed=false
  16. sfx_timer=0
  17. has_key=false
  18. pause_player=false
  19. flash_bg=false
  20. music_timer=0
  21.  
  22. k_left=0
  23. k_right=1
  24. k_up=2
  25. k_down=3
  26. k_jump=4
  27. k_dash=5
  28.  
  29. px = 0
  30. py = 0
  31. rx = 0
  32. ry = 0
  33. player_=nil
  34. spawn_fruit = false
  35. beat_level=false
  36. loaded_first = false
  37. collected_fruit = false
  38. got_key = false
  39. die = false
  40. time_draw=true
  41. start_level=false
  42. set_timer2 = false
  43. show_level = true
  44. hair_draw = false
  45.  
  46. -- entry point --
  47. -----------------
  48.  
  49. function _init()
  50.         title_screen()
  51. end
  52.  
  53. function title_screen()
  54.         got_fruit = {}
  55.         for i=0,29 do
  56.                 add(got_fruit,false) end
  57.         frames=0
  58.         deaths=0
  59.         max_djump=1
  60.         start_game=false
  61.         start_game_flash=0
  62.         music(40,0,7)
  63.  
  64.         load_room(7,3)
  65. end
  66.  
  67. function begin_game()
  68.         frames=0
  69.         seconds=0
  70.         minutes=0
  71.         music_timer=0
  72.         start_game=false
  73.         music(0,0,7)
  74.         load_room(0,0)
  75.         loaded_first = true
  76. end
  77.  
  78. function level_index()
  79.         return room.x%8+room.y*8
  80. end
  81.  
  82. function is_title()
  83.         return level_index()==31
  84. end
  85.  
  86. -- effects --
  87. -------------
  88.  
  89. clouds = {}
  90. for i=0,16 do
  91.         add(clouds,{
  92.                 x=rnd(128),
  93.                 y=rnd(128),
  94.                 spd=1+rnd(4),
  95.                 w=32+rnd(32)
  96.         })
  97. end
  98.  
  99. particles = {}
  100. for i=0,24 do
  101.         add(particles,{
  102.                 x=rnd(128),
  103.                 y=rnd(128),
  104.                 s=0+flr(rnd(5)/4),
  105.                 spd=0.25+rnd(5),
  106.                 off=rnd(1),
  107.                 c=6+flr(0.5+rnd(1))
  108.         })
  109. end
  110.  
  111. dead_particles = {}
  112.  
  113. -- player entity --
  114. -------------------
  115.  
  116. player =
  117. {
  118.         init=function(this)
  119.                 this.p_jump=false
  120.                 this.p_dash=false
  121.                 this.grace=0
  122.                 this.jbuffer=0
  123.                 this.djump=max_djump
  124.                 this.dash_time=0
  125.                 this.dash_effect_time=0
  126.                 this.dash_target={x=0,y=0}
  127.                 this.dash_accel={x=0,y=0}
  128.                 this.hitbox = {x=1,y=3,w=6,h=5}
  129.                 this.spr_off=0
  130.                 this.was_on_ground=false
  131.                 create_hair(this)
  132.                 start_level=true
  133.         end,
  134.         update=function(this)
  135.  
  136.                 if (pause_player) return
  137.  
  138.                 local input = btn(k_right) and 1 or (btn(k_left) and -1 or 0)
  139.  
  140.                 -- spikes collide
  141.                 if spikes_at(this.x+this.hitbox.x,this.y+this.hitbox.y,this.hitbox.w,this.hitbox.h,this.spd.x,this.spd.y) then
  142.                   die = true
  143.                 end
  144.                  
  145.                 -- bottom death
  146.                 if this.y>128 then
  147.                         die = true end
  148.  
  149.                 local on_ground=this.is_solid(0,1)
  150.                 local on_ice=this.is_ice(0,1)
  151.  
  152.                 -- smoke particles
  153.                 if on_ground and not this.was_on_ground then
  154.                  init_object(smoke,this.x,this.y+4)
  155.                 end
  156.  
  157.                 local jump = btn(k_jump) and not this.p_jump
  158.                 this.p_jump = btn(k_jump)
  159.                 if (jump) then
  160.                         this.jbuffer=4
  161.                 elseif this.jbuffer>0 then
  162.                  this.jbuffer-=1
  163.                 end
  164.  
  165.                 local dash = btn(k_dash) and not this.p_dash
  166.                 this.p_dash = btn(k_dash)
  167.  
  168.                 if on_ground then
  169.                         this.grace=6
  170.                         if this.djump<max_djump then
  171.                          psfx(54)
  172.                          this.djump=max_djump
  173.                         end
  174.                 elseif this.grace > 0 then
  175.                  this.grace-=1
  176.                 end
  177.  
  178.                 this.dash_effect_time -=1
  179.   if this.dash_time > 0 then
  180.    init_object(smoke,this.x,this.y)
  181.         this.dash_time-=1
  182.         this.spd.x=appr(this.spd.x,this.dash_target.x,this.dash_accel.x)
  183.         this.spd.y=appr(this.spd.y,this.dash_target.y,this.dash_accel.y)  
  184.   else
  185.  
  186.                         -- move
  187.                         local maxrun=1
  188.                         local accel=0.6
  189.                         local deccel=0.15
  190.  
  191.                         if not on_ground then
  192.                                 accel=0.4
  193.                         elseif on_ice then
  194.                                 accel=0.05
  195.                                 if input==(this.flip.x and -1 or 1) then
  196.                                         accel=0.05
  197.                                 end
  198.                         end
  199.  
  200.                         if abs(this.spd.x) > maxrun then
  201.                         this.spd.x=appr(this.spd.x,sign(this.spd.x)*maxrun,deccel)
  202.                         else
  203.                                 this.spd.x=appr(this.spd.x,input*maxrun,accel)
  204.                         end
  205.  
  206.                         --facing
  207.                         if this.spd.x!=0 then
  208.                                 this.flip.x=(this.spd.x<0)
  209.                         end
  210.  
  211.                         -- gravity
  212.                         local maxfall=2
  213.                         local gravity=0.21
  214.  
  215.         if abs(this.spd.y) <= 0.15 then
  216.         gravity*=0.5
  217.                         end
  218.  
  219.                         -- wall slide
  220.                         if input!=0 and this.is_solid(input,0) and not this.is_ice(input,0) then
  221.                         maxfall=0.4
  222.                         if rnd(10)<2 then
  223.                                 init_object(smoke,this.x+input*6,this.y)
  224.                                 end
  225.                         end
  226.  
  227.                         if not on_ground then
  228.                                 this.spd.y=appr(this.spd.y,maxfall,gravity)
  229.                         end
  230.  
  231.                         -- jump
  232.                         if this.jbuffer>0 then
  233.                         if this.grace>0 then
  234.                         -- normal jump
  235.                         psfx(1)
  236.                         this.jbuffer=0
  237.                         this.grace=0
  238.                                         this.spd.y=-2
  239.                                         init_object(smoke,this.x,this.y+4)
  240.                                 else
  241.                                         -- wall jump
  242.                                         local wall_dir=(this.is_solid(-3,0) and -1 or this.is_solid(3,0) and 1 or 0)
  243.                                         if wall_dir!=0 then
  244.                                         psfx(2)
  245.                                         this.jbuffer=0
  246.                                         this.spd.y=-2
  247.                                         this.spd.x=-wall_dir*(maxrun+1)
  248.                                         if not this.is_ice(wall_dir*3,0) then
  249.                                                 init_object(smoke,this.x+wall_dir*6,this.y)
  250.                                                 end
  251.                                         end
  252.                                 end
  253.                         end
  254.  
  255.                         -- dash
  256.                         local d_full=5
  257.                         local d_half=d_full*0.70710678118
  258.  
  259.                         if this.djump>0 and dash then
  260.                         init_object(smoke,this.x,this.y)
  261.                         this.djump-=1
  262.                         this.dash_time=4
  263.                         has_dashed=true
  264.                         this.dash_effect_time=10
  265.                         local v_input=(btn(k_up) and -1 or (btn(k_down) and 1 or 0))
  266.                         if input!=0 then
  267.                         if v_input!=0 then
  268.                         this.spd.x=input*d_half
  269.                         this.spd.y=v_input*d_half
  270.                         else
  271.                         this.spd.x=input*d_full
  272.                         this.spd.y=0
  273.                         end
  274.                         elseif v_input!=0 then
  275.                                 this.spd.x=0
  276.                                 this.spd.y=v_input*d_full
  277.                         else
  278.                                 this.spd.x=(this.flip.x and -1 or 1)
  279.                         this.spd.y=0
  280.                         end
  281.                  
  282.                         psfx(3)
  283.                         freeze=2
  284.                         shake=6
  285.                         this.dash_target.x=2*sign(this.spd.x)
  286.                         this.dash_target.y=2*sign(this.spd.y)
  287.                         this.dash_accel.x=1.5
  288.                         this.dash_accel.y=1.5
  289.                  
  290.                         if this.spd.y<0 then
  291.                          this.dash_target.y*=.75
  292.                         end
  293.                  
  294.                         if this.spd.y!=0 then
  295.                          this.dash_accel.x*=0.70710678118
  296.                         end
  297.                         if this.spd.x!=0 then
  298.                          this.dash_accel.y*=0.70710678118
  299.                         end              
  300.                         elseif dash and this.djump<=0 then
  301.                          psfx(9)
  302.                          init_object(smoke,this.x,this.y)
  303.                         end
  304.  
  305.                 end
  306.  
  307.                 -- animation
  308.                 this.spr_off+=0.25
  309.                 if not on_ground then
  310.                         if this.is_solid(input,0) then
  311.                                 this.spr=5
  312.                         else
  313.                                 this.spr=3
  314.                         end
  315.                 elseif btn(k_down) then
  316.                         this.spr=6
  317.                 elseif btn(k_up) then
  318.                         this.spr=7
  319.                 elseif (this.spd.x==0) or (not btn(k_left) and not btn(k_right)) then
  320.                         this.spr=1
  321.                 else
  322.                         this.spr=1+this.spr_off%4
  323.                 end
  324.  
  325.                 -- next level
  326.                 if this.y<-4 and level_index()<30 then beat_level=true end
  327.  
  328.                 -- was on the ground
  329.                 this.was_on_ground=on_ground
  330.  
  331.  
  332.                 --update positions (my code)
  333.                 px = this.x
  334.                 py = this.y
  335.  
  336.                 rx = this.rem.x
  337.                 ry = this.rem.y
  338.  
  339.                 player_ = this
  340.         end, --<end update loop
  341.  
  342.         draw=function(this)
  343.  
  344.                 -- clamp in screen
  345.                 if this.x<-1 or this.x>121 then
  346.                         this.x=clamp(this.x,-1,121)
  347.                         this.spd.x=0
  348.                 end
  349.  
  350.                 set_hair_color(this.djump)
  351.                 if hair_draw then
  352.                         draw_hair(this,this.flip.x and -1 or 1)
  353.                 end
  354.                 spr(this.spr,this.x,this.y,1,1,this.flip.x,this.flip.y)
  355.                 unset_hair_color()
  356.         end
  357. }
  358.  
  359. psfx=function(num)
  360.  if sfx_timer<=0 then
  361.   sfx(num)
  362.  end
  363. end
  364.  
  365. create_hair=function(obj)
  366.         obj.hair={}
  367.         for i=0,4 do
  368.                 add(obj.hair,{x=obj.x,y=obj.y,size=max(1,min(2,3-i))})
  369.         end
  370. end
  371.  
  372. set_hair_color=function(djump)
  373.         pal(8,(djump==1 and 8 or djump==2 and (7+flr((frames/3)%2)*4) or 12))
  374. end
  375.  
  376. draw_hair=function(obj,facing)
  377.         local last={x=obj.x+4-facing*2,y=obj.y+(btn(k_down) and 4 or 3)}
  378.         foreach(obj.hair,function(h)
  379.                 h.x+=(last.x-h.x)/1.5
  380.                 h.y+=(last.y+0.5-h.y)/1.5
  381.                 circfill(h.x,h.y,h.size,8)
  382.                 last=h
  383.         end)
  384. end
  385.  
  386. unset_hair_color=function()
  387.         pal(8,8)
  388. end
  389.  
  390. player_spawn = {
  391.         tile=1,
  392.         init=function(this)
  393.          sfx(4)
  394.                 this.spr=3
  395.                 this.target= {x=this.x,y=this.y}
  396.                 this.y=128
  397.                 this.spd.y=-4
  398.                 this.state=0
  399.                 this.delay=0
  400.                 this.solids=false
  401.                 create_hair(this)
  402.         end,
  403.         update=function(this)
  404.                 -- jumping up
  405.                 if this.state==0 then
  406.                         if this.y < this.target.y+16 then
  407.                                 this.state=1
  408.                                 this.delay=3
  409.                         end
  410.                 -- falling
  411.                 elseif this.state==1 then
  412.                         this.spd.y+=0.5
  413.                         if this.spd.y>0 and this.delay>0 then
  414.                                 this.spd.y=0
  415.                                 this.delay-=1
  416.                         end
  417.                         if this.spd.y>0 and this.y > this.target.y then
  418.                                 this.y=this.target.y
  419.                                 this.spd = {x=0,y=0}
  420.                                 this.state=2
  421.                                 this.delay=5
  422.                                 shake=5
  423.                                 init_object(smoke,this.x,this.y+4)
  424.                                 sfx(5)
  425.                         end
  426.                 -- landing
  427.                 elseif this.state==2 then
  428.                         this.delay-=1
  429.                         this.spr=6
  430.                         if this.delay<0 then
  431.                                 destroy_object(this)
  432.                                 init_object(player,this.x,this.y)
  433.                         end
  434.                 end
  435.         end,
  436.         draw=function(this)
  437.                 set_hair_color(max_djump)
  438.                 draw_hair(this,1)
  439.                 spr(this.spr,this.x,this.y,1,1,this.flip.x,this.flip.y)
  440.                 unset_hair_color()
  441.         end
  442. }
  443. add(types,player_spawn)
  444.  
  445. spring = {
  446.         tile=18,
  447.         init=function(this)
  448.                 this.hide_in=0
  449.                 this.hide_for=0
  450.         end,
  451.         update=function(this)
  452.                 if this.hide_for>0 then
  453.                         this.hide_for-=1
  454.                         if this.hide_for<=0 then
  455.                                 this.spr=18
  456.                                 this.delay=0
  457.                         end
  458.                 elseif this.spr==18 then
  459.                         local hit = this.collide(player,0,0)
  460.                         if hit ~=nil and hit.spd.y>=0 then
  461.                                 this.spr=19
  462.                                 hit.y=this.y-4
  463.                                 hit.spd.x*=0.2
  464.                                 hit.spd.y=-3
  465.                                 hit.djump=max_djump
  466.                                 this.delay=10
  467.                                 init_object(smoke,this.x,this.y)
  468.  
  469.                                 -- breakable below us
  470.                                 local below=this.collide(fall_floor,0,1)
  471.                                 if below~=nil then
  472.                                         break_fall_floor(below)
  473.                                 end
  474.  
  475.                                 psfx(8)
  476.                         end
  477.                 elseif this.delay>0 then
  478.                         this.delay-=1
  479.                         if this.delay<=0 then
  480.                                 this.spr=18
  481.                         end
  482.                 end
  483.                 -- begin hiding
  484.                 if this.hide_in>0 then
  485.                         this.hide_in-=1
  486.                         if this.hide_in<=0 then
  487.                                 this.hide_for=60
  488.                                 this.spr=0
  489.                         end
  490.                 end
  491.         end
  492. }
  493. add(types,spring)
  494.  
  495. function break_spring(obj)
  496.         obj.hide_in=15
  497. end
  498.  
  499. balloon = {
  500.         tile=22,
  501.         init=function(this)
  502.                 this.offset=rnd(1)
  503.                 this.start=this.y
  504.                 this.timer=0
  505.                 this.hitbox={x=-1,y=-1,w=10,h=10}
  506.         end,
  507.         update=function(this)
  508.                 if this.spr==22 then
  509.                         this.offset+=0.01
  510.                         this.y=this.start+sin(this.offset)*2
  511.                         local hit = this.collide(player,0,0)
  512.                         if hit~=nil and hit.djump<max_djump then
  513.                                 psfx(6)
  514.                                 init_object(smoke,this.x,this.y)
  515.                                 hit.djump=max_djump
  516.                                 this.spr=0
  517.                                 this.timer=60
  518.                         end
  519.                 elseif this.timer>0 then
  520.                         this.timer-=1
  521.                 else
  522.                  psfx(7)
  523.                  init_object(smoke,this.x,this.y)
  524.                         this.spr=22
  525.                 end
  526.         end,
  527.         draw=function(this)
  528.                 if this.spr==22 then
  529.                         spr(13+(this.offset*8)%3,this.x,this.y+6)
  530.                         spr(this.spr,this.x,this.y)
  531.                 end
  532.         end
  533. }
  534. add(types,balloon)
  535.  
  536. fall_floor = {
  537.         tile=23,
  538.         init=function(this)
  539.                 this.state=0
  540.                 this.solid=true
  541.         end,
  542.         update=function(this)
  543.                 -- idling
  544.                 if this.state == 0 then
  545.                         if this.check(player,0,-1) or this.check(player,-1,0) or this.check(player,1,0) then
  546.                                 break_fall_floor(this)
  547.                         end
  548.                 -- shaking
  549.                 elseif this.state==1 then
  550.                         this.delay-=1
  551.                         if this.delay<=0 then
  552.                                 this.state=2
  553.                                 this.delay=60--how long it hides for
  554.                                 this.collideable=false
  555.                         end
  556.                 -- invisible, waiting to reset
  557.                 elseif this.state==2 then
  558.                         this.delay-=1
  559.                         if this.delay<=0 and not this.check(player,0,0) then
  560.                                 psfx(7)
  561.                                 this.state=0
  562.                                 this.collideable=true
  563.                                 init_object(smoke,this.x,this.y)
  564.                         end
  565.                 end
  566.         end,
  567.         draw=function(this)
  568.                 if this.state!=2 then
  569.                         if this.state!=1 then
  570.                                 spr(23,this.x,this.y)
  571.                         else
  572.                                 spr(23+(15-this.delay)/5,this.x,this.y)
  573.                         end
  574.                 end
  575.         end
  576. }
  577. add(types,fall_floor)
  578.  
  579. function break_fall_floor(obj)
  580.  if obj.state==0 then
  581.         psfx(15)
  582.                 obj.state=1
  583.                 obj.delay=15--how long until it falls
  584.                 init_object(smoke,obj.x,obj.y)
  585.                 local hit=obj.collide(spring,0,-1)
  586.                 if hit~=nil then
  587.                         break_spring(hit)
  588.                 end
  589.         end
  590. end
  591.  
  592. smoke={
  593.         init=function(this)
  594.                 this.spr=29
  595.                 this.spd.y=-0.1
  596.                 this.spd.x=0.3+rnd(0.2)
  597.                 this.x+=-1+rnd(2)
  598.                 this.y+=-1+rnd(2)
  599.                 this.flip.x=maybe()
  600.                 this.flip.y=maybe()
  601.                 this.solids=false
  602.         end,
  603.         update=function(this)
  604.                 this.spr+=0.2
  605.                 if this.spr>=32 then
  606.                         destroy_object(this)
  607.                 end
  608.         end
  609. }
  610.  
  611. fruit={
  612.         tile=26,
  613.         if_not_fruit=true,
  614.         init=function(this)
  615.                 this.start=this.y
  616.                 this.off=0
  617.         end,
  618.         update=function(this)
  619.          local hit=this.collide(player,0,0)
  620.                 if hit~=nil or spawn_fruit then
  621.                  player_.djump=max_djump
  622.                         sfx_timer=20
  623.                         sfx(13)
  624.                         got_fruit[1+level_index()] = true
  625.                         collected_fruit = true
  626.                         spawn_fruit = false
  627.                         init_object(lifeup,this.x,this.y)
  628.                         destroy_object(this)
  629.                 end
  630.                 this.off+=1
  631.                 this.y=this.start+sin(this.off/40)*2.5
  632.         end
  633. }
  634. add(types,fruit)
  635.  
  636. fly_fruit={
  637.         tile=28,
  638.         if_not_fruit=true,
  639.         init=function(this)
  640.                 this.start=this.y
  641.                 this.fly=false
  642.                 this.step=0.5
  643.                 this.solids=false
  644.                 this.sfx_delay=8
  645.         end,
  646.         update=function(this)
  647.                 --fly away
  648.                 if this.fly then
  649.                  if this.sfx_delay>0 then
  650.                   this.sfx_delay-=1
  651.                   if this.sfx_delay<=0 then
  652.                    sfx_timer=20
  653.                    sfx(14)
  654.                   end
  655.                  end
  656.                         this.spd.y=appr(this.spd.y,-3.5,0.25)
  657.                         if this.y<-16 then
  658.                                 destroy_object(this)
  659.                         end
  660.                 -- wait
  661.                 else
  662.                         if has_dashed then
  663.                                 this.fly=true
  664.                         end
  665.                         this.step+=0.05
  666.                         this.spd.y=sin(this.step)*0.5
  667.                 end
  668.                 -- collect
  669.                 local hit=this.collide(player,0,0)
  670.                 if hit~=nil or spawn_fruit then
  671.                  player_.djump=max_djump
  672.                         sfx_timer=20
  673.                         sfx(13)
  674.                         collected_fruit = true
  675.                         spawn_fruit = false
  676.                         got_fruit[1+level_index()] = true
  677.                         init_object(lifeup,this.x,this.y)
  678.                         destroy_object(this)
  679.                 end
  680.         end,
  681.         draw=function(this)
  682.                 local off=0
  683.                 if not this.fly then
  684.                         local dir=sin(this.step)
  685.                         if dir<0 then
  686.                                 off=1+max(0,sign(this.y-this.start))
  687.                         end
  688.                 else
  689.                         off=(off+0.25)%3
  690.                 end
  691.                 spr(45+off,this.x-6,this.y-2,1,1,true,false)
  692.                 spr(this.spr,this.x,this.y)
  693.                 spr(45+off,this.x+6,this.y-2)
  694.         end
  695. }
  696. add(types,fly_fruit)
  697.  
  698. lifeup = {
  699.         init=function(this)
  700.                 this.spd.y=-0.25
  701.                 this.duration=30
  702.                 this.x-=2
  703.                 this.y-=4
  704.                 this.flash=0
  705.                 this.solids=false
  706.         end,
  707.         update=function(this)
  708.                 this.duration-=1
  709.                 if this.duration<= 0 then
  710.                         destroy_object(this)
  711.                 end
  712.         end,
  713.         draw=function(this)
  714.                 this.flash+=0.5
  715.  
  716.                 print("1000",this.x-2,this.y,7+this.flash%2)
  717.         end
  718. }
  719.  
  720. fake_wall = {
  721.         tile=64,
  722.         if_not_fruit=true,
  723.         update=function(this)
  724.                 this.hitbox={x=-1,y=-1,w=18,h=18}
  725.                 local hit = this.collide(player,0,0)
  726.                 if hit~=nil and hit.dash_effect_time>0 or spawn_fruit then
  727.                         if hit ~= nil then
  728.                                 player_.spd.x=-sign(player_.spd.x)*1.5
  729.                                 player_.spd.y=-1.5
  730.                                 player_.dash_time=-1
  731.                         end
  732.                         sfx_timer=20
  733.                         sfx(16)
  734.                         destroy_object(this)
  735.                         init_object(smoke,this.x,this.y)
  736.                         init_object(smoke,this.x+8,this.y)
  737.                         init_object(smoke,this.x,this.y+8)
  738.                         init_object(smoke,this.x+8,this.y+8)
  739.                         init_object(fruit,this.x+4,this.y+4)
  740.                 end
  741.                 this.hitbox={x=0,y=0,w=16,h=16}
  742.         end,
  743.         draw=function(this)
  744.                 spr(64,this.x,this.y)
  745.                 spr(65,this.x+8,this.y)
  746.                 spr(80,this.x,this.y+8)
  747.                 spr(81,this.x+8,this.y+8)
  748.         end
  749. }
  750. add(types,fake_wall)
  751.  
  752. key={
  753.         tile=8,
  754.         if_not_fruit=true,
  755.         update=function(this)
  756.                 local was=flr(this.spr)
  757.                 this.spr=9+(sin(frames/30)+0.5)*1
  758.                 local is=flr(this.spr)
  759.                 if is==10 and is!=was then
  760.                         this.flip.x=not this.flip.x
  761.                 end
  762.                 if this.check(player,0,0) or has_key then
  763.                         sfx(23)
  764.                         sfx_timer=10
  765.                         destroy_object(this)
  766.                         has_key=true
  767.                         got_key = true
  768.                 end
  769.         end
  770. }
  771. add(types,key)
  772.  
  773. chest={
  774.         tile=20,
  775.         if_not_fruit=true,
  776.         init=function(this)
  777.                 this.x-=4
  778.                 this.start=this.x
  779.                 this.timer=20
  780.         end,
  781.         update=function(this)
  782.                 if has_key then
  783.                         this.timer-=1
  784.                         this.x=this.start-1+rnd(3)
  785.                         if this.timer<=0 then
  786.                          sfx_timer=20
  787.                          sfx(16)
  788.                                 init_object(fruit,this.x,this.y-4)
  789.                                 destroy_object(this)
  790.                         end
  791.                 end
  792.         end
  793. }
  794. add(types,chest)
  795.  
  796. platform={
  797.         init=function(this)
  798.                 this.x-=4
  799.                 this.solids=false
  800.                 this.hitbox.w=16
  801.                 this.last=this.x
  802.         end,
  803.         update=function(this)
  804.                 this.spd.x=this.dir*0.65
  805.                 if this.x<-16 then this.x=128
  806.                 elseif this.x>128 then this.x=-16 end
  807.                 if not this.check(player,0,0) then
  808.                         local hit=this.collide(player,0,-1)
  809.                         if hit~=nil then
  810.                                 hit.move_x(this.x-this.last,1)
  811.                         end
  812.                 end
  813.                 this.last=this.x
  814.         end,
  815.         draw=function(this)
  816.                 spr(11,this.x,this.y-1)
  817.                 spr(12,this.x+8,this.y-1)
  818.         end
  819. }
  820.  
  821. message={
  822.         tile=86,
  823.         last=0,
  824.         draw=function(this)
  825.                 this.text="-- celeste mountain --#this memorial to those# perished on the climb"
  826.                 if this.check(player,4,0) then
  827.                         if this.index<#this.text then
  828.                          this.index+=0.5
  829.                                 if this.index>=this.last+1 then
  830.                                  this.last+=1
  831.                                  sfx(35)
  832.                                 end
  833.                         end
  834.                         this.off={x=8,y=96}
  835.                         for i=1,this.index do
  836.                                 if sub(this.text,i,i)~="#" then
  837.                                         rectfill(this.off.x-2,this.off.y-2,this.off.x+7,this.off.y+6 ,7)
  838.                                         print(sub(this.text,i,i),this.off.x,this.off.y,0)
  839.                                         this.off.x+=5
  840.                                 else
  841.                                         this.off.x=8
  842.                                         this.off.y+=7
  843.                                 end
  844.                         end
  845.                 else
  846.                         this.index=0
  847.                         this.last=0
  848.                 end
  849.         end
  850. }
  851. add(types,message)
  852.  
  853. big_chest={
  854.         tile=96,
  855.         init=function(this)
  856.                 this.state=0
  857.                 this.hitbox.w=16
  858.         end,
  859.         draw=function(this)
  860.                 if this.state==0 then
  861.                         local hit=this.collide(player,0,8)
  862.                         if hit~=nil and hit.is_solid(0,1) then
  863.                                 music(-1,500,7)
  864.                                 sfx(37)
  865.                                 pause_player=true
  866.                                 hit.spd.x=0
  867.                                 hit.spd.y=0
  868.                                 this.state=1
  869.                                 init_object(smoke,this.x,this.y)
  870.                                 init_object(smoke,this.x+8,this.y)
  871.                                 this.timer=60
  872.                                 this.particles={}
  873.                         end
  874.                         spr(96,this.x,this.y)
  875.                         spr(97,this.x+8,this.y)
  876.                 elseif this.state==1 then
  877.                         this.timer-=1
  878.                  shake=5
  879.                  flash_bg=true
  880.                         if this.timer<=45 and count(this.particles)<50 then
  881.                                 add(this.particles,{
  882.                                         x=1+rnd(14),
  883.                                         y=0,
  884.                                         h=32+rnd(32),
  885.                                         spd=8+rnd(8)
  886.                                 })
  887.                         end
  888.                         if this.timer<0 then
  889.                                 this.state=2
  890.                                 this.particles={}
  891.                                 flash_bg=false
  892.                                 new_bg=true
  893.                                 init_object(orb,this.x+4,this.y+4)
  894.                                 pause_player=false
  895.                         end
  896.                         foreach(this.particles,function(p)
  897.                                 p.y+=p.spd
  898.                                 line(this.x+p.x,this.y+8-p.y,this.x+p.x,min(this.y+8-p.y+p.h,this.y+8),7)
  899.                         end)
  900.                 end
  901.                 spr(112,this.x,this.y+8)
  902.                 spr(113,this.x+8,this.y+8)
  903.         end
  904. }
  905. add(types,big_chest)
  906.  
  907. orb={
  908.         init=function(this)
  909.                 this.spd.y=-4
  910.                 this.solids=false
  911.                 this.particles={}
  912.         end,
  913.         draw=function(this)
  914.                 this.spd.y=appr(this.spd.y,0,0.5)
  915.                 local hit=this.collide(player,0,0)
  916.                 if this.spd.y==0 and hit~=nil then
  917.                  music_timer=45
  918.                         sfx(51)
  919.                         freeze=10
  920.                         shake=10
  921.                         destroy_object(this)
  922.                         max_djump=2
  923.                         hit.djump=2
  924.                 end
  925.  
  926.                 spr(102,this.x,this.y)
  927.                 local off=frames/30
  928.                 for i=0,7 do
  929.                         circfill(this.x+4+cos(off+i/8)*8,this.y+4+sin(off+i/8)*8,1,7)
  930.                 end
  931.         end
  932. }
  933.  
  934. flag = {
  935.         tile=118,
  936.         init=function(this)
  937.                 this.x+=5
  938.                 this.score=0
  939.                 this.show=false
  940.                 for i=1,count(got_fruit) do
  941.                         if got_fruit[i] then
  942.                                 this.score+=1
  943.                         end
  944.                 end
  945.         end,
  946.         draw=function(this)
  947.                 this.spr=118+(frames/5)%3
  948.                 spr(this.spr,this.x,this.y)
  949.                 if this.show then
  950.                         rectfill(32,2,96,31,0)
  951.                         spr(26,55,6)
  952.                         print("x"..this.score,64,9,7)
  953.                         draw_time(49,16)
  954.                         print("deaths:"..deaths,48,24,7)
  955.                 elseif this.check(player,0,0) then
  956.                         sfx(55)
  957.           sfx_timer=30
  958.                         this.show=true
  959.                 end
  960.         end
  961. }
  962. add(types,flag)
  963.  
  964. room_title = {
  965.         init=function(this)
  966.                 this.delay=5
  967.  end,
  968.         draw=function(this)
  969.                 this.delay-=1
  970.                 if this.delay<-30 then
  971.                         destroy_object(this)
  972.                         show_level = false
  973.                 elseif this.delay<0 then
  974.  
  975.                         if show_level then
  976.                                 rectfill(24,58,104,70,0)
  977.                                 --rect(26,64-10,102,64+10,7)
  978.                                 --print("---",31,64-2,13)
  979.                                 if room.x==3 and room.y==1 then
  980.                                         print("old site",48,62,7)
  981.                                 elseif level_index()==30 then
  982.                                         print("summit",52,62,7)
  983.                                 else
  984.                                         local level=(1+level_index())*100
  985.                                         print(level.." m",52+(level<1000 and 2 or 0),62,7)
  986.                                 end
  987.                                 --print("---",86,64-2,13)
  988.                         end
  989.  
  990.                         if time_draw then
  991.                                 draw_time(4,4)
  992.                         end
  993.                 end
  994.         end
  995. }
  996.  
  997. -- object functions --
  998. -----------------------
  999.  
  1000. function init_object(type,x,y)
  1001.         if type.if_not_fruit~=nil and got_fruit[1+level_index()] then
  1002.                 return
  1003.         end
  1004.         local obj = {}
  1005.         obj.type = type
  1006.         obj.collideable=true
  1007.         obj.solids=true
  1008.  
  1009.         obj.spr = type.tile
  1010.         obj.flip = {x=false,y=false}
  1011.  
  1012.         obj.x = x
  1013.         obj.y = y
  1014.         obj.hitbox = { x=0,y=0,w=8,h=8 }
  1015.  
  1016.         obj.spd = {x=0,y=0}
  1017.         obj.rem = {x=0,y=0}
  1018.  
  1019.         obj.is_solid=function(ox,oy)
  1020.                 if oy>0 and not obj.check(platform,ox,0) and obj.check(platform,ox,oy) then
  1021.                         return true
  1022.                 end
  1023.                 return solid_at(obj.x+obj.hitbox.x+ox,obj.y+obj.hitbox.y+oy,obj.hitbox.w,obj.hitbox.h)
  1024.                  or obj.check(fall_floor,ox,oy)
  1025.                  or obj.check(fake_wall,ox,oy)
  1026.         end
  1027.  
  1028.         obj.is_ice=function(ox,oy)
  1029.                 return ice_at(obj.x+obj.hitbox.x+ox,obj.y+obj.hitbox.y+oy,obj.hitbox.w,obj.hitbox.h)
  1030.         end
  1031.  
  1032.         obj.collide=function(type,ox,oy)
  1033.                 local other
  1034.                 for i=1,count(objects) do
  1035.                         other=objects[i]
  1036.                         if other ~=nil and other.type == type and other != obj and other.collideable and
  1037.                                 other.x+other.hitbox.x+other.hitbox.w > obj.x+obj.hitbox.x+ox and
  1038.                                 other.y+other.hitbox.y+other.hitbox.h > obj.y+obj.hitbox.y+oy and
  1039.                                 other.x+other.hitbox.x < obj.x+obj.hitbox.x+obj.hitbox.w+ox and
  1040.                                 other.y+other.hitbox.y < obj.y+obj.hitbox.y+obj.hitbox.h+oy then
  1041.                                 return other
  1042.                         end
  1043.                 end
  1044.                 return nil
  1045.         end
  1046.  
  1047.         obj.check=function(type,ox,oy)
  1048.                 return obj.collide(type,ox,oy) ~=nil
  1049.         end
  1050.  
  1051.         obj.move=function(ox,oy)
  1052.                 local amount
  1053.                 -- [x] get move amount
  1054.         obj.rem.x += ox
  1055.                 amount = flr(obj.rem.x + 0.5)
  1056.                 obj.rem.x -= amount
  1057.                 obj.move_x(amount,0)
  1058.  
  1059.                 -- [y] get move amount
  1060.                 obj.rem.y += oy
  1061.                 amount = flr(obj.rem.y + 0.5)
  1062.                 obj.rem.y -= amount
  1063.                 obj.move_y(amount)
  1064.         end
  1065.  
  1066.         obj.move_x=function(amount,start)
  1067.                 if obj.solids then
  1068.                         local step = sign(amount)
  1069.                         for i=start,abs(amount) do
  1070.                                 if not obj.is_solid(step,0) then
  1071.                                         obj.x += step
  1072.                                 else
  1073.                                         obj.spd.x = 0
  1074.                                         obj.rem.x = 0
  1075.                                         break
  1076.                                 end
  1077.                         end
  1078.                 else
  1079.                         obj.x += amount
  1080.                 end
  1081.         end
  1082.  
  1083.         obj.move_y=function(amount)
  1084.                 if obj.solids then
  1085.                         local step = sign(amount)
  1086.                         for i=0,abs(amount) do
  1087.                         if not obj.is_solid(0,step) then
  1088.                                         obj.y += step
  1089.                                 else
  1090.                                         obj.spd.y = 0
  1091.                                         obj.rem.y = 0
  1092.                                         break
  1093.                                 end
  1094.                         end
  1095.                 else
  1096.                         obj.y += amount
  1097.                 end
  1098.         end
  1099.  
  1100.         add(objects,obj)
  1101.         if obj.type.init~=nil then
  1102.                 obj.type.init(obj)
  1103.         end
  1104.         return obj
  1105. end
  1106.  
  1107. function destroy_object(obj)
  1108.         del(objects,obj)
  1109. end
  1110.  
  1111. function kill_player(obj)
  1112.         sfx_timer=12
  1113.         sfx(0)
  1114.         deaths+=1
  1115.         shake=10
  1116.         destroy_object(obj)
  1117.         dead_particles={}
  1118.         for dir=0,7 do
  1119.                 local angle=(dir/8)
  1120.                 add(dead_particles,{
  1121.                         x=obj.x+4,
  1122.                         y=obj.y+4,
  1123.                         t=10,
  1124.                         spd={
  1125.                                 x=sin(angle)*3,
  1126.                                 y=cos(angle)*3
  1127.                         }
  1128.                 })
  1129.                 restart_room()
  1130.         end
  1131. end
  1132.  
  1133. -- room functions --
  1134. --------------------
  1135.  
  1136. function restart_room()
  1137.         will_restart=true
  1138.         delay_restart=15
  1139. end
  1140.  
  1141. function next_room()
  1142.  if room.x==2 and room.y==1 then
  1143.   music(30,500,7)
  1144.  elseif room.x==3 and room.y==1 then
  1145.   music(20,500,7)
  1146.  elseif room.x==4 and room.y==2 then
  1147.   music(30,500,7)
  1148.  elseif room.x==5 and room.y==3 then
  1149.   music(30,500,7)
  1150.  end
  1151.  
  1152.         if room.x==7 then
  1153.                 load_room(0,room.y+1)
  1154.         else
  1155.                 load_room(room.x+1,room.y)
  1156.         end
  1157. end
  1158.  
  1159. function load_room(x,y)
  1160.         set_timer2 = true
  1161.  
  1162.         has_dashed=false
  1163.         has_key=false
  1164.  
  1165.         --remove existing objects
  1166.         foreach(objects,destroy_object)
  1167.  
  1168.         --current room
  1169.         room.x = x
  1170.         room.y = y
  1171.  
  1172.         -- entities
  1173.         for tx=0,15 do
  1174.                 for ty=0,15 do
  1175.                         local tile = mget(room.x*16+tx,room.y*16+ty);
  1176.                         if tile==11 then
  1177.                                 init_object(platform,tx*8,ty*8).dir=-1
  1178.                         elseif tile==12 then
  1179.                                 init_object(platform,tx*8,ty*8).dir=1
  1180.                         else
  1181.                                 foreach(types,
  1182.                                 function(type)
  1183.                                         if type.tile == tile then
  1184.                                                 init_object(type,tx*8,ty*8)
  1185.                                         end
  1186.                                 end)
  1187.                         end
  1188.                 end
  1189.         end
  1190.  
  1191.         if not is_title() then
  1192.                 init_object(room_title,0,0)
  1193.         end
  1194. end
  1195.  
  1196. -- update function --
  1197. -----------------------
  1198.  
  1199. function _update()
  1200.         frames=((frames+1)%30)
  1201.         if frames==0 and level_index()<30 then
  1202.                 seconds=((seconds+1)%60)
  1203.                 if seconds==0 then
  1204.                         minutes+=1
  1205.                 end
  1206.         end
  1207.  
  1208.         if music_timer>0 then
  1209.          music_timer-=1
  1210.          if music_timer<=0 then
  1211.           music(10,0,7)
  1212.          end
  1213.         end
  1214.  
  1215.         if sfx_timer>0 then
  1216.          sfx_timer-=1
  1217.         end
  1218.  
  1219.         -- cancel if freeze
  1220.         if freeze>0 then freeze-=1 return end
  1221.  
  1222.         -- screenshake
  1223.         if shake>0 then
  1224.                 shake-=1
  1225.                 camera()
  1226.                 if shake>0 then
  1227.                         camera(-2+rnd(5),-2+rnd(5))
  1228.                 end
  1229.         end
  1230.  
  1231.         -- restart (soon)
  1232.         if will_restart and delay_restart>0 then
  1233.                 delay_restart-=1
  1234.                 if delay_restart<=0 then
  1235.                         will_restart=false
  1236.                         load_room(room.x,room.y)
  1237.                 end
  1238.         end
  1239.  
  1240.         -- update each object
  1241.         foreach(objects,function(obj)
  1242.                 obj.move(obj.spd.x,obj.spd.y)
  1243.                 if obj.type.update~=nil then
  1244.                         obj.type.update(obj)
  1245.                 end
  1246.         end)
  1247.  
  1248.         -- start game
  1249.         if is_title() then
  1250.                 if not start_game and (btn(k_jump) or btn(k_dash)) then
  1251.                         music(-1)
  1252.                         start_game_flash=50
  1253.                         start_game=true
  1254.                         sfx(38)
  1255.                 end
  1256.                 if start_game then
  1257.                         start_game_flash-=1
  1258.                         if start_game_flash<=-30 then
  1259.                                 begin_game()
  1260.                         end
  1261.                 end
  1262.         end
  1263. end
  1264.  
  1265. -- drawing functions --
  1266. -----------------------
  1267. function _draw()
  1268.         if freeze>0 then return end
  1269.  
  1270.         -- reset all palette values
  1271.         pal()
  1272.  
  1273.         -- start game flash
  1274.         if start_game then
  1275.                 local c=10
  1276.                 if start_game_flash>10 then
  1277.                         if frames%10<5 then
  1278.                                 c=7
  1279.                         end
  1280.                 elseif start_game_flash>5 then
  1281.                         c=2
  1282.                 elseif start_game_flash>0 then
  1283.                         c=1
  1284.                 else
  1285.                         c=0
  1286.                 end
  1287.                 if c<10 then
  1288.                         pal(6,c)
  1289.                         pal(12,c)
  1290.                         pal(13,c)
  1291.                         pal(5,c)
  1292.                         pal(1,c)
  1293.                         pal(7,c)
  1294.                 end
  1295.         end
  1296.  
  1297.         -- clear screen
  1298.         local bg_col = 0
  1299.         if flash_bg then
  1300.                 bg_col = frames/5
  1301.         elseif new_bg~=nil then
  1302.                 bg_col=2
  1303.         end
  1304.         rectfill(0,0,128,128,bg_col)
  1305.  
  1306.         -- clouds
  1307.         if not is_title() then
  1308.                 foreach(clouds, function(c)
  1309.                         c.x += c.spd
  1310.                         rectfill(c.x,c.y,c.x+c.w,c.y+4+(1-c.w/64)*12,new_bg~=nil and 14 or 1)
  1311.                         if c.x > 128 then
  1312.                                 c.x = -c.w
  1313.                                 c.y=rnd(128-8)
  1314.                         end
  1315.                 end)
  1316.         end
  1317.  
  1318.         -- draw bg terrain
  1319.         map(room.x * 16,room.y * 16,0,0,16,16,4)
  1320.  
  1321.         -- platforms/big chest
  1322.         foreach(objects, function(o)
  1323.                 if o.type==platform or o.type==big_chest then
  1324.                         draw_object(o)
  1325.                 end
  1326.         end)
  1327.  
  1328.         -- draw terrain
  1329.         local off=is_title() and -4 or 0
  1330.         map(room.x*16,room.y * 16,off,0,16,16,2)
  1331.  
  1332.         -- draw objects
  1333.         foreach(objects, function(o)
  1334.                 if o.type~=platform and o.type~=big_chest then
  1335.                         draw_object(o)
  1336.                 end
  1337.         end)
  1338.  
  1339.         -- draw fg terrain
  1340.         map(room.x * 16,room.y * 16,0,0,16,16,8)
  1341.  
  1342.         -- particles
  1343.         foreach(particles, function(p)
  1344.                 p.x += p.spd
  1345.                 p.y += sin(p.off)
  1346.                 p.off+= min(0.05,p.spd/32)
  1347.                 rectfill(p.x,p.y,p.x+p.s,p.y+p.s,p.c)
  1348.                 if p.x>128+4 then
  1349.                         p.x=-4
  1350.                         p.y=rnd(128)
  1351.                 end
  1352.         end)
  1353.  
  1354.         -- dead particles
  1355.         foreach(dead_particles, function(p)
  1356.                 p.x += p.spd.x
  1357.                 p.y += p.spd.y
  1358.                 p.t -=1
  1359.                 if p.t <= 0 then del(dead_particles,p) end
  1360.                 rectfill(p.x-p.t/5,p.y-p.t/5,p.x+p.t/5,p.y+p.t/5,14+p.t%2)
  1361.         end)
  1362.  
  1363.         -- draw outside of the screen for screenshake
  1364.         rectfill(-5,-5,-1,133,0)
  1365.         rectfill(-5,-5,133,-1,0)
  1366.         rectfill(-5,128,133,133,0)
  1367.         rectfill(128,-5,133,133,0)
  1368.  
  1369.         -- credits
  1370.         if is_title() then
  1371.                 print("x+c",58,80,5)
  1372.                 print("matt thorson",42,96,5)
  1373.                 print("noel berry",46,102,5)
  1374.         end
  1375.  
  1376.         if level_index()==30 then
  1377.                 local p
  1378.                 for i=1,count(objects) do
  1379.                         if objects[i].type==player then
  1380.                                 p = objects[i]
  1381.                                 break
  1382.                         end
  1383.                 end
  1384.                 if p~=nil then
  1385.                         local diff=min(24,40-abs(p.x+4-64))
  1386.                         rectfill(0,0,diff,128,0)
  1387.                         rectfill(128-diff,0,128,128,0)
  1388.                 end
  1389.         end
  1390.  
  1391. end
  1392.  
  1393. function draw_object(obj)
  1394.  
  1395.         if obj.type.draw ~=nil then
  1396.                 obj.type.draw(obj)
  1397.         elseif obj.spr > 0 then
  1398.                 spr(obj.spr,obj.x,obj.y,1,1,obj.flip.x,obj.flip.y)
  1399.         end
  1400.  
  1401. end
  1402.  
  1403. function draw_time(x,y)
  1404.  
  1405.         local s=seconds
  1406.         local m=minutes%60
  1407.         local h=flr(minutes/60)
  1408.  
  1409.         rectfill(x,y,x+32,y+6,0)
  1410.         print((h<10 and "0"..h or h)..":"..(m<10 and "0"..m or m)..":"..(s<10 and "0"..s or s),x+1,y+1,7)
  1411.  
  1412. end
  1413.  
  1414. -- helper functions --
  1415. ----------------------
  1416.  
  1417. function clamp(val,a,b)
  1418.         return max(a, min(b, val))
  1419. end
  1420.  
  1421. function appr(val,target,amount)
  1422.  return val > target
  1423.         and max(val - amount, target)
  1424.         or min(val + amount, target)
  1425. end
  1426.  
  1427. function sign(v)
  1428.         return v>0 and 1 or
  1429.                                                                 v<0 and -1 or 0
  1430. end
  1431.  
  1432. function maybe()
  1433.         return rnd(1)<0.5
  1434. end
  1435.  
  1436. function solid_at(x,y,w,h)
  1437.  return tile_flag_at(x,y,w,h,0)
  1438. end
  1439.  
  1440. function ice_at(x,y,w,h)
  1441.  return tile_flag_at(x,y,w,h,4)
  1442. end
  1443.  
  1444. function tile_flag_at(x,y,w,h,flag)
  1445.  for i=max(0,flr(x/8)),min(15,(x+w-1)/8) do
  1446.         for j=max(0,flr(y/8)),min(15,(y+h-1)/8) do
  1447.                 if fget(tile_at(i,j),flag) then
  1448.                         return true
  1449.                 end
  1450.         end
  1451.  end
  1452.         return false
  1453. end
  1454.  
  1455. function tile_at(x,y)
  1456.  return mget(room.x * 16 + x, room.y * 16 + y)
  1457. end
  1458.  
  1459. function spikes_at(x,y,w,h,xspd,yspd)
  1460.  for i=max(0,flr(x/8)),min(15,(x+w-1)/8) do
  1461.         for j=max(0,flr(y/8)),min(15,(y+h-1)/8) do
  1462.          local tile=tile_at(i,j)
  1463.          if tile==17 and ((y+h-1)%8>=6 or y+h==j*8+8) and yspd>=0 then
  1464.           return true
  1465.          elseif tile==27 and y%8<=2 and yspd<=0 then
  1466.           return true
  1467.                 elseif tile==43 and x%8<=2 and xspd<=0 then
  1468.                  return true
  1469.                 elseif tile==59 and ((x+w-1)%8>=6 or x+w==i*8+8) and xspd>=0 then
  1470.                  return true
  1471.                 end
  1472.         end
  1473.  end
  1474.         return false
  1475. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement