tic80-loop.scm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. (define (draw-level-sprites l)
  2. ;; (large-render)
  3. ;; Screen is 15x9 dimensions
  4. ;; Player is at 8 and 5
  5. ;; x-axis starts at 0
  6. ;; y-axis starts at 0
  7. ;;
  8. ;; (small-render)
  9. ;; Screen is 30x17 dimensions
  10. ;; Player is at 15 and 9
  11. ;; x-axis starts at 0
  12. ;; y-axis starts at 0
  13. ;;
  14. ;; cutoff is 10 tall or 14 wide
  15. (define large-level?
  16. (or (>= (level-rows l) 10)
  17. (>= (level-cols l) 14)))
  18. (define (get-sprite-value c i j)
  19. (define t (level-ref l j i))
  20. (cond
  21. ((eq? (tile-type t) 'floor) (if large-level? 35 0))
  22. ((eq? (tile-type t) 'goal-square) (if large-level? 36 2))
  23. ((eq? (tile-type t) 'box-on-goal-square) (if large-level? 37 4))
  24. ((eq? (tile-type t) 'box) (if large-level? 38 6))
  25. ((eq? (tile-type t) 'player-on-goal-square) (if large-level? 39 8))
  26. ((eq? (tile-type t) 'player) (if large-level? 40 10))
  27. ((eq? (tile-type t) 'wall) (if large-level? 41 12))
  28. (else (error "tile type invalid" t))))
  29. (define p (find-player l))
  30. (define x-start (- (tile-col p) (if large-level? 15 8)))
  31. (define y-start (- (tile-row p) (if large-level? 9 5)))
  32. (define x-end (+ x-start (if large-level? 30 15)))
  33. (define y-end (+ y-start (if large-level? 17 9)))
  34. (let loop ((i x-start)
  35. (j y-start)
  36. (screen-x 0)
  37. (screen-y 0))
  38. (cond
  39. ((and (< i x-end) (< j y-end))
  40. (t80::spr (get-sprite-value l i j) screen-x screen-y -1 1 0 0 2 2)
  41. (loop (+ i 1) j (+ screen-x (if large-level? 8 16)) screen-y))
  42. ((< j y-end)
  43. (loop x-start (+ j 1) 0 (+ screen-y (if large-level? 8 16)))))))
  44. (define (draw-menu-sprites)
  45. ;; 6 high, 30 wide
  46. (define x-start 0)
  47. (define y-start 0)
  48. (define x-end (+ x-start 29))
  49. (define y-end (+ y-start 5))
  50. (define (get-sprite-value i j)
  51. (cond
  52. ((and (= i 0) (= j 0)) 32)
  53. ((and (= i 0) (= j (- y-end 1))) 64)
  54. ((and (= i (- x-end 1)) (= j 0)) 34)
  55. ((and (= i (- x-end 1)) (= j (- y-end 1))) 66)
  56. ((= i 0) 48)
  57. ((= j 0) 33)
  58. ((= i (- x-end 1)) 50)
  59. ((= j (- y-end 1)) 65)
  60. (else 49)))
  61. (let loop ((i x-start)
  62. (j y-start)
  63. (screen-x 0)
  64. (screen-y 88))
  65. (cond
  66. ((and (< i x-end) (< j y-end))
  67. (t80::spr (get-sprite-value i j) screen-x screen-y -1 1 0 0 1 1)
  68. (loop (+ i 1) j (+ screen-x 8) screen-y))
  69. ((< j y-end)
  70. (loop x-start (+ j 1) 0 (+ screen-y 8))))))
  71. (define (refresh-output!)
  72. (t80::cls 1)
  73. ;; sprites & status text
  74. (cond
  75. ((current-level)
  76. (draw-level-sprites (current-level))
  77. (let ((level-status (string-split (render-level-status (current-level)) "\n")))
  78. (t80::print (list-ref level-status 0) 120 0 12 #t)
  79. (t80::print (list-ref level-status 1) 216 8 12 #t)))
  80. (else
  81. (t80::spr 192 30 0 -1 3 0 0 4 4)
  82. (t80::print "BOX ZOMBIE" 120 65 12)))
  83. ;; menu text
  84. (cond
  85. ((current-menu)
  86. (draw-menu-sprites)
  87. (t80::print (render-menu (current-menu)) 8 96))))
  88. (define a-held? #f)
  89. (define b-held? #f)
  90. (define x-held? #f)
  91. (define y-held? #f)
  92. (define time-up-held +inf.0)
  93. (define time-down-held +inf.0)
  94. (define time-left-held +inf.0)
  95. (define time-right-held +inf.0)
  96. (define (write-progress! global-state)
  97. (define progress-tracker (global-progress global-state))
  98. (define p1 (assoc 0 progress-tracker))
  99. (define p2 (assoc 1 progress-tracker))
  100. (define p3 (assoc 2 progress-tracker))
  101. (define v1 (if p1 (cdr p1) 0))
  102. (define v2 (if p2 (* 512 (cdr p2)) 0))
  103. (define v3 (if p3 (* 512 512 (cdr p3)) 0))
  104. (define total (+ v1 v2 v3))
  105. (t80::pmem 0 total))
  106. (define (read-progress! global-state)
  107. (define result (t80::pmem 0))
  108. (define v1 (modulo result 512))
  109. (define v2 (modulo (quotient result 512) 512))
  110. (define v3 (modulo (quotient (quotient result 512) 512) 512))
  111. (define progress-tracker
  112. (list (cons 0 v1)
  113. (cons 1 v2)
  114. (cons 2 v3)))
  115. (global-progress-set! global-state progress-tracker))
  116. (define (global-game-event-handler sym)
  117. (define (sokoban-exit)
  118. (t80::exit))
  119. (define (sokoban-victory-sound)
  120. (t80::music 1 -1 -1 #f))
  121. (define (sokoban-level-music)
  122. (t80::music 0 -1 -1 #t))
  123. (case sym
  124. ((kill) (sokoban-exit))
  125. ((victory-sound) (sokoban-victory-sound))
  126. ((level-music) (sokoban-level-music))
  127. (else (error "event not recognized" sym))))
  128. (define (TIC)
  129. (unless global-game-state
  130. (set! global-game-state (make-global-state #f #f #f global-game-event-handler))
  131. (read-progress! global-game-state)
  132. (open-main-menu! global-game-state))
  133. (refresh-output!)
  134. (write-progress! global-game-state)
  135. (cond
  136. ((t80::btn 0)
  137. (cond
  138. ((> time-up-held 30)
  139. (api-push-input! '((command . "UP")))
  140. (set! time-up-held 0))
  141. (else
  142. (set! time-up-held (+ 1 time-up-held)))))
  143. (else
  144. (set! time-up-held +inf.0)))
  145. (cond
  146. ((t80::btn 1)
  147. (cond
  148. ((> time-down-held 30)
  149. (api-push-input! '((command . "DOWN")))
  150. (set! time-down-held 0))
  151. (else
  152. (set! time-down-held (+ 1 time-down-held)))))
  153. (else
  154. (set! time-down-held +inf.0)))
  155. (cond
  156. ((t80::btn 2)
  157. (cond
  158. ((> time-left-held 30)
  159. (api-push-input! '((command . "LEFT")))
  160. (set! time-left-held 0))
  161. (else
  162. (set! time-left-held (+ 1 time-left-held)))))
  163. (else
  164. (set! time-left-held +inf.0)))
  165. (cond
  166. ((t80::btn 3)
  167. (cond
  168. ((> time-right-held 30)
  169. (api-push-input! '((command . "RIGHT")))
  170. (set! time-right-held 0))
  171. (else
  172. (set! time-right-held (+ 1 time-right-held)))))
  173. (else
  174. (set! time-right-held +inf.0)))
  175. (cond
  176. ((t80::btn 4)
  177. (if (not a-held?)
  178. (api-push-input! '((command . "A"))))
  179. (set! a-held? #t))
  180. (else
  181. (set! a-held? #f)))
  182. (cond
  183. ((t80::btn 5)
  184. (if (not b-held?)
  185. (api-push-input! '((command . "B"))))
  186. (set! b-held? #t))
  187. (else
  188. (set! b-held? #f)))
  189. (cond
  190. ((t80::btn 6)
  191. (if (not x-held?)
  192. (api-push-input! '((command . "X"))))
  193. (set! x-held? #t))
  194. (else
  195. (set! x-held? #f)))
  196. (cond
  197. ((t80::btn 7)
  198. (if (not y-held?)
  199. (api-push-input! '((command . "Y"))))
  200. (set! y-held? #t))
  201. (else
  202. (set! y-held? #f))))