Virtual hands-on workshop : “Enjoyable
Introduction to Programming using Drawings”
by Dr.
Jeyakesavan Veerasamy, CS faculty,
University of Texas at Dallas, USA.
While
these materials have been targeted for workshops, they can certainly be used
for self-paced learning from your home as well. Just that it can be more
enjoyable experience if you have at least a partner to discuss and exchange
ideas! Some background in programming concepts will enable you to enjoy the
material – so I recommend you to complete Alice workshop first.
Start
the workshop with one of the shows in following directory – click on any
showX.html (press F11 and go full-screen for the full effect!): http://www.utdallas.edu/~jeyv/KAJS/shows
All
with just ~20 lines of code in Processing.js that contain a few simple math
equations! Math is beautiful :-) You will understand the code behind these images
in this workshop, then you can write your own code & generate your own
dazzling images!!
Description |
Materials/Images |
KhanAcademy-JavaScript installation and
lab setup
– There is no software to download and install, since JavaScript is
interpreted by the browser. Mozilla Firefox is the officially “tested”
browser – Google Chrome may work too, but it is not fully tested for the
examples given below. We need Internet connection to access Khan Academy site
just to get started, then we can work locally as long as you don’t click on
Khan Academy examples. |
|
Why
does it make sense to go through this Drawings workshop? (Why not learn
C/C++/Java directly?) |
|
Welcome to Drawings workshop! Here are a few
suggestions to get the maximum value from this workshop. We
will cycle through 3 modes for each topic/example: Watching, Doing it
individually, helping each other to complete and work on something extra. You
can use www.online-stopwatch.com
to make sure that the workshop is progressing in timely manner. |
|
Core programming concepts – Sequence, selection
and repetition are 3 pillars of programming! |
|
Introduction to KhanAcademy-JavaScript
environment
– www.khanacademy.org/cs - Visual
Programming – free-form typing – you can see the output immediately or with
one-click. |
|
Fun with examples: Click on All
Programs or click here www.khanacademy.org/cs/browse/all-programs
to go there directly. Scroll down and click on a few interest ones and have
fun! After completing this workshop, you can generate similar or even better
images! |
|
Goto https://www.khanacademy.org/cs/programming:
Review all the tutorials listed
under first 2 headings: |
|
Assignment 1: Draw a nice
house! |
I decided NOT to give a sample
house and derail your imagination! :-) |
Documentation: Click on Documentation or click here www.khanacademy.org/cs/docs & processingjs.org/reference.
Each API comes with a sample usage too. |
|
Goto https://www.khanacademy.org/cs/programming:
Review all the tutorials listed
under Video: Draw a ellipse with random size & random color! Documentation: random() noStroke(); fill(random(0,255),random(0,255),
random(0,255)); ellipse(random(0,400),
random(0,400), random(0,100), random(0,100)); You can comment out individual
lines with // and multiple lines with /* ... */ Also, what happens if these lines
are out of order? Try it! How to restrict to circles? See
the power of variable! noStroke(); fill(random(0,255),random(0,255),
random(0,255)); var
diameter = random(0,100); ellipse(random(0,400),
random(0,400), diameter, diameter); Alternate way to draw the circle! stroke(random(0,255),random(0,255),
random(0,255)); strokeWeight(random(0,100)); point(random(0,400),
random(0,400)); |
Flash/YouTube |
Assignment 2: Add a random
square! Unlike ellipse(), x and y parameters in rect() indicate the top, left
corner. |
|
Video: make the circle appear fully inside the canvas area. In
other words, we want to ensure that the circles are never cut off at the
edges. Idea is to push the circle in if
it is too close to the boundaries. Realize the power of IF statements! noStroke(); fill(random(0,255),random(0,255),
random(0,255)); var
dia = random(0,200); var
x = random(0,400); var
y = random(0,400); var
rad = dia / 2; if
(x < rad) { x = rad; } if
(x > 400 - rad) { x = 400 - rad; } if
(y < rad) { y = rad; } if
(y > 400 - rad) { y = 400 - rad; } ellipse(x,
y, dia, dia); Extra: What are the code changes if you want to do the same for
ellipses? Alternate
approach: Both Software Engineering
perfectionists and Mathematicians make like the following one better! Why? noStroke(); fill(random(0,255),random(0,255),
random(0,255)); var
dia = random(0,200); var
rad = dia / 2; var
x = random(rad,400-rad); var
y = random(rad,400-rad); ellipse(x,
y, dia, dia); |
Flash/YouTube |
Assignment 3: Make your square
to appear within the canvas area too – let us go one step further – let us
avoid the edges all-together – make the squares appear within the rectangular
area of (10,10) to (390,390). Extra: What
if we want to do the same for any rectangle? |
|
For
loops: Video:
Draw 10 random circles! for(var
i=0 ; i<10 ; i++) { stroke(random(0,255),random(0,255),
random(0,255)); strokeWeight(random(0,100)); point(random(0,400), random(0,400)); } Now, click near 10 and drag the
mouse left or right. What happens? |
Flash/YouTube |
Assignment
4: Draw 10 concentric randomly
colored circles. What does “concentric” mean? Will you draw in the order of
small to large circles, or other way around? Extra: Define a variable n at the top and write the generic code
to draw n concentric circles instead. var
n=10; ... Change n by clicking near 10 and
dragging mouse left or right. Does your code work properly? |
|
Video: Waiter
carrying the elliptical plates in a fancy way... With
random colors: noStroke(); for (var i = 10; i > 0;
i--) { fill(random(0,255),random(0,255),
random(0,255)); ellipse(200, 200, i * 20, i * 40); ellipse(200, 200, i * 40, i * 20); } With
a color pattern: noStroke(); for (var i = 10; i > 0;
i--) { fill(i*25,50,(10-i)*25); ellipse(200, 200, i * 20, i * 40); ellipse(200, 200, i * 40, i * 20); } |
|
Assignment
5: Adjust the color pattern to use a
loop of 20, then change the color pattern such that Green color appears in
the middle as shown in the image. Extra:
Can you make it perfect Green in
the middle? |
|
Assignment
6: With n specified at the top, how
will you generate n x n equally distributed circles? Keep 50 as the default
diameter size for circles, but reduce as needed to avoid overlapping with
other circles. Take it easy & draw just one
line of n equally distributed circles first, then expand it to n x n circles. Extra: How to draw circles in diamond formation? Middle row
should have n circles, adjacent rows should have (n-2) circles, their
adjacent rows should have (n-4) circles, so on. Top and bottom rows should
have only 1 or 2 circles in the middle |
n = 3:
n =
5: n = 10: |
Play time! Use these code
segments indvidually to learn about the behavior of translate(), rotate() and
scale() – replace A,B,C and D with various values and try to understand the results! fill(255,0,0); ellipse(100,100,50,50); translate(A,B); ellipse(100,100,50,50); translate(C,D); ellipse(100,100,50,50); angleMode =
"degrees"; fill(255,0,0); translate(200,200); ellipse(100,100,50,50); rotate(A); ellipse(100,100,50,50); angleMode =
"degrees"; fill(255,0,0); translate(200,200); ellipse(100,100,50,50); scale(B, C); ellipse(100,100,50,50); Now,
try to use rotate() and scale() together. Add for loop & random fill
color, then adjust the angle – that will take you to artistic creations shown
below! Video: Drawing Bonus:
Rotation! www.khanacademy.org/cs/drawing-bonus-rotation/906448125 Warning: Sometimes,
browsers’ default setting of degrees vs. radians is unpredictable. You may
want to add a line angleMode =
"degrees"; to
the top of your program if you want the angles to be specified in degrees.
Also, you can use the following line to use radians instead (note: 360
degrees = 2 * PI radians): angleMode =
"radians"; This
setting affects the behavior of rotate(), sin(), cos(), tan(), etc. |
|
Video: Artistic creations including
rotating & shrinking squares/ellipses – change the angle within rotate()
and see the wonders! translate() is used to move (0,0) to the center so that
we can see all quadrants, as we do the rotations. scale() is used to change
the size gradually ... noStroke(); translate(200,200); for
(var i = 500; i > 0; i--) { fill(i * 7 % 256, i * 17 % 256, i * 13 %
256); rect(0,0,400,400); scale(0.99,0.99); rotate(5); } noStroke(); translate(200,200); for
(var i = 500; i > 0; i--) { fill(i * 7 % 256, i * 17 % 256, i * 13 %
256); rect(0,0,400,400); scale(0.99,0.99); rotate(30); } Discussion:
You can see colors become bolder, but why they change suddenly? noStroke(); translate(200,200); for
(var i = 0; i <16 ; i++) { fill(random(0,255), random(0,255),
random(0,255)); ellipse(50,100,50,200); rotate(23); } noStroke(); translate(200,200); for
(var i = 50; i > 0; i--) { fill(random(0,255),random(0,255),
random(0,255)); rect(-200,-200,400,400); scale(0.9,0.9); rotate(5); } noStroke(); translate(200,200); for
(var i = 500; i > 0; i--) { fill(sin(i*2)*128+128, sin(4*i)*128+128,
sin(7*i)*128+128); rect(0,0,400,400); scale(0.99,0.99); rotate(16); } Discussion:
Why color change is smooth for the previous one, bit more abrupt for the next
one? noStroke(); translate(200,200); for
(var i = 500; i > 0; i--) { fill(sin(i*5)*128+128, sin(12*i)*128+128,
sin(17*i)*128+128); ellipse(200,200,400,400); scale(0.99,0.99); rotate(5); } noStroke(); translate(200,200); for
(var i = 1000; i > 0; i--) { fill(sin(i*2)*128+128, sin(4*i)*128+128,
sin(6*i)*128+128); ellipse(200,200,100,400); scale(0.995,0.995); rotate(24); } noStroke(); translate(200,200); for
(var i = 500; i > 0; i--) { fill(random(0,255), random(0,255), random(0,255)); ellipse(200,200,400,400); scale(0.93,0.93); rotate(63); } |
|
Assignment
7: Rotating and shrinking triangles
– you have seen the examples using ellipses and rectangles. Try the same
using triangles. |
Flash/YouTube |
Functions: Circle of rockets! noStroke(); var drawRacket = function() { fill(255, 0, 102); triangle(150,0,200,-40,200,40); fill(0, 255, 9); rect(125,-25,50,50); fill(9, 0, 255); triangle(125,-25,125,25,100,0); }; translate(200,200); var n = 12; for(var i=0; i<n ; i++)
{ rotate(360/n); drawRacket(); } Discussion: How will you write this code if we cannot define a new
function? |
|
Assignment
8: Circle of cars - make them face
each other: scale(-1,1) can make it reflect across y axis. Here is the
start-up code to draw one car! Functions bring modularity to the
programs and we can invoke them any # of times wherever we want. var
drawCar = function() { noStroke(); // draw the car body fill(255, 0, 115); rect(90, 0, 100, 20); rect(105, -28, 70, 40); // draw the wheels fill(77, 66, 66); ellipse(115, 21, 24, 24); ellipse(165, 21, 24, 24); }; translate(0,100); drawCar(); Discussion: How will you write this code if we cannot define a new
function? |
|
Recursion is an advanced concept
in Computer Science. Beginners are welcome to skip this portion! You can
always come back later to tackle whenever you want... Growing squares at corners:
functions with parameters & recursion Recursive functions are unique –
they invoke themselves in the body of the function. In the following code,
drawSquare() is invoked 4 times within drawSquare() itself. That sounds like a formula for
trouble, right? If we are not careful, infinite recursion can occur &
programs can get stuck or crash. We control the recursion depth. noStroke(); var
drawSquare = function(level, x, y, len) { fill(x, len, y); rect(x, y, len, len); if (level > 0) { drawSquare(level-1, x-len/2, y-len/2,
len/2); drawSquare(level-1, x+len, y-len/2,
len/2); drawSquare(level-1, x-len/2, y+len,
len/2); drawSquare(level-1, x+len, y+len,
len/2); } }; drawSquare(8,
150, 150, 100); Growing triangles at corners:
functions with parameters & recursion var
drawTriangle = function(level, x1, y1, x2, y2, x3, y3) { fill(x1, y1, x2-y2); strokeWeight(level+1); triangle(x1, y1, x2, y2, x3, y3); if (level > 0) { drawTriangle(level-1, x1, y1,
x1-(x2-x1)/2, y1-(y2-y1)/2, x1-(x3-x1)/2, y1-(y3-y1)/2); drawTriangle(level-1, x2, y2,
x2-(x1-x2)/2, y2-(y1-y2)/2, x2-(x3-x2)/2, y2-(y3-y2)/2); drawTriangle(level-1, x3, y3,
x3-(x1-x3)/2, y3-(y1-y3)/2, x3-(x2-x3)/2, y3-(y2-y3)/2); } }; drawTriangle(5,
200, 125, 125, 250, 275, 250); Growing circles at corners:
functions with parameters & recursion noStroke(); var drawCircle =
function(level, x, y, len) { fill(128+127*sin(x*(level+1)),
128+127*cos(len*(level+1)), 128+127*sin(y*(level+1))); ellipse(x, y, len, len); if (level > 0) { drawCircle(level-1, x-len/2, y-len/2,
len/2); drawCircle(level-1, x+len/2, y-len/2,
len/2); drawCircle(level-1, x-len/2, y+len/2,
len/2); drawCircle(level-1, x+len/2, y+len/2,
len/2); } }; drawCircle(3, 200, 200, 200); |
|
Special function: draw() – KAJS
environment invokes draw() repeatedly & automatically forever. Tutorial: Animation www.khanacademy.org/cs/intro-to-animation/830742281 Assignment 9: Make the car go back and forth. Here is the start-up code: var
drawCar = function(x, y) { noStroke(); // draw the car body fill(255, 0, 115); rect(x, y, 100, 20); rect(x + 15, y-22, 70, 40); // draw the wheels fill(77, 66, 66); ellipse(x + 25, y+21, 24, 24); ellipse(x + 75, y+21, 24, 24); }; var
x = 10; var
draw = function() { drawCar(x, 200); }; |
|
Tutorial: IF statements & animation: www.khanacademy.org/cs/if-statements/836708402 Assignment 10: Make the ball bounce around all 4 walls. Also, change
color and speed with each bounce. Here is the start-up code: //
position of the ball var
x = 50; //
how far the ball moves every time var
speed = 3; var
draw = function() { background(202, 255, 97); fill(66, 66, 66); ellipse(x, 200, 50, 50); // move the ball x = x + speed; }; Extra:
introduce random speed when ball bounces off the walls, also change color
too! |
|
This
version is bit slow compared to loops, but nice to see, right? var
sz = 50; var
limit = 400; translate(200,200); var
draw = function() { ellipse(0,0,sz,sz); sz
+= 5; if (sz > limit) { sz = 50; limit -= 25; } }; Same
using squares: var
sz = 50; var
limit = 400; translate(200,200); var
draw = function() { rect(-sz/2,-sz/2,sz,sz); sz += 5; if (sz > limit) { sz = 50; limit -= 25; } }; |
|
Assignment
11: make the expanding
circles/squares start with a different color each time. Remove the border
black lines too. |
|
Slide show of wonderful images!
You can replace the code in drawIteration() with any code that we have seen
for various artistic creations... noStroke(); var angle = 1; var drawIteration =
function() { translate(200,200); for (var i = 1000; i > 0;
i--) { fill(sin(i*2)*128+128, sin(4*i)*128+128,
sin(6*i)*128+128); ellipse(200,200,100,400); scale(0.995,0.995); rotate(angle); } }; var counter = 0; var draw = function() { counter++; if (counter > 25) { counter = 0; background(0, 0, 0); angle++; resetMatrix(); drawIteration(); } }; |
|
Converting for loop to use draw():
stroke(random(0,255),random(0,255),
random(0,255)); translate(50,100); for(var
i=0 ; i<100 ; i++) { line(0,0,300,0); translate(300,0); rotate(121); } can be re-written with draw()
function. To avoid endless drawings, let us use mouseIsPressed flag (you need
to press the mouse in the canvas area to draw) – this enables us to stop the
drawing at any time! Since the drawing matrix is reset every time before
invoking draw(), I threw in pushMatrix() just to try – that made it work
properly! translate(50,100); stroke(random(0,255),random(0,255),
random(0,255)); var
draw = function() { if (mouseIsPressed) { line(0,0,300,0); translate(300,0); rotate(121); pushMatrix(); } }; Discussion:
why rotate(121) degrees? |
|
Magic pen: mouseX
and mouseY are global variables that track the position of the mouse. Come up
with a mechanism for the brush color to change slowly over time. |
|
Power of Creativity: mouseX
and mouseY are global variables that track the position of the mouse. Here is
the code to draw random colored circle wherever mouse is clicked or pressed
and dragged. var draw = function() { if (mouseIsPressed) { stroke(random(0,255), random(0,255),
random(0,255)); strokeWeight(random(0,50)); point(mouseX, mouseY); } }; Open-ended Assignment 12: Try to draw a
human face or necklace or your favorite one :-) Now, put your thinking cap
ON, close your eyes, let your creativity run wild and think for a few minutes
about what you can do with a magical brush & build something that is
awesome! |
|
Play with sin() wave: Keep track of the
total angle is another approach to get around “drawing matrix reset” issue
associated with draw(). translate(200,200); var angle = 0; var m = 4; var draw = function() { rotate(angle); stroke(random(0,255), random(0,255),
random(0,255)); line(0,0,75+75*sin(m*angle),0); angle+= 0.5; }; Does
the output make sense? Change the multiplication factor m to some other value
and see what happens. |
|
Endless distribution of playing
cards! Card size gets smaller, then gets bigger, then smaller again, bigger
again ... strokeWeight(2); translate(200,200); var
y = 200; var
dir = 1; var
len = 1; var
angle = 10; var
draw = function() { fill(random(0,255), random(0, 255),
random(0,255)); rotate(angle); rect(len, 0, y / 2, y); y -= dir; angle+= 10; if (y < 20) { dir = -1; } if (y > 200) { dir = 1; } }; Extra:
How about slow color change, instead of random colors? |
|
Another
generation of shrinking squares! noStroke(); translate(200,200); var y = 200; var dir = 1; var len = 500; var angle = 0; var draw = function() { fill(random(0,255), random(0, 255),
random(0,255)); rotate(angle); rect(-len, -len, 2*len, 2*len); y -= dir; angle+= 5; len /= 1.1; }; |
|
Hypnoswirl:
http://www.khanacademy.org/cs/hypnoswirl/826002294 Assignment 13: Make the
necessary changes to make your drawing close to each one of these. |
|
Effect
of circles expanding over time and random colors strokeWeight(2); translate(200,200); point(0,0); var sz = 1; var len = 1; var angle = 10; var draw = function() { rotate(angle); fill(random(0,255), random(0,255),
random(0,255)); ellipse(len, 0, sz, sz); angle+=20; len++; sz += 1; }; |
|
Paddle
ball: http://www.khanacademy.org/cs/paddle-ball/830543654 Assignment 14: Make the ball
pick-up speed every time when it hits the paddle. Another
option is to select a random speed within a range when the ball hits the
paddle and bounces. What
is a game without the score? Define a variable score and come up with a
meaningful mechanism to incremenet it & reset it, then use the following
code add the score in the bottom. rect(100,360,200,40); textSize(40); fill(0,0,0); text(score,150,395); |
|
Pebbles
going all around: strokeWeight(2); translate(200,200); point(0,0); var sz
= 1; var len
= 10; var
angle = 10; var
draw = function() { rotate(angle*180/PI); fill(random(0,255), random(0,255),
random(0,255)); ellipse(len, 0, sz % 10 + 10, sz % 10 +
5); angle++; len++; sz += 1; }; Following
variation shows endless collection of coins! Use strokeWeight(2) instead of
noStroke() to see another interesting effect. translate(200,200); var sz
= 1; noStroke(); var
drawPebbles = function(x) { var len = 10; rotate(x); for(var i=0 ; i<500;i++) { rotate(1); fill(random(0,255), random(0,255),
random(0,255)); ellipse(len, 0, sz % 10 + 10, sz % 10
+ 5); len++; sz += 1; } }; var x =
1; var
draw = function() { x++; drawPebbles(x); }; |
|
Arrays: Multiple
balls bouncing off all 4 walls. Let us use different color for each ball.
That means, we need to remember the colors. That is where arrays come in. Here
is sample code to use arrays – it generates and stores 10 random colors, then
randomly selects one color from that list. var colors = []; for(var
i=0; i<10 ; i++) { colors.push(color(random(0,255),random(0,255),
random(0,255))); } fill(colors[random(0,10)]); Extra:
For more complexity, balls can bounce off each other too! But which direction
each ball should go? |
|
Assignment 15: Generate Texas
Lotto numbers – we need to generate 6 unique numbers between 1 and 50. You
can use the following code to output the values: textSize(40); text(value,
x, y); Does
your program scale up easily if we want to generate 20 unique numbers between
1 and 1000. That is why, we like to write the code as generic as possible –
so that future modifications/expansions will be as easy as possible. |
|
Assignment 16: Paddle ball game
using 2 balls. |
|
Assignment 17: How long can you
keep the balls in the air? Press on each air-blower to push the ball up! Game
ends whenever any ball touches the air-blower. If
possible, do realistic ball movements - change the gravity settings and see
the effect! |
|
Assignment 18: “Hit-the-heads”
game: Images randomly replace circles which are arranged in matrix format.
Score should reflect the user’s response speed, negative points for clicking
on circles. Read
the documentation on image(myImage, x, y); |
|
Assignment 19: Implement the
memory game. |
|
Assignment 20: Implement
Connect4 game. |
|
|
|
Additional
Topics
Item |
Description |
Material |
Duration |
A1 |
Running
the JavaScript programs in full screen: |
|
|
|
|
|
|
Additional
resources:
·
Khan
Academy JavaScript documentation: www.khanacademy.org/cs/docs
·
Processing.js
documentation: processingjs.org/reference
·
Sketchpad
CC IDE: sketchpad.cc
·
OpenProcessing
IDE: www.openprocessing.org/sketch/create
·
Processing
examples: processing.org/examples
A
few advanced examples (mostly Recursion):
var depth = 4;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3, 1/3];
var turns = [-90, 90, 90, -90, 0];
var copies = 4;
var angle = 90;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/2);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
rotate(90);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(-angle);
}
Koch Curve & Snowflake (JavaScript)
https://www.khanacademy.org/cs/koch-curve-using-arrays/5909184489979904
var depth = 5;
var length = 325;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 120;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/3.5);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
var depth = 4;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3, 1/3];
var turns = [-90, 90, 90, -90, 0];
var copies = 4;
var angle = 90;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/2);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
var depth = 4;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3, 1/3];
var turns = [-90, 90, 90, -90, 0];
var copies = 4;
var angle = 90;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/2);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
var depth = 4;
var length = 250;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 4;
var angle = 90;
var fractal = function(level, length) {
if (level < 1) {
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/2);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
var depth = 5;
var length = 250;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 4;
var angle = 90;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/2);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
rotate(90);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(-angle);
}
var depth = 4;
var length = 250;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 4;
var angle = 90;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200-length/2, 200-length/2);
for(var i=0 ; i<copies ; i++) {
fractal(depth,length);
rotate(angle);
}
Jewelry Design (JavaScript)
var depth = 5;
var length = 325;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 120;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 25);
rotate(90);
fractal(depth,length);
rotate(180);
fractal(depth,length);
var depth = 3;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 120;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 200);
rotate(90);
for(var i=0 ; i<36; i++) {
fractal(depth,length);
rotate(180);
fractal(depth,length);
rotate(180);
rotate(10);
}
var depth = 5;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 1;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 200);
rotate(90);
var draw = function() {
if
(mouseIsPressed) {
rotate(angle);
angle+=5;
fractal(depth,length);
rotate(180);
fractal(depth,length);
rotate(180);
}
};
var depth = 5;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 1;
var r = random(0,255);
var g = random(0,255);
var b = random(0,255);
var adjustColor = function() {
r +=
random(-20,20);
g +=
random(-20,20);
b +=
random(-20,20);
if (r > 255) {
r = 512 - r;
}
if (g > 255) {
g = 512 - g;
}
if (b > 255) {
b = 512 - b;
}
if (r < 0) {
r = -r;
}
if (g < 0) {
g = - g;
}
if (b < 0) {
b = - b;
}
stroke(r, g, b);
};
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 200);
rotate(random(0,360));
var draw = function() {
if
(mouseIsPressed) {
rotate(angle);
angle+=5;
adjustColor();
fractal(depth,length);
rotate(180);
fractal(depth,length);
rotate(180);
}
};
var depth = 5;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var angle = 1;
var r = random(0,255);
var g = random(0,255);
var b = random(0,255);
var adjustColor = function() {
r +=
random(-20,20);
g +=
random(-20,20);
b +=
random(-20,20);
if (r > 255) {
r = 512 - r;
}
if (g > 255) {
g = 512 - g;
}
if (b > 255) {
b = 512 - b;
}
if (r < 0) {
r = -r;
}
if (g < 0) {
g = - g;
}
if (b < 0) {
b = - b;
}
stroke(r, g, b);
};
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 200);
rotate(random(0,360));
var draw = function() {
if
(mouseIsPressed) {
rotate(angle);
angle+=3;
adjustColor();
fractal(depth,length);
rotate(180);
}
};
var depth = 4;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 120;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 200);
rotate(90);
for(var i=0 ; i<6; i++) {
fractal(depth,length);
rotate(180);
fractal(depth,length);
rotate(180);
rotate(60);
}
var depth = 4;
var length = 200;
var factors = [1/3, 1/3, 1/3, 1/3];
var turns = [-60, 120, -60, 0];
var copies = 3;
var angle = 120;
var fractal = function(level, length) {
if (level < 1)
{
line(0,0,length,0);
translate(length,0);
} else {
//line(0,0,length,0);
for(var i = 0
; i < factors.length ; i++) {
fractal(level-1, length * factors[i]);
rotate(turns[i]);
}
}
};
angleMode="degrees";
translate(200, 150);
rotate(90);
for(var i=0 ; i<3; i++) {
fractal(depth,length);
rotate(180);
fractal(depth,length);
rotate(180);
rotate(120);
}
https://www.khanacademy.org/cs/recursive-triangles/5279369537781760
var depth = 3;
var drawTriangle = function(depth, x1, y1, x2, y2, x3, y3) {
triangle(x1, y1,
x2, y2, x3, y3);
if (depth > 0)
{
var x12 = (x1
+ x2) / 2;
var x13 = (x1
+ x3) / 2;
var x23 = (x2
+ x3) / 2;
var y12 = (y1
+ y2) / 2;
var y13 = (y1
+ y3) / 2;
var y23 = (y2
+ y3) / 2;
depth--;
drawTriangle(depth, x1, y1, x12, y12, x13, y13);
drawTriangle(depth, x2, y2, x12, y12, x23, y23);
drawTriangle(depth, x3, y3, x13, y13, x23, y23);
}
};
stroke(random(0,255), random(0,255), random(0,255));
strokeWeight(2);
drawTriangle(depth, 200,10, 10,390, 390,390);