summaryrefslogtreecommitdiff
path: root/chickadee.scm
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2017-01-04 22:16:26 -0500
committerDavid Thompson <dthompson2@worcester.edu>2017-01-04 22:16:26 -0500
commit98dc87a054c1108bd5f4bb093024d962ce0c8ce2 (patch)
tree9fa25dca82134bcdbe8693bfd5b212ce3b3880f8 /chickadee.scm
First commit!
Diffstat (limited to 'chickadee.scm')
-rw-r--r--chickadee.scm185
1 files changed, 185 insertions, 0 deletions
diff --git a/chickadee.scm b/chickadee.scm
new file mode 100644
index 0000000..e3d128a
--- /dev/null
+++ b/chickadee.scm
@@ -0,0 +1,185 @@
+;;; Chickadee Game Toolkit
+;;; Copyright © 2016 David Thompson <davet@gnu.org>
+;;;
+;;; Chickadee is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published
+;;; by the Free Software Foundation, either version 3 of the License,
+;;; or (at your option) any later version.
+;;;
+;;; Chickadee is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (chickadee)
+ #:use-module (gl)
+ #:use-module (sdl2)
+ #:use-module (sdl2 events)
+ #:use-module (sdl2 input text)
+ #:use-module (chickadee window)
+ #:use-module (chickadee render gl)
+ #:export (load-hook
+ update-hook
+ before-draw-hook
+ draw-hook
+ after-draw-hook
+ quit-hook
+ key-press-hook
+ key-release-hook
+ text-input-hook
+ mouse-press-hook
+ mouse-release-hook
+ mouse-move-hook
+ controller-add-hook
+ controller-remove-hook
+ controller-press-hook
+ controller-release-hook
+ controller-move-hook
+ run-game
+ abort-game
+ time))
+
+(define load-hook (make-hook 0))
+(define update-hook (make-hook 1))
+(define before-draw-hook (make-hook 0))
+(define after-draw-hook (make-hook 0))
+(define draw-hook (make-hook 1))
+(define quit-hook (make-hook 0))
+(define key-press-hook (make-hook 4))
+(define key-release-hook (make-hook 3))
+(define text-input-hook (make-hook 1))
+(define mouse-press-hook (make-hook 4))
+(define mouse-release-hook (make-hook 3))
+(define mouse-move-hook (make-hook 5))
+(define controller-add-hook (make-hook 1))
+(define controller-remove-hook (make-hook 1))
+(define controller-press-hook (make-hook 2))
+(define controller-release-hook (make-hook 2))
+(define controller-move-hook (make-hook 3))
+
+(define open-controller (@@ (chickadee input controller) open-controller))
+(define close-controller (@@ (chickadee input controller) close-controller))
+(define lookup-controller (@@ (chickadee input controller) lookup-controller))
+
+(define game-loop-prompt-tag (make-prompt-tag 'game-loop))
+
+(define* (run-game #:key
+ (window-title "Chickadee!")
+ (window-width 640)
+ (window-height 480)
+ window-fullscreen?
+ (update-hz 60))
+ (sdl-init)
+ (start-text-input)
+ (let ((window (open-window #:title window-title
+ #:width window-width
+ #:height window-height
+ #:fullscreen? window-fullscreen?)))
+ (define (process-event event)
+ (cond
+ ((quit-event? event)
+ (run-hook quit-hook))
+ ((keyboard-down-event? event)
+ (run-hook key-press-hook
+ (keyboard-event-key event)
+ (keyboard-event-scancode event)
+ (keyboard-event-modifiers event)
+ (keyboard-event-repeat event)))
+ ((keyboard-up-event? event)
+ (run-hook key-release-hook
+ (keyboard-event-key event)
+ (keyboard-event-scancode event)
+ (keyboard-event-modifiers event)))
+ ((text-input-event? event)
+ (run-hook text-input-hook (text-input-event-text event)))
+ ((mouse-button-down-event? event)
+ (run-hook mouse-press-hook
+ (mouse-button-event-button event)
+ (mouse-button-event-clicks event)
+ (mouse-button-event-x event)
+ (mouse-button-event-y event)))
+ ((mouse-button-up-event? event)
+ (run-hook mouse-release-hook
+ (mouse-button-event-button event)
+ (mouse-button-event-x event)
+ (mouse-button-event-y event)))
+ ((mouse-motion-event? event)
+ (run-hook mouse-move-hook
+ (mouse-motion-event-x event)
+ (mouse-motion-event-y event)
+ (mouse-motion-event-x-rel event)
+ (mouse-motion-event-y-rel event)
+ (mouse-motion-event-buttons event)))
+ ((and (controller-device-event? event)
+ (eq? (controller-device-event-action event) 'added))
+ (run-hook controller-add-hook
+ (open-controller (controller-device-event-which event))))
+ ((and (controller-device-event? event)
+ (eq? (controller-device-event-action event) 'removed))
+ (let ((controller (lookup-controller
+ (controller-device-event-which event))))
+ (run-hook controller-remove-hook controller)
+ (close-controller controller)))
+ ((controller-button-down-event? event)
+ (run-hook controller-press-hook
+ (lookup-controller
+ (controller-button-event-which event))
+ (controller-button-event-button event)))
+ ((controller-button-up-event? event)
+ (run-hook controller-release-hook
+ (lookup-controller
+ (controller-button-event-which event))
+ (controller-button-event-button event)))
+ ((controller-axis-event? event)
+ (run-hook controller-move-hook
+ (lookup-controller
+ (controller-axis-event-which event))
+ (controller-axis-event-axis event)
+ (/ (controller-axis-event-value event) 32768.0)))))
+ (with-window window
+ (let ((update-interval (round (/ 1000 update-hz))))
+ (call-with-prompt game-loop-prompt-tag
+ (lambda ()
+ ;; Catch SIGINT and kill the loop.
+ (sigaction SIGINT
+ (lambda (signum)
+ (abort-game)))
+ (run-hook load-hook)
+ (let loop ((previous-time (sdl-ticks))
+ (lag 0))
+ (let* ((current-time (sdl-ticks))
+ (delta (- current-time previous-time)))
+ (let update-loop ((lag (+ lag delta)))
+ (if (>= lag update-interval)
+ (begin
+ ;; Process all pending events.
+ (let loop ((event (poll-event)))
+ (when event
+ (process-event event)
+ (loop (poll-event))))
+ ;; Advance the simulation.
+ (run-hook update-hook update-interval)
+ (update-loop (- lag update-interval)))
+ (begin
+ ;; Render a frame.
+ (run-hook before-draw-hook)
+ (gl-clear-color 0.267 0.141 0.204 1.0)
+ (gl-clear (logior (attrib-mask color-buffer)
+ (attrib-mask depth-buffer)
+ (attrib-mask stencil-buffer)))
+ (run-hook draw-hook (/ lag update-interval))
+ (swap-buffers window)
+ (run-hook after-draw-hook)
+ (loop current-time lag)))))))
+ (lambda (cont callback)
+ #f))))))
+
+(define (abort-game)
+ (abort-to-prompt game-loop-prompt-tag #f))
+
+(define (time)
+ (sdl-ticks))