SHARE
TWEET

Celeste Classic (pico8) Code

CuppyBoi Jan 3rd, 2019 (edited) 153 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top