aboutsummaryrefslogtreecommitdiffhomepage
path: root/README.org
diff options
context:
space:
mode:
Diffstat (limited to 'README.org')
-rw-r--r--README.org256
1 files changed, 0 insertions, 256 deletions
diff --git a/README.org b/README.org
index f266ef9..80cac73 100644
--- a/README.org
+++ b/README.org
@@ -43,259 +43,3 @@ Then load one of the example files and call its "start" function:
#+end_src
-** Basic Use
-
- **The best introduction to wheelwork comes through looking at and playing with the examples.** You may find the examples under =examples/= in the source tree of this repository. The following document supplements the examples with a high level overview of wheelwork, its parts, and how those parts are meant to fit together.
-
-*** The Application
-
-When you want to use Wheelwork, you must make a sublcass of ~APPLICATION~. The ~APPLICATION~ is the main container supplied by wheelwork: it is the root of the [[*The Display Tree Protocol: Units and Containers][display tree]], holds references to [[*The Asset Protocol][loaded assets]], and handles [[*Events & Event Handling][events]] from the user.
-
-For example, from the pong example in =examples/08-pong.lisp=, the application class looks like
-
-#+begin_src lisp
-(defclass/std solo-pong (ww:application)
- ((paddle ball game-over intro-text)))
-#+end_src
-
-/note: I'm using defclass-std:defclass/std to define the above, see [[https://quickdocs.org/defclass-std][here]] for more./
-
-This defines a subclass of application along with some state needed for the pong game.
-
-**** The Window & Scale & Coordinates
-
-Wheelwork uses SDL2 to create windows and generate events. The application includes a global scale factor that affects how the game interprets coordinates inside the window. A window, for example, can be 800x600 pixels on your computer monitor, but if the application's scale factor is 2.0, then it will only have a 400x300 logical space of coordinates. If you add a sprite that is 30x30 pixels big, it will appear twice as large, but it will occupy 30x30 "logical pixels".
-
-The =0,0= coordinate is the bottom left corner of the game window, and the top right corner is =w,h=, the width and height of the scaled screen, respectively.
-
-
-**** The Boot Method
-
-It isn't enough to define a subclass, you must also implement a ~ww:boot~ method for your application class. The boot method is called right after the OpenGL context becomes available. Inside boot, you are expected to do everything necessary to start your game: load assets, create some display units, add them to the scene, and add event handlers. Here is what the boot method looks like for the pong game.
-
-#+begin_src lisp
-
-(defmethod ww::boot ((app solo-pong))
- "Adds the intro text and sets up the start button handler."
- (sdl2:hide-cursor)
- (let ((intro-text
- (make-instance
- 'ww:text
- :content "Press any key to start"
- :font (ww::get-asset "Ticketing.ttf")
- :x 160
- :y 300
- :scale-x 3.0
- :scale-y 3.0)))
- (setf (intro-text app) intro-text)
- (ww:add-unit app intro-text)) ; add to scene
- (ww:add-handler app #'press-to-start))
-
-#+end_src
-
-You can see that it does very little. It first creates an instance of ~text~ with the appropriate scale and starting position. Then it just sets the app's ~intro-text~ slot to the newly created text before adding to the scene.
-
-It ends by adding a handler to the app called ~press-to-start~, where presumably, the rest of the game is set up.
-
-**** The Shutdown Method
-
-The shutdown method is optional and is called right before the application exits. If supplied, it is a good place to do things like: make save files, close network connections, clean up foreign memory resources that are not already managed by the [[*The Asset Protocol][asset protocol]].
-
-*** The Display Tree Protocol: Units and Containers
-
-Objects that render to the screen are organized into a display tree. There are two basic kinds of objects: **units** and **containers**. Roughly, units are the things you want to display and containers help to control when and where you to display them.
-
-Units are added to and removed from containers, and a unit will belong to at most one container at a time. In general, the last thing added to a container will be the last thing rendered - i.e. it will appear to be "on top". Containers are themselves units, so they too can be added to other containers. Nesting of containers allows you to render a one set of units before or after some other set of units.
-
-The application is itself a container, and is the only unit that does not need to be added to a scene. No unit will be displayed until it becomes part of the display tree rooted at the application.
-
-Containers have "bounds", which are screen coordinates for the left, right, top, and bottom of the region inside of which units will be displayed. If a unit moves out of bounds, it will not show up on the screen, and will not receive mouse events. (It may, however, still be focused - and hence receive key events.) The bounds of the application are the visible window itself. Other containers may have custom bounds.
-
-See =examples/07-scrollarea.lisp= for an example that uses a container.
-
-**** Containers
-
-The main thing you can do with containers is add and remove units:
-
-: (add-unit app my-unit)
-: (drop-unit my-unit) ;; it knows its container
-
-You can also adjust their bounds, for example:
-
-: (setf (container-top my-container) 100)
-
-**** The Affine Units
-
-Most units of any interest implement the "affine protocol". I.e they have orientation and scale in the 2d plane of the game window.
-
-More specifically, you can use the following accessor functions on them:
-
- : x
- : y
- : width
- : height
- : scale-x
- : scale-y
- : rotation
-
-There are a few convenience functions also defined that use the above functions under-the-hood. I'm not including them here because the API is still stabilizing.
-
-The affine units are things like:
-
-+ ~image~: display an image that has been loaded from a file asset (currently only png is supported)
-+ ~text~: display text
-+ ~frameset~: display an animated sequence of images
-+ ~sprite~: display a "bundle" of framesets
-+ ~canvas~: display a region of mutable pixels
-
-*** Events & Event Handling
-
-Anything that "happens" in a wheelwork application happens through the course of handling some event.
-
-Wheelwork defines an ~event-handler~ class that is used to to create functions for handling events. Instances of ~event-handler~ are funcallable objects with a slot that specifies the kind of event being handled.
-
-Event handlers are added to instances of ~interactive~, which includes most kinds of units and the application itself. Notably, the base ~container~ class is not a subclass of ~interactive~ and so cannot handle events.
-
-Wheelwork provides a macro called ~defhandler~ that can be used easily create instances of ~event-handler~ and bind them to a name. Most event handlers are created using a macro that looks like ~on-EVENTNAME~, which are discussed below.
-
-Here is a simple example where a handler is defined, from the pong game:
-
-#+begin_src lisp
-(ww:defhandler pong-mousemove
- (ww:on-mousemotion (app)
- (with-slots (paddle) app
- (setf (ww:x paddle) (- x (* 0.5 (ww:width paddle)))
- (dx paddle) xrel))))
-#+end_src
-
-See the example for details.
-
-There are two kinds of events: User Interaction Events and Psuedoevents.
-
-**** User Interaction Events
-
-User Interaction events are, curiously enough, generated by user interaction. These include
-
-: keydown
-: keyup
-: mousewheel
-: mousedown
-: mouseup
-: mousemotion
-
-The first three will fire on whichever object has focus. The last three will fire on the first visible object that intersects with the cursor.
-
-**** Psuedoevents
-
-Psuedoevents are generated by the wheelwork itself, and include the following:
-
-Display tree events:
-
-: after-added
-: before-added
-: before-dropped
-
-Focus events
-
-: focus
-: blur
-
-Frame events
-
-: perframe
-
-See the documentation for the ~on-*~ forms for these events to get a sense of how to handle them.
-
-**** Defining event handlers
-
-Event handlers can be defined with ~ww:defhandler~ and ~ww:on-EVENTTYPE~ macros. For example in,
-
-#+begin_src lisp
-
-(ww::defhandler thing-clicked
- (ww::on-mousedown (target x y)
- (format t "~a was clicked at ~a,~a!~%" target x y)))
-#+end_src
-
-The ~on-mousedown~ form creates the event handler, and the ~defhandler~ form assigns it to a name in the function namespace. It has been written this way to allow you to redefine ~thing-clicked~ while your application is running in order to experiment with handlers - i.e. in order to support interactive development.
-
-Another reason that the ~defhandler~ form is separate from the ~on-EVENTNAME~ forms is that each of the ~on-*~ forms accept different arguments, all optional, depending on the event they are handling.
-
-For example, ~on-mousedown~ is a macro. The above could have been written
-
-#+begin_src lisp
-(ww::defhandler thing-clicked
- ;; lambda list variable names are all optional.
- (ww::on-mousedown ()
- (format t "~a was clicked at ~a,~a!~%" target x y)))
-#+end_src
-
-Or it could have been written
-
-#+begin_src lisp
-(ww::defhandler thing-clicked
- ;; lambda list variable names are all optional.
- (ww::on-mousedown (my-unit my-x my-y)
- (format t "~a was clicked at ~a,~a!~%" my-unit my-x my-y)))
-#+end_src
-
-See the docstrings for each ~on-*~ form for specifics.
-
-The upshot is, if you are using SLIME, you will get hints about what arguments your handler code expects.
-
-**** Handling Events
-
-To get an object (either a unit or the application itself) to handle an event, you add a handler to that object. Handlers know what event they are meant to handle, so you just need to call:
-
-: (ww:add-handler my-unit my-handler)
-
-Where ~my-handler~ is either an ~event-handler~ instance.
-
-Likewise you can drop an event handler
-
-: (ww:remove-handler my-unit handler-or-event-type)
-
-If ~handler-or-event-type~ is an event handler instance, it is removed if present. If ~handler-or-event-type~ is symbol whose ~symbol-name~ is the name of an event (e.g. ~:mousedown~ or ~'perframe~), then all handlers of that type are removed from the unit.
-
-
-*** The Asset Protocol
-
-Assets are resources loaded from disk. The application's ~asset-classifiers~ list associates file extensions (like "ttf", and "png") with classes (like ~font~ and ~png~) that load and prepare assets for use in an application.
-
-Every asset has a "key", which is just a string path name that is relative to the application's ~asset-root~. These keys are used by ~get-asset~ to fetch assets, possibly loading them for the first time if they have not been previously fetched.
-
-Some classes (like ~text~ or ~image~) require an instance of an asset class to fill one of their instance slots (like ~font~ or ~texture~) in order to work properly.
-
-E.g. In ~examples/03-font-render.lisp~ you see
-
-#+begin_src lisp
-
-(make-instance
- 'ww::text
- :content (format nil "Hell!~%Oh World...")
- :font (ww::get-asset "Ticketing.ttf"
- :asset-args '(:oversample 2)))
-#+end_src
-
-which fetches the ~"Ticketing.ttf"~ font asset for use in rendering the text content.
-
-The asset root relative to which ~"Ticketing.ttf"~ is resolved can be set during instantiation of the application.
-
-e.g., for the same example:
-
-#+begin_src lisp
-(make-instance
- 'font-display
- :fps 60
- :refocus-on-mousedown-p nil
- :width 800
- :height 600
- :title "Wheelwork Example: Font display"
- :asset-root (merge-pathnames
- "examples/"
- (asdf:system-source-directory :wheelwork)))
-#+end_src
-
-
-
-