Advertisement
CuppyBoi

Celeste Classic (pico8) Code

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