3 ;; Copyright (c) 2022 Omar Polo
5 ;; This program is free software; you can redistribute it and/or
6 ;; modify it under the terms of the MIT license. See LICENSE for
9 (local tick (require :tick))
11 (var game-state :menu) ;; :menu :game :pause :over
18 (var direction :right)
25 (local window-width (* ratio width))
26 (local window-height (* ratio height))
29 "Return the index of the element of seq that is on (x, y), or nil."
30 (accumulate [index nil
33 (if (and (= x (. r :x))
40 (let [x (math.random (- width 1))
41 y (math.random (- height 1))]
42 (when (and (not (hit? x y snake-body))
43 (not (hit? x y candies)))
45 (table.insert candies {: x : y})))))
54 (fn compute-step [{: x : y}]
56 :up (values x (wrap (- y 1) height))
57 :left (values (wrap (- x 1) width) y)
58 :right (values (wrap (+ x 1) width) y)
59 :down (values x (wrap (+ y 1) height))))
62 (let [(x y) (compute-step (. snake-body 1))]
63 (if (hit? x y snake-body)
66 (print "score:" score)
67 (set game-state :over))
69 (match (hit? x y candies)
70 nil (table.remove snake-body)
71 i (do (table.remove candies i)
73 (set score (+ 1 score))))
74 (table.insert snake-body 1 {: x : y})))))
76 (fn centered-text [x y rectw recth scale text]
77 (let [font (love.graphics.getFont)
78 tw (font:getWidth text)
80 (love.graphics.print text
81 (+ (* x ratio) (* (/ rectw 2) ratio))
82 (+ (* y ratio) (* (/ recth 2) ratio))
88 (love.graphics.setColor 0 1 0 1)
89 (centered-text 0 0 width height 2 "SN4K3")
90 (centered-text 0 6 width height 1 "press any key to play"))
93 (love.graphics.setColor 255 255 255)
94 (each [_ r (ipairs snake-body)]
96 (love.graphics.rectangle :fill (* ratio x) (* ratio y) 20 20)))
98 (love.graphics.setColor 255 0 0)
99 (each [_ r (ipairs candies)]
101 (love.graphics.rectangle :fill (* ratio x) (* ratio y) 20 20))))
105 (love.graphics.setColor 0 1 0 1)
106 (centered-text 0 0 width height 2 "PAUSED")
107 (centered-text 0 6 width height 1 "press any key to resume"))
111 (love.graphics.setColor 0 1 0 1)
112 (centered-text 0 0 width height 2 "GAME OVER!")
113 (centered-text 0 6 width height 1 (string.format "score: %03d" score)))
116 (set snake-body [{:x 14 :y 9}
120 (set direction :right)
125 (tick.remove tick-event))
126 (set tick-event (tick.recur move-snake .25)))
129 (love.window.updateMode window-width window-height {:fullscreen false}))
132 (love.graphics.setColor 0 0 0)
133 (love.graphics.rectangle :fill 0 0 window-width window-height)
135 (if (= game-state :menu)
141 (= game-state :pause)
148 (and (not= key "lctrl")
156 (not= key "scrollock")))
158 (fn love.keypressed [key]
159 (if (or (= game-state :menu)
160 (= game-state :over))
161 (if (= key :q) (love.event.quit 0)
162 (key-ok? key) (do (set game-state :game)
167 (where (or :up :down :left :right)) (set direction key)
168 (where (or :p :escape)) (set game-state :pause))
170 (= game-state :pause)
172 (set game-state :game))))
175 (when (= game-state :game)