Skip to content

Instantly share code, notes, and snippets.

@alysbrooks
Last active October 18, 2021 19:26
Show Gist options
  • Save alysbrooks/5d51c0b47fd037626a609f4691ffe59d to your computer and use it in GitHub Desktop.
Save alysbrooks/5d51c0b47fd037626a609f4691ffe59d to your computer and use it in GitHub Desktop.
Hallway animation in Quil

This is copied from a larger project that lets you flip through multiple animations, so there's no defsketch here. If you want to get it up and running, you can insert the code into the fun-mode example.

The basic way this works is that we have a vector that basically determines the size of each square. Each frame, we make each one a bit bigger. Since larger objects appear closer and should look like they're moving faster, we want to make them a percentage bigger rather than a constant amount.

When using Quil and live reloading, the state tends to get out of whack, so I use a few tricks to help reset it if necessary:

  • initialized? and initialize-state functions that check if the state seems to be invalid, and reset it, respectively.
  • Binding the R key to a function that clears the state. This causes initialized? to be false and initialize-state to add the animation-specific starting state.
  • Namespaced keywords (notice the double semicolons ::positions). This is unnecessary for most Quil projects, but is good here because there are multiple animations, each in its own namespace and that way they won't clobber each other's state if they happen to have a keyword of the same name.
(ns hallway
(:require [quil.core :as q :include-macros true]
[quil.middleware :as m])
#?(:clj (:gen-class)))
;(defn key-press [state event]
; (if (= :r (:key event))
; {}) ;Literal with the clean state could go here instead of a blank hashmap.
; state ;handling other keys would go here
;)
(defn draw-state [{:keys [ ::positions]}]
(q/background 0 0 0 )
(q/with-fill [0 0 0 0]
(doseq [position positions]
(q/with-stroke [255 0 255 (max 10 (* 4 position))]
(q/rect (- (/ (q/width) 2) (/ position 2)) (- (/ (q/height) 2) (/ position 2)) position position)))))
(defn initialize-state [state]
(merge state
{::positions (into [] (range 10 300 40))}))
(defn initialized? [{:keys [::positions]}]
(and positions (seq positions)))
(defn move [x]
(* x 1.05))
(defn update-state [state]
(if (initialized? state)
;; (assoc state ::positions (map move (::positions state)))
(-> state
(assoc ::positions (map move (::positions state)))
(update ::positions #(if (> (apply min %) 3) (conj % 2) %) ) ;add new squares
(update ::positions (fn [p] (filter #(< % 1000) p) ))) ;drop squares that are out of frame.
(initialize-state state)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment