35
1 Procedural Content Generation with Clojure Mike Anderson

Procedural Content Generation with Clojure

Embed Size (px)

Citation preview

Page 1: Procedural Content Generation with Clojure

1

Procedural Content Generation with ClojureMike Anderson

Page 2: Procedural Content Generation with Clojure

2

Contents

1. Procedural Content Generation

2. Introducing Clojure

3. Creating content with Clisk

Page 3: Procedural Content Generation with Clojure

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

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

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

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

7

Contents

1. Procedural Content Generation

2. Introducing Clojure

3. Creating content with Clisk

Page 8: Procedural Content Generation with Clojure

8

What is Clojure?

JVM Language

Functional Dynamic

Page 9: Procedural Content Generation with Clojure

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

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

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

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

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

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

15

“Code is Data”

=> (+ 2 3)5

=> '(+ 2 3)(+ 2 3)

=> (eval '(+ 2 3))5

Page 16: Procedural Content Generation with Clojure

16

Java Interop

Java myObject.doSomething(foo, bar);

Clojure (.doSomething myObject foo bar)

Page 17: Procedural Content Generation with Clojure

17

Contents

1. Procedural Content Generation

2. Introducing Clojure

3. Creating content with Clisk

Page 18: Procedural Content Generation with Clojure

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

19

Collaborative spirit – all about sharing!

Open Source Project

Open Source Language

Open Source content “Recipes”

Page 20: Procedural Content Generation with Clojure

20

Example from “TweeGeeMee”

https://twitter.com/tweegeemee/status/676985464813953029

Page 21: Procedural Content Generation with Clojure

21@TweeGeeMee twitter bot by Roger Allen

@TweeGeeMee evolved images

Page 22: Procedural Content Generation with Clojure

22

Example from “Clevolution”

https://twitter.com/deathbob/status/661294702759669760

Page 23: Procedural Content Generation with Clojure

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

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

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

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

27

Transformations - scaling

Base (show (checker red pink))

Scaled

(show (scale 0.3(checker red pink)))

Page 28: Procedural Content Generation with Clojure

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

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

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

31

Live coding time!

Page 32: Procedural Content Generation with Clojure

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

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

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

3535

BACKUP / OUT