Advertisement
Guest User

Untitled

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