Week 13:
Title and/or one-sentence description
Link:
https://main.d23xbgja7t4djw.amplifyapp.com/
Project summary:
Eterna is an online music streaming platform for DJs, musicians, and listeners with a blend of DJ mixing tools and social media features. Unlike traditional platforms, Eterna prioritizes community engagement and audio player features that allow the user the personalize their listening experience. Users can personalize their music exploration with in-app EQ controls and DJ-style mixing options. The platform will also support playlist creation and encourages community interaction, creating a space where music lovers can connect and discover new tracks together.
Inspiration: These are my own thoughts based on what I observed working in music. One big artist who has a similar perspective is James Blake, who recently started his own platform called “Vault” https://twitter.com/jamesblake/status/1764200702837191119
The reason I wanted to make Eterna is because I think the current music streaming platforms are souless and don’t foster community. 10 years ago Soundcloud was one of the best music platforms available because it was free, lenient with copyright i.e. allowing bootleg (unofficial) remixes of songs, and incentivized culture through its social aspects such as free uploading, commenting, and messaging. More recently soundcloud has needed to find a way to monetize their platform and has introduced ads between every song and a premium subscription. Additionally copyright restrictions have increased on the platform due to pressure by major labels sending DMCAs to the platform. Soundcloud was never perfect but the culture that existed on the platform 10 years ago created huge cultural shifts within music culture and the music industry. One of the biggest issues for creators on Soundcloud was the lack of opportunities to monetize your tracks. Even with subscription plans the per stream payout is too low for most artists to make a living off their music alone. Recently, with TikTok’s popularity, artists have turned to become influencers as way to supplement their lack of income from music or purely promote their tours. Since TikTok’s content thrives off of 30 second videos, it also encourages music artists to create shorter catchier songs for the TikTok market specifically. This has negatively impacted the artistic narritives that existed in music previously in my opinion because TikTok’s platform encourages creators to make more shallow, easily relatable music.
I hope to solve these issues in Eterna through alternative monetization methods and digging deeper into features that incentivize creativity and social community. I think integrating DJ software features directly will encourage casual users to explore their music library in a more creative way, as well as giving artists a way to perform virtually for fans.
Process • Eterna is a webapp built in React, AWS Lambda, and MongoDB. Utilizing WebAudio and Wavesurfer.js for live audio processing that allows turntable esque controls right in your browser. I built components in React for each portion of the interface. I followed the documentation examples for wavesurfer to build the DJDeck components with live waveform view. Wavesurfer has plugins built-in for the looping functionality. All my static audio and image files are hosted in AWS S3. I then stored the links to those in MongoDB and make an api call to the MongoDB using my AWS Lambda backend script. I prefer AWS Lambda to NodeJS because it only charges you when you call it versus having a 24/7 active server.
Audience/context • The audience is music listeners and music creators. They will be able to listen to tracks, DJ tracks, upload their own tracks and interact with other users through text chats.
Code references • I used wavesurfer.js examples and learned how to build a lot of features from asking ChatGPT how to setup my backend with AWS.
Next steps • I will add more DJ effects, user accounts, social features.
https://github.com/Ray2/Eterna
Week 11:
Reflection: This week I made progress on adding a DJ mixer interface with a crossfader, and 2 track cueing
Timeline:
Week 12 -Add pitch shift + FX to DJ Interface + zoom + looping
Week 13 - Add user account features
https://github.com/Ray2/Eterna
Week 10:
User Feedback:
“You could keep the UI design focused around the DIY space”
“I would have no clue how to use DJ sofware so maybe keep tht part simple to understand for the user”
Reflection: This week I made progress on adjusting my search UI and adding artist pages to my search and as a seperate page element. I also got nodeJS working to host my audio and image files but ended up moving them to s3 for a cheaper and easier workflow
Timeline:
Week 11 - Add second track cueing and build DJ interface with waveforms that can be placed by the mouse
Week 12 -Add pitch shift + FX to DJ Interface
Week 13 - Add user account features
https://github.com/Ray2/Eterna
Week 9:
Reflection: This week I made progress on implementing a search bar into my site that pulls from a local set of files. Coding the interaction between pressing on search bar results and getting it to play in the playback control was difficult but I think this is a pretty good step to getting the core features of my site down.
https://github.com/Ray2/Eterna
Week 8:
SMART Goal: I will make a home page with an audio player and non-functional search bar
Reflection: I was only able to get the player and basic homepage layout done because i’m too new to react. I made an alternate version in html at first but decided I really want to learn how to use react for this project so I started over. I need to dedicate more time to make significantly more progress.
https://github.com/Ray2/Eterna
WEEK 7:
Research your project, collect some notes to answer the following questions, and prepare to share your proposal in class next week:
Ideas for a project title?
Inanimate - Eterna (sound)
Project description (max 100 words)
A music streaming site with a focus on DJ mixing features in-site and community social media aspects such as artist-fan interaction chats, concert/event rsvping, and a “listen together” feature.
Who is the user? (the intended audience can also be you)
music listeners, music creators
What is the user experience?
listen immediately to a library of user uploaded music on the web or make an account for more community interaction. make playlists, make friends, text-chat with strangers, mix songs with in-app dj tool.
What is the creative aesthetic/angle/approach?
focus on letting the user interact with their music library in a personalized way with in-app EQ, DJ-esque mixing and playlisting features and community interaction. The design should be as accessible as possible but allow deeper feature access
What technologies are required? Why?
HTMl, CSS, JS, React or such, audio streaming api, backend database, various other apis
What do you need to learn/research/decide?
JS/React, various apis integration, everything about backend, design aesthetic choices
What assets/content/code already exists? (your own sketches or other people's sketches)
api implementation for music streaming
What assets/content/code needs to be created?
basically everything else
What resources/books/sites/examples will you rely on?
ChatGPT, Copilot, various GitHub libraries
What is the end goal?
make a functioning website with music streaming capabilities and user profile/login capabilities.
How will you determine if this project is a success?
if I can make significant progress on implementing these functions and learn more web dev in the process
Cite 3 sources of inspiration (How did you become interested in this idea? Quotes, photographs, products, projects, people, music, political events, social ills, etc.)
Soundcloud
Serato
My inspiration for starting this project is wanting more in depth features from existing music streaming platforms and being fed up with the current streaming platforms lack of consciousness of the music community(ies)
Do you think all of this feasible in 7 weeks? Why?
Absolutely not to the extent that I wish
It will be a good start though
Questions for your classmates. What are you unsure of, conceptually and technically? On what aspect(s) would you like feedback?
None
WEEK 6:
Re/Code 6:
My sketch this week is the same as week 4’s re / code. I refactored the code by removing old code that was commented out and also turning the function for my arrow dials into a class to clean up the code.
CODE: https://pastebin.com/Jwcmv2Aa
Reflection: In this weeks practice, I practiced more with git branches, merging, github, and code refactoring. I’m not sure if I think removing commented out code is the best idea. I think there’s a lot of commented out code that was written previously that could still be helpful to know what i was trying to do before so removing it might make things more difficult for certain feature additions in the future.
LINK: home.inanimate.space
WEEK 5:
Re/Code 4:
My sketch this week is adapted from Exercise 3. After modifying the number of lines and movement I ended up with an oculus-esque shape. I also added two additional smaller oculus on either side of the main oculus. The image is very satisfying for my else to follow at this frameRate. Not a super complex modification but a good way for me to practice git version control. I want to thrive for complexity in future sketches
Reflection: In this weeks practice, I learned about using functions of git that I had never used before such as branch and merge. I also learned about combining sin and cos in variables to create interesting movement variations.
https://github.com/Ray2/p5screensaver
WEEK 4:
Decode 1:
- A white background
- Shapes will have a black outline with a width of 2
- a grid of squares, one square less than the windowsize will be generated on the canvas
- the squares will be progressively more angled as they get closer to the end of their generation:
Decode 2:
Elements -
- A white background
- Shapes will have a black outline with a width of 2
- a grid of squares covering the whole canvas
- 5 squares will be generated inside of each other recursively in each grid squares
- each of the 5 sqaures will get smaller an smaller an have a randomly ofset position inside of each grid square
Encode 3:
Elements -
White Background
There is a grid of small black circles that make up about half the canvas. the grid is about 100 by 200.
the grid is morphed into a faux-3D blob with some circles overlapping at dense points to emulate extrusions
the grid is possibly morphed by a 3D noise function
Non-Scalable Window
No Interaction
Encode 4:
Elements -
White Background
There is a grid of 13 by 14 lines
The lines are randomly rotated left or right
At 2/3 of the screen the line turns into 2 lines per grid location and at 3/3 of the screen the line turns into 3 lines per grid location
Scalable Window
No Interaction
AI Tutor Chat:
Re/Code 4: This sketch is a larger project I’ve been working on non-stop for the past 1.5 weeks. It’s designed to be a web tool for taking lo-fi pictures and videos as a homage to the Gameboy Camera
My approach uses the webcam capture and transforms the image into live greyscale blocks. The blocks are resizable and the user is able to customize the the 4 color sets of the greyscale blocks. There are additional features such as the abiliy to change brightness, exposure, swap cameras, hide ui, lock color selections, and a bug-filled camera glitch mode.
I am using the p5.capture library for capturing the canvas to allow the user to export their creations as jpgs and gifs.
My current goal is to make it publically accessible on web to mobile and desktop users. Adding mobile support has been quite the headache the past couple days.
Reflection: In this weeks practice, I learned about applying making image pattern iterations and further applying noise to create faux-3D patterns. In my re/code work, I learned about capture reprocessing and a lot about the difficulty of trying to adapt a program to work in multiple environments (desktop, mobile, VScode local vs p5js hosted) with many use case variables.
You
/* Inspired by Vera Molnár's Un, deux, trois Based on a translation from Generative Artistry: https://generativeartistry.com/tutorials/un-deux-trois/ */ //def setup function function setup() { //set canvas to window width and height createCanvas(windowWidth, windowHeight); //end each stroke with a rounded end strokeCap(ROUND); //set stroke width to 4 strokeWeight(4); } //start draw loop function draw() { //set background to white background(255); //define step as 1/15 of width or height, whichever is smaller let step = min(width / 15, height / 15); //initiate for loop. set y to step. if y is less than height - step, add step to y for (let y = step; y < height - step; y += step) { //initiate for loop. set x to step. if x is less than width - step, add step to x for (let x = step; x < width - step; x += step) { //if y is less than 1/3rd of height if (y < height / 3) { //draw a line drawLine(x, y, step, [0.5]); } else if (y < (height / 3) * 2) { drawLine(x, y, step, [0.2, 0.8]); } else { drawLine(x, y, step, [0.1, 0.5, 0.9]); } } } noLoop(); } function drawLine(_x, _y, _step, positions) { push(); translate(_x + _step / 2, _y + _step / 2); rotate(random(5)); translate(-_step / 2, -_step / 2); for (let i = 0; i <= positions.length; i++) { line(positions[i] * _step, 0, positions[i] * _step, _step); } pop(); } function windowResized() { resizeCanvas(windowWidth, windowHeight); } /* MIT License Copyright (c) 2018 Tim Holman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ can you help me understand how [0.5] in drawLine(x, y, step, [0.5]);, affects the line drawing
AI Tutor
Absolutely, I'd be delighted to help you understand how [0.5]
affects the line drawing in the drawLine
function within your sketch inspired by Vera Molnár's "Un, deux, trois".
The drawLine
function is designed to draw one or more lines within a grid square based on the positions specified in its last parameter, which in the example you've given is [0.5]
. This array of positions determines where within the grid square the lines should be drawn. Let's break it down step by step:
Function Signature:
function drawLine(_x, _y, _step, positions)
_x
and_y
are the coordinates of the top-left corner of the grid square in which the line(s) will be drawn._step
is the size of the grid square (both width and height, assuming squares).positions
is an array indicating where within the square the lines should start, relative to the square's width.
Understanding
[0.5]
: The array[0.5]
contains a single value,0.5
. This value represents the fractional position across the width of the grid square where the line should be drawn. In this case,0.5
means "halfway across the square."Drawing the Line: Inside
drawLine
, the function translates the drawing context to the center of the grid square (translate(_x + _step / 2, _y + _step / 2)
) and then back (translate(-_step / 2, -_step / 2)
) to make rotations around the square's center easier and to position the line drawing correctly. When it comes time to draw the line(s), thepositions
array is iterated over with a loop.For
[0.5]
, the calculationpositions[i] * _step
effectively finds the midpoint of the square's width (0.5 * _step
). This means the line will start at the halfway point across the square's width and extend vertically (line(positions[i] * _step, 0, positions[i] * _step, _step)
), from the top to the bottom of the square.
Visual Interpretation: Visually, this results in a vertical line drawn right down the middle of each grid square in the first third of the canvas height (as per your
draw
function's logic). This creates a balanced, symmetrical pattern in this section of your artwork.
In essence, [0.5]
in drawLine(x, y, step, [0.5])
is what creates the precise, centrally aligned vertical line within each square it's applied to, contributing to the geometric aesthetic of the piece. By adjusting the array passed to positions
, you can control the number of lines within each square and their horizontal positions, offering a rich avenue for creative exploration in generative art.
LINK: home.inanimate.space
WEEK 3:
Review Loops:
Encode 1:
Elements -
A random assortment of Black and White Squares in a 20x10 grid
Scalable Window
Regenerates new assortment of squares when clicked by the mouse
Encode 2:
Elements -
the canvas is split into three rows
each row has 39 rectangles in it horizontally
the rectangles are skinny, filled with white, and with a black outline on a white background
the rectangles are randomly offset from vertically on a small scale, with each rectangle at a slightly different y-axis
Decode 1:
A white background
Shapes will have a black outline with a width of 2
Random Seed will be consistent to 2
a grid of square cells will appear on the screen. the angle and size of the cells will be randomized
pressing the mouse button will change the random seed to another seed
Decode 2:
A white background
Shapes will have a black outline with a width of 2
Random Seed will be consistent to 2
a grid of square cells will appear on the screen. the angle and size of the cells will be randomized
pressing the mouse button will change the random seed to another seed
AI Tutor Chat:
Re/Code 3: In this sketch I used the concepts applied in the Decode and Encode practices this week. I used an incrementing loop to randomly generate circles location on an alpha plane. I created variability in strokeWeight by also using my incrementing variable and I controlled the generation of the circles with a slowed framerate of 5fps for a more jagged generation
Reflection: In this weeks practice, I learned about applying chance in different ways to achieve different pattern results. I didn’t have many issues this time
explain about why this angle code is written this way: let angle = (TWO_PI * round(random(1, 5))) / 6; /* Inspired by Zdeněk Sýkora's Red-Green Structure 1, 1968, and based onb2renger's offscreen graphics 6: https://b2renger.github.io/p5js_patterns/pg_6/ */ //define variables let cellSize; let pg; //set seed to 100 let seed = 100; //initiate setup function function setup() { //create canvas to window width and height createCanvas(windowWidth, windowHeight); //change mode to place images from their center imageMode(CENTER); //run makeTileDesign function makeTileDesign(); } //start draw loop function draw() { //set background to white background(255); //set seed to random randomSeed(seed); //start for loop, define x to half of cellSize, add cellSize until x reaches width for (let x = cellSize/2; x <= width; x += cellSize) { //start for loop, define y to half of cellSize, add cellSize until y reaches height for (let y = cellSize/2; y <= height; y += cellSize) { //start transformation push(); //move shape to x, y coordinates translate(x, y); //define angle to PI times two multiplied by a rounded random number of 1 to 5 divided by 4 let angle = (TWO_PI * round(random(1, 5))) / 6; //rotate by angle degree rotate(angle); // draw the off-screen pixel graphics onto the canvas // just like an image file image(pg, 0, 0); //finish transform pop(); } } } //initiate makeTileDesign function function makeTileDesign() { //set cellSize to 1/5 of the width or height cellSize = min(width / 5, height / 5); // create an extra buffer of pixels "off screen" // on which to draw shapes (just like drawing on the canvas) // it needs a width and height (just like the canvas) pg = createGraphics(cellSize, cellSize); // draw an "outline" around it pg.noFill(); pg.strokeWeight(2) pg.square(0, 0, cellSize); // draw a circle on it pg.fill(255); pg.circle(0, pg.height / 2, pg.width); } //randomize the seed if the mouse is pressed function mousePressed() { seed = random(50000); } //resize the canvas and rerun the tile design if window is resized function windowResized() { resizeCanvas(windowWidth, windowHeight); makeTileDesign(); }
AI Tutor
This code snippet is a creative programming example that draws inspiration from Zdeněk Sýkora's artwork and uses offscreen graphics to generate a tile design pattern. Let's break down the specific part you're asking about and then how it fits into the broader context of the code.
The Angle Calculation
javascriptCopy code
let angle = (TWO_PI * round(random(1, 5))) / 6;
This line of code is used to generate a random angle for rotating tiles in the pattern. Here's what each part does:
random(1, 5): Generates a random floating-point number between 1 and 5.
round(...): Rounds the random number to the nearest whole number to ensure discrete rotation values. This limits the randomness to 1, 2, 3, 4, or 5.
TWO_PI: Represents a full circle in radians (approximately 6.28 radians). In p5.js, TWO_PI is used instead of 360 degrees for angle measurements.
(TWO_PI * round(random(1, 5))): Multiplies the rounded random number by TWO_PI, scaling the random number to a proportion of a full circle.
/ 6: Divides the product by 6, further scaling the angle to one of six possible segments of a full circle (0, 1/6, 2/6, 3/6, 4/6, or 5/6 of TWO_PI).
Purpose of the Angle in the Code
This angle calculation is part of a drawing function that places and rotates tiles to create a visually appealing, grid-based pattern. The randomness of the angle introduces variation in the orientation of the tiles, contributing to the dynamism and aesthetic complexity of the pattern. This method echoes the element of randomness and order seen in Zdeněk Sýkora's work.
Broader Context
The code defines a sketch using the p5.js library, which is designed for creative coding. It uses functions like setup() and draw() to initialize the sketch and continuously render the pattern, respectively. The pattern is composed of tiles, each rotated by a random angle calculated as described above, and drawn using offscreen graphics (pg). The makeTileDesign() function sets up these offscreen graphics, and the draw() function places and rotates them across the canvas to create the pattern.
Interaction
The sketch also includes interaction through the mousePressed() and windowResized() functions, allowing the pattern's seed to be randomized or the canvas to be resized and the pattern redrawn accordingly. These interactions add an interactive element to the artwork, allowing viewers to influence its appearance.
In essence, the angle code snippet is a crucial part of the algorithm that introduces randomness and variation into the tile pattern, inspired by the balance between order and randomness found in abstract art.
WEEK 2:
Decode 1:
30 randomly sized and placed squares
a set of 30 randomly sized squares,
smaller than the 30% of the canvas size will be placed in the canvas
I missed the aspect of the square getting smaller each time
Decode 2:
400 randomly placed white rectangle outlines will appear in a black canvas with various positions and width and heights between 5-150
the output ran as expected
Decode 3:
The program will create 100 lines with a random X and Y start after 20 of the canvas border. The end of the line will also be randomized with a 1/10 chance of an increased X coordinate, and a 9/10 chance of an increased Y coordinate. The randomness will follow a consistent order.
The output is mostly as expected, I think the jagged look of the lines output is more interesting than I assumed,
Decode 4:
The program will show a set of 40 white connected lines on a black background, with one line connected at the end of the previous. Each line will end on a random point on the canvas anywhere from 10 pixels away from the edge of the canvas.
Ran as expected
Decode 5:
The program will show a set of 1000 white connected lines on a black background, with one line connected at the end of the previous. Each line will end on a random point on the canvas. The positions will use the noise function to smooth the flow of the lines.
The program ran mostly as expected but the lines were curvier than I expected
AI Tutor Chat:
Re/Code 2: In this sketch I used the concepts applied in the Decode sketches using noise on a 3D box in OpenGL. I created rotating rectangles flying in space that slowly transform using the noise function.
Reflection: In this weeks practice, I think I fully learned how to apply the noise function. One thing I didn’t understand at first was how the tx and ty variables chose different locations to start from in the noise map in one of the decode sketches. The AI tutor explaination helped a lot. I should try to explore more complex transformations in my shape sketches.
in the case of this p5js sketch, what difference does ty and tx make in " startX = map(noise(tx), 0, 1, 0, width); startY = map(noise(ty), 0, 1, 0, height);" code: /* Inspired by Colette and Charles J. Bangert's Complex Intersecting Line (1976) and Roman Verostko's Sketch (1987) */ //init variables let startX; let startY; let endX; let endY; let num = 0; let total = 1000; let tx = 0; let ty = 1000; //setup function init function setup() { //resizable canvas with window size createCanvas(windowWidth, windowHeight); //background black background(0); //outline white stroke(255); //outline width 2 strokeWeight(2); //call find start and end point functions getStartPoint(); getEndPoint(); } //draw loop start function draw() { //while loop when num(0) is less than total(1000) while (num < total) { //draw line with variable values for start and end line(startX, startY, endX, endY); //set new start to previous end startX = endX; startY = endY; //find new end point with function getEndPoint(); //add 1 to num (until reaches 1000) num++; } } //find start point function function getStartPoint() { //scale noise value to the canvas size (height and width). X will start closer to 0 and Y will start closer to the edge of the canvas size startX = map(noise(tx), 0, 1, 0, width); startY = map(noise(ty), 0, 1, 0, height); } //find end point function function getEndPoint() { //scale noise value to the canvas size (height and width). X will end closer to 0 and Y will end closer to the edge of the canvas size endX = map(noise(tx), 0, 1, 0, width); endY = map(noise(ty), 0, 1, 0, height); tx += 0.01; ty += 0.01; }
AI Tutor
In this p5.js sketch, tx
and ty
play a crucial role in determining the starting points (startX
, startY
) and ending points (endX
, endY
) of the lines drawn on the canvas, using Perlin noise for generating smooth, naturalistic transitions in values. The noise()
function in p5.js generates Perlin noise values, which are more organic and less random-looking than the values generated by the random()
function. The values produced by noise()
range between 0 and 1.
The use of tx
and ty
as arguments in the noise()
function is a way to get smooth, continuous changes in the noise values over time. This is because Perlin noise is generated in a multidimensional space, and by slowly incrementing tx
and ty
, you effectively move through this space, creating a smooth transition of values rather than abrupt changes.
The lines:
javascriptCopy code
startX = map(noise(tx), 0, 1, 0, width); startY = map(noise(ty), 0, 1, 0, height);
and
javascriptCopy code
endX = map(noise(tx), 0, 1, 0, width); endY = map(noise(ty), 0, 1, 0, height);
map the noise values (which are between 0 and 1) to the dimensions of the canvas. For startX
and endX
, the noise value based on tx
is mapped to a range between 0
and width
of the canvas, effectively determining the horizontal position of the line's start and end points. Similarly, for startY
and endY
, the noise value based on ty
is mapped to a range between 0
and height
of the canvas, determining the vertical position of the line's start and end points.
The initial values of tx = 0
and ty = 1000
ensure that the starting points for generating noise values are different for the x and y coordinates, likely leading to a variety of starting and ending points for the lines. By incrementing tx
and ty
slightly with each call to getEndPoint()
, you ensure that each line drawn will have a slightly different starting and ending point, leading to a complex, intertwined pattern.
Can you think about how changing the increments of tx
and ty
might affect the drawing? Or what might happen if tx
and ty
started at the same value?
You
the movement might be too linear if they started at the same value. but what i dont understand is why ty starts at 1000 before being scaled
AI Tutor
You've made an insightful observation about the potential for movement to appear too linear if tx
and ty
started at the same value. The distinct starting values for tx
and ty
indeed contribute to creating a more varied and interesting pattern in the drawing. Now, let's address your question about why ty
starts at 1000.
In the context of Perlin noise, the starting values (also known as "seeds") for tx
and ty
are arbitrary points in the noise space. Perlin noise is generated over an infinite, continuous n-dimensional space. When you choose different starting points for tx
and ty
, you are essentially sampling different parts of this noise space for your x and y coordinates, which ensures that the noise values (and thus the coordinates based on these values) for x and y are not in sync. This desynchronization helps in creating more organic and less predictable patterns.
Starting ty
at 1000 is a deliberate choice to ensure that the noise function generates a significantly different set of values for startY
and endY
than it does for startX
and endX
. The large initial difference between tx
and ty
ensures that the vertical and horizontal movements are based on different parts of the noise space, contributing to the complexity and visual appeal of the pattern. The exact value of 1000 isn't inherently special; it's the relative difference between tx
and ty
that matters, creating distinct horizontal and vertical movements.
This approach of using distinct seeds for different dimensions is common in generative art and simulations to produce more complex and less predictable outcomes. It leverages the smooth, coherent randomness of Perlin noise to create visually interesting and varied patterns that wouldn't be possible if both dimensions followed the exact same path through the noise space.
Does this explanation help clarify the role of ty
starting at 1000 and its impact on the sketch?
WEEK 1:
Encode 1:
Elements -
Black Background
1 White Triangle
1 White Circle
1 White Square rotating clockwise at moderate speed
Inverted white to black on overlapping spaces on Triangle and Circle
Shapes layered back to front: Circle, Triangle, Square
Scalable Window
No Interaction
Encode 2:
Elements -
Black Background
1 Black Circle with a thick white outline moving on the x axis at a medium velocity
Scalable Window
No Interactionck Background
1 Black Circle with a thick white outline moving on the x axis at a medium velocity
Scalable Window
No Interaction
Encode 3:
Elements -
Black Background
1 Black Circle with a thick white outline. The outline is increasing and decreasing in thickness as well as the black circle is getting bigger and smaller.
Scalable Window
No Interaction
Encode 4: Elements -
Black Background
1 Black Circle with a white outline moving clockwise in a 360 around the center of the canvas. The circle has a blurred faded trail of its movement pattern that disappears shortly after
Scalable Window
No Interaction
Encode 5: Elements -
Black Background
1 White Filled Circle moving clockwise in a 360 around the center of the canvas with small overlaps. The circle has a blurred faded trail of its movement pattern that disappears shortly after. The circle rotates 10 times around in a pattern like a loading animation
Probably using alpha on background to make fading animation
Scalable Window
No Interaction
AI Tutor Chat:
Re/Code 1:
Pseudocode:
Define variables for x, y, and angle
Create setup function {
Make a canvas set to the window’s Width and Height
Set the color of the shapes outline to white
No color fill on shapes
}
Create draw function {
Create a minimum dimension variable that allows elements to be scaled to the window/canvas size
Start movement of line to rotate around the center clockwise:
Set X to the sin of angle multiplied by 1/4th of the minimum dimension
Set Y to the negative cosin of angle multiplied by 1/4th of the minimum dimension
Set background to black with an alpha to create a blur of the line’s movement
Move elements to the center of the screen
Create a line in center of the canvas with X and Y as it’s end points
Create a circle in the center of the screen with the same dimension as the end of the line.
Increase angle each repeat
}
Reflection:
In this week’s practice I learned how to effectively pseudocode and encode for programs. I think learning about these sketches in depth enabled me to learn more about creating patterns and movement in p5.
You
/* Based on p5.js demos by Matt DesLauriers https://github.com/mattdesl/workshop-p5-intro The MIT License (MIT) Copyright (c) 2019 Matt DesLauriers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ //define variable for angle let angle = 0; //setup function function setup() { //Make Canvas resizable to window createCanvas(windowWidth, windowHeight); //Don't fill shapes noFill(); //Outline color white stroke(255); } //resize Canvas when window is resized function windowResized() { resizeCanvas(windowWidth, windowHeight); } //draw loop initiation function draw() { //set background to black background(0); //define minimum dimension to either width or height depending on which is smallest let minDimension = min(width, height); //define amount to a sine movement let amount = sin(angle)/2 + 0.6; let thickness = minDimension/20 * amount; strokeWeight(thickness); let diam = minDimension/2; circle(width / 2, height / 2, diam); angle += 0.03; } what does sin(angle)/2 + 0.6; do
ChatGPT
ChatGPT
The expression sin(angle)/2 + 0.6
is used to create a dynamic, oscillating value based on the sine of the variable angle
, which is then used to modify some aspect of the drawing in the p5.js sketch. Here's a breakdown of how it works:
sin(angle)
: The sine function calculates the sine of an angle (in radians). The result ofsin(angle)
will oscillate between -1 and 1 asangle
increases. This oscillation creates a smooth, periodic wave pattern.sin(angle)/2
: Dividing the sine of the angle by 2 scales down the output range to -0.5 to 0.5. This reduces the amplitude of the oscillation, making the effect subtler.sin(angle)/2 + 0.6
: Adding 0.6 to the scaled sine value shifts the entire range of the output upwards. After this addition, the range of the expression becomes from 0.1 (whensin(angle)/2
is -0.5) to 1.1 (whensin(angle)/2
is 0.5).
The purpose of this specific calculation is to generate a value (amount
) that oscillates smoothly over time, which can be used to modulate visual properties in the sketch. In this case, it's used to vary the thickness of the stroke and potentially other properties tied to the visual appearance of the drawing. The result is an animation effect where elements of the sketch grow and shrink or change in intensity in a smooth, periodic manner, creating an engaging and dynamic visual experience.
The addition of 0.6 ensures that the amount
value never goes below 0.1, preventing the stroke weight from becoming too thin or disappearing entirely, while allowing it to grow thicker in a controlled manner. This technique is often used in creative coding to add dynamism and variability to visual outputs.