diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | chickadee/buffer.scm | 240 | ||||
-rw-r--r-- | doc/api.texi | 211 | ||||
-rw-r--r-- | examples/buffer.scm | 33 |
4 files changed, 15 insertions, 470 deletions
diff --git a/Makefile.am b/Makefile.am index 80acadb..fac8d7c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,7 +60,6 @@ SOURCES = \ chickadee/render/blend.scm \ chickadee/render/texture.scm \ chickadee/render/shader.scm \ - chickadee/render/buffer.scm \ chickadee/render/viewport.scm \ chickadee/render/framebuffer.scm \ chickadee/render/shapes.scm \ diff --git a/chickadee/buffer.scm b/chickadee/buffer.scm deleted file mode 100644 index a7a22fc..0000000 --- a/chickadee/buffer.scm +++ /dev/null @@ -1,240 +0,0 @@ -;;; Chickadee Game Toolkit -;;; Copyright © 2017 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 buffer) - #:use-module (chickadee) - #:use-module (chickadee scripting) - #:use-module (oop goops) - #:export (<buffer> - started? - start - stop - pause - resume - update - before-draw - draw - after-draw - abort - key-press - key-release - text-input - mouse-press - mouse-move - controller-add - controller-remove - controller-press - controller-release - controller-move - current-buffer - push-buffer! - pop-buffer! - replace-buffer! - use-buffers!)) - -(define-class <buffer> () - (started? #:init-value #f #:accessor buffer-started?) - (agenda #:init-thunk make-agenda #:getter buffer-agenda)) - -(define-method (start (buffer <buffer>)) - #t) - -(define-method (stop (buffer <buffer>)) - #t) - -(define-method (pause (buffer <buffer>)) - #t) - -(define-method (resume (buffer <buffer>)) - #t) - -(define-method (update (buffer <buffer>) dt) - #t) - -(define-method (abort (buffer <buffer>)) - (abort-game)) - -(define-method (before-draw (buffer <buffer>)) - #t) - -(define-method (draw (buffer <buffer>) alpha) - #t) - -(define-method (after-draw (buffer <buffer>)) - #t) - -(define-method (key-press (buffer <buffer>) key scancode modifiers repeat?) - #t) - -(define-method (key-release (buffer <buffer>) key scancode modifiers) - #t) - -(define-method (text-input (buffer <buffer>) text) - #t) - -(define-method (mouse-press (buffer <buffer>) button clicks x y) - #t) - -(define-method (mouse-release (buffer <buffer>) button x y) - #t) - -(define-method (mouse-move (buffer <buffer>) x y x-rel y-rel buttons) - #t) - -(define-method (controller-add (buffer <buffer>) controller) - #t) - -(define-method (controller-remove (buffer <buffer>) controller) - #t) - -(define-method (controller-press (buffer <buffer>) controller button) - #t) - -(define-method (controller-release (buffer <buffer>) controller button) - #t) - -(define-method (controller-move (buffer <buffer>) controller axis value) - #t) - - -;;; -;;; Buffer management -;;; - -(define *buffers* '()) - -(define (current-buffer) - "Return the current buffer." - (and (not (null? *buffers*)) - (car *buffers*))) - -(define-syntax-rule (with-buffer buffer body ...) - (with-agenda (buffer-agenda buffer) - body ...)) - -(define-syntax-rule (with-current-buffer name body ...) - (let ((name (current-buffer))) - (with-buffer name - body ...))) - -(define* (switch-buffers old new #:optional replace?) - (when (is-a? old <buffer>) - (with-buffer old - (if replace? - (stop old) - (pause old)))) - (with-buffer new - (if (buffer-started? new) - (resume new) - (begin - (start new) - (set! (buffer-started? new) #t))))) - -(define (push-buffer! buffer) - "Pause the current buffer and switch to BUFFER." - (let ((old (current-buffer))) - (set! *buffers* (cons buffer *buffers*)) - (switch-buffers old buffer))) - -(define (pop-buffer!) - "Stop the current buffer and switch back to the previously active -buffer, or terminate the game loop if the buffer stack is empty." - (let ((old (current-buffer))) - (set! *buffers* (cdr *buffers*)) - (if (null? *buffers*) - (begin - (stop old) - (abort-game)) - (switch-buffers old (current-buffer) #t)))) - -(define (replace-buffer! buffer) - "Stop the current buffer and switch to BUFFER." - (let ((old (current-buffer))) - (set! *buffers* (cons buffer (cdr *buffers*))) - (switch-buffers old buffer #t))) - -(define (use-buffers! initial-buffer) - "Install buffers into the game engine and set the current buffer to -INITIAL-BUFFER." - (add-hook! load-hook - (lambda () - (push-buffer! initial-buffer))) - (add-hook! update-hook - (lambda (dt) - (with-current-buffer buffer - (update-agenda 1) - (update buffer dt)))) - (add-hook! before-draw-hook - (lambda () - (with-current-buffer buffer - (before-draw buffer)))) - (add-hook! after-draw-hook - (lambda () - (with-current-buffer buffer - (after-draw buffer)))) - (add-hook! draw-hook - (lambda (alpha) - (with-current-buffer buffer - (draw buffer alpha)))) - (add-hook! quit-hook - (lambda () - (with-current-buffer buffer - (abort buffer)))) - (add-hook! key-press-hook - (lambda (key scancode modifiers repeat?) - (with-current-buffer buffer - (key-press buffer key scancode modifiers repeat?)))) - (add-hook! key-release-hook - (lambda (key scancode modifiers) - (with-current-buffer buffer - (key-release buffer key scancode modifiers)))) - (add-hook! text-input-hook - (lambda (text) - (with-current-buffer buffer - (text-input buffer text)))) - (add-hook! mouse-press-hook - (lambda (button clicks x y) - (with-current-buffer buffer - (mouse-press buffer button clicks x y)))) - (add-hook! mouse-release-hook - (lambda (button x y) - (with-current-buffer buffer - (mouse-release buffer button x y)))) - (add-hook! mouse-move-hook - (lambda (x y x-rel y-rel buttons) - (with-current-buffer buffer - (mouse-move buffer x y x-rel y-rel buttons)))) - (add-hook! controller-add-hook - (lambda (controller) - (with-current-buffer buffer - (controller-add buffer controller)))) - (add-hook! controller-remove-hook - (lambda (controller) - (with-current-buffer buffer - (controller-remove buffer controller)))) - (add-hook! controller-press-hook - (lambda (controller button) - (with-current-buffer buffer - (controller-press buffer controller button)))) - (add-hook! controller-release-hook - (lambda (controller button) - (with-current-buffer buffer - (controller-release buffer controller button)))) - (add-hook! controller-move-hook - (lambda (controller axis value) - (with-current-buffer buffer - (controller-move buffer controller axis value))))) diff --git a/doc/api.texi b/doc/api.texi index 694a236..5b02d60 100644 --- a/doc/api.texi +++ b/doc/api.texi @@ -4,7 +4,6 @@ * Math:: Linear algebra and more. * Graphics:: Eye candy. * Audio:: Sound effects and music. -* Buffers:: Splitting games into logical components. * Scripting:: Bringing the game world to life. @end menu @@ -595,62 +594,58 @@ While @code{gpu-apply} will draw every vertex in @var{vertex-array}, @end deffn @deffn {Procedure} current-viewport -Return the currently bound viewport. @xref{Viewports} for more -details about using viewports. +Return the currently bound viewport (@pxref{Viewports}). @end deffn @deffn {Procedure} current-framebuffer -Return the currently bound framebuffer. @xref{Framebuffers} for more -details about using framebuffers. +Return the currently bound framebuffer (@pxref{Framebuffers}). @end deffn @deffn {Procedure} current-blend-mode -Return the currently bound blend mode. @xref{Blending and Depth -Testing} for more details about using blend modes. +Return the currently bound blend mode (@pxref{Blending and Depth +Testing}). @end deffn @deffn {Procedure} current-depth-test -Return @code{#t} if depth testing is currently enabled. -@xref{Blending and Depth Testing} for more details about using the -depth test. +Return @code{#t} if depth testing is currently enabled (@pxref{Blending and Depth Testing}). @end deffn @deffn {Procedure} current-texture -Return the currently bound texture. @xref{Textures} for more details -about using textures. +Return the currently bound texture (@pxref{Textures}). @end deffn @deffn {Procedure} current-projection -Return the currently bound projection matrix. @xref{Matrices} for -more details about matrices. +Return the currently bound projection matrix (@pxref{Matrices}). @end deffn @deffn {Syntax} with-viewport @var{viewport} @var{body} ... -Evaluate @var{body} with the current viewport bound to @var{viewport}. +Evaluate @var{body} with the current viewport bound to @var{viewport} (@pxref{Viewports}). @end deffn @deffn {Syntax} with-framebuffer @var{framebuffer} @var{body} ... Evaluate @var{body} with the current framebuffer bound to -@var{framebuffer}. +@var{framebuffer} (@pxref{Framebuffers}). @end deffn @deffn {Syntax} with-blend-mode @var{blend-mode} @var{body} ... Evaluate @var{body} with the current blend mode bound to -@var{blend-mode}. +@var{blend-mode} (@pxref{Blending and Depth Testing}). @end deffn @deffn {Syntax} with-depth-test @var{depth-test?} @var{body} ... Evaluate @var{body} with the depth-test disabled if @var{depth-test?} -is @code{#f}, or enabled otherwise. +is @code{#f}, or enabled otherwise (@pxref{Blending and Depth +Testing}). @end deffn @deffn {Syntax} with-texture @var{texture} @var{body} ... -Evaluate @var{body} with the current texture bound to @var{texture}. +Evaluate @var{body} with the current texture bound to @var{texture} +(@pxref{Textures}). @end deffn @deffn {Syntax} with-projection @var{projection} @var{body} ... Evaluate @var{body} with the current projection matrix bound to -@var{projection}. +@var{projection} (@pxref{Matrices}). @end deffn @node Textures @@ -1031,182 +1026,6 @@ Return @code{#t} if music is currently playing. Return @code{#t} if music is currently paused. @end deffn -@node Buffers -@section Buffers - -Games are big state machines and they can get complex quickly, thus we -need tools to manage that complexity. One useful technique is to -separate the many ``screens'' of a game (such as the main menu, player -select screen, high score table, game over screen, etc.) from each -other, so that it is possible to program the logic for one section of -the game independent of another. In Chickadee, these ``screens'' are -called ``buffers''. In other game engines this same construct may be -called a ``scene'' or ``room''. - -A buffer knows how to update its state, render, handle input events, -etc. Only one buffer is ever active at a time, and the current buffer -can be changed with procedures like @code{push-buffer}, -@code{replace-buffer}, and @code{pop-buffer}. - -Buffers are implemented using Guile's object oriented programming -system (@pxref{GOOPS,,, guile, GNU Guile Reference Manual}). Each -type of buffer is represented as a subclass of the @code{<buffer>} -class. Once a new buffer class has been created, there are many -methods that can be specialized for that class. - -To install buffer support and set the initial buffer, call the -@code{use-buffers!} procedure. - -Let's take a look at a simple example to see how it all comes -together: - -@example -(use-modules (chickadee) - (chickadee buffer) - (chickadee math vector) - (chickadee render sprite) - (chickadee render texture) - (oop goops)) - -;; Define a new buffer type. -(define-class <splash-screen> (<buffer>) - (chickadee #:accessor chickadee #:init-value #f)) - -;; Define the logic for when the buffer is first activated. -(define-method (start (splash <splash-screen>)) - (set! (chickadee splash) (load-image "images/chickadee.png"))) - -;; Define how the buffer should be rendered. -(define-method (draw (splash <splash-screen>) alpha) - (draw-sprite (chickadee splash) (vec2 256.0 176.0))) - -;; Hook into the game engine and make the splash screen the initial buffer. -(use-buffers! (make <splash-screen>)) - -;; Start the game! -(run-game) -@end example - -@deffn {Class} <buffer> -The parent class for all buffers. -@end deffn - -@deffn {Method} started? @var{buffer} -Return @code{#t} if @var{buffer} has been activated by the game engine. -@end deffn - -@deffn {Method} start @var{buffer} -Called when @var{buffer} becomes the current buffer for the first time. -@end deffn - -@deffn {Method} stop @var{buffer} -Called when @var{buffer} is no longer in use. -@end deffn - -@deffn {Method} pause @var{buffer} -Called when @var{buffer} is no longer the current buffer but still in -use. -@end deffn - -@deffn {Method} resume @var{buffer} -Called when @var{buffer} becomes the current buffer after having been -suspended. -@end deffn - -The following methods are simply wrappers around the hooks described -in @xref{Kernel}, so see that section for more detail about the -arguments to these methods. The engine calls these methods with the -current buffer as the first argument. - -@deffn {Method} update @var{buffer} @var{dt} -Advance the simulation running in @var{buffer} by @var{dt} units of -time. -@end deffn - -@deffn {Method} abort @var{buffer} -Called when the user tries to close the game window. -@end deffn - -@deffn {Method} before-draw @var{buffer} -Called before @var{buffer} is rendered. -@end deffn - -@deffn {Method} after-draw @var{buffer} -Called after @var{buffer} is rendered. -@end deffn - -@deffn {Method} draw @var{buffer} @var{alpha} -Render @var{buffer}. -@end deffn - -@deffn {Method} key-press @var{buffer} @var{key} @var{scancode} @var{modifiers} @var{repeat?} -Handle key press event. -@end deffn - -@deffn {Method} key-release @var{buffer} @var{key} @var{scancode} @var{modifiers} -Handle key release event. -@end deffn - -@deffn {Method} text-input @var{buffer} @var{text} -Handle text input event. -@end deffn - -@deffn {Method} mouse-press @var{buffer} @var{button} @var{clicks} @var{x} @var{y} -Handle mouse press event. -@end deffn - -@deffn {Method} mouse-release @var{buffer} @var{button} @var{x} @var{y} -Handle mouse release event. -@end deffn - -@deffn {Method} mouse-move @var{buffer} @var{x} @var{y} @var{x-rel} @var{y-rel} @var{buttons} -Handle mouse move event. -@end deffn - -@deffn {Method} controller-add @var{buffer} @var{controller} -Handle controller add event. -@end deffn - -@deffn {Method} controller-remove @var{buffer} @var{controller} -Handle controller remove event. -@end deffn - -@deffn {Method} controller-press @var{buffer} @var{controller} @var{button} -Handle controller press event. -@end deffn - -@deffn {Method} controller-release @var{buffer} @var{controller} @var{button} -Handle controller release event. -@end deffn - -@deffn {Method} controller-move @var{buffer} @var{controller} @var{axis} @var{value} -Handle controller move event. -@end deffn - -The following procedures are used to manage the buffer stack: - -@deffn {Procedure} use-buffers! @var{initial-buffer} -Install buffers into the game engine and set the current buffer to -@var{initial-buffer}. -@end deffn - -@deffn {Procedure} push-buffer! @var{buffer} -Pause the current buffer and switch to @var{buffer}. -@end deffn - -@deffn {Procedure} pop-buffer! -Stop the current buffer and switch back to the previously active -buffer, or terminate the game loop if the buffer stack is empty. -@end deffn - -@deffn {Procedure} replace-buffer! @var{buffer} -Stop the current buffer and switch to @var{buffer} -@end deffn - -@deffn {Procedure} current-buffer -Return the current buffer. -@end deffn - @node Scripting @section Scripting diff --git a/examples/buffer.scm b/examples/buffer.scm deleted file mode 100644 index 4712ea4..0000000 --- a/examples/buffer.scm +++ /dev/null @@ -1,33 +0,0 @@ -(use-modules (chickadee) - (chickadee buffer) - (chickadee math vector) - (chickadee render font) - (chickadee render sprite) - (chickadee render texture) - (chickadee scripting) - (oop goops)) - -(define-class <splash-screen> (<buffer>) - (chickadee #:accessor chickadee #:init-value #f)) - -(define-method (start (splash <splash-screen>)) - (set! (chickadee splash) (load-image "images/chickadee.png")) - (after 120 (replace-buffer! (make <main-menu>)))) - -(define-method (draw (splash <splash-screen>) alpha) - (draw-sprite (chickadee splash) (vec2 256.0 176.0))) - -(define-class <main-menu> (<buffer>) - (font #:accessor menu-font #:init-value #f)) - -(define-method (start (menu <main-menu>)) - (set! (menu-font menu) (load-font "fonts/good_neighbors_starling.xml"))) - -(define-method (draw (menu <main-menu>) alpha) - (draw-text (menu-font menu) "press any key to exit" (vec2 200.0 240.0))) - -(define-method (key-press (menu <main-menu>) key scancode modifiers repeat?) - (pop-buffer!)) - -(use-buffers! (make <splash-screen>)) -(run-game) |