Placeholder Image

Subtitles section Play video

  • (train whistle)

  • - Hello, and welcome to a holiday coding challenge.

  • This coding challenge is a fundraiser

  • for Support P5 this Giving Season.

  • The Processing Foundation is the foundation

  • that maintains the open source software projects Processing,

  • p5 JS, Python Mode for Processing,

  • Processing for the Raspberry Pi, and Processing for Android.

  • And, if you use any of those tools

  • in your professional life, as a student, as a teacher,

  • and you have the means and can donate, please do.

  • There's a link in this video's description

  • for how to donate.

  • Also, you can donate directly on YouTube.

  • Right here, somewhere over there, I think,

  • is where you can donate on YouTube.

  • All of the information about Support P5 is on this post.

  • There are wonderful artworks that you can get

  • as giveaways from Maya Man, from Kate Hollenbach,

  • from The Coding Train itself.

  • That's me.

  • And Cy, The Coding Train community manager, designed a zine.

  • Saskia Freeke and more, so please donate.

  • The giveaways are available through this webpage.

  • And, of course, we'll gladly accept your donation

  • through the donate link right here on this page itself.

  • Thank you to Violet, who suggested this idea

  • as the holiday coding challenge.

  • This is a kaleidoscope painter that I found online

  • on this website, permadi.com.

  • Incidentally, this website has a lot

  • of wonderful tutorials and other information.

  • Go check it out.

  • But, we were thinking,

  • "Could this be used to create a snowflake?

  • "Could I make something like this where you could paint

  • "in p5 and make a snowflake pattern

  • "with six fold symmetry because we all know

  • "that snowflakes have six fold symmetry."

  • Which would give it some symmetry

  • and then rotate it also around six times,

  • and I think I'm pretty sure that's what that is happening

  • in that animation that I showed at the beginning.

  • So, this should be, hopefully, pretty beginner friendly.

  • If you're new to coding, I'm gonna do this

  • right here in the p5 web editor.

  • And, if you're using the p5 web editor,

  • that's because the Processing Foundation

  • maintains the p5 web editor.

  • It's a project created by Cassie Tarakajian,

  • and your donations are helping to support the web editor,

  • the p5 library, and more throughout 2020

  • as we go into this new year, new decade.

  • So, first, let's begin by just creating a program where,

  • when I click the mouse, I draw something.

  • And, this is actually quite easy to do because,

  • in the draw loop itself p5 has set up,

  • which will create a canvas, you can see it right there.

  • That's 400 by 400 pixels.

  • The draw function loops over and over again

  • and is always drawing a black background.

  • Black because of the number zero in the background function.

  • So, if I say stroke, which sets a stroke color,

  • and I say line between mouse X, mouse Y, those are

  • the coordinates where your mouse is actually in the sketch.

  • And, I wanna draw a line from there

  • to where I previously was, where the mouse previously was.

  • So, I could use some kind of variable

  • to keep track of the previous mouse

  • and know the current mouse and update it.

  • But, guess what.

  • (dings)

  • P5 has that built in for you, and I can say P mouse X

  • for previous mouse X, and P mouse Y for previous mouse Y.

  • So, if I run this again.

  • (laughs)

  • No!

  • What have I done wrong?

  • Oh, I know what!

  • I've forgotten everything that I ever learned

  • in the last 20 years.

  • (laughs)

  • Look, there's the little line.

  • Do you see it?

  • There it is.

  • I'm drawing the background over and over again in draw.

  • (sighs)

  • Classic.

  • So, I've got to move this into setup

  • because I only wanna draw the background once so that,

  • now, the line always appears, so there I am drawing.

  • So, some things I could do.

  • I can say, "If mouse is pressed,

  • "I only wanna draw that line if I am pressing the mouse."

  • That's going to allow me to do things like this.

  • And then, we can start to think about the thickness

  • of the line, so there's a lot of different ways I could.

  • Maybe I'll have that be pro line noise or something,

  • but I'm just gonna make it a little thicker right now.

  • Stroke weight, four.

  • Oh, let me auto refresh here.

  • So, that's thicker.

  • Let's do this, let's do this.

  • The speed of how I move the mouse is

  • how thick the line will be, so slower will be thicker.

  • Faster will be thinner.

  • I think that makes sense.

  • I think that's probably

  • what that kaleidoscope picture I showed does.

  • I can find the distance

  • between the current mouse and the previous mouse.

  • That's, you know, basically a value

  • that indicates to me the speed.

  • How far have I gone on each cycle through draw?

  • And then, I can say, "The stroke weight is map the distance,

  • "which could be anywhere from zero, right,

  • "if I'm not moving at all, all the way up."

  • I mean, it could.

  • Let's just give it, sort of, think about a maximum range

  • of something like 20, and I'm gonna invert that, 20 down.

  • I'm always going to have a stroke weight of at least one,

  • so let's see what happens there.

  • So, as I move.

  • Oh, well, of course, then

  • (laughs)

  • I'm making all of these kind of crazy mistakes.

  • Then, I also need to actually use

  • the stroke weight variable in the stroke weight function.

  • So, if I move really fast, it's really thick.

  • Well, I kind of wanna interpolate that

  • so that it's a little smoother, but this'll do.

  • This'll do just fine.

  • All right, so here's the thing.

  • This was the easy part, right.

  • This is the easy part.

  • I just want to draw using the mouse.

  • Now, I need to figure out how to get that symmetry.

  • I think maybe we'll wanna use

  • the whiteboard for this for a second.

  • So, we have a canvas.

  • That's 400 by 400.

  • We can see here this idea

  • of a snowflake with six fold symmetry.

  • One, two, three, four, five, six.

  • So, the angle that's important here is

  • this particular angle, right, which is 60 degrees I believe.

  • So, lets say, for the sake of argument,

  • I'm using the mouse to draw over here, so mouse X.

  • Mouse Y is happening over here.

  • What I wanna do is draw the same thing here,

  • and here, and here, and here, kind of rotating along.

  • But, also, I think I wanna flip it each time.

  • In this case, I think that's going to create

  • where you can see that these two are kind of pointing

  • at each other, so I think there's

  • also gonna be some aspect of flipping it.

  • No wonder this, by the way.

  • There's a big mistake here.

  • No wonder this was going wonky.

  • Code Bulletin pointed this out.

  • And, also, maybe other people in the chat.

  • P mouse Y, that's why it was kind of doing some weird stuff.

  • Yeah, this is much more like what I expected.

  • Let's try this.

  • So, just as the simplest way of thinking about it

  • for a second, let's go, "I goes from zero to six, right."

  • I wanna repeat what I'm doing six times.

  • I think all this is also going to be easier

  • if I translate to the center,

  • so I'm gonna need to use translate and rotate.

  • Translate and rotate.

  • Translate takes as its arguments an X and a Y,

  • and rotate takes as its argument an angle.

  • And, what this allows me to do is reposition

  • wherever the origin is, so I want

  • the origin to be in the center.

  • And, I'm gonna draw a relative to that,

  • but then I can also rotate what I'm drawing

  • to also duplicate it here, rotate to duplicate it here,

  • rotate to duplicate it here.

  • I kind of glossed over that very quickly, but I will refer

  • you to my p5 JS transformations video tutorial,

  • which goes through translate and rotate in much more detail.

  • So, I'm also going to now create a variable called MX,

  • which is mouse X minus minus width divided by two.

  • And, MY and PMX and PMY.

  • Ultimately, what I want is I want the mouse position

  • relative to the center, so the easiest way

  • for me to do that is just store it in separate variables.

  • So, I've got the same code here.

  • Same thing's happening.

  • It's just everything's now being drawn relative

  • to the center, and I am also drawing it six times.

  • But, I'm drawing it six times in the same place.

  • I'm gonna add some alpha so we see what's going on.

  • Could I now say, "Rotate by I times 60 degrees"?

  • Because what I wanna do is, first, draw it here,

  • then here, then here, and I wanna rotate one,

  • two, three, four, five, six times.

  • Oh, and let's set angle mode to degrees

  • because I'm thinking, in terms of degrees, 60 degrees.

  • I could think in terms of radians,

  • and that would be pi divided by three.

  • There we go.

  • Now, this is isn't exactly doing what I would expect.

  • It's the right idea, interesting.

  • Getting kind of a little bit of a kaleidoscope feel to it.

  • I think what I actually want is

  • to bisect each one of these and, basically,

  • take whatever I'm drawing here and invert it.

  • How can I draw this?

  • I'm so bad at drawing.

  • Invert it there, right.

  • I need, actually, to create something

  • that feels much more like a snowflake pattern.

  • What I'm drawing, essentially, is this element here

  • that's on this side of the snowflake.

  • So, I need to flip it over, draw it here,

  • flip it, draw it here, so I actually

  • wanna rotate not six times but 12 times.

  • And, each time, I want to flip what I'm drawing.

  • So, I want to rotate 12 times.

  • And, this, by the way,

  • I should have the angle, 360 divided by 12.

  • I mean, this is kind of crazy

  • that I'm having these hard coded values.

  • There, so this is what I want.

  • This is much more close to what I want,

  • but what I want to see now is, also,

  • I want to invert every other one.

  • And, Simon is making a good suggestion

  • in the chat, to draw a line.

  • So, I think it actually would be

  • quite useful for me to do that.

  • I'm gonna draw more than just the background,

  • just so we sort of see.

  • I wanna just draw these lines.

  • Woo, something weird is going on.

  • (buzzing)

  • I've done something ridiculous.

  • I've made a pretty serious error.

  • I forgot.

  • I mean, I should know this.

  • I should know all of this stuff, but even I.

  • I've done this so many times I just forget it.

  • Transformations and the word transformation applies

  • to any translation, rotation, or scale.

  • I'm gonna scale in a minute.

  • They're cumulative.

  • So, if I say rotate by 30 degrees, I'm gonna do this.

  • So, rotate I times 30.

  • Rotate 30 degrees.

  • Now, well, rotate zero.

  • Then, I is one, rotate one times 30 is 30.

  • Then, I is two, rotate two times 30 is 60.

  • Ah!

  • I just wanna rotate 30 each time.

  • I was thinking about how far,

  • from the beginning, I wanna rotate.

  • But, ultimately, of course, I just wanna rotate that amount.

  • Let's create a variable.

  • We'll call it symmetry,

  • and we're gonna have 12 fold symmetry here.

  • I really want six fold symmetry,

  • but each six fold symmetry segment will be symmetrical.

  • So, I'm gonna say, "Angle equals 360 divided by symmetry."

  • I goes from zero to symmetry.

  • And then, I'm just gonna rotate by the angle.

  • There we go.

  • That's what I'm looking to do.

  • And then, the same thing.

  • And, this, I think, can just be

  • a global variable for right now.

  • That way, I can just do the same exact thing here.

  • And, we see this is what I was looking to see,

  • something more like this.

  • Now, this is one, two, three,

  • four, five, six, seven, eight, nine, 10.

  • We should count, we should get 12.

  • So, let me see if I can do that extra flipping.

  • Another transformation function that I can use,

  • beside translate and rotate, is a function called scale.

  • Now, typically, we think of scale

  • as scaling something bigger or smaller.

  • So, for example, if I were to use the ellipse function

  • to draw a circle and, right before that, I were

  • to say scale is two, that means double the size or 200%.

  • So, it would look, yeah.

  • I'm not gonna.

  • In this case, it's double the radius, so I would have

  • something like an ellipse that looks like this.

  • But, scale, first of all, you can scale on different axes.

  • So, I could say, "2, 1."

  • And, if I did that, it would just scale the horizontal axis

  • but not the vertical, would still be the same scale.

  • So, my ellipse would look like this.

  • It would be stretched horizontally.

  • Incidentally, I can also apply a negative number to scale.

  • If I apply a negative number to scale,

  • then it's going to draw it in the opposite direction.

  • It's going to invert it, which, in the case of a circle,

  • doesn't matter because it's symmetrical along the axis.

  • But, if I were drawing something like a triangle,

  • then, if I had negative two, I would see

  • the triangle suddenly be drawn like this.

  • What I thought would make sense is for me to, for any odd.

  • I mean, it doesn't really matter.

  • I don't know if I want odd or even.

  • For every other one, if I module is, is zero or one,

  • I'm not sure which one, to invert the scale horizontally.

  • So, in that, say, "Scale, negative one, one."

  • But, once again, this is happening cumulatively.

  • So, in this case, maybe what I wanna do just to allow myself

  • to be less confused is to add push and pop

  • so that any rotations or translations or scales

  • that happen within each, and not outside the loop,

  • right inside the loop, for each section, are contained.

  • And so, in this case, I would wanna go back

  • to rotating I times the angle.

  • So, now, they're not cumulative because I'm saving

  • the transformation state in its original way,

  • scaling by inverting it, drawing, sorry, rotating.

  • Do I wanna scale before rotate?

  • Rotate?

  • I think I wanna rotate and then flip it.

  • We're gonna find out.

  • Okay, so this is kind of what I was expecting,

  • except I'm not actually seeing where I'm drawing

  • because I think this should be one.

  • Yeah, there we go.

  • This is more like what I was expecting, there.

  • Is this a way to draw a snowflake?

  • (laughs)

  • I feel like these are snowflake like.

  • One, two, three.

  • But, really getting 12.

  • If I just change this now to six,

  • did I overthink the symmetry?

  • And, actually, this is now gonna give me six fold symmetry.

  • Yeah, okay, I overthought the symmetry, I guess.

  • Oh, wait, this has to be symmetry.

  • All right, I think we've made kaleidoscope snowflakes.

  • Basically, I see.

  • Look at this.

  • Rotate by the angle, push, pop,

  • and draw the line twice.

  • And, the second time with it flipped.

  • There we go.

  • Ah!

  • Finally.

  • Tada!

  • Okay, what we have now.

  • Now, Zachary is suggesting, yeah.

  • I think this would make a lot more sense,

  • to give a lot more space now, and here we go.

  • So, what I would like to do, and then the next thing

  • I wanna do is add a button to save the image.

  • Button mouse pressed, and save snowflake.

  • And, I'm gonna write a little function.

  • Save snowflake, that, and let's make a clear button also.

  • So, we're gonna have a save button and a clear button.

  • And, with two callbacks, save snowflake and clear canvas.

  • So, when I wanna save, I just wanna save snowflake.png.

  • This will take whatever's in the canvas

  • and send it to the downloads directory.

  • And, when I wanna clear, I just wanna draw the background,

  • reclear the background at zero.

  • I have a pair of unnecessary push and pop.

  • Yeah, so you're right that this push and pop

  • is unnecessary, so let's take that out.

  • I sort of like having it in there,

  • but you're right that it's unnecessary.

  • Let's think about color,

  • and let's think about line thickness.

  • So, right now, the line thickness is determined

  • by the speed of the mouse.

  • I guess that kind of makes sense,

  • but I wonder if it would actually be better

  • to have the line thickness be controlled by a slider.

  • And, we'll have color be automated.

  • So, we're gonna create a slider that has a range

  • between one pixel and 32, and we'll start it at four.

  • And, we'll give it increments of 0.1.

  • And then, what I'm gonna do is say

  • the stroke weight is not the distance any more,

  • but is actually the value from the slider.

  • So, I wanna actually be able to see this more full screen,

  • so I'm going to go to share.

  • And, I'm gonna look at this full screen URL

  • and just open that up here.

  • So, now, if I'm drawing, that's the line thickness.

  • If I were to make this larger, look at this.

  • So, I need the mouse is pressed to be only if the mouse is

  • within the canvas, but that's not a huge deal.

  • But, if I make it thicker, right,

  • I could do something thicker here, and then I could

  • really be much more intricate about my design.

  • This is kind of awkward to have to go down to the slider.

  • I don't love this interaction, but this is better.

  • So, I'm just gonna fix that bug to only do stuff

  • if mouse X is greater than zero, less than the width.

  • I wanna make sure the mouse is in the window,

  • so that should fix this issue.

  • And, I'm gonna just refresh over here where,

  • if I'm operating the slider,

  • we don't see any drawing happen.

  • Let's use noise for the color,

  • so I'm gonna have an offset start at zero.

  • I'm gonna set the color mode to HSB, 255, 255, 255.

  • And then, what I will do is I will get the hue value

  • to be the noise function of X offset times 255.

  • And, we'll set hue, and we'll have a saturation

  • and brightness all the way up.

  • So, you can see it's always green right now.

  • But, now, if I were to have X offset change over time,

  • that hue is gonna change,

  • so this is my rainbow, multicolored snowflake.

  • So, I think this is done.

  • I'm gonna attempt to design a snowflake now.

  • We're gonna see.

  • How good is my snowflake design tool?

  • So, right now, if I design the snowflake,

  • get a little thicker, and get in the center,

  • and then make it a little thinner for over here,

  • a lot of green and blue.

  • If I do this and then I hit save, now I have my snowflake.

  • So, I want a way of collecting all of these

  • into a nice collection of snowflakes.

  • Let's have the hue move with the sign function.

  • Needs to stay gray scale.

  • The people are really advocating for gray scale.

  • (laughs)

  • I'm good with that.

  • So, I'm gonna start out with sort of a thick line

  • towards the center, and I'm gonna use

  • a thinner line to do some nice detail.

  • There, this is my snowflake that I made.

  • Goth snowflakes.

  • People prefer the color.

  • Okay, I give up.

  • This is the end of this coding challenge.

  • Here is a kaleidoscope snowflake drawing generator.

  • I'm sure you can make your own version of this

  • and think about color and the interface

  • and all sorts of different and creative ways,

  • and I hope that you will do that.

  • On the 12th day of coding

  • My p5 gave to me

  • ♪ 12 neural networks

  • ♪ 11 index errors

  • ♪ 10 people posing

  • Nine for loops looping

  • Eight fractals forming

  • Seven sorters sorting

  • Six cameras switching

  • Five golden

  • - Ah!

  • Five golden rings

  • Four dripping

  • Four flocking boids

  • Three of these dots

  • Two pull requests

  • And a null pointing binary tree

  • (upbeat ukulele music)

  • (air kiss)

  • - Happy holidays!

  • (upbeat music)

(train whistle)

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it