procedural content generation with clojure
TRANSCRIPT
![Page 1: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/1.jpg)
1
Procedural Content Generation with ClojureMike Anderson
![Page 2: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/2.jpg)
2
Contents
1. Procedural Content Generation
2. Introducing Clojure
3. Creating content with Clisk
![Page 3: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/3.jpg)
3
Definition
Procedural content generation (PCG)
is the programmatic generation
of content using algorithms, which may
incorporate random or pseudo-random
processes
![Page 4: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/4.jpg)
4
Some applicationsContent Types Examples
Images
• 3D model textures
• Abstract art
Pioneering work by Ken
Perlin (inventor of Perlin
noise)
Music
• Melodies
• Synthesised sounds
Work by Jeremy
Leach
http://algorithmiccomposition.org/
Game content
• Game items
• Random maps
Roguelike games
Virtual Worlds
• Landscapes
• Plants / animals
• Alien races
No Man’s Sky
(planned release 2016)
![Page 5: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/5.jpg)
5
Image Generation
(0,0)y-a
xis
(0,1) (1,1)
(1,0)
pixel colour = f(x, y)
x-axis
![Page 6: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/6.jpg)
6
Image “Composition”
x
f(x, y) g(x, y)
=
f(x, y) * g(x, y)
The Big Idea: Use a functional language to compose images!
![Page 7: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/7.jpg)
7
Contents
1. Procedural Content Generation
2. Introducing Clojure
3. Creating content with Clisk
![Page 8: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/8.jpg)
8
What is Clojure?
JVM Language
Functional Dynamic
![Page 9: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/9.jpg)
9
Data types – The Usual
Type Representation
Long integers 42
Double precision reals 3.14159265359
Strings “Hello World”
Characters \M
Hex 0xFF8000
All represented by equivalent Java
Objects “under the hood”
![Page 10: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/10.jpg)
10
Data types – The Not-So Usual
Type Representation
Keywords :foo
Symbols 'hello
Ratios 1/3
Regexes #"[0-9]+"
BigInt 15511210043330985984000000N
BigDecimal 189675.1678969698698969986M
Base-N numbers 3r1201200
![Page 11: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/11.jpg)
11
Data types – Collections
Type Representation
Maps {:foo 10 :bar 20}
Sets #{2 3 5 7 11 13}
Vectors [1 2 3 :foo]
Lists '(foo a b c)
All collections in Clojure are Immutable!
![Page 12: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/12.jpg)
12
Lisp = “Lots of Irritating Silly Parentheses”?
myfunction(alpha, beta)C-like languages
(myfunction alpha beta)Lisp
Usually the same number of parentheses!
![Page 13: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/13.jpg)
13
Expressions
Function
application
=> (+ 11 31)42
Nested
Expressions
=> (+ 11 (* 30 30))911
Local definitions
=> (let [x 11](* x 100))
1100
![Page 14: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/14.jpg)
14
Functions
Function definition
=> (defn triple [x](* x 3))
=> (triple 10)30
Higher order
functions
=> (map triple [1 2 3])(3 6 9)
![Page 15: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/15.jpg)
15
“Code is Data”
=> (+ 2 3)5
=> '(+ 2 3)(+ 2 3)
=> (eval '(+ 2 3))5
![Page 16: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/16.jpg)
16
Java Interop
Java myObject.doSomething(foo, bar);
Clojure (.doSomething myObject foo bar)
![Page 17: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/17.jpg)
17
Contents
1. Procedural Content Generation
2. Introducing Clojure
3. Creating content with Clisk
![Page 18: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/18.jpg)
18
https://github.com/mikera/clisk
To follow along:
- Clone the repo at: https://github.com/mikera/clisk
- All examples are in: src/test/clojure/clisk/workshop/
![Page 19: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/19.jpg)
19
Collaborative spirit – all about sharing!
Open Source Project
Open Source Language
Open Source content “Recipes”
![Page 20: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/20.jpg)
20
Example from “TweeGeeMee”
https://twitter.com/tweegeemee/status/676985464813953029
![Page 21: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/21.jpg)
21@TweeGeeMee twitter bot by Roger Allen
@TweeGeeMee evolved images
![Page 22: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/22.jpg)
22
Example from “Clevolution”
https://twitter.com/deathbob/status/661294702759669760
![Page 23: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/23.jpg)
23
Image Generation
(0,0)
y-a
xis
(0,1) (1,1)
(1,0)
pixel colour = [x 0 0]
x-axis
REPL
Command(show [x 0 0])
![Page 24: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/24.jpg)
24
Image Generation
(0,0)
y-a
xis
(0,1) (1,1)
(1,0)
pixel colour = [x y 0]
x-axis
REPL
Command(show [x y 0])
![Page 25: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/25.jpg)
25
Implementation notes
• Clisk functions actually generate ASTs
• “show” function compiles the AST into efficient low-level code, something like*:
• Lisp makes this (comparatively) easy!
This is very simplified! The real compiled code includes support for multi-threading,
caching of texture objects, making use of fast primitive maths etc.
*
(dotimes [y height](dotimes [x width](let [colour ....calculation code....](.setRGB image x y colour))))
![Page 26: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/26.jpg)
26
Many primitives
Solid colours (show [0.1 0.7 1.0])
Patterns (show (checker red pink))
Texture maps (show clojure)
![Page 27: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/27.jpg)
27
Transformations - scaling
Base (show (checker red pink))
Scaled
(show (scale 0.3(checker red pink)))
![Page 28: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/28.jpg)
28
Transformations – offsets
Base (show (checker red pink))
Offset
(show (offset [0.2 0.2](checker red pink)))
![Page 29: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/29.jpg)
29
Transformations – warps
Base (show (checker red pink))
Warped
(show (warp(scale 0.2 vnoise)(checker red pink)))
![Page 30: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/30.jpg)
30
Noise functions
Monochomatic
noise(show (scale 0.2 noise))
Vector noise (show (scale 0.2 vnoise))
Plasma (show (scale 0.2 plasma))
![Page 31: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/31.jpg)
31
Live coding time!
![Page 32: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/32.jpg)
32
Images from the Gallery: Stained Glass
(show (let [voronoi1 (voronoi :points 512)] (v*(v* 20.0 (voronoi-blocks :voronoi voronoi1))(warp (voronoi-points :voronoi voronoi1) grain)))
:size 512)
Key techniques:
• Use a Voronoi map to create “cells”
• Multiply with the psuedo-random “grain” function to colour cells
![Page 33: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/33.jpg)
33
Images from the Gallery: Mandelbrot
(show (viewport [-2 -1.5] [1 1.5](fractal:while (v- 2 (length [x y])):update (v+ c [(v- (v* x x) (v* y y))
(v* 2 x y)]):result (vplasma (v* 0.1 'i)):bailout-result black:max-iterations 1000)) :size 256)
Key techniques:
• Use the “fractal” function to create an iterative process
• Simulate complex numbers (x+ iy) using regular clisk vectors
• Use a viewport to see the relevant region of the Mandelbrot set
![Page 34: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/34.jpg)
34
Images from the Gallery: Voronoi Fractal
(show (let [voronoi1 (voronoi :points 32)] (fractal
:while (v- 0.97 (voronoi-function(v- 1 (v* (vdivide (v- y x) y)
(vdivide (v- z x) z))):voronoi voronoi1))
:update (v+ (v* pos 2) pos):result (vdivide 3 (v+ 3 'i)):max-iterations 4)) :size 512)
Key techniques:
• Voronoi map used to create a “net” pattern
• Use the “fractal” function to create iterative layers
• If it hits the net, stop
• Else continue to next layer with a scaled version of the net
![Page 35: Procedural Content Generation with Clojure](https://reader034.vdocuments.site/reader034/viewer/2022052117/5aaac19e7f8b9aa0578b4569/html5/thumbnails/35.jpg)
3535
BACKUP / OUT