Optimize my Conway Game of Life in Quil in Clojure

Ok so in clojure REPL (time (conway-state cells)) returns about 0.43 milliseconds more than fast enough for 15 FPS. However the actual draw loop seems to be really lagging on drawing my rects. code below:``

  1(ns hello-quil.core                                                                                                  
  2                                                                                                                     
  3 (:require [quil.core :as q]                                                                                         
  4            [quil.middleware :as m]                                                                                  
  5            [clojure.core.reducers :as r]))                                                                          
  6                                                                                                                     
  7(def scaler 10.0)                                                                                                    
  8(defstruct cell :index :alive :x :y)                                                                                 
  9(defn scale-w [] (Math/floor (/ 640 scaler) ))                                                                       
 10(defn scale-h [] (Math/floor (/ 360 scaler) ))                                                                       
 11                                                                                                                     
 12                                                                                                                     
 13(defn scaledCoord [coord] (if (= coord 0) coord (* scaler coord)))                                                   
 14                                                                                                                     
 15(def initState                                                                                                       
 16  ; the initial state                                                                                                
 17  (map-indexed                                                                                                       
 18    (fn [index num]                                                                                                  
 19      (struct cell index (rand-int 2) (scaledCoord (mod index (scale-w)))                                            
 20        (scaledCoord(Math/floor (/ index (scale-w))))))                                                              
 21    (range 0 (* (scale-w) (scale-h))))                                                                               
 22)                                                                                                                    
 23                                                                                                                     
 24(defn setup []                                                                                                       
 25  ; Set frame rate to 30 frames per second.                                                                          
 26  (q/frame-rate 15)                                                                                                  
 27  ; Set color mode to HSB (HSV) instead of default RGB.                                                              
 28  (q/color-mode :hsb)                                                                                                
 29  ; setup function returns initial state. It contains                                                                
 30  {:cells (into [] initState)}                                                                                       
 31)                                                                                                                    
 32                                                                                                                     
 33(defn getNeighbor [x y cells]                                                                                        
 34  ; gets the neigbor or return a random alive if no neighbor                                                         
 35  (let [result (into [] (r/filter (fn [c] (and (= x (:x c)) (= y (:y c)))) cells))]                                  
 36  (if (empty? result) (rand-int 2) (:alive (first result))))                                                         
 37)                                                                                                                    
 38                                                                                                                     
 39                                                                                                                     
 40(defn getNeighbors [c cells]                                                                                         
 41  ; get neighbors in 8 directions                                                                                    
 42  (let [x (:x c) y (:y c) left (- x scaler) right (+ x scaler) up (+ y scaler) down (- y scaler)]                    
 43    (map                                                                                                             
 44      (fn [[newX newY]](getNeighbor newX newY cells))                                                                
 45      [[right y] [left y] [right up] [left up] [x up] [x down] [right down] [left down]]))                           
 46)                                                                                                                    
 47                                                                                                                     
 48                                                                                                                     
 49(defmulti cell-state                                                                                                 
 50  ; takes a vector of neighbors and sums them                                                                        
 51  (fn [c cells] (reduce + cells))                                                                                    
 52)                                                                                                                    
 53; if there are 2 the cell stays the same                                                                             
 54(defmethod cell-state 2 [c cells] c)                                                                                 
 55; if there are 3 neighbors we reproduce 1                                                                            
 56(defmethod cell-state 3 [c _] (assoc c :alive 1))                                                                    
 57; everything else it dies                                                                                            
 58(defmethod cell-state :default [c _] (assoc c :alive 0))                                                             
 59                                                                                                                      60(defn update-cell [cells]                                                                                            
 61  ; curried func that takes the state, then return a mappable func                                                   
 62  (fn [c] (let [neighbors (getNeighbors c cells)]                                                                    
 63    (cell-state c neighbors)))                                                                                       
 64)                                                                                                                    
 65                                                                                                                     
 66(defn conway-state [cells]                                                                                           
 67  ; update conway's game of life                                                                                     
 68  (map (update-cell cells) cells)                                                                                    
 69)                                                                                                                    
 70                                                                                                                     
 71(defn update-state [state]                                                                                           
 72  ; Update sketch state by changing circle color and position.                                                       
 73  {:cells (conway-state (:cells state))}                                                                             
 74)                                                                                                                    
 75                                                                                                                     
 76(defn getFill [alive]                                                                                                
 77  (if (> alive 0) 255 0)                                                                                             
 78)                                                                                                                    
 79                                                                                                                     
 80(defn draw-cell [c]                                                                                                  
 81  (q/with-fill [(getFill (:alive c))] (q/rect (:x c) (:y c) scaler scaler))                                          
 82)                                                                                                                    
 83                                                                                                                     
 84(defn draw-state [state]                                                                                             
 85  ; Clear the sketch by filling it with light-grey color.                                                            
 86  (q/background 240)                                                                                                 
 87  ; Calculate x and y coordinates of the cell and the color.                                                         
 88  (doseq [cell (:cells state) ]                                                                                      
 89    (draw-cell cell))                                                                                                
 90)            
91                                                                                                                     
 92(q/defsketch hello-quil                                                                                              
 93  :title "Basic Conway Game of Life"                                                                                 
 94  :size [640 360]                                                                                                    
 95  ; setup function called only once, during sketch initialization.                                                   
 96  :setup setup                                                                                                       
 97  ; update-state is called on each iteration before draw-state.                                                      
 98  :update update-state                                                                                               
 99  :draw draw-state                                                                                                   
100  :features [:keep-on-top]                                                                                           
101  ; This sketch uses functional-mode middleware.                                                                     
102  ; Check quil wiki for more info about middlewares and particularly                                                 
103  ; fun-mode.                                                                                                        
104  :middleware [m/fun-mode])                 

Answers

  • this is a forum for processing (which is based on JAVA)

    Maybe you want to ask in a Clojure / Quil forum instead, not here?

  • edited June 2017
  • Interesting -- I didn't know about Quil. I've been spending enough time immersed in Processing.R lately that when I saw it my first thought was "why isn't there a Processing Clojure mode?"

    Although I really know almost nothing about Clojure, so I'm not the person to advocate for that.

  • Clojure runs on the jvm actually anyways thanks for the suggestions I will try stack overflow I guess. sucks I would have thought someone who uses Quil would be here.

  • edited June 2017

    looking through this it looks like there a few weird typos caused by the cut and paste`

    60 (defn update-cell [cells]

    61 ; curried func that takes the state, then return a mappable func

    62 (fn [c] (let [neighbors (getNeighbors c cells)]

    63 (cell-state c neighbors)))

    64) `

Sign In or Register to comment.