|
1 | 1 | {
|
2 |
| - "title": "Wave Function Collapse - Overlapping Model", |
| 2 | + "title": "Wave Function Collapse: Overlapping Model", |
3 | 3 | "videoNumber": "186",
|
4 |
| - "description": "", |
5 |
| - "videoId": "", |
6 |
| - "nebulaSlug": "codingtrain-coding-challenge-186-wfc-overlapping-model", |
| 4 | + "description": "Wave Function Collapse is an algorithm for procedural image generation. In this long overdue follow-up to my tiled model video, I dive into the overlapping model, coding it step by step (complete with struggles and messy debugging interludes) in JavaScript with p5.js.", |
| 5 | + "videoId": "5iSAvzU2WYY", |
| 6 | + "nebulaSlug": "codingtrain-coding-challenge-186-wave-function-collapse", |
7 | 7 | "date": "2025-01-28",
|
8 | 8 | "languages": ["p5.js", "JavaScript"],
|
9 | 9 | "topics": ["wave function collapse", "overlapping model", "procedural generation"],
|
10 | 10 | "canContribute": true,
|
11 | 11 | "relatedChallenges": ["171-wave-function-collapse"],
|
12 | 12 | "timestamps": [
|
13 | 13 | { "time": "0:00:00", "title": "Introduction" },
|
14 |
| - { "time": "0:01:12", "title": "The Nature of Code" }, |
15 |
| - { "time": "0:02:20", "title": "References" }, |
16 |
| - { "time": "0:08:19", "title": "Write a function to extract tiles from a source image" }, |
17 |
| - { "time": "0:14:32", "title": "Write a function to copy tiles" }, |
18 |
| - { "time": "0:21:30", "title": "Add a list of allowed adjacencies to the Tile object" }, |
19 |
| - { "time": "0:24:34", "title": "Write an overlapping() function" }, |
20 |
| - { "time": "0:32:20", "title": "Look at the first tile's neighbors" }, |
21 |
| - { "time": "0:43:30", "title": "Add a Cell class" }, |
22 |
| - { "time": "0:44:15", "title": "Add a grid of Cells" }, |
23 |
| - { "time": "0:46:21", "title": "Retrieve previous WFC code" }, |
24 |
| - { "time": "0:50:50", "title": "Write a reduceEntropy() function" }, |
25 |
| - { "time": "0:55:56", "title": "Add a function to render the center pixel" }, |
26 |
| - { "time": "0:58:05", "title": "Filter by the valid options" }, |
27 |
| - { "time": "1:01:57", "title": "Use recursion to reduce entropy" }, |
28 |
| - { "time": "1:05:32", "title": "Add depth of recursion" }, |
29 |
| - { "time": "1:06:32", "title": "We have WFC!" }, |
30 |
| - { "time": "1:09:42", "title": "Fix mistake" }, |
31 |
| - { "time": "1:11:26", "title": "Start refactoring code" }, |
32 |
| - { "time": "1:18:41", "title": "Add a console.log if alogrithm gets stuck" }, |
33 |
| - { "time": "1:21:38", "title": "Optimizations" }, |
34 |
| - { "time": "1:26:28", "title": "Discuss redundant tiles" }, |
35 |
| - { "time": "1:28:30", "title": "Rotations and Reflections" }, |
| 14 | + { "time": "0:01:12", "title": "The Nature of Code book!" }, |
| 15 | + { "time": "0:02:20", "title": "WFC Resources and References" }, |
| 16 | + { "time": "0:08:19", "title": "Extracting tiles from a source image" }, |
| 17 | + { "time": "0:21:30", "title": "Calculating adjacency rules for tiles" }, |
| 18 | + { "time": "0:24:34", "title": "Checking for overlapping pixel colors" }, |
| 19 | + { "time": "0:32:20", "title": "Debugging tile adjacencies" }, |
| 20 | + { "time": "0:43:30", "title": "Creating a Cell class" }, |
| 21 | + { "time": "0:46:21", "title": "Incorporate code from WFC tile model" }, |
| 22 | + { "time": "0:50:50", "title": "Reduce entropy of neighboring tiles" }, |
| 23 | + { "time": "0:55:56", "title": "Rendering the center pixel for each tile" }, |
| 24 | + { "time": "0:58:05", "title": "Cross checking valid tile options" }, |
| 25 | + { "time": "1:01:57", "title": "Recursive entropy reduction" }, |
| 26 | + { "time": "1:05:32", "title": "Limit recursion depth" }, |
| 27 | + { "time": "1:06:32", "title": "Challenge complete?" }, |
| 28 | + { "time": "1:08:26", "title": "Bugs found between Day 1 and Day 2" }, |
| 29 | + { "time": "1:09:13", "title": "Starting Day 2" }, |
| 30 | + { "time": "1:10:02", "title": "Correcting pixel color if statement" }, |
| 31 | + { "time": "1:11:16", "title": "Refactoring redundant code" }, |
| 32 | + { "time": "1:17:26", "title": "Running out of tile options" }, |
| 33 | + { "time": "1:21:24", "title": "Optimizing the code" }, |
| 34 | + { "time": "1:23:47", "title": "Rendering average pixel color of remaining tile options" }, |
| 35 | + { "time": "1:26:23", "title": "How to handle redundant tiles?" }, |
| 36 | + { "time": "1:28:30", "title": "More tiles with rotations and reflections" }, |
36 | 37 | { "time": "1:29:39", "title": "Additional performance optimizations" },
|
37 |
| - { "time": "1:31:40", "title": "Outro" } |
| 38 | + { "time": "1:31:40", "title": "Thanks for watching!" } |
38 | 39 | ],
|
39 | 40 | "codeExamples": [
|
40 | 41 | {
|
41 |
| - "title": "WFC Overlapping", |
42 |
| - "description": "The sketch implements the overlapping model.", |
43 |
| - "image": "1.png", |
| 42 | + "title": "Wave Function Collapse: Overlapping Model", |
| 43 | + "description": "Unoptimized code exactly matching the video.", |
| 44 | + "image": "wfc.png", |
44 | 45 | "urls": {
|
45 |
| - "p5": "https://editor.p5js.org/codingtrain/sketches/PX0Hn6TF8" |
| 46 | + "p5": "https://editor.p5js.org/codingtrain/sketches/SI0c2D_tQ" |
46 | 47 | }
|
47 | 48 | },
|
48 | 49 | {
|
49 |
| - "title": "WFC Overlapping - Shannon entropy", |
50 |
| - "description": "This sketch adds Shannon entropy.", |
51 |
| - "image": "1.png", |
| 50 | + "title": "WFC Overlapping Model Refactored", |
| 51 | + "description": "Refactored code with optimizations.", |
| 52 | + "image": "wfc_refactored.png", |
| 53 | + "urls": { |
| 54 | + "p5": "https://editor.p5js.org/codingtrain/sketches/2sV4KtcoD" |
| 55 | + } |
| 56 | + }, |
| 57 | + { |
| 58 | + "title": "WFC Overlapping Model: Shannon entropy", |
| 59 | + "description": "This sketch counts tile frequency and incorporates entropy formula.", |
| 60 | + "image": "wfc_entropy.png", |
52 | 61 | "urls": {
|
53 | 62 | "p5": "https://editor.p5js.org/codingtrain/sketches/PX0Hn6TF8"
|
54 | 63 | }
|
55 | 64 | },
|
56 | 65 | {
|
57 |
| - "title": "WFC Overlapping - Rotations and Reflections", |
| 66 | + "title": "WFC Overlapping Model: More tiles!", |
58 | 67 | "description": "This sketch adds tile rotations and reflections",
|
59 |
| - "image": "1.png", |
| 68 | + "image": "wfc_rot_reflect.png", |
60 | 69 | "urls": {
|
61 | 70 | "p5": "https://editor.p5js.org/codingtrain/sketches/z_N2TVjRH"
|
62 | 71 | }
|
63 |
| - }, |
64 |
| - { |
65 |
| - "title": "WFC Overlapping - Restart", |
66 |
| - "description": "This sketch restarts WFC if there are no more valid choices.", |
67 |
| - "image": "1.png", |
68 |
| - "urls": { |
69 |
| - "p5": "https://editor.p5js.org/codingtrain/sketches/2sV4KtcoD" |
70 |
| - } |
71 |
| - }, |
72 |
| - { |
73 |
| - "title": "WFC Overlapping - Refactored", |
74 |
| - "description": "This sketch refactors the code and adds performance enhancements.", |
75 |
| - "image": "1.png", |
76 |
| - "urls": { |
77 |
| - "p5": "https://editor.p5js.org/codingtrain/sketches/paJcuQLI0" |
78 |
| - } |
79 |
| - } |
| 72 | + } |
80 | 73 | ],
|
81 | 74 | "groupLinks": [
|
82 | 75 | {
|
83 | 76 | "title": "References",
|
84 | 77 | "links": [
|
85 |
| - { |
86 |
| - "icon": "📕", |
87 |
| - "title": "The Nature of Code", |
88 |
| - "url": "https://natureofcode.com/", |
89 |
| - "description": "The Nature of Code book (2024 p5.js edition)" |
90 |
| - }, |
91 |
| - { |
92 |
| - "icon": "🛒", |
93 |
| - "title": "Nature of Code shop", |
94 |
| - "url": "https://store.natureofcode.com/products/the-nature-of-code", |
95 |
| - "description": "The Nature of Code book (2024 p5.js edition) is now available for purchase!" |
96 |
| - }, |
97 | 78 | {
|
98 | 79 | "icon": "🗄",
|
99 |
| - "title": "Wave Function Collapse Algorithm", |
| 80 | + "title": "Wave Function Collapse GitHub Repo", |
100 | 81 | "url": "https://github.com/mxgmn/WaveFunctionCollapse",
|
101 |
| - "description": "The original GitHub repository from mxgmn for the Wave Function Collapse algorithm." |
| 82 | + "description": "Maxim Gumin's source code and documentation for Wave Function Collapse." |
102 | 83 | },
|
103 | 84 | {
|
104 | 85 | "icon": "🗄",
|
105 | 86 | "title": "Model Synthesis",
|
106 | 87 | "url": "https://paulmerrell.org/model-synthesis/",
|
107 |
| - "description": "Paul Merrell's 2009 PhD Thesis that is a predecessor to WFC." |
| 88 | + "description": "Documentation of Paul Merrell's work on Model Synthesis." |
108 | 89 | },
|
109 | 90 | {
|
110 | 91 | "icon": "🗄",
|
111 | 92 | "title": "Procedural Generation with Wave Function Collapse",
|
112 | 93 | "url": "https://www.gridbugs.org/wave-function-collapse/",
|
113 |
| - "description": "Article on using WFC for procedural generation." |
| 94 | + "description": "Wave Function Collapse overlapping model algorithm walk through." |
114 | 95 | },
|
115 | 96 | {
|
116 | 97 | "icon": "🗄",
|
|
120 | 101 | },
|
121 | 102 | {
|
122 | 103 | "icon": "🔗",
|
123 |
| - "title": "p5 copy()", |
| 104 | + "title": "p5.js copy()", |
124 | 105 | "url": "https://p5js.org/reference/p5/copy/",
|
125 |
| - "description": "Reference for the copy function" |
| 106 | + "description": "p5.js reference page for copy() function" |
126 | 107 | },
|
127 | 108 | {
|
128 | 109 | "icon": "🔗",
|
129 |
| - "title": "Github issue RE console.log problem", |
| 110 | + "title": "p5.js web editor console log GitHub issue", |
130 | 111 | "url": "https://github.com/processing/p5.js-web-editor/issues/3178",
|
131 |
| - "description": "Cannot console.log objects having circular references." |
| 112 | + "description": "Issue discussing console.log and objects with circular references." |
132 | 113 | },
|
133 | 114 | {
|
134 | 115 | "icon": "🔗",
|
135 |
| - "title": "concat() function", |
| 116 | + "title": "JavaScript concat() method", |
136 | 117 | "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat",
|
137 |
| - "description": "Reference for the concat function." |
| 118 | + "description": "JavaScript documentation for array concat() method." |
138 | 119 | },
|
139 | 120 | {
|
140 | 121 | "icon": "🔗",
|
141 |
| - "title": "randomSeed()", |
| 122 | + "title": "p5.js randomSeed()", |
142 | 123 | "url": "https://p5js.org/reference/p5/randomSeed/",
|
143 |
| - "description": "Reference for the randomSeed function" |
| 124 | + "description": "p5.js reference page for randomSeed() function" |
144 | 125 | }
|
145 | 126 | ]
|
146 | 127 | },
|
|
151 | 132 | "icon": "🎥",
|
152 | 133 | "title": "Pixel Array",
|
153 | 134 | "url": "/tracks/p5-tips-and-tricks/more-p5/pixel-array",
|
154 |
| - "description": "Coding Train video with explanation of tracking 2D grid in 1D array (for pixels)." |
| 135 | + "description": "Video tutorial on how to work with pixel array in p5.js." |
155 | 136 | },
|
156 | 137 | {
|
157 | 138 | "icon": "🎥",
|
158 | 139 | "title": "Modulo Operator",
|
159 | 140 | "url": "https://www.youtube.com/watch?v=r5Iy3v1co0A",
|
160 |
| - "description": "Golan Levin explains what modulus means and its applications in creative coding with p5.js and Processing." |
| 141 | + "description": "Video tutorial with Golan Levin explaining modulo operator." |
161 | 142 | },
|
162 | 143 | {
|
163 | 144 | "icon": "🎥",
|
164 | 145 | "title": "Array Functions: filter() - Topics of JavaScript/ES6",
|
165 | 146 | "url": "/tracks/topics-in-native-javascript/js/array-filter",
|
166 |
| - "description": "This video covers the JavaScript Array higher order function filter()." |
| 147 | + "description": "Video tutorial on higher order array function filter()." |
167 | 148 | },
|
168 | 149 | {
|
169 | 150 | "icon": "🎥",
|
170 | 151 | "title": "Arrow Function",
|
171 | 152 | "url": "/tracks/topics-in-native-javascript/js/arrow-functions",
|
172 |
| - "description": "Coding Train video covering JavaScript arrow (=>) function." |
| 153 | + "description": "Video tutorial on JavaScript arrow notation." |
| 154 | + } |
| 155 | + ] |
| 156 | + }, |
| 157 | + { |
| 158 | + "title": "Creative Works Featured", |
| 159 | + "links": [ |
| 160 | + { |
| 161 | + "icon": "🎨", |
| 162 | + "title": "Townscaper", |
| 163 | + "url": "https://www.townscapergame.com/", |
| 164 | + "description": "Created by Oskar Stålberg, 3D WFC system that creates cute little houses, arches, stairways, bridges and lush backyards." |
| 165 | + }, |
| 166 | + { |
| 167 | + "icon": "🎨", |
| 168 | + "title": "unity-wave-function-collapse", |
| 169 | + "url": "https://selfsame.itch.io/unitywfc", |
| 170 | + "description": "A fork of Wave Function Collapse with tools for the Unity Game engine by @ExUtumno." |
| 171 | + }, |
| 172 | + { |
| 173 | + "icon": "🎨", |
| 174 | + "title": "Super Mario WFC", |
| 175 | + "url": "https://observablehq.com/@makio135/super-mario-wfc", |
| 176 | + "description": "Generating variations of Super Mario Bros worlds with Wave Function Collapse." |
| 177 | + }, |
| 178 | + { |
| 179 | + "icon": "🎨", |
| 180 | + "title": "Zelda WFC", |
| 181 | + "url": "https://observablehq.com/@makio135/zelda-wfc", |
| 182 | + "description": "Generating variations of Zelda maps with Wave Function Collapse." |
| 183 | + }, |
| 184 | + { |
| 185 | + "icon": "🎨", |
| 186 | + "title": "Infinite procedurally generated city", |
| 187 | + "url": "https://marian42.de/article/wfc/", |
| 188 | + "description": "a game where you walk through an infinite city that is procedurally generated as you walk." |
173 | 189 | }
|
174 | 190 | ]
|
175 | 191 | }
|
|
0 commit comments