You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p> So to simulate our ball's motion, we would: </p>
456
456
457
457
<ol>
458
-
<li> Update the velocity with acceleration </li>
459
-
<li> Update the position with velocity </li>
458
+
<li> Update the velocity according to acceleration </li>
459
+
<li> Update the position according to velocity </li>
460
460
</ol>
461
461
462
462
<p> As we'll soon see, we have to do this in a <em>very careful</em> way. </p>
463
463
464
464
<h4>Enter deltaTime</h4>
465
465
466
466
<p>Until now, we've not really considered how long each frame takes.
467
-
It'd be reasonable to assume each frame takes about 1/60 seconds to process <em>however</em> each frame takes a slightly different amount of time and, when simulations get more complex, each frame might take a non-slight different amount of time!
467
+
It'd be reasonable to assume each frame takes about 1/60 seconds to process <em>however</em> each frame <strong>actually</strong>takes a slightly different amount of time. When simulations get more complex, this difference in time may increase!
468
468
</p>
469
469
470
-
<p>To test this theory, console.log the <em>deltaTime</em> variable inside the <em>draw()</em> function; it will set itself to the time taken to process the previous frame! </p>
470
+
<p>To test this theory, console.log the <em>deltaTime</em> variable inside the <em>draw()</em> function in a blank sketch; deltaTime will be set to the time taken to process the previous frame! You should see differences in the values logged despite not much going on.</p>
471
+
472
+
<h4>Why should we care?</h4>
473
+
474
+
<p>Imagine two different devices: device A and device B. A runs slowly and can only handle the simulation running at 20 FPS, and B runs quickly and can handle the simulation running at its intended 60 FPS.
475
+
476
+
If we <em>don't</em> use deltaTime, then B will run the simulation 3 times as quickly as A! If this is a game, then A will be running the game at a third of the speed
477
+
it's meant to be played at. Imagine playing your favourite platformer where everything is 3 times slower!
478
+
</p>
479
+
480
+
<p>Of course, this doesn't matter massively for simple simulations </p>
471
481
472
-
<h4>Using deltaTime</h4>
482
+
<h4>Using deltaTime (Incorrectly)</h4>
473
483
474
-
<p> We know $v = p/t$ (where )</p>
484
+
<p> We know acceleration is the rate of change of velocity, and velocity is the rate of change of position so it'd be reasonable to write our motion simulation as:</p>
<p> The aim of this workshop is to recreate boids, which are a simulation of birds and other flocking entities (like fishes).
47
+
Hopefully, you'll be able to apply this in your own projects!
48
+
Along the way, we'll learn a little bit about p5.js, rendering, and simulating physics. </p>
49
+
50
+
<divid="BoidContainer"></div>
51
+
52
+
<em> (This is not an actual boids sketch btw - this is a random stepper) </em>
53
+
54
+
55
+
<p> We will be coding in JavaScript but don't worry about knowing the ins and outs of the language; you should be able to pick it up as we go! </p>
56
+
57
+
<h2> Introduction to p5.js </h2>
58
+
59
+
We will be using JavaScript and a library called <strong> p5.js</strong>, made by the lovely <ahref="https://processingfoundation.org/"> Processing Foundation</a>.
60
+
61
+
<ol>
62
+
<li><p>To get started, create an account for the <ahref="https://editor.p5js.org/signup">web editor</a>. </p></li>
63
+
<li><p> Open a new sketch (File->New) </p></li>
64
+
</ol>
65
+
66
+
<h3> What is a sketch? </h3>
67
+
68
+
<p>A sketch is a small program that will work with p5.js to produce a simulation.
69
+
Just like a game, your simulation will have frames (an image of your simulation) and p5.js will aim to show 60 frames a second.
70
+
You'll be able to code what happens on certain events e.g. just before a frame is shown, just before the simulation starts, when the mouse is clicked.
71
+
72
+
In this lab, since we're just drawing an image, we'll only concern ourselves with drawing before the simulation starts and when the mouse is clicked.
73
+
</p>
74
+
75
+
<br>
76
+
77
+
<p> Your new sketch should have 2 functions: </p>
78
+
79
+
<ul>
80
+
<li><strong> setup() </strong> which is a function executed once at the start </li>
81
+
<li><strong> draw() </strong> which is a function executed every frame </li>
82
+
</ul>
83
+
84
+
We're going to <strong>ignore</strong> the <strong>draw()</strong> function, since we'll just be using the setup function. In other words, in this lab, just delete the <strong>draw()</strong> function.
85
+
86
+
We create the canvas (arguments being the width and length) in <strong> setup() </strong>; this is something you only do once pretty much regardless of the simulation.
87
+
<pre>
88
+
<codeclass="language-js">
89
+
function setup() {
90
+
createCanvas(400, 400);
91
+
let redV = 128; // if you're new to js, use "let" to declare variables
92
+
let greenV = 12;
93
+
let blueV = 128;
94
+
background(redV, greenV, blueV); // my favourite colour; purple!
95
+
}
96
+
</code>
97
+
</pre>
98
+
<em> RGB values have R,G,B values ranging from 0-255 </em>
99
+
100
+
<p><strong>Mini-Task:</strong> Try running the above simulation! Maybe change the variables to display your own favourite colour. </p>
101
+
102
+
<h3> Creating Random Noise </h3>
103
+
104
+
<divid="RandomHeightMap"></div>
105
+
<em>Click to generate new random noise</em>
106
+
107
+
<p>Let's dive straight into generating random noise! We'll need to know a couple things: </p>
108
+
109
+
<ol>
110
+
<li>Drawing a pixel to the screen, with a specific colour</li>
111
+
<li>Generating random values</li>
112
+
<li>Turning a random value into a colour</li>
113
+
</ol>
114
+
115
+
<p>Let's tackle (1) first!</p>
116
+
117
+
<h4>Pixels</h4>
118
+
119
+
<pre>
120
+
<codeclass="language-js">
121
+
function setup() {
122
+
createCanvas(400, 400);
123
+
124
+
// the eyes
125
+
point(25, 25);
126
+
point(28, 25);
127
+
128
+
// the smile
129
+
point(25, 30);
130
+
point(26, 30);
131
+
point(27, 30);
132
+
point(28, 30);
133
+
134
+
point(24, 29);
135
+
point(23, 28);
136
+
137
+
point(29, 29);
138
+
point(30, 28);
139
+
}
140
+
</code>
141
+
</pre>
142
+
143
+
<p>We can use the <strong>point()</strong> function to draw a pixel at specified <strong>X,Y</strong> coordinates. What about the colour? </p>
144
+
145
+
<pre>
146
+
<codeclass="language-js">
147
+
function setup() {
148
+
createCanvas(400, 400);
149
+
150
+
// eye colour
151
+
stroke(0, 0, 255);
152
+
153
+
// the eyes
154
+
...
155
+
156
+
// smile colour
157
+
stroke(255, 0, 0);
158
+
159
+
// the smile
160
+
...
161
+
}
162
+
</code>
163
+
</pre>
164
+
165
+
<p>We can use the <strong>stroke()</strong> function to determine the colour of the pixels drawn from that point on; we can supply it with 3 values to specify an RGB colour.
166
+
If we're only using grayscale colours, then we can provide just a single value (to represent the brightness or "value" of the colour) e.g. 255 for pure white, 0 for pure black.
167
+
</p>
168
+
169
+
<br>
170
+
171
+
<p>Using this knowledge, can you guess what the following code does?</p>
172
+
173
+
<pre>
174
+
<codeclass="language-js">
175
+
function setup() {
176
+
createCanvas(400, 400);
177
+
178
+
for(let y = 0; y < 400; y++){
179
+
for(let i = 0; i <= 255; i++){
180
+
stroke(i);
181
+
point(i,y);
182
+
}
183
+
}
184
+
}
185
+
</code>
186
+
</pre>
187
+
188
+
<p><strong>Mini-Task:</strong> Run the above simulation, and see if you guessed what it does correctly! </p>
189
+
190
+
<h4>Random Values</h4>
191
+
192
+
<p>A key thing to remember about p5.js is that ultimately, it is still JavaScript. Therefore, we can use JavaScript functions and libraries with p5.js. </p>
193
+
<br>
194
+
<p>To handle randomness, we'll use js' Math library; in particular, the function <strong>Math.random()</strong>! Let's use the JavaScript console to test it out. </p>
195
+
196
+
<pre>
197
+
<codeclass="language-js">
198
+
for(let i = 0; i < 20; i++){
199
+
console.log(Math.random()); // values between 0-1
200
+
}
201
+
</code>
202
+
</pre>
203
+
204
+
<p> Okay cool, there's only a slight problem now; we get random values in the range 0-1, but the colour values are in the range 0-255. All we need to do is multiply up :) </p>
205
+
206
+
<h4>Use the docs! </h4>
207
+
208
+
<p>If you ever have questions about p5 functions, then please refer to the excellent <ahref="https://p5js.org/reference/">documentation</a>! </p>
209
+
210
+
<h3>Task: Random Noise</h3>
211
+
212
+
<p>It's now your job to replicate the random noise sketch! Use the tools above and the template below to create some random noise. </p>
213
+
214
+
<pre>
215
+
<codeclass="language-js">
216
+
217
+
const width = 400; // these are "constant" variables, as they don't change
218
+
const height = 400; // made to be variables since they're used in 2 places (iterating and createCanvas)
219
+
220
+
function drawRandomNoise(){
221
+
for(let x = 0; x < width; x++){
222
+
for(let y = 0; y < height; y++){
223
+
// FILL ME
224
+
}
225
+
}
226
+
}
227
+
function setup() {
228
+
createCanvas(width, height);
229
+
drawRandomNoise();
230
+
}
231
+
</code>
232
+
</pre>
233
+
<em>Generally, taking this out into its own function for this is a good idea; especially since this function's sole purpose is drawing random noise </em>
234
+
235
+
<h3>Perlin Noise</h3>
236
+
237
+
<p>Okay so we've programmed <em>random noise</em> which is "incoherent" noise - you can have sharp constrasts between neighbouring pixels.
238
+
If we want nice smooth gradients, then we can use perlin noise! </p>
239
+
240
+
<divid="NoiseHeightMap"></div>
241
+
242
+
<p>We can definitely see that the noise is more ordered than random noise, however we want it to be less sharp; we want it to be smoother. </p>
243
+
244
+
<h4>Smoothing it out</h4>
245
+
246
+
<p>So how do we achieve a smoother noise? We can figure this out by looking at 1D noise, and think about sampling 10 points from perlin noise. </p>
<p>From the above, we can see that the values sampled can be quite different. You can think of this as sampling the 10 points at $x=1, 2, 3, \dots$ </p>
251
+
252
+
<p>What if we sampled points more frequently instead?</p>
<p>From the above, we can see that the values sampled are <em>a lot closer</em>; you can think of this as sampling the 10 points at $x=0.2, 0.4, 0.6 \dots$</p>
0 commit comments