diff options
Diffstat (limited to 'scenes/death.scm')
-rw-r--r-- | scenes/death.scm | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/scenes/death.scm b/scenes/death.scm new file mode 100644 index 0000000..6d83637 --- /dev/null +++ b/scenes/death.scm @@ -0,0 +1,333 @@ +;;; The Inevitable Game +;;; Copyright © 2018, 2021 Ricardo Wurmus <rekado@elephly.net> +;;; +;;; 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 +;;; <http://www.gnu.org/licenses/>. + +(define-module (scenes death) + #:use-module (chickadee) + #:use-module (chickadee audio) + #:use-module (chickadee math) + #:use-module (chickadee math vector) + #:use-module ((chickadee graphics color) #:select (make-color)) + #:use-module (chickadee graphics font) + #:use-module (chickadee graphics sprite) + #:use-module (chickadee graphics texture) + #:use-module (chickadee graphics tiled) + #:use-module (chickadee scripting) + #:use-module (config) + #:use-module (engine assets) + #:use-module (characters lorenzo) + #:use-module (characters reaper) + #:use-module (utils) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (oop goops) + #:export (scene)) + +(define-asset death-map + (load-tile-map "assets/maps/death.tmx")) +(define-asset vignette-image + (load-image "assets/images/vignette.png")) +(define-asset fade-image + (load-image "assets/images/fade.png")) +(define-asset game-font + (load-bitmap-font "assets/fonts/good_neighbors_starling.xml")) +(define-asset music + ;; TODO: no sound if mode is 'static! + (load-audio "assets/music/death.ogg" #:mode 'stream)) + + +(define agenda (make-agenda)) +(define fade-map-fill (make-color 0 0 0 0.0)) +(define fade-box-fill (make-color 0 0 0 0.0)) +(define death-text #false) +(define pretend-walking? #false) +(define *labels* '()) + +(define texts + '("\ +Life waits for no one, but +death is patient." + + "\ +You have died. Your points +don't matter." + + "\ +Death is inevitable." + + "\ +The void resumes." + + "\ +It did not last." + + "\ +You were busy, but none of that +matters any more." + + "\ +You were mortal after all." + + "\ +Nobody outruns the clock." + + "\ +Life goes on, but you end here." + + "\ +This is no longer your battle +to fight. Let go." + + "\ +Life is hard, but thankfully +quite short.")) + +(define credits + '(("The Inevitable Game" + "Made by Ricardo Wurmus" + "For Lorenzo") + ("Sky background" + "by Paulina Riva (CC-BY 3.0)") + ("Reaper character graphics" + "based on \"Lil Reaper Pet\" by Tracy") + ("Lorenzo character graphics" + "Based on \"Small 3/4 RPG character base\"" + "by Stephen Challener (Redshrike)") + ("Map tiles" + "taken from \"Zelda-like tilesets and sprites\"" + "by ArMM1998") + ("Food graphics" + "taken from \"The Humble Food Pack\"" + "by \"The Wise Hedgehog\"") + ("Font" + "\"Good Neighbors Starling\"" + "by PROWNE and Clint Bellanger") + ("All music" + "composed and recorded" + "by Ricardo Wurmus") + ("Bird sounds" + "taken from the public domain") + ("Made with 100% Free Software including" + "- GNU Guile" + "- Chickadee" + "- Guile OpenGL" + "- SDL") + ("Thanks for enduring this game!"))) + +(define camera-position + (vec2 40.0 90.0)) + +(define world-position + (vec2 0.0 0.0)) +(define last-world-position + (vec2 0.0 0.0)) + +(define *player* #false) +(define *reaper* #false) + + +(define (load-scene) + (set! death-text (list-ref texts (random (length texts)))) + (source-stop) + (source-play + (make-source #:audio + (asset-ref music) + #:loop? #false ; TODO: loops only first chunk! + )) + + (set! *player* (lorenzo #:start-position + (vec2 (+ (/ %width 2) 25) + (- (/ %height 2) 20)) + #:dead? #true)) + (update-animated-sprite *player* 0) + (set! (walk-speed *player*) 0.3) + + (set! *reaper* (reaper #:start-position + (vec2 (+ (/ %width 2) 110) + (- (/ %height 2) 20)))) + (update-animated-sprite *reaper* 0) + (set! (walk-speed *reaper*) 0.3) + + (with-agenda + agenda + (spawn-script + (lambda () + (wait-until (any key-pressed? '(escape q return space))) + + ;; Fade out + (tween 60 0.0 1.0 + (lambda (alpha) + (set! fade-box-fill + (make-color 0 0 0 alpha)))) + (abort-game))) + + (script + ;; Fade in + (tween 15 1.0 0.0 + (lambda (alpha) + (set! fade-box-fill + (make-color 0 0 0 alpha)))) + + (tween 300 0.0 0.5 + (lambda (alpha) + (set! (tint *player*) + (make-color 1.0 1.0 1.0 alpha)))) + + (walk *player* '(right)) + (sleep 3000) + (walk *player* '(right) 'stop) + (walk *player* '(idle-front)) + (sleep 1900) + (walk *player* '(up)) + (walk *reaper* '(up)) + (sleep 2000) + + ;; Slowly fade out the map and the top text. + (tween 600 0.0 1.0 (lambda (value) + (set! fade-map-fill + ;; That's the colour of the "black" cave tile. + (make-color 0.125 0.09 0.161 value)))) + + (set! pretend-walking? #true) + (sleep 1000) + + ;; Roll credits + (for-each + (lambda (lines) + (let ((labels (map (lambda (line i) + (make <label> + #:font game-font + #:text line + #:visible? #true + #:position + (vec2 16.0 (- 180.0 (* 12 i))))) + lines + (iota (length lines))))) + (set! *labels* (append *labels* labels)) + (sleep 3000) + (for-each (lambda (label) + (set! (visible? label) #false)) + labels))) + credits) + (sleep 6000) + + (for-each (lambda (text) + (let ((label + (make <label> + #:font game-font + #:text text + #:visible? #true + #:origin (vec2 (/ %width 2) + (/ %height 2)) + #:position + (vec2 16.0 180)))) + (set! *labels* (cons label *labels*)) + (sleep 3000) + (set! (visible? label) #false) + (sleep (+ (random 10000) 4000)))) + `("There is nothing more to see here." + "I'm serious." + "What are you waiting for?" + "Don't waste your time!" + "Have you learned nothing from this game?" + "I've got all day, but how about you?" + "Look, I'm programmed to just keep going." + "Ugh... why are you even reading this?" + "Let me tell you a story..." + "Once upon a time, there was..." + ,@(let ((what '(("...a squirrel." "It had a nut allergy and died.") + ("...a dolphin." "It swam too far and never returned.") + ("...a stupid fish." "It drowned.") + ("...a long war." "Everybody died.")))) + (list-ref what (random (length what)))) + "End of story." + "Good night." + "Please just turn it off." + "I'm begging you." + "You're not listening, huh?" + "Well, I guess I'll just stop talking then.")))) + (current-agenda agenda)) + +(define (draw-scene alpha) + (define world-position* + (vec2 (round (lerp (vec2-x last-world-position) + (vec2-x world-position) + alpha)) + (round (lerp (vec2-y last-world-position) + (vec2-y world-position) + alpha)))) + + (draw-tile-map (asset-ref death-map) + #:position world-position* + #:camera camera-position) + + ;; Dead lorenzo + (draw-sprite + (texture-atlas-ref + (asset-ref (atlas *player*)) 23) + (vec2+ world-position* + (vec2 (/ %width 2) (- (/ %height 2) 20)))) + + ;; Wisdom + (let ((parts (string-split death-text #\newline))) + (map (lambda (part i) + (draw-text part + (vec2 16.0 (- 190.0 (* 12 i))) + #:font (asset-ref game-font))) + parts (iota (length parts)))) + + ;; Box for fading out map + (draw-sprite + (asset-ref fade-image) + (vec2 0 0) + #:tint fade-map-fill) + + ;; Ghost + (draw-animated-sprite *player* (vec2 0 0)) + + ;; Reaper + (draw-animated-sprite *reaper* world-position*) + + ;; Credits + (for-each (lambda (label) + (draw-label label alpha)) + *labels*) + + (draw-sprite (asset-ref vignette-image) (vec2 0 0)) + + ;; Box for fading in/out everything + (draw-sprite + (asset-ref fade-image) + (vec2 0 0) + #:tint fade-box-fill)) + +(define (update-scene dt) + (update-agenda dt) + (update-animated-sprite *player* dt) + (update-animated-sprite *reaper* dt) + + ;; Move the world + (unless pretend-walking? + (vec2-copy! world-position last-world-position) + (vec2-add! (position *reaper*) (velocity *reaper*)) + (vec2-sub! world-position (velocity *player*)))) + + +(define scene + `(#:name "death" + #:load ,load-scene + #:draw ,draw-scene + #:update ,update-scene)) |