diff --git a/console.lisp b/console.lisp index a4c87c7..b98c515 100644 --- a/console.lisp +++ b/console.lisp @@ -57,6 +57,14 @@ disabled." "Generate an all-purpose sequence number." (+ x (incf *sequence-number*))) +;;; Physics timestep callback + +;; These must be set before initialization. + +(defvar *dt* 10) + +(defvar *physics-function* nil) + ;;; Mixer channels (defvar *channels* 64 "Number of audio mixer channels to use.") @@ -129,7 +137,7 @@ and the like." ;; TODO why does this crash: ;; (show-widgets)) -;;; Key repeat +;;; Key repeat emulation (defvar *key-table* (make-hash-table :test 'equal)) @@ -534,12 +542,15 @@ window. Set this in the game startup file.") "Initialize the console, open a window, and play. We want to process all inputs, update the game state, then update the display." - (if *fullscreen* - (sdl:window *screen-width* *screen-height* - :title-caption *window-title* - :flags sdl:SDL-FULLSCREEN) - (sdl:window *screen-width* *screen-height* - :title-caption *window-title*)) + (let ((fps (make-instance 'sdl:fps-unlocked :dt *dt* :ps-fn *physics-function*))) + (if *fullscreen* + (sdl:window *screen-width* *screen-height* + :fps fps + :title-caption *window-title* + :flags sdl:SDL-FULLSCREEN) + (sdl:window *screen-width* *screen-height* + :fps fps + :title-caption *window-title*))) (reset-joystick) (sdl:clear-display sdl:*black*) (show-widgets) @@ -606,12 +617,12 @@ display." (setf (gethash event *key-table*) -1))) (break-events event))))) (:idle () - (when *timer-p* + (if *timer-p* (if (zerop *clock*) (progn (sdl:clear-display sdl:*black*) ;; send held events - (when *held-keys* + (when *held-keys* (send-held-events)) ;; send timer event (dispatch-event *timer-event*) @@ -622,7 +633,15 @@ display." (show-widgets) (sdl:update-display) (setf *clock* *timer-interval*)) - (decf *clock*))))))) + (decf *clock*)) + ;; clean this up. these two cases aren't that different. + (progn + (sdl:clear-display sdl:*black*) + (when *held-keys* + (send-held-events)) + (show-widgets) + (sdl:update-display))))))) + ;;; The .xe2rc user init file @@ -1273,6 +1292,52 @@ The default destination is the main window." (sdl:draw-rectangle-* x y width height :color (find-resource-object color) :surface destination)) +;;; Audio + +(defvar *frequency* 44100) + +(defvar *output-chunksize* 128) + +(defvar *output-channels* 2) + +(defvar *sample-format* SDL-CFFI::AUDIO-S16LSB) + +(defun cffi-sample-type (sdl-sample-type) + (ecase sdl-sample-type + (SDL-CFFI::AUDIO-U8 :uint8) ; Unsigned 8-bit samples + (SDL-CFFI::AUDIO-S8 :int8) ; Signed 8-bit samples + (SDL-CFFI::AUDIO-U16LSB :uint16) ; Unsigned 16-bit samples, in little-endian byte order + (SDL-CFFI::AUDIO-S16LSB :int16) ; Signed 16-bit samples, in little-endian byte order + ;; (SDL-CFFI::AUDIO-U16MSB nil) ; Unsigned 16-bit samples, in big-endian byte order + ;; (SDL-CFFI::AUDIO-S16MSB nil) ; Signed 16-bit samples, in big-endian byte order + (SDL-CFFI::AUDIO-U16 :uint16) ; same as SDL(SDL-CFFI::AUDIO-U16LSB (for backwards compatability probably) + (SDL-CFFI::AUDIO-S16 :int16) ; same as SDL(SDL-CFFI::AUDIO-S16LSB (for backwards compatability probably) + (SDL-CFFI::AUDIO-U16SYS :uint16) ; Unsigned 16-bit samples, in system byte order + (SDL-CFFI::AUDIO-S16SYS :int16) ; Signed 16-bit samples, in system byte order + )) + +(defun cffi-chunk-buffer (chunk) + (sdl:fp chunk)) + +(defun convert-cffi-sample (chunk) + (let* ((input-buffer (cffi-chunk-buffer chunk)) + (type (cffi-sample-type *sample-format*)) + (size (length (cffi:mem-ref input-buffer type)))) + (assert (eq *sample-format* SDL-CFFI::AUDIO-S16LSB)) ;; for now + (let ((output-buffer (make-array size))) + (prog1 output-buffer + (dotimes (n size) + (setf (aref output-buffer n) + (/ (float (cffi:mem-aref input-buffer type n)) + 32768.0))))))) + +;(defun convert-internal-audio (input-buffer output-stream) + +;; (REGISTER-MUSIC-MIXER +;; (lambda (user stream len) +;; 'FILL-THE-AUDIO-OUTPUT-BUFFER)) + + ;;; Engine status (defun quit (&optional shutdown) @@ -1286,11 +1351,9 @@ The default destination is the main window." (setf *next-module* module-name) (sdl:push-quit-event)) -(defparameter *audio-chunksize* 512) - (defvar *copyright-text* "XE2 Game Engine -Copyright (C) 2006, 2007, 2008, 2009 David O'Toole +Copyright (C) 2006, 2007, 2008, 2009, 2010 David O'Toole This program is free software: you can redistribute it and/or modify @@ -1334,7 +1397,7 @@ and its .startup resource is loaded." (loop while (and (not *quitting*) *next-module*) do (unwind-protect - ;; dynamically load libs (needed for GNU/Linux) + ;; dynamically load libs (needed for GNU/Lpinux) (progn (cffi:define-foreign-library sdl (:darwin (:or (:framework "SDL") (:default "libSDL"))) @@ -1385,7 +1448,10 @@ and its .startup resource is loaded." (initialize-colors) (when *use-sound* ;; try opening sound - (when (null (sdl-mixer:open-audio :chunksize *audio-chunksize*)) + (when (null (sdl-mixer:open-audio :frequency *frequency* + :chunksize *output-chunksize* + :format *sample-format* + :channels *output-channels*)) ;; if that didn't work, disable effects/music (message "Could not open audio driver. Disabling sound effects and music.") (setf *use-sound* nil)) diff --git a/drez/drez.lisp b/drez/drez.lisp index 8b13789..5c4f65a 100644 --- a/drez/drez.lisp +++ b/drez/drez.lisp @@ -1 +1,38 @@ +;;; drez.lisp --- 7DRL + +;; Copyright (C) 2010 David O'Toole + +;; Author: David O'Toole +;; Keywords: + +;; This program 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. + +;; This program 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 . + +;;; Commentary: + +;; + +;;; Code: + +(defpackage :drez + (:documentation "dRez is a hybrid dance engine game in Common Lisp.") + (:use :xe2 :common-lisp) + (:export drez)) + +(in-package :drez) + + + + +;;; drez.lisp ends here diff --git a/drez/drez.org b/drez/drez.org index 8815877..8bb1fe0 100644 --- a/drez/drez.org +++ b/drez/drez.org @@ -4,13 +4,26 @@ DEE-rezz -* Links +* Tasks + +** TODO review luke's mixer.lisp +** TODO create standard variables for sdl-mixer output format configuration +*** TODO frequency +** TODO convert SDL sample buffers into internal format +*** TODO (sdl:fp chunk) gets the buffer pointer from a chunk loaded with load-sample +*** TODO http://common-lisp.net/project/cffi/manual/cffi-manual.html#Accessing-Foreign-Memory +*** http://common-lisp.net/project/cffi/manual/cffi-manual.html#Built_002dIn-Types +*** TODO http://lispbuilder.sourceforge.net/lispbuilder-sdl-mixer.html#+default-format+ +** TODO convert internal format to SDL output stream, see also register-mixer or whatever http://lispbuilder.sourceforge.net/lispbuilder-sdl-mixer.html#register-music-mixer +** TODO resampler http://en.wikipedia.org/wiki/Interpolation -** TODO Read "Fix your timestep" article -** TODO Decouple physics from framerate: http://code.google.com/p/lispbuilder/wiki/UsingLispbuilderSDL#Frame_Rate_and_Timestep -** TODO Find/create bd, snare, hihat samples ** TODO Code event/sequencer basics +** DONE Decouple physics from framerate: http://code.google.com/p/lispbuilder/wiki/UsingLispbuilderSDL#Frame_Rate_and_Timestep +CLOSED: [2010-02-22 Mon 11:55] +** TODO Find/create bd, snare, hihat samples ** TODO Basic UI/button config +** TODO Design blocky font +** TODO Add scalable font support * Thoughts @@ -29,13 +42,17 @@ ** Piano roll edit ui ** simfiles ideas, i.e. beats plus freestyling game -* Tasks +* Music representation -** TODO Reexamine old music code.... ligeti, ecaspace -** TODO Decide on music event data format, simple hierarchical OSC-ish namespace? -** TODO Find some external programs to create and process basic samples. +** Mixing + + - (sdl:fp chunk) gets the buffer pointer from a chunk loaded with load-sample + - http://lispbuilder.sourceforge.net/lispbuilder-sdl-mixer.html#register-music-mixer + +** Timing + - ticks + - beats per minute -* Music representation ** Events *** One possibility: (start-time &rest p-fields) *** Another: (integer-tick type &rest p-fields) diff --git a/forest/base.lisp b/forest/base.lisp index da05e31..0c3e577 100644 --- a/forest/base.lisp +++ b/forest/base.lisp @@ -9,7 +9,7 @@ (add-hook 'xe2:*initialization-hook* #'(lambda () (xe2:enable-timer) - (xe2:set-frame-rate 15) + (xe2:set-frame-rate 10) (xe2:set-timer-interval 0) (xe2:enable-held-keys 1 3))) diff --git a/void/void.pak b/void/void.pak index a62291f..6ebdfed 100644 --- a/void/void.pak +++ b/void/void.pak @@ -436,7 +436,7 @@ (:name "black-thunder" :type :music :file "black0999.ogg" :properties (:volume 18)) - (:name "blast-lisp" :type :lisp :file "blast.lisp" :properties (:autoload t)) + (:name "void-lisp" :type :lisp :file "void.lisp" :properties (:autoload t)) (:name "effect-lisp" :type :lisp :file "effect.lisp" :properties (:autoload t)) (:name "terrain-lisp" :type :lisp :file "terrain.lisp" :properties (:autoload t)) (:name "sector-lisp" :type :lisp :file "sector.lisp" :properties (:autoload t)) diff --git a/xe2.lisp b/xe2.lisp index d1e91a2..f35c0eb 100644 --- a/xe2.lisp +++ b/xe2.lisp @@ -61,44 +61,45 @@ (:nicknames :xe2) (:use :common-lisp :clon) (:export *default-frame-width* *default-frame-height* =viewport= - =equipment= *default-world-axis-size* *default-world-z-size* - =browser= install-widgets *initialization-hook* initialize-engine - split-string-on-lines message *screen-width* transform-method-body - roll-under make-stat =formatter= initialize-colors - *standard-categories* *default-action-points* =world= roll - bind-key-to-method *colors* get-color =prompt= =menu-item= - =direction-chooser= define-method *default-font* *startup* - field-value set-field-value object-fields dispatch-event run - *user-init-file-name* distance icon-resource icon-image - *compass-directions* *compass-opposites* find-resource-property - compose-blank-fields font-width font-height *browser* browser - set-browser transform-field-reference *screen-height* =inventory= - formatted-line-width formatted-line-height formatted-string-height - formatted-string-width get-color create-image draw-image play - define-prototype has-field defcell *choose-direction-menu* - set-field-options field-option-value index-resource find-module-path - index-module load-image-resource load-lisp-resource *executable* - *resource-handlers* load-resource find-resource find-resource-object - *colors* *world* load-user-init-file *module-directories* - resource-to-plist make-event =widget= *active-widgets* - bind-key-to-prompt-insertion make-field-initializer clone - make-field-initializer-body make-key-modifier-symbol make-key-string - normalize-event make-keyword make-object queue-head queue-max - queue-count *sender* make-special-variable-name field-reference-p - null-parent *message-send-symbol-suffix* *x11-color-data* - object-name object-parent send send-super send-queue self - opposite-direction object-address-string object step-in-direction - direction-to =cell= plasma-rect subdivide-rect render-plasma - add-hook run-hook queue-tail make-queue queue unqueue queue-message - queued-messages-p unqueue-message send-queue field-value - random-direction load-font-resource draw-string-solid read-pak - *resource-table* initialize-resource-table percent-of-time - render-formatted-paragraph make-formatted-string draw-string-shaded - render-formatted-string render-formatted-line resource - font-text-extents write-sexp-to-file with-message-sender - *message-sender* =textbox= read-sexp-from-file write-pak *grammar* - one-of left-hand-side right-hand-side expansions generate - send-event-to-widgets play-music halt-music seek-music + *frequency* *output-chunksize* *output-channels* + *dt* *physics-function* =equipment= *default-world-axis-size* + *default-world-z-size* =browser= install-widgets + *initialization-hook* initialize-engine split-string-on-lines + message *screen-width* transform-method-body roll-under make-stat + =formatter= initialize-colors *standard-categories* + *default-action-points* =world= roll bind-key-to-method *colors* + get-color =prompt= =menu-item= =direction-chooser= define-method + *default-font* *startup* field-value set-field-value object-fields + dispatch-event run *user-init-file-name* distance icon-resource + icon-image *compass-directions* *compass-opposites* + find-resource-property compose-blank-fields font-width font-height + *browser* browser set-browser transform-field-reference + *screen-height* =inventory= formatted-line-width + formatted-line-height formatted-string-height formatted-string-width + get-color create-image draw-image play define-prototype has-field + defcell *choose-direction-menu* set-field-options field-option-value + index-resource find-module-path index-module load-image-resource + load-lisp-resource *executable* *resource-handlers* load-resource + find-resource find-resource-object *colors* *world* + load-user-init-file *module-directories* resource-to-plist + make-event =widget= *active-widgets* bind-key-to-prompt-insertion + make-field-initializer clone make-field-initializer-body + make-key-modifier-symbol make-key-string normalize-event + make-keyword make-object queue-head queue-max queue-count *sender* + make-special-variable-name field-reference-p null-parent + *message-send-symbol-suffix* *x11-color-data* object-name + object-parent send send-super send-queue self opposite-direction + object-address-string object step-in-direction direction-to =cell= + plasma-rect subdivide-rect render-plasma add-hook run-hook + queue-tail make-queue queue unqueue queue-message queued-messages-p + unqueue-message send-queue field-value random-direction + load-font-resource draw-string-solid read-pak *resource-table* + initialize-resource-table percent-of-time render-formatted-paragraph + make-formatted-string draw-string-shaded render-formatted-string + render-formatted-line resource font-text-extents write-sexp-to-file + with-message-sender *message-sender* =textbox= read-sexp-from-file + write-pak *grammar* one-of left-hand-side right-hand-side expansions + generate send-event-to-widgets play-music halt-music seek-music *joystick-mapping* *generic-joystick-mapping* *ps3-joystick-mapping* draw-resource-image *event-handler-function* *use-sound* trace-rectangle trace-row trace-column trace-octagon trace-line diff --git a/xiobreak/xiobreak.xcf b/xiobreak/xiobreak.xcf index 52eda75..4d53c00 100644 Binary files a/xiobreak/xiobreak.xcf and b/xiobreak/xiobreak.xcf differ diff --git a/xiotank/#xiotank.org# b/xiotank/#xiotank.org# new file mode 100644 index 0000000..709607c --- /dev/null +++ b/xiotank/#xiotank.org# @@ -0,0 +1,70 @@ +#+TITLE: 7-Day Roguelike 2010 CHALLENGE Ideas + +* TODO RELEASE 7DRL ENTRY +DEADLINE: <2010-03-14 Sun 23:59> + +* Tasks +** DONE Translate game design doc into asset/code todos +CLOSED: [2010-03-08 Mon 10:44] +** DONE square/triangle/sine icons in pink/blue/green (sprites?) +CLOSED: [2010-03-08 Mon 10:44] +** TODO [#C] generate waveforms programmatically for all notes +** TODO establish pulsators for beats +** TODO draw tank and walls and background and some basic enemies +** TODO set up tank and basic dungeon +** TODO light and sound reveal locations of objects even on dark portions of map +** TODO tank firing waves with sound +** TODO firing enemies +** TODO oscillators and tone clusters +** TODO [#C] disembarking pilot +** TODO themes a la xiobreak + +* Entry mail + +** About the entrant + +I am David O'Toole and I program games in Common Lisp. My blog is at +http://lispgamesdev.blogspot.com, where I will be making daily +progress reports. + +** Re-use declaration + +For my entry I will be re-using my own Common Lisp game engine called +XE2 (see http://dto.github.com/notebook/xe2-reference.html for +details.) Among its features are support for grid-based worlds of +interacting objects, sprites, basic lighting and field-of-view, sound, +and other useful code. + +Aside from the XE2 library itself, all game logic and assets (sound, +images) will be original and produced during the 7 days of the +challenge. + +** Start time + + 11:59 PM on Sunday March 7 2010, US Eastern Time. + +** Game concept + +In this roguelike you control a tank pilot who can enter and exit +different tank vehicles. The tank can fire sound waves in 8 +directions. There are square waves, sine waves, and triangle +waves. You select which wave to fire with the Z, X, C keys. The +numeric keypad and/or nethack keys are used for choosing a direction +to move in. Either CONTROL or ALT, combined with a directional key, to +fire the currently selected waveform in that direction. + +To eliminate enemy bullets, fire the corresponding wave types at +them. Other activities involve firing waves at oscillators to turn +them on and off. Combining tones can unlock puzzle elements and create +chords. Oscillators have a number frequency or note attached. C4 +etc. Tracker game. + +Some waves must be identified by sound alone. + +The pilot can disembark from the tank and even take over other tanks, +and there are certain areas where the tank cannot go. The pilot is +extremely vulnerable, and has only one hit point. + +Death is permanent, the game ends when you run out of hit points. + +The goal is to defeat all the enemies and unlock all the gates. diff --git a/xiotank/.#xiotank.org b/xiotank/.#xiotank.org new file mode 120000 index 0000000..3700dba --- /dev/null +++ b/xiotank/.#xiotank.org @@ -0,0 +1 @@ +dto@pod.16731:1267377872 \ No newline at end of file diff --git a/xiotank/A-2-saw.wav b/xiotank/A-2-saw.wav new file mode 100644 index 0000000..52f4e1f Binary files /dev/null and b/xiotank/A-2-saw.wav differ diff --git a/xiotank/A-2-sine.wav b/xiotank/A-2-sine.wav new file mode 100644 index 0000000..2c9c607 Binary files /dev/null and b/xiotank/A-2-sine.wav differ diff --git a/xiotank/A-2-square.wav b/xiotank/A-2-square.wav new file mode 100644 index 0000000..c9c1e86 Binary files /dev/null and b/xiotank/A-2-square.wav differ diff --git a/xiotank/A-4-saw.wav b/xiotank/A-4-saw.wav new file mode 100644 index 0000000..2c645d3 Binary files /dev/null and b/xiotank/A-4-saw.wav differ diff --git a/xiotank/A-4-sine.wav b/xiotank/A-4-sine.wav new file mode 100644 index 0000000..1e3af27 Binary files /dev/null and b/xiotank/A-4-sine.wav differ diff --git a/xiotank/A-4-square.wav b/xiotank/A-4-square.wav new file mode 100644 index 0000000..d10c8c8 Binary files /dev/null and b/xiotank/A-4-square.wav differ diff --git a/xiotank/README b/xiotank/README new file mode 100644 index 0000000..ede8d27 --- /dev/null +++ b/xiotank/README @@ -0,0 +1 @@ +((("Placeholder text."))) diff --git a/xiotank/README~ b/xiotank/README~ new file mode 100644 index 0000000..20277f3 --- /dev/null +++ b/xiotank/README~ @@ -0,0 +1 @@ +Placeholder text. diff --git a/xiotank/blue-space.png b/xiotank/blue-space.png new file mode 100644 index 0000000..5e8033d Binary files /dev/null and b/xiotank/blue-space.png differ diff --git a/xiotank/green-space.png b/xiotank/green-space.png new file mode 100644 index 0000000..7396c70 Binary files /dev/null and b/xiotank/green-space.png differ diff --git a/xiotank/launchpad.png b/xiotank/launchpad.png new file mode 100644 index 0000000..e3afd95 Binary files /dev/null and b/xiotank/launchpad.png differ diff --git a/xiotank/magenta-space.png b/xiotank/magenta-space.png new file mode 100644 index 0000000..2947ac6 Binary files /dev/null and b/xiotank/magenta-space.png differ diff --git a/xiotank/purity.ogg b/xiotank/purity.ogg new file mode 100644 index 0000000..a62c2a5 Binary files /dev/null and b/xiotank/purity.ogg differ diff --git a/xiotank/purity.xm b/xiotank/purity.xm new file mode 100644 index 0000000..c08e524 Binary files /dev/null and b/xiotank/purity.xm differ diff --git a/xiotank/purple-space.png b/xiotank/purple-space.png new file mode 100644 index 0000000..2ade99a Binary files /dev/null and b/xiotank/purple-space.png differ diff --git a/xiotank/saw-cyan.png b/xiotank/saw-cyan.png new file mode 100644 index 0000000..07e61aa Binary files /dev/null and b/xiotank/saw-cyan.png differ diff --git a/xiotank/saw-green.png b/xiotank/saw-green.png new file mode 100644 index 0000000..bc28cff Binary files /dev/null and b/xiotank/saw-green.png differ diff --git a/xiotank/saw-magenta.png b/xiotank/saw-magenta.png new file mode 100644 index 0000000..c96fc74 Binary files /dev/null and b/xiotank/saw-magenta.png differ diff --git a/xiotank/saw-yellow.png b/xiotank/saw-yellow.png new file mode 100644 index 0000000..7f32531 Binary files /dev/null and b/xiotank/saw-yellow.png differ diff --git a/xiotank/sine-cyan.png b/xiotank/sine-cyan.png new file mode 100644 index 0000000..61f7b42 Binary files /dev/null and b/xiotank/sine-cyan.png differ diff --git a/xiotank/sine-green.png b/xiotank/sine-green.png new file mode 100644 index 0000000..52e2e15 Binary files /dev/null and b/xiotank/sine-green.png differ diff --git a/xiotank/sine-magenta.png b/xiotank/sine-magenta.png new file mode 100644 index 0000000..4c90705 Binary files /dev/null and b/xiotank/sine-magenta.png differ diff --git a/xiotank/sine-yellow.png b/xiotank/sine-yellow.png new file mode 100644 index 0000000..f246a06 Binary files /dev/null and b/xiotank/sine-yellow.png differ diff --git a/xiotank/square-cyan.png b/xiotank/square-cyan.png new file mode 100644 index 0000000..ea823ff Binary files /dev/null and b/xiotank/square-cyan.png differ diff --git a/xiotank/square-green.png b/xiotank/square-green.png new file mode 100644 index 0000000..0abb82a Binary files /dev/null and b/xiotank/square-green.png differ diff --git a/xiotank/square-magenta.png b/xiotank/square-magenta.png new file mode 100644 index 0000000..f2fc3dd Binary files /dev/null and b/xiotank/square-magenta.png differ diff --git a/xiotank/square-yellow.png b/xiotank/square-yellow.png new file mode 100644 index 0000000..8b564c1 Binary files /dev/null and b/xiotank/square-yellow.png differ diff --git a/xiotank/tank-north.png b/xiotank/tank-north.png new file mode 100644 index 0000000..3249c57 Binary files /dev/null and b/xiotank/tank-north.png differ diff --git a/xiotank/tank-northeast.png b/xiotank/tank-northeast.png new file mode 100644 index 0000000..4792b26 Binary files /dev/null and b/xiotank/tank-northeast.png differ diff --git a/xiotank/white-noise.png b/xiotank/white-noise.png new file mode 100644 index 0000000..7d6784c Binary files /dev/null and b/xiotank/white-noise.png differ diff --git a/xiotank/xiotank-old.lisp b/xiotank/xiotank-old.lisp new file mode 100644 index 0000000..b0ba8d1 --- /dev/null +++ b/xiotank/xiotank-old.lisp @@ -0,0 +1,46 @@ + +(defconstant +ticks-per-minute+ 60000 "Each tick is one millisecond.") + +(defvar *beats-per-minute* 120) + +(defun ticks-per-beat (bpm) + (float (/ +ticks-per-minute+ bpm))) + +(defvar *position* 0.0 "Song position in ticks. Fractional ticks are allowed.") + +(defun position-seconds () + (float (/ *position* 1000))) + +(defvar *wall-ticks* 0) + +;;; Events + +;; Events are lists the form (start-time &rest parameters-plist). For +;; events in a sequence, START-TIME (in ticks) is relative to the beginning of +;; the sequence's start time. + +;;; Sequences + +;; Sequences are sorted lists of events for a particular channel. + +;;; Patterns + +;; Patterns are groups of sequences that play simultaneously on +;; multiple channels. A pattern is a vector of event sequences, with +;; the nth element being the sequence for channel N. + +;; When a pattern is triggered, + +;;; Channels + +;; A channel is a single synthesizer voice. The default channel type +;; triggers samples. + +(define-prototype channel () + channel-number ;; integer + ) + +(define-method play channel (&key sample volume) + + + diff --git a/xiotank/xiotank.fasl b/xiotank/xiotank.fasl new file mode 100644 index 0000000..9e2d456 Binary files /dev/null and b/xiotank/xiotank.fasl differ diff --git a/xiotank/xiotank.lisp b/xiotank/xiotank.lisp new file mode 100644 index 0000000..47cbd2e --- /dev/null +++ b/xiotank/xiotank.lisp @@ -0,0 +1,594 @@ +;;; xiotank.lisp --- 7DRL + +;; Copyright (C) 2010 David O'Toole + +;; Author: David O'Toole +;; Keywords: + +;; This program 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. + +;; This program 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 . + +;;; Commentary: + +;; + +;;; Code: + +(defpackage :xiotank + (:documentation "xiotank is a sonic roguelike combat game.") + (:use :xe2 :common-lisp) + (:export xiotank)) + +(in-package :xiotank) + +(setf xe2:*dt* 10) +(setf xe2:*physics-function* #'(lambda (&rest ignore) + [run-cpu-phase *world* :timer])) + +;;; Sound waves + + +(defparameter *wave-types* '(:sine :square :saw)) +(defparameter *wave-colors* '(:yellow :cyan :magenta :green)) + +(defparameter *wave-samples* + '((:sine "A-2-sine" "A-4-sine") + (:saw "A-2-saw" "A-4-saw") + (:square "A-2-square" "A-4-square"))) + +(defun wave-sample (type &optional (note "A-4")) + (assert (member type *wave-types*)) + (concatenate 'string note "-" (string-downcase (symbol-name type)))) + +(defparameter *wave-images* + '((:sine :green "sine-green" :yellow "sine-yellow" :magenta "sine-magenta" :cyan "sine-cyan") + (:square :green "square-green" :yellow "square-yellow" :magenta "square-magenta" :cyan "square-cyan") + (:saw :green "saw-green" :yellow "saw-yellow" :magenta "saw-magenta" :cyan "saw-cyan"))) + +(defun wave-image (type color) + (assert (and (member type *wave-types*) + (member color *wave-colors*))) + (getf (cdr (assoc type *wave-tiles*)) + color)) + +(defsprite wave + (type :initform :sine) + (image :initform nil) + (direction :initform nil) + (speed :initform (make-stat :base 20)) + (movement-distance :initform (make-stat :base 2)) + (movement-cost :initform (make-stat :base 10)) + (categories :initform '(:wave :actor))) + +(define-method start wave (&key note (type :sine) (direction :north)) + (setf type) + (setf (wave-image type)) + (setf (wave-sample type note)) + (setf direction)) + +(define-method run wave () + [expend-action-points self 2] + (mutliple-value-bind (y x) (xe2:step-in-direction + [stat-value self :movement-distance]) + [update-position self x y])) + +;;(define-method do-collision wave () + +;;(define-method die wave + +(defcell tank + (tile :initform "tank-north") + (hit-points :initform (make-stat :base 45 :min 0 :max 45)) + (movement-cost :initform (make-stat :base 10)) + (max-items :initform (make-stat :base 2)) + (speed :initform (make-stat :base 10 :min 0 :max 25)) + (strength :initform (make-stat :base 10)) + (defense :initform (make-stat :base 10)) + (hearing-range :initform 15) + (energy :initform (make-stat :base 40 :min 0 :max 40 :unit :gj)) + (hit-points :initform (make-stat :base 45 :min 0 :max 45)) + (movement-cost :initform (make-stat :base 10)) + (max-items :initform (make-stat :base 2)) + (stepping :initform t) + (direction :initform :north) + (attacking-with :initform nil) + (firing-with :initform :center-bay) + (categories :initform '(:actor :player :target :container :light-source :vehicle :repairable)) + (equipment-slots :initform '(:left-bay :right-bay :center-bay :extension))) + +(defparameter *tank-tiles* '(:north "tank-north" + :south "tank-south" + :east "tank-east" + :west "tank-west" + :northeast "tank-northeast" + :northwest "tank-northwest" + :southeast "tank-southeast" + :southwest "tank-southwest")) + +(define-method move tank (direction) + (setf direction) + (setf (getf *tank-tiles* direction)) + [parent>>move self direction]) + +(define-method run tank () + nil) + +;;;; Basic blue world + +(defcell blue-space + (tile :initform "blue-space")) + +(define-prototype blue-world (:parent xe2:=world=) + (ambient-light :initform :total) + (required-modes :initform nil) + (scale :initform '(3 m)) + (edge-condition :initform :block)) + +(define-method begin-ambient-loop blue-world () + (play-music "purity" :loop t)) + +;; (define-method drop-base blue-world (row column &optional (size 5)) +;; (labels ((drop-panel (r c) +;; (prog1 nil [drop-cell self (clone =xiotank-base=) r c]))) +;; (trace-rectangle #'drop-panel row column size size :fill) +;; (dotimes (i 8) +;; [drop-cell self (clone =guardic-eye=) +;; (+ row (random size)) (+ column (random size)) :loadout t]) +;; (dotimes (i (* 2 size)) +;; [drop-cell self (clone =xiotank-wires=) +;; (+ row (random size)) (+ column (random size))]))) + +(define-method generate blue-world (&key (height 200) + (width 30) + sequence-number) + (setf height width) + [create-default-grid self] + (dotimes (i height) + (dotimes (j width) + [drop-cell self (clone =blue-space=) + i j])) + ;; (dotimes (i 20) + ;; [drop-cell self (clone =star=) (random height) (random width)] + ;; [drop-base self (random height) (random width) (+ 5 (random 10))]) + [drop-cell self (clone =launchpad=) (- height 8) 5]) + +;;; Splash screen + +(defvar *pager* nil) + +(define-prototype splash (:parent =widget=)) + +(define-method render splash () + (xe2:draw-resource-image "splash" 0 0 + :destination )) + +(defvar *space-bar-function*) + +(define-method dismiss splash () + [select *pager* :game] + (when (functionp *space-bar-function*) + (funcall *space-bar-function*)) + (xe2:show-widgets)) + +(define-prototype splash-prompt (:parent =prompt=) + (default-keybindings :initform '(("SPACE" nil "dismiss .")))) + +;;; Player status + +(defvar *status* nil) + +(define-prototype status (:parent xe2:=formatter=) + (character :documentation "The character cell.")) + +(define-method set-character status (character) + (setf character)) + +(define-method print-stat status (stat-name &key warn-below show-max) + (let* ((stat (field-value stat-name )) + (value [stat-value stat-name])) + (destructuring-bind (&key min max base delta unit) stat + (let ((color (if (and (numberp warn-below) + (< value warn-below)) + ".red" + ".gray40"))) + [print self (symbol-name stat-name) + :foreground ".white"] + [print self ":["] + [print self (format nil "~S" value) + :foreground ".yellow" + :background color] + (when show-max + [print self (format nil "/~S" max) + :foreground ".yellow" + :background color]) + (when unit + [print self " "] + [print self (symbol-name unit)]) + [print self "]"] + )))) + +(defparameter *status-bar-character* " ") + +(define-method print-stat-bar status (stat &key + (color ".yellow") + (background-color ".gray40") + (divisor 1)) + (let ((value (truncate (/ [stat-value stat] divisor))) + (max (truncate (/ [stat-value stat :max] divisor)))) + (dotimes (i max) + [print self *status-bar-character* + :foreground ".yellow" + :background (if (< i value) + color + background-color)]))) + +(define-method update status () + [delete-all-lines self] + (let* ((char )) + (when char + [print-stat self :hit-points :warn-below 10 :show-max t] + [print-stat-bar self :hit-points :color ".red" :divisor 2] + [print-stat self :energy :warn-below 10 :show-max t] + [print-stat-bar self :energy :color ".yellow" :divisor 2] + +;; [print self (format nil " SCORE:~S" [stat-value char :score])] + [newline self]))) + +;;; Custom bordered viewport + +(define-prototype view (:parent xe2:=viewport=)) + +(define-method render view () + [parent>>render self] + (xe2:draw-rectangle 0 0 + + + :color ".blue" :destination )) + +(defvar *view* (clone =view=)) + +;;; Keyboard controls + +(define-prototype xiotank-prompt (:parent xe2:=prompt=)) + +(defparameter *basic-keybindings* + '(("KP7" nil "move :northwest .") + ("KP8" nil "move :north .") + ("KP9" nil "move :northeast .") + ("KP4" nil "move :west .") + ("KP6" nil "move :east .") + ("KP1" nil "move :southwest .") + ("KP2" nil "move :south .") + ("KP3" nil "move :southeast .") + ;; + ("KP7" (:control) "fire :northwest .") + ("KP8" (:control) "fire :north .") + ("KP9" (:control) "fire :northeast .") + ("KP4" (:control) "fire :west .") + ("KP6" (:control) "fire :east .") + ("KP1" (:control) "fire :southwest .") + ("KP2" (:control) "fire :south .") + ("KP3" (:control) "fire :southeast .") + ;; + ("KP7" (:alt) "fire :northwest .") + ("KP8" (:alt) "fire :north .") + ("KP9" (:alt) "fire :northeast .") + ("KP4" (:alt) "fire :west .") + ("KP6" (:alt) "fire :east .") + ("KP1" (:alt) "fire :southwest .") + ("KP2" (:alt) "fire :south .") + ("KP3" (:alt) "fire :southeast .") + ;; + ("KP7" (:meta) "fire :northwest .") + ("KP8" (:meta) "fire :north .") + ("KP9" (:meta) "fire :northeast .") + ("KP4" (:meta) "fire :west .") + ("KP6" (:meta) "fire :east .") + ("KP1" (:meta) "fire :southwest .") + ("KP2" (:meta) "fire :south .") + ("KP3" (:meta) "fire :southeast ."))) + ;; ;; + ;; ("JOYSTICK" (:north :circle) "attack :north .") + ;; ("JOYSTICK" (:northeast :circle) "attack :northeast .") + ;; ("JOYSTICK" (:northwest :circle) "attack :northwest .") + ;; ("JOYSTICK" (:east :circle) "attack :east .") + ;; ("JOYSTICK" (:west :circle) "attack :west .") + ;; ("JOYSTICK" (:south :circle) "attack :south .") + ;; ("JOYSTICK" (:southwest :circle) "attack :southwest .") + ;; ("JOYSTICK" (:southeast :circle) "attack :southeast .") + ;; ;; + ;; ("JOYSTICK" (:north :cross) "move :north .") + ;; ("JOYSTICK" (:northeast :cross) "move :northeast .") + ;; ("JOYSTICK" (:northwest :cross) "move :northwest .") + ;; ("JOYSTICK" (:east :cross) "move :east .") + ;; ("JOYSTICK" (:west :cross) "move :west .") + ;; ("JOYSTICK" (:south :cross) "move :south .") + ;; ("JOYSTICK" (:southwest :cross) "move :southwest .") + ;; ("JOYSTICK" (:southeast :cross) "move :southeast .") + ;; ;; + ;; ("JOYSTICK" (:north :square) "fire :north .") + ;; ("JOYSTICK" (:northeast :square) "fire :northeast .") + ;; ("JOYSTICK" (:northwest :square) "fire :northwest .") + ;; ("JOYSTICK" (:east :square) "fire :east .") + ;; ("JOYSTICK" (:west :square) "fire :west .") + ;; ("JOYSTICK" (:south :square) "fire :south .") + ;; ("JOYSTICK" (:southwest :square) "fire :southwest .") + ;; ("JOYSTICK" (:southeast :square) "fire :southeast ."))) + +(defparameter *qwerty-keybindings* + (append *basic-keybindings* + '(("Y" nil "move :northwest .") + ("K" nil "move :north .") + ("U" nil "move :northeast .") + ("H" nil "move :west .") + ("L" nil "move :east .") + ("B" nil "move :southwest .") + ("J" nil "move :south .") + ("N" nil "move :southeast .") + ;; + ("Y" (:alt) "fire :northwest .") + ("K" (:alt) "fire :north .") + ("U" (:alt) "fire :northeast .") + ("H" (:alt) "fire :west .") + ("L" (:alt) "fire :east .") + ("B" (:alt) "fire :southwest .") + ("J" (:alt) "fire :south .") + ("N" (:alt) "fire :southeast .") + ;; + ("Y" (:meta) "fire :northwest .") + ("K" (:meta) "fire :north .") + ("U" (:meta) "fire :northeast .") + ("H" (:meta) "fire :west .") + ("L" (:meta) "fire :east .") + ("B" (:meta) "fire :southwest .") + ("J" (:meta) "fire :south .") + ("N" (:meta) "fire :southeast .") + ;; + ("Y" (:control) "fire :northwest .") + ("K" (:control) "fire :north .") + ("U" (:control) "fire :northeast .") + ("H" (:control) "fire :west .") + ("L" (:control) "fire :east .") + ("B" (:control) "fire :southwest .") + ("J" (:control) "fire :south .") + ("N" (:control) "fire :southeast .") + ;; + ("W" nil "wait .") + ("SPACE" nil "wait .") + ("PERIOD" (:control) "restart .") + ("KP-ENTER" nil "enter .") + ("RETURN" nil "enter .") + ("ESCAPE" (:control) "show-location .") + ("Q" (:control) "quit .")))) + +(defparameter *alternate-qwerty-keybindings* + (append *basic-keybindings* + '(("Q" nil "move :northwest .") + ("W" nil "move :north .") + ("E" nil "move :northeast .") + ("A" nil "move :west .") + ("D" nil "move :east .") + ("Z" nil "move :southwest .") + ("X" nil "move :south .") + ("C" nil "move :southeast .") + ;; + ("Q" (:alt) "attack :northwest .") + ("W" (:alt) "attack :north .") + ("E" (:alt) "attack :northeast .") + ("A" (:alt) "attack :west .") + ("D" (:alt) "attack :east .") + ("Z" (:alt) "attack :southwest .") + ("X" (:alt) "attack :south .") + ("C" (:alt) "attack :southeast .") + ;; + ("Q" (:meta) "attack :northwest .") + ("W" (:meta) "attack :north .") + ("E" (:meta) "attack :northeast .") + ("A" (:meta) "attack :west .") + ("D" (:meta) "attack :east .") + ("Z" (:meta) "attack :southwest .") + ("X" (:meta) "attack :south .") + ("C" (:meta) "attack :southeast .") + ;; + ("Q" (:control) "fire :northwest .") + ("W" (:control) "fire :north .") + ("E" (:control) "fire :northeast .") + ("A" (:control) "fire :west .") + ("D" (:control) "fire :east .") + ("Z" (:control) "fire :southwest .") + ("X" (:control) "fire :south .") + ("C" (:control) "fire :southeast .") + ;; + ("S" nil "wait .") + ("ESCAPE" (:control) "show-location .") + ("SPACE" nil "wait .") + ("PERIOD" (:control) "restart .") + ("P" (:control) "quit .")))) + +;; g c r +;; \|/ +;; h-.-n +;; /|\ +;; m w v + +(defparameter *dvorak-keybindings* + (append *basic-keybindings* + '(("G" nil "move :northwest .") + ("C" nil "move :north .") + ("R" nil "move :northeast .") + ("H" nil "move :west .") + ("N" nil "move :east .") + ("M" nil "move :southwest .") + ("W" nil "move :south .") + ("V" nil "move :southeast .") + ;; + ("G" (:alt) "fire :northwest .") + ("C" (:alt) "fire :north .") + ("R" (:alt) "fire :northeast .") + ("H" (:alt) "fire :west .") + ("N" (:alt) "fire :east .") + ("M" (:alt) "fire :southwest .") + ("W" (:alt) "fire :south .") + ("V" (:alt) "fire :southeast .") + ;; + ("G" (:meta) "fire :northwest .") + ("C" (:meta) "fire :north .") + ("R" (:meta) "fire :northeast .") + ("H" (:meta) "fire :west .") + ("N" (:meta) "fire :east .") + ("M" (:meta) "fire :southwest .") + ("W" (:meta) "fire :south .") + ("V" (:meta) "fire :southeast .") + ;; + ("G" (:control) "fire :northwest .") + ("C" (:control) "fire :north .") + ("R" (:control) "fire :northeast .") + ("H" (:control) "fire :west .") + ("N" (:control) "fire :east .") + ("M" (:control) "fire :southwest .") + ("W" (:control) "fire :south .") + ("V" (:control) "fire :southeast .") + ;; + ("S" nil "wait .") + ("SPACE" nil "wait .") + ("KP-ENTER" nil "enter .") + ("RETURN" nil "enter .") + ("ESCAPE" (:control) "show-location .") + ("PERIOD" (:control) "restart .") + ("Q" (:control) "quit .")))) + +(define-method install-keybindings xiotank-prompt () + (let ((keys (ecase xe2:*user-keyboard-layout* + (:qwerty *qwerty-keybindings*) + (:alternate-qwerty *alternate-qwerty-keybindings*) + (:dvorak *dvorak-keybindings*)))) + (dolist (k keys) + (apply #'bind-key-to-prompt-insertion self k)))) + ;; ;; we also want to respond to timer events. this is how. + ;; [define-key self nil '(:timer) (lambda () + ;; [run-cpu-phase *world* :timer])]) + +;;; Main program. + +(defun generate-level-address (ignore) + '(=blue-world=)) + +(defparameter *xiotank-window-width* 800) +(defparameter *xiotank-window-height* 600) + +(defvar *viewport*) + +(defun xiotank () + (xe2:message "Initializing Xiotank...") + (setf xe2:*window-title* "Xiotank") + (setf clon:*send-parent-depth* 2) + (xe2:set-screen-height *xiotank-window-height*) + (xe2:set-screen-width *xiotank-window-width*) + ;; go! + (let* ((prompt (clone =xiotank-prompt=)) + (universe (clone =universe=)) + (narrator (clone =narrator=)) + (player (clone =tank=)) + (splash (clone =splash=)) + (help (clone =formatter=)) + (quickhelp (clone =formatter=)) + (viewport (clone =viewport=)) + (status (clone =status=)) + (splash-prompt (clone =splash-prompt=)) + (terminal (clone =narrator=)) + (stack (clone =stack=))) + ;; + (setf *viewport* viewport) + (setf *status* status) + ;; + [resize splash :height (- *xiotank-window-height* 20) :width *xiotank-window-width*] + [move splash :x 0 :y 0] + [resize splash-prompt :width 10 :height 10] + [move splash-prompt :x 0 :y 0] + [hide splash-prompt] + [set-receiver splash-prompt splash] + ;; + [resize *status* :height 20 :width *xiotank-window-width*] + [move *status* :x 0 :y 0] + ;; + [resize prompt :height 20 :width 100] + [move prompt :x 0 :y 0] + [hide prompt] + [install-keybindings prompt] + ;; + (labels ((spacebar () + ;; + ;; enable pseudo timing + ;; (xe2:enable-timer) + ;; (xe2:set-frame-rate 30) + ;; (xe2:set-timer-interval 1) + + (xe2:enable-held-keys 1 3) + ;; + [set-player universe player] + [play universe + :address (generate-level-address 1) + :prompt prompt + :narrator terminal + :viewport viewport] + [loadout player] + ;; + [set-character *status* player] + ;; + [set-tile-size viewport 16] + [resize viewport :height 470 :width *xiotank-window-width*] + [move viewport :x 0 :y 0] + [set-origin viewport :x 0 :y 0 + :height (truncate (/ (- *xiotank-window-height* 130) 16)) + :width (truncate (/ *xiotank-window-width* 16))] + [adjust viewport])) + (setf *space-bar-function* #'spacebar)) + ;; + ;; [resize help :height 540 :width 800] + ;; [move help :x 0 :y 0] + ;; (let ((text (find-resource-object "help-message"))) + ;; (dolist (line text) + ;; (dolist (string line) + ;; (funcall #'send nil :print-formatted-string help string)) + ;; [newline help])) + ;; ;; + ;; [resize quickhelp :height 85 :width 250] + ;; [move quickhelp :y (- *xiotank-window-height* 130) :x (- *xiotank-window-width* 250)] + ;; (let ((text (find-resource-object "quickhelp-message"))) + ;; (dolist (line text) + ;; (dolist (string line) + ;; (funcall #'send nil :print-formatted-string quickhelp string)) + ;; [newline quickhelp])) + ;; ;; + ;;(play-music "xiotank-theme" :loop t) + (set-music-volume 255) + ;; + [resize stack :width *xiotank-window-width* :height (- *xiotank-window-height* 20)] + [move stack :x 0 :y 0] + [set-children stack (list viewport terminal status)] + ;; + [resize terminal :height 80 :width *xiotank-window-width*] + [move terminal :x 0 :y (- *xiotank-window-height* 80)] + [set-verbosity terminal 0] + ;; + (setf *pager* (clone =pager=)) + [auto-position *pager*] + (xe2:install-widgets splash-prompt splash) + [add-page *pager* :game prompt stack viewport terminal *status* quickhelp] + [add-page *pager* :help help])) + +(xiotank) + + +;;; xiotank.lisp ends here + diff --git a/xiotank/xiotank.lisp~ b/xiotank/xiotank.lisp~ new file mode 100644 index 0000000..5c4f65a --- /dev/null +++ b/xiotank/xiotank.lisp~ @@ -0,0 +1,38 @@ +;;; drez.lisp --- 7DRL + +;; Copyright (C) 2010 David O'Toole + +;; Author: David O'Toole +;; Keywords: + +;; This program 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. + +;; This program 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 . + +;;; Commentary: + +;; + +;;; Code: + +(defpackage :drez + (:documentation "dRez is a hybrid dance engine game in Common Lisp.") + (:use :xe2 :common-lisp) + (:export drez)) + +(in-package :drez) + + + + +;;; drez.lisp ends here + diff --git a/xiotank/xiotank.org b/xiotank/xiotank.org new file mode 100644 index 0000000..4ab408d --- /dev/null +++ b/xiotank/xiotank.org @@ -0,0 +1,70 @@ +#+TITLE: 7-Day Roguelike 2010 CHALLENGE Ideas + +* TODO RELEASE 7DRL ENTRY +DEADLINE: <2010-03-14 Sun 23:59> + +* Tasks +** DONE Translate game design doc into asset/code todos +CLOSED: [2010-03-08 Mon 10:44] +** DONE square/triangle/sine icons in pink/blue/green (sprites?) +CLOSED: [2010-03-08 Mon 10:44] +** TODO generate waveforms programmatically for all notes +** TODO establish pulsators for beats +** TODO draw tank and walls and background and some basic enemies +** TODO set up tank and basic dungeon +** TODO light and sound reveal locations of objects even on dark portions of map +** TODO tank firing waves with sound +** TODO firing enemies +** TODO oscillators and tone clusters +** TODO [#C] disembarking pilot +** TODO themes a la xiobreak + +* Entry mail + +** About the entrant + +I am David O'Toole and I program games in Common Lisp. My blog is at +http://lispgamesdev.blogspot.com, where I will be making daily +progress reports. + +** Re-use declaration + +For my entry I will be re-using my own Common Lisp game engine called +XE2 (see http://dto.github.com/notebook/xe2-reference.html for +details.) Among its features are support for grid-based worlds of +interacting objects, sprites, basic lighting and field-of-view, sound, +and other useful code. + +Aside from the XE2 library itself, all game logic and assets (sound, +images) will be original and produced during the 7 days of the +challenge. + +** Start time + + 11:59 PM on Sunday March 7 2010, US Eastern Time. + +** Game concept + +In this roguelike you control a tank pilot who can enter and exit +different tank vehicles. The tank can fire sound waves in 8 +directions. There are square waves, sine waves, and triangle +waves. You select which wave to fire with the Z, X, C keys. The +numeric keypad and/or nethack keys are used for choosing a direction +to move in. Either CONTROL or ALT, combined with a directional key, to +fire the currently selected waveform in that direction. + +To eliminate enemy bullets, fire the corresponding wave types at +them. Other activities involve firing waves at oscillators to turn +them on and off. Combining tones can unlock puzzle elements and create +chords. Oscillators have a number frequency or note attached. C4 +etc. Tracker game. + +Some waves must be identified by sound alone. + +The pilot can disembark from the tank and even take over other tanks, +and there are certain areas where the tank cannot go. The pilot is +extremely vulnerable, and has only one hit point. + +Death is permanent, the game ends when you run out of hit points. + +The goal is to defeat all the enemies and unlock all the gates. diff --git a/xiotank/xiotank.org~ b/xiotank/xiotank.org~ new file mode 100644 index 0000000..8bb1fe0 --- /dev/null +++ b/xiotank/xiotank.org~ @@ -0,0 +1,72 @@ +#+TITLE: DREZ ideas + +* Pronunciation + + DEE-rezz + +* Tasks + +** TODO review luke's mixer.lisp +** TODO create standard variables for sdl-mixer output format configuration +*** TODO frequency +** TODO convert SDL sample buffers into internal format +*** TODO (sdl:fp chunk) gets the buffer pointer from a chunk loaded with load-sample +*** TODO http://common-lisp.net/project/cffi/manual/cffi-manual.html#Accessing-Foreign-Memory +*** http://common-lisp.net/project/cffi/manual/cffi-manual.html#Built_002dIn-Types +*** TODO http://lispbuilder.sourceforge.net/lispbuilder-sdl-mixer.html#+default-format+ +** TODO convert internal format to SDL output stream, see also register-mixer or whatever http://lispbuilder.sourceforge.net/lispbuilder-sdl-mixer.html#register-music-mixer +** TODO resampler http://en.wikipedia.org/wiki/Interpolation + +** TODO Code event/sequencer basics +** DONE Decouple physics from framerate: http://code.google.com/p/lispbuilder/wiki/UsingLispbuilderSDL#Frame_Rate_and_Timestep +CLOSED: [2010-02-22 Mon 11:55] +** TODO Find/create bd, snare, hihat samples +** TODO Basic UI/button config +** TODO Design blocky font +** TODO Add scalable font support + +* Thoughts + +** Trigger beats and loops with your feet (or any other kind of controller) +** Variety of input options: mouse, dance pad, joystick, keyboard, MIDI, network +** Simple, button-based interface usable with simpler controllers (like dance pad) +** Supplement CL audio capabilities with external programs +** Establish a consistent beat via numeric input or tap-tempo +** Layer looped triggers to create a beat +** Basic sequencer subdivides a group into beats/ticks +** Musical trigger event lists; make these the same as XE2 events +** Ecasound programmatic integration? +** Rez-ish color coded interface widgets and simple cell-mode layout +** Atari Basic Programming style UI +** Choreography edit UI +** Piano roll edit ui +** simfiles ideas, i.e. beats plus freestyling game + +* Music representation + +** Mixing + + - (sdl:fp chunk) gets the buffer pointer from a chunk loaded with load-sample + - http://lispbuilder.sourceforge.net/lispbuilder-sdl-mixer.html#register-music-mixer + +** Timing + - ticks + - beats per minute + +** Events +*** One possibility: (start-time &rest p-fields) +*** Another: (integer-tick type &rest p-fields) +**** tick is relative to pattern +*** Pattern: (sorted vector of events +** Channels +*** Numbered 1-8+ +*** Monophonic +*** Delivers p-fields to a function at event trigger time, this defines what happens on the channel. +*** Event params must match function. +*** Sampler channel type accepts these p-fields: &key sample-name-or-number +** Projects +*** named +*** foo/ directory and foo/foo.drez +*** foo.drez contains channel and sample defs +*** foo/bar.wav, baz.wav, etc + diff --git a/xiotank/xiotank.pak b/xiotank/xiotank.pak new file mode 100644 index 0000000..99fc2b7 --- /dev/null +++ b/xiotank/xiotank.pak @@ -0,0 +1,46 @@ +( + (:name "splash" :type :image :file "xiotank.png") + + (:name "purity" :type :music :file "purity.ogg" :properties (:volume 13)) + (:name "launchpad" :type :image :file "launchpad.png") + + (:name "blue-space" :type :image :file "blue-space.png") + (:name "purple-space" :type :image :file "purple-space.png") + (:name "green-space" :type :image :file "green-space.png") + (:name "magenta-space" :type :image :file "magenta-space.png") + + (:name "saw-yellow" :type :image :file "saw-yellow.png") + (:name "saw-magenta" :type :image :file "saw-magenta.png") + (:name "saw-cyan" :type :image :file "saw-cyan.png") + (:name "saw-green" :type :image :file "saw-green.png") + + (:name "sine-yellow" :type :image :file "sine-yellow.png") + (:name "sine-magenta" :type :image :file "sine-magenta.png") + (:name "sine-cyan" :type :image :file "sine-cyan.png") + (:name "sine-green" :type :image :file "sine-green.png") + + (:name "square-yellow" :type :image :file "square-yellow.png") + (:name "square-magenta" :type :image :file "square-magenta.png") + (:name "square-cyan" :type :image :file "square-cyan.png") + (:name "square-green" :type :image :file "square-green.png") + + (:name "A-2-sine" :type :sample :file "A-2-sine.wav" :properties (:volume 20)) + (:name "A-2-square" :type :sample :file "A-2-square.wav" :properties (:volume 20)) + (:name "A-2-saw" :type :sample :file "A-2-saw.wav" :properties (:volume 20)) + (:name "A-4-sine" :type :sample :file "A-4-sine.wav" :properties (:volume 20)) + (:name "A-4-square" :type :sample :file "A-4-square.wav" :properties (:volume 20)) + (:name "A-4-saw" :type :sample :file "A-4-saw.wav" :properties (:volume 20)) + + (:name "tank-disabled" :type :image :file "tank-disabled.png") + (:name "tank-north" :type :image :file "tank-north.png") + (:name "tank-east" :type :alias :data ":rotate 90:tank-north") + (:name "tank-south" :type :alias :data ":rotate 180:tank-north") + (:name "tank-west" :type :alias :data ":rotate 270:tank-north") + (:name "tank-northeast" :type :image :file "tank-northeast.png") + (:name "tank-southeast" :type :alias :data ":rotate 90:tank-northeast") + (:name "tank-southwest" :type :alias :data ":rotate 180:tank-northeast") + (:name "tank-northwest" :type :alias :data ":rotate 270:tank-northeast") + + (:name "help-message" :type :text :file "README") + (:name ".startup" :type :lisp :file "xiotank.lisp" :properties (:autoload t)) +) diff --git a/xiotank/xiotank.pak~ b/xiotank/xiotank.pak~ new file mode 100644 index 0000000..5ab2ef0 --- /dev/null +++ b/xiotank/xiotank.pak~ @@ -0,0 +1,4 @@ +( + (:name "help-message" :type :text :file "README") + (:name ".startup" :type :lisp :file "drez.lisp" :properties (:autoload t)) +) diff --git a/xiotank/xiotank.png b/xiotank/xiotank.png new file mode 100644 index 0000000..4c061eb Binary files /dev/null and b/xiotank/xiotank.png differ diff --git a/xiotank/xiotank.xcf b/xiotank/xiotank.xcf new file mode 100644 index 0000000..93e8561 Binary files /dev/null and b/xiotank/xiotank.xcf differ