Flowy Noise | Hadeel Alharthi | Skillshare
Drawer
Search

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Introduction

      0:47

    • 2.

      What's noise?

      0:26

    • 3.

      Example: What's noise?

      15:00

    • 4.

      Flow field

      22:49

    • 5.

      One agent

      6:47

    • 6.

      Many agents

      7:51

    • 7.

      Three dimensional noise

      5:01

    • 8.

      Static noise

      9:10

    • 9.

      Different brushes

      13:04

    • 10.

      Coloring techniques

      3:29

    • 11.

      Saving images

      20:04

    • 12.

      Inspiration and more info

      1:28

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

540

Students

7

Projects

About This Class

This course will teach you everything you need to know about creating fluid movement in Processing, producing artworks that will make people wonder. The basic noise function is used by many generative artists but adding your own touch or building layers of imagery with varied parameters can make it unique to you. We'll go through the basic function so you understand how it works but we'll after explore the different ways to use it for diversified results.

Meet Your Teacher

Teacher Profile Image

Hadeel Alharthi

Creative Coder and Artist

Teacher

ABOUT

Hi! I'm Hadeel, and this is my humble digital abode. I'm a creative coder and artist whose sole passion is to learn all there is to know about generative art — or rather the digital art world in general. I'm curious by nature, and I love to share my findings. So if you're interested in learning generative art, this is the place to be. Welcome!

 

HOW TO NAVIGATE THE COURSES

If you're new to generative art, I recommend starting with either Back to the Basics or Intro to Generative Art. The latter is a much shorter course for anyone with too little time on their hands. Next, I'd go with Switches since that showcases my whole process, from ideating to the final design. The rest you can follow in any order since yo... See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction: Hello everyone. My name is heavier and this is flowing noise, of course, that delves deeper into the realm of generative art. Presenting me with a glorious algorithm known as Perlin noise. Noise is a function implemented by many journalists, artists in a multitude of forms. We will however, primarily focus on movement in a flow field by first understanding the noise function in processing, visualizing its values go some simple animation like an oscillating circle and smoothed randomized rotations, which will help transitioning into generating fluid animations in static artworks like this, the formula will learn can present numerous results by adjusting a few parameters such as scales, step size, or even the geometry used. So I'll take you through each one in the hopes of helping you understand how noise works and ultimately reach your flow goes. So let's hop into the lessons and start learning. 2. What's noise?: Both the noise and random function produce random values. Only noise is more organic compared to random because noise values are influenced by their neighboring values, generating smooth fluid movement occurring in nature like clouds, hair, and water streams. Syntactically, the noise function takes either 12 or three arguments, but the resulting values will always be between 01. Will see in the next lesson a couple of examples to visualize the noise functions outward. 3. Example: What's noise?: Okay, before we get into the more advanced stuff, I want to explain or you want to show you how we're going to use the noise function. Now, the noise function only produces values from 0 to one no matter what values you put into it. It's very different from the random function where you put a minimum value and a maximum value and you get values are floating values between those numbers. But for noise, no matter how big the values that you put into it, it will always produce a value from 0 to one. So we'll need to scalar up, but at the same time, we'll also need to zoom into it. So we want only a chunk of that wave of those noise values because we want a very smooth fluid movement, because it's going to give us a very rigid movement. If we don't zoom into a part of that, I'm going to start by showing you the example with the sine wave. And then we'll look at the example with the noise function because a sine wave is much easier to visualize because it's very uniform. When the nice function is a little bit harder to decipher whether there were changes or not, or whether we're still using the same wave or not. Okay, let's, let's first start by creating the wave. So I'm going to need an x and y point. And then inside of the setup function, I'm going to draw the wave. The wave is going to go from 0 to width, and then it's going to be in the middle or in the center of the canvas. Height wise for the x will go from 0 to the width. But then for the y values, I'm going to use the sine function. And then I'll input inside of it the x values. And I'll draw a vertex on x and y. And I'll also initialize y, height divided by two. We need to begin shapes and for each vertex to connect with the other. And now we have a very, very small sine wave. Now in order to scale it up, we are going to multiply it by a height. Because if I want to scale it up by one to give it an amplitude which is the height of the wave. So let's say I want to give it a height of ten. Now we start to actually see the wave. Let's actually go even higher. So I'll do a 100. And you can see that the wave has almost no width, it's very narrow. In order to do that, we need to kind of zoom into it. So that's why they call it the scales and times. I'm going to call it width here because it's the width of the wave. So in order to scale the width of each wave, I'm going to divide the x value over here by 1000. So we already see that it's much bigger because we increased the width of the wave. And let's actually decrease this to ten instead. Now we start to actually see the wave better. So now that we know that we have though waves width and the waves height, I'm going to add two more values over here. One cult w for which I am going to give it a value of ten. And then I'm going to make this called edge switches height. And I'm gonna give it a value of two because that's what I tested before. So I'm gonna change this with width and height. Okay, so now we know that we have a sine wave with a width of ten and a height of two. Now in order to make this in the center, directly in the center, I'm going to subtract the width multiplied by the height from why. This is not necessarily important, but I like to put my wave in the center and it's much easier for you to visualize how the wave changes if we change the values. So now we can see that it's in the center and now the values are actually correct. And I can see the height of two or a wave with a height of two and a width of ten. And if we ever want to change this, let say 200, which is the width to 100, you can see that it's a much bigger because the width now is much higher. And then if I do, Let's say 15, now it's two wave. And if we do five, it's much smaller. So yeah, it depends on how you want to do it. So the point to take away here is that the width or whatever value you put over here skills up the Wave. So if we put 40, then we're scaling up the wave. I like to think of it as zooming into the wave. And then the bigger this value is where the height then the more steep waves are going to be. So if we were going to move a circle on this wave, and we can do it right now so you can see it. But before we can do that, I'm going to save this wave into appreciate class. Because then we can just draw the shape once inside of the draw function. So you can use the for loop to move the circle on the Wave and to create a piece shape. It's very simple. You just create the class P shape and then you call it whatever you want. And then in here or in the setup function, you initialize it using clean shape. And then you use wave or the methods inside of the PCA class instead of just using began shape that is directly used inside of processing. And then here as well, you do wave and use the vertex inside of the T-shaped class instead. And now you have the shape that won't appear unless he used the shape function. This way we can use it over here. So I'm going to just draw back, because we don't want it to draw, we want an animation to have done. And then I'm going to call the wave. Inside of the shape function over here. And now we can see it appearing over here. If I remove the background, it's going to draw it up, whether it's going to be very chunky. And also you want to move the circle and we don't want it to draw. Okay, so now we can draw the circle at the same point as the vertex. And I'm going to give the circle width of ten. And then in here, as we did here, we increased x by one. I'm going to increase x by one as well. And then I'm going to increase y i, the sine wave, divided by, which is x divided by the width, to zoom into it and make it a lot bigger. So the movement is much smoother. And then we multiply it by a hide, so give it a strength to strength because now it's getting to be steeper. The more, the bigger the number it's getting to be steeper and the hardware for the circle longer Fred the circle to go up and down. And now I'm going to do also if x is greater than the width. And I wanted to go back to 0 because I want the circle to move. And then once it gets out of the screen and goes back here. So now I can see the circle actually moving through the wave and you can see how the movement is very smooth. Now. The higher this is, the height is which is the strength or the steepness of these waves. The faster for the circles to move because it needs to reach all of this and the same time or in the same frame, frame rate. Now let's move on to the noise examples, since that's what we're going to use. So there are a few things that I'm going to change because we're not going to use a width and height that's only usually used with the sine function because it's very apparent where the width is and the height is. But for the noise, I'm going to change the width to scale because it's zooms in and scale up the look of the wave. And then I'm going to call the height the strength. Because the higher it is, the more you get out of whatever you using the noise function, which we're going to use it with angle. So the higher the spring is, the higher the rotation or the more rotation you will get. And then I'm going to change each width to scale. You're actually not getting used. This part. We're going to do it differently here. And strength for the height. And also here to do something different. And then this also is going to be scale in furnaces went to E strings. Ok, so let's say it changed this to noise. So whatever value comes out of Aaron's going to be from 0 to one and multiplied by the strength, it's going to make it larger. So it's going to give it more strength. And I'm not going to add to it, noise function works a little bit different. And we need to change it here as well. But we're going to leave everything else the same. And we start height at the wyatt height divided by two. But then we're also going to have to move this down instead. So plus. But let's actually see how it looks now and then change it later. Okay, so the reason why I pushed it down, so I said y plus height divided by two. It's because it goes up here near the 0. So I'm going to just move it by adding height divided by two will be here and then the same over here. So I'm just pushing it down here because now the strength is only ten. And so it's gonna give us a value from 0 to ten. As you can see, the wave is very chunky. And the way we can enhance this or actually look into one of these pieces is by adjusting the scale. So you can needs very big skill numbers in order to get very smooth movements. So if I go a 100, you can see that it's much smoother and out, but then there is no rotation or there is a lot of height into this wave. So I'm going to also increase this. And as you can see, we're starting to get some nice shapes or nice fluid movement. And if I go even higher for the rotation, then I'd get hill like movements. And this can produce very nice results if we add it to the angle or the way the shapes rotate. And that's what we're going to use in the upcoming exam. Also, we are using here is a one dimensional noise. So we're only using one argument inside of the noise function when you can actually use a two-dimensional noise, any three-dimensional noise. And yeah, I'm not going to introduce it now. That is going to have its own chapter. But right now, all you need to know is that the scale zooms into the wave so you can see, so you can see it better, has more fluid movement because now we're moving from 0 to the width using only a chunk of the wave. When, before, when it was only ten, we actually moved through a lot more. And then the strength gives you more height. Now we can use the NOI seed function to give it the same shape over and over again so we can see how things are actually moving. So if I do, I'll just give it a 0. You can give it whatever number you. So every time I run it right now, we're going to have the same exact wave. I want you to focus on the first area of the wave. And I'm going to increase this just a little bit. As you can see, it's the same exact looking ways, but it's getting a little bit bigger because we're getting closer to it. So it's actually getting this chunk of the wave, the bigger this number is. So if you go 30, you're going to see that this, it is going to get bigger. And as you can see, it's the same exact way, but it's getting bigger. And if I go 50, then it's the same exact wave. Let's go even higher and get you a 100. And you can see that it's the same exact movement, but it's much bigger because we're scaling it up. And then if we increase the strength, you're gonna see that the peaks are going to get higher and the lower parts are going to get lower. So this part is going to actually go out of the screen. So if I go, let's say 400. And you can see that it's the same exact ways, but now it's going lower over here and higher over here. If you get confused by this, don't worry. It's the same exact formula you only play with the skill and the strength. And we're not going to change that much even in two-dimensional noise function. And in the three-dimensional annoys function, it's only going to be the same exact thing, just adding a y value or Z value. And we will see that in the upcoming chapter. And for now focus on what skill and strength due to the noise wave. 4. Flow field: Before we can start creating artworks using noise, I want to show you how a flow field looks like, because that's basically the basis of everything that we're going to create. In the previous section, I mentioned that we're going to use noise for movement angle. So as the shapes move across the screen, either direction of the canvas boundaries, but then adding the angle or adding noise to the angle. Property of each of these factors are, each of these agents is actually creating that fluid movement. I'm going to just create a simple grid and then show you how the angles actually move across the screen using the noise function. We're going to start by just using a normal vector and then we're going to incorporate the noise function to see how the angles change. Creed fluid movement across the screen. To start, I'm going to save my file because I want to import or you want to save into it the RL by creating some gang to simply save that in my desktop, I'm gonna call it flow field. And then inside of this file, I'm going to create a data file and that's how you import images or shapes your project. So I'm going to copy and paste my SVG file into the state of older. And I called it just the arrow. And it's very simple arrow that I created in Illustrator and saved it as an SVG. I'm going to link this in the resources section. So you can follow along with me. Now to create the flow field, I'm going to create a class called flow field. Inside of the flow field, I'm going to need a p vector. A b vector is easier to use here because it has an angle already built into it. But in the upcoming chapters are not going to use a key factor. I'm just going to use a quaint and an x and y position. But since I want to create a grid and I want to store the positions of each of the vectors. I'm going to just do it this way. And I'm going to call this field. So the majority of this code is very similar to the nature of code. It's just the way that I create the grid is a little bit different. And I think in my opinion, much easier to comprehend just because we're actually focusing on the way we create a grant in real life. Rather than focusing on the resolution of the grades and maybe thinking a little bit backwards. So I'm going to just use columns or rows because it's much easier for me to explain. It's much easier for me to also understand as I go through it. I'm going to just do columns and rows for the number of columns and rows. And then I'm also going to use column width and height to calculate the width and height of each cell inside of that grit. And then inside of the constructor of this class. I'm giving. He parameters, what are called columns and the rows. Because I want the number of columns and rows inside of our class to be decided or mean program over here. And then this columns will equal. The first parameter is underscore columns and rows. And by the way, you can call this whatever you want. And then column width. Actually I'm just going to call this silhouettes and Scala. And then as it's much easier to understand that it's sounds height and width. And this is going to be the width of our canvas divided by the number of columns. And then sell height, young TV, the height divided by the rows. And then further field vector. We're going to create a new vector array with the number of columns and then the number of rows. So this is a two-dimensional array. And then in here I'm going to create a inet function. To initialize our grid. You just use a simple for loop gain from 0 to the columns and then nested for loop to create the rows. So this is going to be the columns. I is less than number of columns. And then last, we're going to call it here. Because I want to initialize it just one inside of the setup function over here. And then we're going to try over here, can now to position our arrow. We're getting to those positions. And to create the positions, I'm just getting to create an x position, y position. And for the exposition, the values going to be i multiplied by the cell. So each eye position, each eye point is going to mean multiplied beta-cell with. So the first one is going to be 0 multiplied benzoate, so that's going to be 0. And then the second square, the second cell is going to be an one multiplied by n cell with, so whatever the silhouettes or if you have a silhouette of a 100 based on the number of columns and rows, then you'll have a position of x at a 100 and so on and so forth. The same goes for j at this time is cell height. And then I'm going to create a P vector in here, a local p vector. And I'm going to give it a position 00 to, again, just to see how it's going to look like. And then I'm going to store this position where this p vector inside of our field to be vector array at i, j for the rows at points i. And then at point j, we're going to give it the value of the vector in here. So this is basically going to go for the first. And then it's going to loop through each row inside of our grid. And it's going to give each point or each cell the position using this vector in here, a very simple grid. And I'm going to show you later where we're going to use the axiom I positions in here. Now we just initialized it. Let's display. So I'm going to create a display methods. And in here I'm just gonna do the same for loop. And now I'm going to draw whatever we want. Here. It's going to be the arrow shape using those positions that we just created. I'm going to use a push matrix. And I talked about this in my back to the basics course. If you want to know more about push matrix and pop matrix. But I'm gonna give you a brief of what they do. So basically push matrix and pop matrix creates a different layer or a different matrix basically for each shape. So instead of moving the shapes themselves, I'm going to simply move the whole layer. So I'm going to create a layer for the first cell in the grid. And I'm going to position it in that area where I want the first cell TB and then I'm going to push a different matrix are another layer. And I'm going to push that whole layer next to or at the position of the second cell. And then we'll do the same for the rest of the grit because we're using the for loop. So that will make it easier for us to position or shape at the 00 position of each layer. Also, you have to use push matrix and pop matrix because if you ever use translate, rotate, and scale outside of the push matrix and pop matrix is going to perform the same. Let's say translation. If we're using translate to move the shapes, it's going to use the same translation on the same layer. So It's going to move until it moves out of the screen. Because it's going to move the canvas's 00 position, which is the top left corner to the right and then down based on the position of the cells until it moves to the last cell. So it's going to be the same one. But if we use push matrix and pop matrix, then we are creating a different layer and then we're moving that layer to the new position. So it's going to move the first one to 00 of the whole canvas. And then it's going to move the second layer two, the second position, which is going to be 0. And then the cell width and moving across the columns and then across the rows. So now I can safely use Translate, knowing that it's only going to do that translation on that layer. So I'm going to do the same thing that we did over here. And I'm not going to use whenever position I haven't here just because I want to show you a few things before I use the x and y position. So this is going to break this for us. So I'm gonna just do i multiplied by cell with in drain, multiply it by cell height. And then for rotate, I'm going to be vector is heading. Which basically is the angle in radians. So heading is basically telling you where the vector is heading. That's pretty much it. So to get the rotation of each vector or where it's heading, then I'm going to just use INJ to get each vector. And then I'm going to use the heading method. And you can print this if he wants to see the values of it. So I'm going to scale the shape as well to twenty-five percent its original size because it's really big Eye how's mine at a 100 by a 100? And since my canvas is giving to be small, 500 by 500, it's pretty much better to scale it down to 25%. And then I'm going to draw the shapes. So the shape is called Arrow. I haven't actually created it. So I'm getting to create an ovary here using key. I'm going to call it. And then in here, I'm going to import it by using load shape. It's called Arrow dot SVG. And then I'm also going to disable Skype. You don't have to. I like to make it a habit of disabling the style of my SVGs just in case I want to change the color later. I don't get confused why it's not changing. So now since we disabled the styles, I can actually change the stroke weight to I basically Dustin all of those so you don't have to worry about following exactly. You can play around with the stroke weight and colors and all of that. And then I'm going to stop the looping in the draw function because you just want to draw the grid and show you how it looks. Ok, now I can draw the shape over here. It sees that it's an arrow, but it needs a position for the shape. I'm going to just do 00 for now and we'll see how to fix that later if you see any problems. So that's pretty much it. Before creating the grant, briefly, we initialized the positions of each vector and then we displayed it. So let's actually see how it looks like. Let's create a flow field out of the class. So this is our instance and just call it flow field. And then I'm going to initialize it here. So for instance, the flow field. And we're gonna give it the number of columns and rows. I'm going to just initialize this array here. So columns equals 20. And then for rows, and I'll shake and give it 20 since we have a square. And let me fix this. And now inside of the draw function, I'm going to just do flow field dot display. And it should work now. Ok, we don't need to fix any of the shapes. It looks good. Now let's look at how we can change the direction of these arrows. So for 00 it's moving to the right. And then also from one for X and 0 for y, it's going to move to the right as well because we're only moving it. Or it's kinda like at a speed of one to the right side. And then if I want it to look downward, I say y one. And you'll see that all of the arrows will actually move downward. And now if I want it to move diagonally at a 45 degree to the right and down. I'll just write one for X. And now it's moving at a 45 degree angle. And now if I wanted to go on the opposite direction, on the y-axis, I'll just do negative one. So it's basically like a moving any shape across the screen based on his speed. So if you said x plus one, then we know that it's going to move to the right and say y minus one, that is going upward. So if I want to also take this to the left, which is the opposite direction or the opposite of the default direction. It's negative one. And if I do this at 0, you'll see that it's going to go directly to the left. If we change this to x and y, we can see different rotations for each vector based on its position. So you can see as we're moving to the rate, the majority of them are looking to the right and then as we going downward, it's going down. And then diagonally, it's actually going diagonally because that's when the position of the x and y are actually equal or almost equal. And so they direct to a 45-degree angle. And if I do negative x, then we're actually reversing everything from the right side to the left side. And then the same thing for y. And we'll get a different rotation as well. So it'll go upward. So now that we understand this, let's actually used the noise function. That means before it was before. Do any of that, let me fix this translation issues. So as you can see, the whole canvas or the bigger canvas where we're displaying our flow field is at the zero-zero point in them. There is gaps over here. So I'm going to just move it to the right by 12.5 and then downwards 12.5. The reason why I'm doing this, because each arrow is actually a, a 100 pixels by a 100 pixels. And then scaling them by May 25% have of each of them 12.5, because 25% of a 100 is going to meet 25 pixels by 25 pixels for each arrow. And then half as God is 12.5. And I just want to move by half because I want to move each arrow to the center of the cell instead of at the top left corner of each cell. And I'm also going to fix this because now I'm drying at the 00 position of each. But since I'm moving the whole canvas to the right and down, I have to move each shape upward by half its width, to the left by half its width. So we can do that by using the shapes width. So if I do negative arrow dot width divided by two, so and moving to the left side by half of its width. And then I'm moving upward. I have never run this. It should look perfect. And so instead of using x and y, now Willie's noise functions for the angle and then I'm going to cosine and sine the positioning of the P vector. Because I'm going to just call this angle or theta, whatever you wanna call it. And I'm going to map the values. Noise, as he said before, noise. Whatever values you put inside noise, it will always produce a 0 or a value from 0 to one. And we want to map that from 0 to 10 to two pi for angles. In the previous example, we actually divided the values inside of the noise function by the scale, and then we multiplied the whole Noyce function by strength. The only difference here is that we're not going to multiply by his strengths, but we're just going to map the values produced by the noise function, which is from 0 to one, to evaluate from 0 to two pi and the char, the minimum and maximum values of angles in radians. So I'm going to just use the noise function like we did before. I'm going to just do x divided by noise scale. And then I'm going to map this value from 0 to one, which are the original values that comes out of the noise function. To 0 to two pi, which is a full circle. And then I'm going to initialize noise scale over here. I'm going to just make it 300. And now I'm going to use angle over here. So for x I'm going to use cosine angle. And then for y I'm going to use sine of the angle. And then if I run this right now, we are going to see a flowing movement. It's not that apparent because it's a one-dimensional noise function. So I'm going to introduce briefly the two-dimensional noise function. So the only thing that you're going to change is adds another arguments for why. And we're also going to divide it by the noise scale. When we run this, we'll find that the movement is more fluid because it's a two-dimensional array. And as you can see, everything is moving downward over here and then it starts to rotate based on the noise functions. So if you change the noise scale, so lets say make it 100, you'll see more rotations. And then the higher it is you'll see less rotations because as we saw in the previous example, when we talked about scaling noise or scaling noise wave. As the scale increases, the waves are actually getting smoother because we're zooming into one part or the left side of the wave. So the movement or the circle used to move slower rate is moving through the first chunk of the wave instead of moving screw more hills and lower parts of the wave. So a hundreds gang to produce more angles. And then the higher we go, it's going to be smoother and movements. So as you can see, the angles are actually smoother. And because we don't have annoy seed USE different values every time. So if you go back to 300, we can start seeing different angles in. If you put a purines on top of these, and then you follow the angle of each of these arrows. You'll find that circles are actually moving with the angle or to the direction of the arrows. This alone can create nice artworks. If you play around with the shape that you're using, you can create any SVG files or whatever program that can produce SVGs he can import into here. And play around with the wave that this creates. And also play around with the number of columns and rows. Because the higher the value for those, you're going to see the ways better because then you're not gonna see the shapes as much, but you're going to see more of the movements or a wave. So if you create a line, for instance, you're gonna see the wave better, the arrow that Daniel shoes when users in the nature of code examples is much easier to see the wave through because it, it's just a line. It's not an arrow that looks like this. You can create the area yourself or you can find it in the resources for the nature of code book. You can find all of the code into GetHub section. So you can study that also because I think his way of doing it or the process, although it's different, can produce other results. Because he also shows you how to make an agent or a robot, follows the arrows on top of it by looking up the value of the rotation and movements and making it follow that. Again, it's a little different. So if you have any questions, just let me know and maybe I can help you with that as well. 5. One agent: So for this chapter will talk more about how to move using the noise function instead of just looking at the rotation like we did before. Now for this time, we don't need a class for flow field, we just need a class for an agent that is going to move across this queen. We don't really need to see the rotation. The only thing that the agent needs in order to move is to understand its speed, decides that it needs to be, and what kind of rotation you will get based on the noise function. So let's begin by creating a new tab. And then inside here, I'll just write my new class which is called agents as well. Okay, the first thing that the agent needs is an x and y position and speeds and the size. Let's start by writing down the physician and then seeing how things are actually moving in them restart incorporating size and we'll see where we're going to use the speeds. So again, just start with x and y. So x and y is going to be used the same way that we used in the flow field. But this time we're going to use speed in order to move our agents around the campus. So I'm going to initialize x width divided by two because I don't want to use random. And then it moves out of the screen or it goes from one edge of them outwards because I'm not going to check the boundaries yet for the screen or ever actually because I like it when they go outside of the screen or fill the page with the design. And then I'm going to do y, x height divided by two. And I have my width and height AD 500 by 500. And then for speed, I'm going to give it a speed of, let's say one. Okay, now, this flow is moving and we're going to just use a point stroke weight. And then I'm going to draw my x and y to run it. And we can see agent class. Let's initialize it. And we don't need any parameters. I'm only gonna do everything inside of the class and then on display. And if I run this, we'll see the point in center. Great, now it's time to use the updates. In the update method, we'll need to move X and Y using cosine and sine like we did in the flow field example. So we actually initialize the P doctor basically said, give me a nu p vector at position x at cosine of angle y, sine of the angle. So this is basically the same thing here, however, we're moving. So I'll need to add the cosine. The position of extra to the previous position or the spread out point, then I'm going to do the same thing. Now we are going to need an angle. So I just created and the angle is going to function as we're doing the same thing that we did in the full field. X divided by y divided by scale. Not going to use one-dimensional, two-dimensional. And then we'll learn about the three-dimensional lattice. And then I'm multiplying it by. So I'll initialize those over here. We're going to make no scale at 300. Let say ten. Now this is not going to match because we still didn't add the update over here. So I'm going to, and if we're going to start with and now we can add the speed to it. This will increase the speed of light. So three, for instance, is going to be faster. And the faster it is given Muslim deaths because the smaller the speed disorder the movements because there is no space in between because you're moving only 1 at a time. When we have SP3. However, it's moving sweep pixels at a time, so it's more tricky. So let's do, for instance, and you'll see that it has more space. This is also you can use at this rate and increases v In this becomes hairstyle. So now we're going to just stick with one and see how it's actually moving. So as you can see, the Muslims is very smooth because we have a very high scale. If I decrease this 400, let's say we're gonna see more rotations because now it's moving through more higher points or more points in the wave. And if I increase this, let's say 50, you're going to see more rotations. So think about it as if it's giving you more, getting the rotation, more strength. So it has the upper hand sort of more angles and then we can add a color to it as well. So what's meant? The same thing. Maybe change it to three so you can see a little bit of a change size over here. And then I'll initialize, give it a stroke, color. And that's it. That's all you need to do in order to get all these amazing artwork that you see. In the next chapter, we'll see how we can create an array of agents. Move randomly through the screen for each one of the ligands. 6. Many agents: Now let's create our array of agents. And before I can do any of that, I want to add the color array so we can randomize the color as well. Okay, we'll need to change this to an array. And then over here, instead of initializing the agent itself, we're going to initialize the array and I'm going to just make a 100 for now. And then inside of a for loop that is less than the agents length. We're going to initialize our agents at agent i. So for each event is going to be or for each item inside of the array are going to happen. And then in here, I can use the loop for agent in each agents. So a foreach loop, because they don't need to use the index. So I'll just use for agents, agents. So this ensures that it'll look through the whole thing anymore. Right eye or the position over here. And we didn't change agents. And now every agent is initialized that width divided by two and height divided by two. And they all have same movement because we don't have a random speed or random size. Now if I run this, you'll see that they're all on top of each other. So they have the same speed and same size. So you won't see any changes over here. But let's first change the size. I'm going to randomize it from one to five. Now if I run this, you'll see that it's just much better because now the five is kind of dominating the movements. The other ones are either below or above, so you can't see them. You're less randomized speeds. So you can see it because now they have varying speed. And so some of them are moving faster. And you can see that maybe one of the smaller ones is moving faster. And so it was clear that this is smaller. So it's as if it's varying size or if it's the same one bearing interest, but it's not, it's multiples. Now let's randomize the colors so you can see them on top of each other on the same line. Before I start randomizing the axon acquisition, we are going to just randomized the position or the index that we're getting from this array. So I call this cause, I'm going to use the so called array. And once you get a random index, so it will be a random from the colors that went so whatever. So if I ever ads over here. It's going to be consistent and he won't need to change it in books. But this is going to complain because it's not integer. Indices have to integers. So I'm going to just cast this into an integer. And now if I run this, we'll see that there are multiple colors. So there are in fact multiple agents on top of each other. So now let's actually randomize the x and y position. So I wanted to be from any area from 0 to the width, from 0 to height. Now this should work in based on Illinois k_l and you're nice strain, this is going to look different. So let's change their noise scale. If we reduce this to ten, maybe even reduce the size a little bit to three. Again, to meet the speed instead of, instead of from one to negative three or even slower. So I will go negative 222 because I wanted to move in both directions and with just one direction for both the x and y and the speed is being used for both x and y. Okay? And you can see that it's much nicer, but it isn't. Vehicles are moving upward while others are moving downwards. And same goes for x and y. From left to right or from right to left, we can increase the number of agents right now. So let's make it 1000. And in the more agency have the nicer episode that actually I like to go to very small size. So mine is usually five to one or two. Is if you have very thin lines, ten, it looks nicer. And I'm going to even change the background because weight seems to be a little first sometimes. And colors. So have a sketchbook colour, there is a little page. It looks nice. And you can also add other colors. Maybe we can wait a year and because we chose to choose the indices from the collars that length. So whatever length you have here, meaning it won't ruin your callers are worn at declares glare. So there's making everything dynamic is much better, much nicer. Now the white adds a nice touch to the design. So I only need to do right now is just play with us, kill. One of my favorite scales isn't 1000, so I like to use 3 thousand because it's much smoother and then I like to add a rotation to that. So maybe let me get 30, a Kindle even higher to 50 and still look nice. It actually gives it a very abstract painting work that's even more rotation you add when the wave is very zoom, then wait, here. It's 3 thousand smoother rotations or bigger smoother rotations you're going to have. So if I do, let's say 200, you're going to see that they're all moving the same direction or over the scene side of the wave. But then they're rotating with a very high angle. And so they did the best work. We can also increase this to say. And because we didn't have no ISI and random seeds, it's going to change every time. But if you want, you can see it before you're even centralization. So yeah, it's right here. And just always start with a 0, just record year, whatever. Random sleep because of the colors. Because the only randomization right now that we have is because, and you'll see that we'll get the same thing. But now I also want to show you if I reverse this, others is going to look. So if I have miscalled is smaller, then the miss Frank. So let's say one to 2 thousand over here. And your strength in 300 nanoscale and going to have more rotations and less of a smooth movement. So even if you look at some probes over here, there is a lot of noisy movement, kind of similarity random that they stick to their position, which is much nicer than it's OK, go down 2000 million. You can see their rotation. This is actually one of my favorite words over here. It's much nicer than this one because it gives you variation in shapes as well. In the next chapter, we'll talk a little bit about how you can add a third dimension to your announcement. 7. Three dimensional noise: Okay, so for three-dimensional noise, you only need to add one more argument to the noise function. So we already have x and y, and the third dimension is naturally going to be easy. This is just to conventional naming for three-dimensional, which is x, y, and z. But feel free to call it whatever you think makes more sense to your work. So I'll just add Z over here and then I'll initialize it with a random value. And I'm gonna make it from 2.4. Then I'll end over here. And santo garners function and incremented down here. Now incremented by 0.1. And that's pretty much it for the third dimension. It's very simple. And the reason why I'm not dividing it by the noise scale because I want it to be influenced or you want the rotation to be influenced by more than just x and y. Because if I divide it by the NuScale is not going to make that much of a difference, but I want z to drive the rotation a little bit more. And before I run this, I just want to preface that the majority of the work that I do, or actually all of the work that I've done before is just two-dimensional and noise. So I've never really worked with three-dimensional noise as in outputted artwork that I share because I'm still experimenting with what looks good. However, I think introducing it here is very important. Although I don't have examples with the third dimension. I think it's integral to understanding the noise function. Okay? And I'm going to run it. And then we'll start to do a few adjustments to see what changes. Now you'll see that the rotation is very noisy because it's rotating way more than it used to. But we can fix this by either changing the random value, the initial random value for z over here, or we can reduce, which is what I found most effective is to decrement the amount that we are incrementing Z by. So if I do 0.01, it's going to give me less rotation than before. So it is still very rotated, but as you can see, it's not the same rotation as before. So it's moving a little bit and then its rotating 360 degrees and moving again in a very flowing movements. So it is still gives you a very nice result, but it doesn't look as nice with colors. And also it doesn't look as nice with opaque colors. So I'm going to first change this 250 just to see what happens. And immediately it's much better because you start seeing the movement a little bit better. But I still don't like the results with colors. So I'm getting to create a different Clara array. I'm going to just make this way. Now this doesn't look as nice. So I'm going to change this to 0.001, this to reduce the amount of rotation that happens. So it's less frequent than before. And I can see that it looks more like hair movements or smoke movement. And it looks much nicer even with less capacity, it will look nicer, but you'll have to wait for it a little bit more because it's going to have to build up the color. That's why I don't necessarily work with a third dimension, because I like to work with colors a lot. Although this looks very interesting, it doesn't look as intriguing as a wanted to be big because my work tends to be very colorful. But if you're someone who works with black and white lot, then this would look perfect even in black and white, or do a tone colors because it'll give you a multidimensional design. And you can also play around with the noise kill or rehear. So let's make it 3 thousand. You'll get more circles in the design. And then if I reduce this to ten, we can see that there is less rotation altogether. But then the z influencing THE rotation, so it's still rotating but on a much smoother path. And it's also distorting, does shape or distorting the actual flow of the two-dimensional in ways. And sometimes that can give a very nice results. It's a very simple formula. And just by changing the nice functions from a two-dimensional noise function to a three-dimensional nice function you can get with a multitude of different results. You'll have to play around with it, see what works best for you. Play around with the coloring. And we're also going to talk about cloning techniques and using shapes other than reigns in order to make your design. But before we can do any of that in the next chapter, I'm going to introduce how to make this design static. 8. Static noise: Working with static design is more fun to me than working with a dynamic moving design. Mainly because I like to see the results as soon as I run the program rather than wait for the animation to end. And making this design static is very simple and the results are completely different. You're going to the same paths that the animation goes through. But it's going to look more vector. And it will look as if you use BCA curves in Adobe Illustrator and did this design by hand. And then you'll be able to get more variations because you can just run the program and save every page that you get. Okay, so we're going to start from where we left off before, but I'm going to remove everything that we did for the three dimensional noise. Because again, I usually work with two dimensional noise. And then I'm going to remove this as well. So we don't need it to be transparent and then we weren't leaving the size as well. Okay, so for us to create this static design or create vectors are busy curves out of the movement. We're going to use the begin shape, an entry, and use the current vertex inside of it. And we're going to use a for loop in here, because now we're not just moving throughout, we have to think about the movement as a for loop. So before it was moving because he was in the draw function and the draw function is basically a wild loop that never ends. But I want to have more control over my design. So I'm going to use a for loop with a fixed length. So I'm going to create length in here. I'm going to make it an integer. And we'll start with ten. Then I'm going to leave the stroke. And the coloring same speed x and y are the same. But instead of drawing a planes, I'm going to use begin shape. Shape can draw using vertices inside. And I'm going to use the for loop less than the length increments. Now if I draw the vertex in here and then I go in here in display an update the agents, what I'm trying to do over here, it's going to be very broken because I want to draw every vertex at the mean value from here. So I'm going to just draw it inside of the update function. And then I'm going to call the update function inside of my for loop. So basically inside of my for loop, every time I'm getting a new angle and then I'm changing the position. So it was the same thing that we did over here when I called the update methods. Because inside of the draw function we were updating. So basically what we're calling the noise function over and over again. And then we're calling x and y, or we're incrementing x and y every time by their values are by these values. So now instead, I'm going to put all of this inside of the for loop because we don't want to draw loop anymore or the draw function that loops forever. And I'm going to just use curved vertex is I wanted to curve ends again to put it at x, n, y. And then I'm going to call the update function inside of my for loop. So now we recreated what we were doing inside of the jaw function. But inside of them were controlled loop. And then before we run it, we have to be sure that this is not looping because we don't want to loops to go on forever. And then I'm going to remove the updates function from here. Great. Now because we did the colour of white sworn for this three-dimensional environment, your material go back to my colors. Okay, we're already seeing something, but because our length for the for loop is very small and he started to attend, we are seeing very small lines. So if I increase this to, let's say 30, now we're starting to see the design a lot better. Also, I'm going to have to remove the film, so I'm going to just do still. Now we're not getting fill anymore. It looks much nicer. We can also increase the speeds because now if I increase the speed, it's only going to make my length even longer because some, one vertex to another, there is a speed of slice pixels instead of just two. So now if I run this, you're going to see more fluid movement. So you have to kind of balance between the speeds and your length of each of these paths. The less speed is going to give you a shorter length. But then you can increase it from here and you'll get similar results. Also, what's nice about static designs is that you can look at the pads of your noise function immediately. So if you want to test something, maybe you want to make it static and then you start and you want the visuals, the moving design, then you can MiniTest it using this and then go ahead with whatever values you from Newton re-scale angry string. And if I do the opposite like we did before, so I'll do a 100 over here and then maybe a thousand and over here, you're going to see design that looks more like doodles or the scratches that data on a piece of paper it using colors. In if you want to increase the number of agents, you can do that here as well. And it'll give you a denser design. But one of my favorite looks about this design is if we go back to 300 and then this one, and then reduce the number of agents go back 2 thousand, just so you can see it better. And then instead of stroke, we actually make it fill and we make no stroke here. And that's when things start to become very, very interesting to me. Now the length is very, very high, especially for fills. The higher the length, the chunkier the fill is going to look. If you've ever worked with Adobe Illustrator and you worked with the Bessie or the pen Curve tool in any other program as well. It works the same. If you have very strong rotations in your curves, then you'll have felt that seals the gaps from the first to the last point. So if you want to reduce this, you can play around with the length. So you'll have less rotation for each hats or each group of vertices that are connected to each other. But then you're going to have to see the same look on the same design using those curves. So let's go up. 3030 can produce much nicer results. Now I can also increase the speed. I can also increase the number of agents. Now it looks more like an illustration of plans, especially if you use colors that mimic plans a little bit more. So all the greens. And then maybe we can reduce this, even learn. So we have less rotation. Let's go over here and we're going to increase the nice Celtic 3 thousand, so we have less rotations as well. And then I'm going to increase now rotation a little bit, or the strength of their noise values or we can play around with it. We can go down with his feet. You can also go from one to two. We don't need to go on directions, just one direction. It will still produce very nice results. You can go up to 1000, and that's literally what I do every time. I want to see a design that looks good. I tried a desk blotter values together until something clicks or until something happens. That's why I also like to work with noise seed, the random seed. I think this is one of the reasons why we're not getting different balance. Yeah. Now we're getting a lot of different variations. We can also increase this to a 100 indicates there so you can get them more rotation design but using this vector style. And now you'll get this design, which also looks very, very interesting. I also want to introduce in the next chapter how to play around with shapes in this direct design to come up with designs of your ellen based on the shapes that you're using in following the noise function paths. 9. Different brushes: I talked about creating custom shapes in my previous course. Back to the basics. We can do that here to paint these fluid movements with some interesting shapes. This is very similar to creating custom Photoshop or procreate pressures if you've ever done so, each brush can give a distinct texture producing variant results instead of you drawing, however the computer is, I'll create one brush with you and after I'll show you some of my designs with other brushes and walk you briefly through the brushes components. Okay, starting from where we left off in the previous chapter or in the previous lesson, we'll only need to change the shape at the moment we are drawing using the current vertex. Because we change to our dynamic design into a static design. And we are going to continue on that. The only difference is that we are going to create a brush function. So let's create that over here. I'm going to call it a brush. And it's going to be a method inside of our class or agent class. And for my brush, I'm going to need an exposition and the y position and also a count. The count isn't necessarily needed here, but I like to add it to add that randomness effect into the brush. So let's start with an x and y first. So I'll do float position x, I'll just call it. And the other one is going to be called position. Why? Because they don't want to confuse myself with the x and y inside of my class every here. So I just changed it up. And now in here we're going to create our brush. So he said we wanted to create a random circles brush. So for a random circles brush, we're going to need a few circles. So let's start by actually creating the circle and then will change that into a more dynamic approach. So we'll first start with, let's say drying three circles. And then I'm going to put the first one at random position from five to ten, and then another random position for the Y from five to ten. And then I'm going to give it a random size because circle takes three arguments as opposed to the ellipse which takes four. Because it's a circle, the width and height are the same. So it's only going to be a third argument instead of a third, fourth argument for width and height. So here I'm going to just do one ohm five, or from one to five. So I'll get a random size from one to five, okay, and I'll do the same thing for all of these. The reason why I said from five to ten is because I want to contain this shape into one square because a brush usually has its own container. And in order to do that, I'm going to have to push a matrix and then translate this whole box of shapes. So the whole brush using the position x and position y. So I'm going to just do translate and then the position x and position y. And because I All, I want the translation to only happen for each fresh separately, I'm going to have to push a matrix for each one of them. So push matrix and pop matrix. So that produces a new canvas for us and then it'll translate that to wherever I want and inside of it. Or that whole brush is going to be three circles of random positioning. And they will start from the position x and position y. So five to ten is actually five pixels from position x and ten pixels from position x. And the same goes for y as well. Okay? And now let's call the brush over here instead of the current vertex. And we'll do x and y, like we did with the current vertex. I'm going to increase the size a little bit over here because I don't think are going to see it clearly. And I'm going to decrease the length to only one because I want to happen in here. And then I'll remove the begin shape and trade because we're not drawing with vertices anymore. And I also removed the no Stroke and I had a stroke of black. And then in here I want to use, let's say two agents because I really want to see it clearly. Okay? So this is drying three circles on top of each other and this one as well. I want to change the randomness, so I'll do 15 to 20 over here, and then 22, let's say 30 over here. Because I want to change, change it on the x-axis a little bit so we can see it. So we can see that there are three circles. Okay? So here are three circles and this is also three circles. And as we run it, we'll get random locations for the x-axis and the y-axis. Now instead of drawing the three circles like this, I'm going to change it into a for-loop. So I'll do for integer i equals 0 to normal for-loop and i is less than, let's say three. And we will increment it, and then we'll have just one circle. So now we reduced our code by two lines to unnecessary lines because this way I got the three circles and they all have randomized location for x and y. Okay, and if we run this, now, we are going to get similar results to the previous. The only difference here is that before we had a different range for random. Here we have the same range. So maybe you can make THE range a little bit bigger so you get a lot more variation and the positioning. So if I do 15 to 20 for the x axis over here, or 5-20 actually. So I'm just increasing the range and you'll see the positioning has a little bit more variation. So I'll just bring it back to ten. And here is where the counts comes in or a the count parameter, because I want this to not only be three, I want it to be a random value based on what I give it over here. So I'm going to just do integer count. And I'm going to put that as the length for the array. And in here I'm going to say random value from one to five. So I'll either have. One circle, 23 up to five, and I'm rounding it. So it's actually not up to five, it's to four. If you want it to be up to five, then go up to six. But I'll stick with five. And then you have to cast it into an integer. Because here we have an integer inside of the for loop because counting is always non decimal when it comes to stuff like this. So I can draw half circle, for instance, three circles on half, so it has to be in. And now if I run it, I will either get 123 or four circles on top of each other. So if I go over here and do 100, I'll get a lot more. And then I can increase the length again to, let's say ten. And we can remove the stroke so we can see the design better. And I'm also going to increase the speed because I want more gaps in between the circles so he can get the effect of that brush. So it's increased this to 20 and increase the noise strength to a thousand because I want that flowing movement and reduce this to ten. And then I'll even make this 1000 or even 4 thousand. Now we are getting that random circles brush into the design. We can also reduce the size right now because I haven't very big from before. So from one to five, I would say is really good. Random just going to copy and paste a different way to color this, because I want to see it a little bit better because the effect doesn't always, or the effects of other brushes doesn't always look nice when it's the same way or coloring it. So you have to sometimes just changed the way you are coloring your designs in order to see the effects of what you're creating. Sometimes what you're creating actually looks cool if maybe you use just two colors. But here, I'm actually going to call this palette for. Instead of changing it three times here, I'm just can change the array name. So what I'm doing here is mapping the sine of the angle over here from negative one to one to 0 to the pallets dot length. So I want to map the values of the sine angle. So whatever his outcome from the sine angle function, I want it to be mapped to these colors or the indices of these colors. And indices goes from 0 to one less than the palette dot length. So I'm constraining it over here. Just to avoid any misleading values are any errors. So I'm going to just say again, index is going to equal, constrain the index from 0 to palette dot length minus one. So we'll never get array out of bound exception. And then I'm going to use that for colors. So instead of coloring up here using the random, which I'm going to actually Just change it for later. And yeah, instead of doing it randomly over here, I'm going to do it inside of the update function. And I'm going to call the palette with the index that we just created. And by the way, all of the code for the different brushes and the coloring technique will be linked in the resources section of this course. So let's run this and see what happens. Okay, I have to change the fill from here to over here because that's where we're changing the color before. We're not really doing anything to the color. And now it should work great. So now you can see it kind of like oil pastel colors if you've ever worked with those, it has a very waxy texture and this reminds me of that. So you can increase the speeds, let's say 15. And you can play around with it. You can see the texture is more grainy this way because as I said before, The more speed you have, the more space in between each shape one another. And again, playing with the noise kale and noise strengths can produce a lot of different results. So if I do a 100 over here, you're going to see a very different design. Let's reduce this to even six. I'm going to just remove the white because they don't like it. Yeah, that's pretty much what you need to know about creating brushes. All you need to do is create your brush over here, and then you can also create it out here into its own function. Its fine, however, you need to call it in here. And if you are doing the coloring in here, then just remember to do the fill or stroke over here, but this is not necessary. The only necessary thing is too dry it inside of the update function after your angle and x and y because then you're going to call the update function inside of your for loop, inside of your display function method inside of your agent class. Now let's go back to the other shapes. Now that you saw how to use your custom brushes, here are some examples of other breath is a created and the results I got. It's fun to play with shadows sometimes to give depth to your work. In these examples are used the brush made of a view thick clients then copied the same brush with some offset, creating a shadow effect. You only need to color the top shape with your colors array as your bottom one should have one dark hue to create that shadow effect. Very simple yet very interesting. The trick with this one though, is to increase the step size and decrease the number of agents so it's not too crowded. Here's how the function looks. I wanted to also create a thin strokes brush to mimic those frayed square paintbrushes. They annoy me an analogue work. But for computer generated images, they were quite nice. They are the same as the random circles brush, but with lines instead, take a look at the function and tried to recreate it. Those are just a few that I came up with as I was planning this course. It's time to create yours and come up with something unique to you. 10. Coloring techniques: One algorithm can produce so many unique results by changing your coloring techniques other than randomly selecting colors from an array or mapping colors to position and rotation, you can grab colors from an interesting image by getting the colors of each pixel at the same position as your shapes, you simply import the image, resize it to fit your canvas preferably in the same ratio as your canvas. Feel free to be unconventional and stretch it out. Then use the getMethod in the PMF class to grab your color of the underlying pixel. These examples show some of my other generative art as input. One is generating colors during agents initialization and the other is grabbing the colors as it moves, producing varying results. Another technique that I picked up from Taylor Hobbes posts on his site is coloring based on a few scattered colors on the screen. It's a long process, but the gist is scattered and displayed objects with some randomly stored colors. Then checking the distance between your moving agents and those objects, the shortest distance determines the color of your moving agent. Now you can read more in Tyler hubs website as his technique has a bit more steps to it. Here's one example where I tracked the distance constantly as the agents move, producing a Voronoi texture. You can also grab colors from rows of colors on the screen horizontally or vertically using the x or y property. It's similar to mapping the position, but this approach will keep the colors relatively unmatched, creating a gradient look. However, the longer this program runs, the more merged the colors will be and the gradient effect will dissipate. You can achieve this by using this equation, for example, for your palettes indices as this gives the remainder of dividing x by r pallets length counting from 0 to one less than your palettes array length when rounded. Since x is moving with very small increments, this will give you very thin columns. To salvage that you can divide x by r desired columns width. I chose to give each color column by dividing x by the width of the canvas divided by my pallets length. This can produce someone wanted values. So a constraint method is advice to keep your index values constraint between 0 and the last index of your color array. These are some of the resulting artworks from this coloring technique. The next coloring method is quite interesting as it yields cloud-like textures, giving more depth to your art. You can get the slope by using this formula, which is very similar to the previous one year. Here, we're using the angle of the movement instead of the x and y position. Here are the results. Last but not least, for playing with color is using color interpolation. I talked about this a bit more in detail in my back to the basics course in the color section, feel free to check that to get more info. The justice that blurb color function creates an array of colors using only two colors. For my design, I created this gradient function to create a new palette by interpolating between each subsequent color in my original array. This allows for a smoother color transition as the agents move, you can use any of the previous techniques to use this new palette. I use this formula for my index to create an oscillating color transition by updating my sine function angle by one in the update method and dividing it by a 100 to scale it up so there is more time for each color to appear. It's not my favorite technique with this program, but play around with it. You may find that a value to you. There's definitely a lot more you can do in terms of coloring your designs. But I hope these techniques are enough to expand your horizons and get your creative juices flowing. I'm excited to see what you come up with. 11. Saving images: Now we have created, Oliver designs, static and dynamic. And it's time to save. I talked about saving your designs or some of the ways that he can save your designs in my other courses. But I'm going to repeat it over here. Because it also want to mention when to save an animation, when to save a single still image or went to save a high-quality vector image. The first thing that I usually do is save still images, and I sometimes do it in my test size. So like 500 by 500, like this one right now. Just to see how things look. Mainly because right now we can see that the colors are really bright, even though the colors that I chose are bit muted than these. But for some reason the view over here shows you very, very bright colors. But once you save it, the colors are going to be a little muted. Maybe you want to change them. You actually like those bright colors, so you'll have to brighten them up and do it again. So testing using a size that is small, like this one is a good way to go. So if you want to save just a PNG, you can do it this way. So let's open a new tab. I'll just call it save. And now inside it I want to save it when the keys pressed, especially with this work because I have to wait for it to run and see the results that I like. And then I want to save it. I'll have to wait to a certain point and click a button. So you can either click the mouse if you like. You can choose mousePressed or mouseClicked as the function that you want to look for as an input. But what I like or what I prefer is to use key pressed. The reason for this is because if I want to save the same image as a vector image, and still that is a Raster image, then it's much easier for me to use keyPressed because then I'll look for the letter s If I want to save it as a PNG, but then I'll ask for the letter P to save it as a PDF, which is the vector format. Here we're only going to save it as a raster image, as a PNG. So we don't have to think much about it, but I still like to keep it a habit of just put it inside of a keypress function. So I'm going to just do key pressed and pressed is actually capital, okay? And they'll just use if and then the keyword key. So key looks for any letter or any character that you push on keyboard. And for characters, you have to do a single quote. And I'm saying, OK, if the key is the key that is pressed, then do this. So I'm going to save my PNG, but I want to save it first inside of an output file. I like to keep my work organized. And then plus times TAM and plus dot PNG. The reason why I use timestamp over here as because that's what I learned from generative design, the book. And I've been doing it ever since because it makes the most sense in saving your files and it assures that you don't overwrite your older files because there's no date and time like others. So you can just save your files without worrying about naming them. And you also know when you actually created them. So that's also a plus. Now in order to create the timestamp function, I just write string because I'm returning a string because that's what I'm adding over here, concatenating with the other two strings. And before we actually start doing this, I want to show you that I still don't have any files saved. So this is my folder. I have my agent file, which is my even tap over here. Many agents, which is the minivans tap over here, which is the name of the main file. And then my saved dot p, which is my safe tap over here. Okay, now we can continue on creating the timestamp functions. So I will just do timestamp. And inside of it, I'm going to get an instance of the calendar, which is a class from the Java utility class. So let's actually import it first. So it doesn't complain. So I'm going to just import something called java.util for you to Lee and then calendar. So now we have the calendar class. And I can say from the calendar class, give me an instance called now, and you don't create it by saying new calendar. You actually say calendar. So you have to call the class again and then dot get instance. And now we can format it. So I'm going to just return string dot format so you can format the string that we get from here. Inside a format. You format, or you write your format in here using a string. And then in here you write your variable over here. So here we'll write the format string. And the format string is going to be the percent sign and one and then dollar signs. So this is directing to this basically. So we are saying take the value in here and then get me the year. So the year is T y and this will get me a urine two digits. And then I'll do the same thing. So I'll copy this part because it's targeting this argument over here, which is the first argument inside of the format, because he can add even more arguments in here. So this is going to be the first argument. This is the second argument for this to format it, but we only have one. So I'll just do this again. And then this time I want the month, and then I'll do it again and this time I won the day and then I'll do an underscore. So I get the Year, two digits of the year, two digits of the month, and then two digits of the day. And then I want an underscore and then the time. So if you save multiple images in the same day, it's going to have different times using the seconds as well. So if he even save in the same minute, it's going to still be different and won't overwrite your old one. So we have to again includes this and then the hour. And this will give me the two digits of the hour and ten minutes and then seconds. So now when we say that we're going to see two digits of each year, month and day, and then our minutes and seconds, and our minutes and seconds aren't going to be capital. You can find this or other formats in the Java documentation. So if you say string formats, it, you'll get all of this and how you can format your Spanx, and that's pretty much it. So now if I run this again, so I have to save it and run it. Now, I'll let it run a little bit and then I'll hit the S key while this is activated. So if I ever go back here and I want to save it, it won't save, it will write S over here. So we have to make sure that this is activated. Once you run it actually, it's just automatically activated so you can just press the ascii. So I'm going to press the ascii and now we're gonna go back to our folder. And we can see the output folder right now, if the output folders was already created, that it'll just save it inside of it. We can see the image in here, and the image has the name that we formatted. So it has 20. So 20-20 than October 18th and underscore 1705 o'clock in 26 minutes and then 24 seconds. So now even if I go back and save another version of this, I'll get the other one. The only difference between those two is that this is in at this was created at five o'clock and 26 minutes. And this was created at five o'clock and 27 minutes and nine seconds of your accounting. That's the easiest way to see even image. But what if you want a high-quality image that you want to share? So this I only create Whenever I test my files or test my images. I sometimes even test with the resolution that I needs because maybe later on actually liked the results that I got from those tests that I wanna use. So I like to change or I like to code and 500 by 500. And once I establish the design that I like, I just take it up to 1920, by 1920. And it'll actually be cut off from the screen. But you can see the design clearly. The lines are a little bit SAN or I don't have as many agencies I want. So I can just go back and enhance it. And even just seeing a part of the screen is not going to ruin the design so much for you because it's still very random. Even the noise function is producing random values. So it's not going to be the same every time. If you want it to be the same, you can definitely use the noisy and random seed. What you do is do float seeds and then long random seed. Names you want to call them. And then in here I'm going to say, actually I'm going to just do it over here. And I'm going to make it an integer instead. You don't need a float. And then in here I'm going to do random seed. And it's going to equal random value from the seeds that we get. So this is the maximum value that we were going to use. And then this is going to complain because it says type mismatch because random is going to produce a float value when it needs to be long because random seat as long. So I'm going to just cast it into a long. And the reason why I'm using the long datatype is because the noisy doesn't accept a float except so long. So I'm going to just use those here. Random seed and I'm going to use the same thing. You can create another one for random seat, but I want to use it over here and then I'm going to print the random seed. So whenever you find a design that you like and you want to go back to it. You can save this seat over here. So now I printed the seed sown inside of noise seed is actually 974, and inside the random seed it's 974 as well. So if you want to repeat this design, maybe you want to save it at a bigger scale for someone who requested it, you can go back to the seeds and you can save the seeds into your file name. Okay, I just wanted to include that into saving the file because it's kind of part of how I saved my file sometimes. Now let's save an animation instead. So let's say I want to have that animation that is happening. So I'm gonna go back to 500 by 500 and actually show it so you can see the designs better. So let's say I want to save the animation. Now if I want to save a frame, I can just hit S anytime and it'll save it. But if I want to save the animation, I'm going to do it down here. So after the draw function, and of course the draw function has to loop because I mean it's an animation. And then I'm going to do say frame. So it's the same as safe. But here, safe frame basically saves every frame that happened in your design. And it'll add numbers from one up to whatever frame that you stop at. So let's say I want afford digits, file name because usually I would go up to the thousands frames. So up to 2 thousand, sometimes even more just to get the time that I want. And then got PNG. So that's all you need to do in order to save the animation. I also like to give it a different output, especially if I have an original outputs so or folder, output folder, I mean, so output two, I'm going to call it because I already have an output and then it'll say ventilation. And now if I run this and go to my outputs. Two, I'll see the frames saving. So we're up to a 100. And you can see that the animation ism is much slower inherit because it's saving each frame, so it's taking its time while saving it. And now let's say I want to stop here and owner to make these and animation, I'll have to go to processing's menu. It's not being captured in the screen over here, but I'm going to show you exactly where you can find them. It's in the Tools menu as called Movie Maker. So if you click on movie maker, became just drag a folder with image files into the field below. So I'm gonna just drag the folder instead of browsing. And now it has the path. And it's by default 60 frames per second because this is running on 60 frames per second, but it can change that. So if I wanted to be a little bit choppy, can do 12th frame rates. I've done animations with a frame rate of one per second to make it kind of like a clock moving. And then I want the compression to be an animation. You can make it a jpeg sequence or PNG sequence, but I'm going to just do an animation and same size as the original. So it's not going to look at the width and height. Don't worry about that. If you remove this, it's going to to ask you to change. But if we said same size as original, it's going to give us 500 by 500 and for this one. And then if you want to drag a sound file into the movie that you're creating or the animation. And you can just drag it to here. And now I can just say create the movie and it'll ask me where to save it. So I'm going to just save it inside of the same folder. I'll just save it up here. So now it's done creating the movie over here. The only problem I found lately with this one, with the newer Mac versions is that it's not going to play in quick time. So what I do is just go to any software that changes any movie file into an mp4 and interest convert that. So yeah, that's pretty much how you create an animation. And now let's talk about saving a PDF or a vector formats. Saving a PDF for saving a vector format produces very, very high-quality images because he can then convert your PDF files into PNG images. And that will be a much higher quality than just saving it straight away. And without also doing all the changes when you change the size of your Canvas. So basically, if I want to save this as 500 by 500 is not going to save it as 500 by 500 because it's going to be a very much high-quality image because it saved it as a vector format instead of a raster image. So if I want to save it, I'm just going to copy and paste everything that we created over here. So I don't have to create the time stamp again. And I'm going to create a new tab and just call it save. And then I'll do the same thing over here. I have to also. The calendar. Ok, so now everything is the same. And if I run this again, I can easily save this and it'll save. So now my output over here and you can see what the image is very small. But since this is a static image, I can easily do a PDF. So in order to do a PDF, or I save a PDF file, I'm just going to do the same thing that I did over here. But this time I'm going to do if key is P. So if it's Pete and I want to save it as a PDF and it's not going to be this is going to be a begin record. And record. So I'll begin the recording here. And then when I hit that key, I want it to end required. And then begin accord. It requires more arguments and record doesn't require any arguments, so I'll have to just do PDF as the formats and then I'll do what I did over here. So I'll just copy and paste this part. And then I'll do PDF instead here instead of PNG. So it's basically the same thing. I wanted to be inside of my output folder. And the timestamp function is over here as well. But now, if I want to save this, it's not going to save my image. So let's say p and then I write E. First of all, it's not gonna save because we forgot to import the PDF library showed a PDF library is basically a processing libraries import from processing dot PDF. And then I want everything. And then if I run this again, so I just do p and then I'll do e. And now this is my PDF. So my PDF is an empty canvas. It didn't really do anything because it began recording. But then there is nothing in here to record it because it doesn't look for this over here. It has to know what's what's being recorded and that has to be encompassed in between the begin record and the record. But there's nothing really sandwiched in between them. So I'm just going to call the setup function because I require everything over here, because I need the background color. I need the number of agents or the initialization of the agents, and then I need the movement over here. So I'll just do setup and then draw. And now if I run this again and then I click the PI letter, and then you'll see that the pdf is created, but it's not finished because we didn't really end the recording. So if I go again, activate this and then hit the E, you'll see this changing into the design. And then you can see that it's a very high-quality image. So you can convert this into a PNG. There are a lot of platforms where you can do that. I usually do it inside of my Mac because I credit an action where I can convert this into a PNG directly in here. And then it saves it inside of a folder that I asked it to save inside of my actions. And it saves it as a PNG. That's a whole other story, but changing it or converting this into a P&G isn't really a hard task. And you can find a lot of platforms that doing. So, yeah, that's pretty much how you save a vector format. And if you want to open this as a vector, you can just click or right-click and then open with Adobe Illustrator. And it'll open it for you and show you how to open and manipulate the work in my other course. So you can go and track that in my Intro to January of art, where you can create a Grids and there you can learn how to open this into Illustrator and edit it. There. 12. Inspiration and more info: No matter how many examples and give you, I'm just one person with one brain. So for inspiration on what you can do with information from this course, visit or cause Open processing page. He has a ton of incredible work with noise. One of my absolute favorites is this clock one. He uses the noise function to destroy his image. It looks very complicated, but the code is fairly clear and straightforward. This artist uses p5 js, which is equivalent to processing in JavaScript form. It's very easy to decipher as they both use the same methods. But if you get stuck at any point, feel free to ask me in the discussion section or check both of the languages documentation for some answers. Now I keep going back to Tyler Hobbes work as He never cease to amaze me. He has an article and working with noise and flow fields that has some valuable information and interesting techniques of waste and distort the agents movements. The way he is, is the flow field is different from the way I use it. If you visit the nature of code website by Daniel shipment, which is another great reference for working with flow fields. You can understand better how Tyler Hobbes uses flow fields. The concept here in this course, in there, and the references is similar, but the process is different. If you find more references, please share them with your coursemates. In the notes of this video or in the discussion section, I'm always looking for some new inspiration and challenges. Also, feel free to share your process with everyone in the discussion section or in your projects notes. It's nice to get and give constructive feedback. Let's help each other progress.