|
111 | 111 | (defmethod initialize-instance :after ((this game-state) &key) |
112 | 112 | (with-slots (player food-pos) this |
113 | 113 | (setf food-pos (new-food-pos)) |
| 114 | + ;; TODO(bsvercl): We should really have a CENTERED function or something. |
114 | 115 | (setf player (make-snake (gamekit:vec2 (/ +segments-across-width+ 2) |
115 | 116 | (/ +segments-across-height+ 2)))))) |
116 | 117 |
|
117 | 118 | (defmethod update ((this game-state)) |
118 | | - (with-slots (player food-pos score) this |
| 119 | + (with-slots (player food-pos score end-callback) this |
119 | 120 | (let* ((pos (snake-position player)) |
120 | 121 | (ate-food-p (bodge-math:vec= food-pos pos))) |
121 | 122 | (advance player ate-food-p) |
122 | 123 | (when ate-food-p |
123 | 124 | (setf food-pos (new-food-pos)) |
124 | 125 | (incf score 50)) |
125 | 126 | (when (hit-itself player) |
126 | | - (setf score -1))))) |
| 127 | + (setf score -1) |
| 128 | + (funcall end-callback))))) |
127 | 129 |
|
128 | 130 | (defmethod draw ((this game-state)) |
129 | 131 | ;; TODO(bsvercl): Drop into CL-BODGE to speed this up. |
|
147 | 149 | (gamekit:draw-text (format nil "Score: ~A" (score-of this)) |
148 | 150 | (gamekit:vec2 25 (- +screen-height+ 25)))) |
149 | 151 |
|
150 | | -(defmethod handle-key ((state game-state) key) |
151 | | - (with-slots (player) state |
| 152 | +(defmethod handle-key ((this game-state) key) |
| 153 | + (with-slots (player food-pos) this |
152 | 154 | (case key |
153 | 155 | (:w (change-direction player :up)) |
154 | 156 | (:s (change-direction player :down)) |
155 | 157 | (:a (change-direction player :left)) |
156 | 158 | (:d (change-direction player :right)) |
157 | | - (:space (change-direction player :nothing))))) |
| 159 | + (:space (change-direction player :nothing)) |
| 160 | + (:q (setf food-pos (new-food-pos)))))) |
| 161 | + |
| 162 | +(defclass game-over-state (state) |
| 163 | + ((restart-callback :initarg :restart))) |
| 164 | + |
| 165 | +(defmethod draw ((this game-over-state)) |
| 166 | + (declare (ignore this)) |
| 167 | + (gamekit:draw-text "Good job, dummy! You ate yourself." |
| 168 | + (gamekit:vec2 (/ +screen-width+ 2) |
| 169 | + (/ +screen-height+ 2))) |
| 170 | + (gamekit:draw-text "Press SPACE to restart." |
| 171 | + (gamekit:subt (gamekit:vec2 (/ +screen-width+ 2) |
| 172 | + (/ +screen-height+ 2)) |
| 173 | + (gamekit:vec2 0 20)))) |
| 174 | + |
| 175 | +(defmethod handle-key ((this game-over-state) key) |
| 176 | + (with-slots (restart-callback) this |
| 177 | + (when (eq key :space) |
| 178 | + (funcall restart-callback)))) |
158 | 179 |
|
159 | 180 | (gamekit:defgame snake-game () |
160 | | - ((current-state :accessor state-of)) |
| 181 | + ((current-state)) |
161 | 182 | (:viewport-title "Snake") |
162 | 183 | (:viewport-width +screen-width+) |
163 | 184 | (:viewport-height +screen-height+) |
|
173 | 194 | (labels ((start () |
174 | 195 | (setf current-state (make-instance 'game-state :end #'end))) |
175 | 196 | (end () |
176 | | - ;; TODO(bsvercl): Game over state. |
177 | | - (print "uh oh, we haven't implemented this yet."))) |
| 197 | + (setf current-state (make-instance 'game-over-state :restart #'start)))) |
178 | 198 | (setf current-state (make-instance 'main-menu-state :start #'start))) |
179 | 199 | (macrolet ((%binder (key &body body) |
180 | 200 | `(gamekit:bind-button ,key :pressed #'(lambda () ,@body)))) |
|
0 commit comments