creating ‘voids’p5
Had to create voids / scars for a new project. Used vertices and contours inside to cut out voids / scars.
//going to use a contour cut out from a solid shape.
//exterior vertices have to be clockwise winding.
var left = 100;
var top = 100;
var w = 100; //left + w gives right-most coordinates.
var h = 100; //top + h gives bottom-most coordinates.
var right = left + w;
var bottom = top + h;
beginShape();
vertex (left, top); // LEFT TOP
vertex (right, top);
vertex (right, bottom);
vertex (left, bottom);
//now i need a shape to form inside this, anti-clockwise winding.
var leftInside = random(left, (left+w/2)); //from left to midpoint
var topInside = random(top, (top+h/2));
var rightInside = random(leftInside, right);
var bottomInside = random(topInside, bottom);
beginContour();
vertex (leftInside, topInside);
vertex (leftInside, bottomInside);
vertex (rightInside, bottomInside);
vertex (rightInside, topInside);
endContour();
endShape(CLOSE);
as classes:
let scars = [];
function setup(){
createCanvas(1000, 562); //in 16:9 aspect ratio.
scars [0] = new Scar(100, 100, 100, 100);
}
function draw(){
background (190);
for (let i = 0; i<scars.length; i++){
scars[i].display();
}
}
class Scar{
constructor(left, top, w, h){
this.left = left;
this.top = top;
this.w = w;
this.h = h;
this.right = this.left+this.w;
this.bottom = this.top + this.h;
this.leftInside = random(this.left, (this.left+this.w/2));
this.topInside = random(this.top, (this.top+this.h/2));
this.bottomInside = random(this.topInside, this.bottom);
this.rightInside = random(this.leftInside, this.right);
const deviationRange = 10;
const gap = 5;
this.leftRowXs = [];
this.leftRowYs = [];
this.rightRowXs = [];
this.rightRowYs = [];
for (let y = this.topInside; y<=this.bottomInside; y+=gap){
var deviation = random(-deviationRange, deviationRange);
this.leftRowXs.push(this.leftInside + deviation);
this.leftRowYs.push(y);
}
for (let y = this.bottomInside; y>=this.topInside; y-=gap){
var deviation = random(-deviationRange, deviationRange);
this.rightRowXs.push(this.rightInside + deviation);
this.rightRowYs.push(y);
}
}
display(){
beginShape();
vertex (this.left, this.top);
vertex (this.right, this.top);
vertex (this.right, this.bottom);
vertex (this.left, this.bottom);
beginContour();
vertex (this.leftInside, this.topInside);
for (let i = 0; i<this.leftRowXs.length; i++){
vertex (this.leftRowXs[i], this.leftRowYs[i]);
}
vertex (this.rightInside, this.bottomInside);
for (let i = 0; i<this.rightRowXs.length; i++){
vertex (this.rightRowXs[i], this.rightRowYs[i]);
}
endContour();
endShape(CLOSE);
}
}
more existence artworkp5
looking at the shape of cells, introducing some randomness, etc.
19:20, 2024-11-06
existencep5
made a sketch that has been on my mind for a while.
the idea is to represent existence.
each ‘cell’ (circles) have links to other ‘cells’.
14:20, 2024-11-06
water-boystrudelhydra
spent 30 minutes today learning some hydra. had an idea in mind and could figure out how to execute it.
i’ll get there slowly.
await initHydra()
s0.initCam()
src(s0)
.modulate(noise(2, 0.5))
//.pixelate(100, 100)
.color(1,3,5)
.mult(noise(4, 0.5))
.out(o0)
//drums
$: s ("bd bd bd bd").bank("AlesisSR16").delay("0.2 0.4 0.8").echo(4, 1/4, .2).gain("0.1")._punchcard()
$: s("[hh]*4 [hh]*2 [hh] [hh]*4").bank("AlesisSR16").gain("0 0.2 0.6 1 0 0.2 0.6 1").chop("2 4 6 8 10 2 4 6 8 10")
//bass
$: n("[0] 2 [4 6] 2").scale("D3:minor").sound("gm_contrabass").scaleTranspose("-2 -4 2 -2").echo(8, 1/4, .02)
//highfreqMelody
$: n("[1 3 7 4] [7 5 4 1] [3 5 7 2] [1 4 7 2]").scale("D4:minor").sound("triangle")._scope().slow(2).lpf(1000).gain("sine")
17:36, 2024-11-05
strudelhydra
day 0 at the b-side festival. messed around with some code, in my room, at night.
//$: s("[hh*4, bd, oh] [hh hh] [hh]*6 [hh , oh]")
await initHydra()
noise (10)
.layer(gradient().r())
.thresh(0.5,0.1)
.color (0, 0.4, 0.7)
.modulateRepeat(noise(1000),2, 2, 0.5, 0.5)
.out(o0)
$: note("<c4 a4 b3 f4 c3> , [f5*2 g5/4 g6]*2 , [g5 b4*2 a4] ").sound("piano , gm_epiano2 ").gain("0.3 , 0.6 0.9")
$: s("cp").gain(1)
$: s("[hh*2 [sd , mt] bd]*2").lpf("1000").gain("0.2")
$: note("f3 f1/2 f2").sound("gm_electric_guitar_clean")
//$: note("[c4, a4, b3] , b5 g4/2 a@5").sound("gm_electric_bass_pick").lpf("800")
23:00, 2024-10-15
strudel + hydra learningstrudelhydra
spent some time trying to study sheet-music-theory and recreating melodies from a new coldplay song. paired with some hydra learning for visuals. hydra’s simple, but powerful.
// feelslikeimfallinginlove inspired
/*
reference sheet: https://musescore.com/user/60217162/scores/19154851
reference video: https://www.youtube.com/watch?v=7pr7GpLdBxU&t=40s
*/
//modular bd from bank = EmuModular
//hydra
await initHydra()
noise(Math.sin(10)+5, 0.5).thresh(0.5, 0.8).color(10, 20, 2).kaleid(50).rotate( () => (time%90)/10).out(o0)
//music
$: n("<5 ~ >/2"). sound("gm_synth_choir").lpf("1000").gain(choose("0.2 0.5 0.7"))
$: s ("<bd>").cpm ("121").bank ("KorgKR55").stretch ("0 0.06 0 0.06").lpf("300").gain("0.4")
//base chord
$: note ("<[c2,c3] [c@3] [c!3] [c@3] [c3]>*2").cpm("120").sound("gm_piano"). gain("0.09")
//melody2
$: note("<[g3 , e4] ~ [c4 e@4 g4 a5] [c5 , f4] [f4 , a4]>/2").cpm("120").sound("gm_epiano2").gain(choose("0.5")).adsr(".09:0.2:0.3:0.5")
//hh
$: s("<[oh] ~ [hh]*3 [hh , oh, sd] [oh ,sd] [hh]*3 [hh , oh, sd] >*2").cpm("120").bank("AlesisHR16").gain("0.01")
//c note
//$: note ("<[c2, c3] c3 [c3 c3@ c3]>").sound("gm_piano")
//melody
//$: note ("<<g4 , e5> [c5 e5 g5 a6] [f5, c6@] <f5 , a6> [g5] <e5, g5>>*2").sound ("piano")
22:33, 2024-10-12
drawings with the cartesian coordinate systemp5
i have been toying around the idea of using the cartesian coordinate system as a framework to generate drawings.
some outputs from 11th october:
i think this sets the base for a long-term project, perhaps something that i can explore over the course of months. it also improves my understanding of drawing with 2D geometry.
outputs will get increasingly complex with time.
19:55, 2024-10-11
lift patternp5
saw the original (static) pattern on the roof of sakina’s lift. an ellipse is overlaid with a rotating square. messing around with radii leads to scope of exploration with figure & ground.
//Sakina's Lift; October, 2024.
let r = 50;
let margin = r;
function setup() {
createCanvas(1000, 1000);
rectMode(CENTER);
angleMode (DEGREES);
noStroke();
}
function draw() {
background(0);
var t = frameCount/60;
for (let x = margin; x<=width-margin; x+=r){
for (let y = margin; y<=height-margin; y+=r){
fill (255);
ellipse (x, y, r);
push();
translate (x,y);
//debug
/*
rotate (45);
fill ('red');
*/
//actual
fill (0);
rotate (sin(t)*500);
square (0,0,r/1.3, r/10);
pop();
}
}
}
21:02, 2024-10-08
maybe i need to make it staticp5
if it runs in real time, it lags quite a bit. anyway, made progress on the new painter.
parameters:
/*
PARAMETERS
//brush selection
- brushWidth = how thick the end-stroke is supposed to be. think of it like paintbrush 'size' (breadth).
- frayness = how far apart (vertically) are the bristles from each other?
- fineness = how far apart (horizontally) are the bristles from each other?
- bristleWidth = how thick are the bristles themselves?
//colour
- colour = what (all) colours do you want in your painting?
- opacity = how opaque or transparent do you want your strokes to be?
//starting position
- margin = set the margin for your composition.
- originX, originY = starting x and y position on the canvas.
- startingAngle = at what angle do you place your paintbrush.
//travel
- directionToMove = what direction are you going to move your brush in?
- distance = what distance should the paintbrush travel?
- pace = how fast should the paintbrush travel?
*/
14:37, 2024-09-30
new painting algorithmp5
i revisited my old computer-painting algorithm.
since my understanding of programming has become better, i was able to rethink the algorithm. now, each brushStroke is treated as an object that gets the following data as input:
//A brushStroke has a starting position (originX, originY), brushWidth (the breadth of the stroke), startingAngle, distance (that it has to travel), pace (speed at which it is supposed to travel), colour & opacity of that colour, how much the bristles have frayed (frayness), fineness (how close or apart the bristles are from each other) and bristleWidth (how small or big are the bristles).
constructor(originX, originY, brushWidth, startingAngle, distance, pace, colour, opacity, frayness, fineness, bristleWidth, directionProbability){
}
23:13, 2024-09-29
everything is about u
p5 sketch.
Used the shape of a parabola to represent ‘u’. Wanted a trail system but couldn’t figure it out; so gave variance by changing size.
var seconds = frameCount / 60;
//yStretch=map(noise(seconds), 0, 1, 10, 50);
this.x = map(sin(seconds), -1, 1, -xStretch, xStretch);
this.y = map(this.x * this.x * 6, 0, xStretch * xStretch, 0, yStretch);
this.s = map(noise(seconds), 0, 1, 3, 20);
//circle(initX + x, initY - y , 50);
circle(this.initX + this.x, this.initY - this.y, this.s);
The formula for a (reverse) parabola is this:
var seconds = frameCount / 60;
var x = map(sin(seconds), -1, 1, -xStretch, xStretch);
//quadratic equation to give parabola y = x*x
var y = map((x*x)*1, 0, xStretch*xStretch, 0, yStretch);
circle(initX + x, initY - y , 50);
Also, fixed my lettersToPoints library to include maxWidth and maxHeight as well. And now it’s deliverable via CDN: https://github.com/arjunmakesthings/p5.textToPoints
17:28, 2024-09-22
this is how i feelp5 +strudel
visuals and music.
visuals inspired by the thought – we’re two bodies in space. music inspired by gravity, john mayer. i miss you.
//we're two bodies in space, september 2024.
$: s ("[[hh , [bd]] hh hh [hh , sd] hh hh] , <oh>/4").cpm(23).bank("ViscoSpaceDrum").room("0 0.2")
$: n("<[0@ 1 3 5@] ~ [5@ 3 1 0@] ~> ").scale("G:major").sound("gm_electric_guitar_clean").cpm(23).room("0 0.2 1")
$: n ("0 , 0").sound("gm_fx_echoes").loopAt( "0.4 , 0.7").gain("0.2 ").lpf(500).room("0 0.2 0.4")
//sketching; squares and sine; september 2024.
let margin = 200;
let w = 800;
let h = 25;
let amp = 70;
function setup() {
createCanvas(1000, 1000);
noStroke();
rectMode(CENTER);
}
function draw() {
//background('#176383');
background(0);
var t = frameCount / 60;
fill(255);
//noFill();
for (let x = margin; x <= width - margin; x += w/2) {
for (let y = margin; y <= height - margin; y += h) {
push();
translate (x + sin(y + t) * amp, y);
//var ang = map(sin(t), -1, 1, 0, TWO_PI);
var ang = (t+sin(y+t))*0.2
rotate (ang)
rect(0, 0, w*(sin(y+t)*0.4), h);
pop();
}
}
}
23:29, 2024-09-21
strudel + learning hydrastrudelhydralivecoding
i like the idea of ‘livecoding’. someday, perhaps, i can perform for people.
i enjoyed reading a little bit about hydra. i think there’s a lot of potential there. will deep-dive.
//21 Sep, 2024.
await initHydra()
osc(10 , 0.09 , (Math.PI*2)*0.1).kaleid(Math.PI*2).scale(1,1,()=>window.innerWidth/window.innerHeight).out()
$: n("[<3 [5 7] [3@] 1>*2] , <<[4]*2> <[5]*2> <[7]*2> <[3]*2>>").scale("A2:minor, C3:major").sound("gm_slap_bass_2").gain ("0.7 , [0.3 0.6 0.9]")
$: s ("[hh]*12 [oh , bd]").delay("0 0.6 , 0").gain("0.1 [0.3 , 0.1]").bank("RolandCompurhythm1000 , EmuSP12").lpf("[500 1000 1500 2000] 5000")
$: note("<[f5]*3 [e4]*3 [d3]*3 ~ >*2 , <c2@ b2 a2 c2@>*2").sound("gm_drawbar_organ").lpf("8000")
17:34, 2024-09-21
circles and sinep5
//sketching; circles and sine; september 2024.
let w = 50;
let margin = 0;
let amp = 200;
function setup() {
createCanvas(1000, 1000);
noStroke();
}
function draw() {
//background('#176383');
background(255);
var t = frameCount / 60;
//fill(255);
for (let x = margin; x <= width - margin; x += 300) {
for (let y = margin; y <= height - margin; y += w / 2) {
fill (62, 210+(sin(y+t))*10, 198)
circle(x + sin(x + y + t) * amp, y, w + sin(y + t) * 100);
}
}
}
20:37, 2024-09-20
20 sept - rainy daystrudel
//20 sept, rainy day
$: s ("<hh [hh hh hh] hh [hh hh hh] hh [hh hh hh] hh hh>*4").gain ("[0.1 1 0.1] 0.5")
$: s ("<oh - [oh oh] - >*2").gain("0.6")
$: s ("bd [bd - bd]*2").bank("BossDR110").amp("0.5"). gain("0.09 0.5")
$: note ("<[c]*2 [f g e a] [d]*2>").sound("gm_electric_guitar_jazz").gain ("[0.5 0.7 0.3] 0.4")
$: note ("<c c f g>").sound("gm_epiano1").echo(3, 1/6, .4).gain(0.4)
01:35, 2024-09-20
finally a livecoding tool that works for me!strudel
Discovered strudel during a computational arts festival here in Delhi. Love the software. Plus it’s javascript; wondering how to combine p5 and strudel for some audio-visual stuff.
I swear I had a sicker beat.
//cfgd melody
$: s("oh sd , bd -").delay ("0.3 0 ").amp("2 0").hush()
$: note ("[[c]*4 [f]*4 [g]*4 [d]*4]").sound("gm_synth_strings_2").amp ("0.8").lpf("1000")
$: s("<hh hh [hh hh] hh - sd ->*8").amp ("1").hush()
//$: s("[[hh]*16], [sd - sd oh], [bd - bd]*2").amp("0.01")
18:28, 2024-09-17
make visual artefacts of digital rantsp5
You can rant openly, without anyone else ever making full sense of what you said that day. I think this could be an interesting tool.
I need to debug overlaps, add dates and the ability for people to save pictures of their rants.
22:53, 2024-08-22
physics typographyp5matterjs
Based on my matterjs boilerplate, I used some elements of my previous writing tool work.
You type, and create a ‘sentence’.
function keyTyped() {
if ((keyCode != ENTER) & (key != " ")) {
typedSentence += key;
//actual display of letters
/*
xoff+=0.001;
xPos += textWidth(key)*random(2, 3, 5);
ang += noise(xoff);
letters.push(new Letter(key, xPos, yPos, ang));
*/
} else if ((key == " ") | (key == ENTER)) {
sentences.push(
new Sentence(
typedSentence,
random(
width / 2 - textWidth(typedSentence),
width / 2 + textWidth(typedSentence)
),
yPos
)
);
//xPos += textWidth('OO') * 10;
typedSentence = "";
}
}
The sentence is a ‘body’.
class Sentence {
constructor(t, x, y) {
this.t = t;
this.x = x;
this.y = y;
// Adjust density and remove slop
this.body = Bodies.rectangle(
this.x,
this.y,
textWidth(this.t) * 1.82,
tSize * 1.2,
{
friction: 1, // High friction to reduce sliding
restitution: 0.0005, // No bouncing
mass: 0, // Adjust density to reduce overlap
inertia: Infinity, // Prevent rotation
frictionAir: 0.005 // Slight air resistance to slow down
}
);
Composite.add(engine.world, this.body);
}
display() {
fill(255);
textSize(tSize);
textFont ("Crimson Pro");
push();
translate(this.body.position.x, this.body.position.y);
// Debug: Show the bounding box
fill(255);
strokeWeight (1);
stroke (0);
rect(0, 0, textWidth(this.t) * 1.82, tSize * 1.2);
// Display the text
fill(0);
noStroke();
text(this.t, 0, 0);
pop();
}
}
I think I need to look at why the bodies aren’t solid enough. They seem to overlap after some time. Is the density not enough? Maybe that could be set to infinity. Crap, forgot that.
I think there’s literal ‘weight’ in words. And a tool that allows you to write but also feel the weight in your words could be interesting. Maybe different words could have different ‘weights’?
I don’t know. Still exploring.
23:30, 2024-08-19
matter.js boilerplatep5matterjs
Made this to never watch a video again to learn the fundamentals of matter.js. Further reference is here: https://brm.io/matter-js/docs/classes/World.html
//Boilerplate for getting started with matter.js; Arjun, August 2024.
//Ensure you've added the matter.js file to your index.html file.
//Most libraries are namespaced to avoid clashes with other language-specific variables. We create variables to avoid using matter.something every single time.
var Engine = Matter.Engine,
//Render = Matter.Render, //matter.js has an in-built renderer as well. However, since we're using p5, this isn't necessary for us.
Runner = Matter.Runner,
Bodies = Matter.Bodies,
Composite = Matter.Composite;
//global variables that will be used later:
var engine;
var runner;
//this is where you can declare your 'bodies' for later:
var particle;
//this is for the ground:
var ground;
function setup() {
createCanvas(windowWidth, windowHeight);
//physics engine takes rect from center, center; so doing the same for p5
rectMode (CENTER);
// Matter is a physics engine. So, we create an engine in the program:
engine = Engine.create();
// This is where we can create bodies. Any initialisations of arrays can also go here.
particle = Bodies.rectangle (width/2, 0, 100,100);
// This is where we're creating a ground
ground = Bodies.rectangle(width/2, height/2, 200, 20, {isStatic: true});
// All bodies are composited, along with adding them to a 'world'.
Composite.add(engine.world, [particle, ground]);
// A runner keeps updating the engine and syncs it with the browser frame-rate.
runner = Runner.create();
Runner.run(runner,engine);
}
function draw() {
background(0);
// Bodies have inherent properties that are namespaced. We can use this to draw things.
rect (particle.position.x, particle.position.y, 100,100);
//also drawing the ground for reference:
fill (170);
rect(width/2, height/2, 200, 20);
}
22:09, 2024-08-19
writing tool v1p5
I’m working on a journalling tool of sorts? The goal is to try and help people capture a visual memoir of an automatic writing session. I think I’ll work on this slowly, solving problems and exploring the scope through multiple versions.
Today it was just about cracking the idea of typing on the screen and the letters being processed as individual shapes (so that I can perhaps try and manipulate them in some way).
function keyTyped() {
if (keyCode != ENTER) {
// automatic line break
if (xPos > width - 100) {
yPos += tSize * 2; //consider this leading; at the moment double of text size.
xPos = 100;
}
//actual display of letters
xoff++;
xPos += textWidth(key)*random(2, 3, 5);
ang += noise(xoff);
letters.push(new Letter(key, xPos, yPos, ang));
} else if (key == " ") {
xPos += textWidth(O) * 3;
}
// forced line break
if (keyCode == ENTER) {
yPos += tSize * 2.5; //consider this after-para
xPos = 100;
}
}
00:51, 2024-08-18
gaze-tracking prototypep5
finished working on an open-source gaze-tracking research tool prototype.
code here: https://github.com/arjunmakesthings/gaze-tracker use here: https://arjunmakesthings.github.io/gaze-tracker/index.html
maybe i have the potential to make more micro-tools and share them with the world; some silly, some, just perhaps, useful.
02:51, 2024-08-11
webgazep5
Figuring out gaze tracking via the webgaze.js library. Using a sketch by CedHon.
I think it could be interesting to see if open source, accessible gaze-tracking tools could be made for UX research.
I just need to figure out easier ways to train it, move it out of the training zone, track eye-movement data, and then present a summary of the findings. Time for a mini-program maybe?
Too sleepy to do this right now. But yes, in the works.
00:02, 2024-07-29
i’m losing myselfp5
Type sketch. Would be nice to sync it to a piano melody. Maybe I should create one using the same mathematical expressions? That could be interesting.
//I'm Losing Myself, June 2024.
let message =
"i'm losing myself";
let horSpacing = 1;
let margin = 100;
let tSize = 12;
function setup() {
createCanvas(800, 800);
textAlign(CENTER, CENTER);
rectMode(CENTER);
textSize(tSize);
fill(0);
angleMode(DEGREES);
}
function draw() {
background(255);
var t = frameCount / 60;
translate(width / 2, height / 2);
for (let i= 0; i<message.length; i++){
noStroke();
var a = 10;
var x = 300-i*40;
var y = i*8;
var ySpeed = (sin(t*i*4));
var xSpeed = sin(t*10);
text(message, x*xSpeed, y*ySpeed);
a+=200;
strokeWeight (0.5);
stroke (100);
line (x, y, x*xSpeed, y*ySpeed);
}
}
function mousePressed() {
//save("frame.jpeg");
}
13:32, 2024-07-03
first ever scriptp5
Published a script to help people draw with text. It uses a resolved version of what Navya originally shared with me during a collaborative experiment, made a lot easier for anyone to plug & play.
All the documentation is on GitHub.
19:46, 2024-06-28
growing up is messyp5
Type sketch. Made while mum was in surgery and I was writing my ‘growing up’ article.
for (let y = 20; y<=height-20; y+=50){
for (let x = 20; x<=width-20; x+=230){
for (let i = 0; i<t.length; i++){
textSize (140+tSize);
tSize = sin(frameCount*0.03)*100;
text (t[i], x+(i*20), y)
}
}
}
12:20, 2024-06-27
gravity-basedSonicPi
Added a melody on top of the existing drum beat. Melody structure was simple, took notes from the Gravity intro and made SonicPi choose from the array.
Fun melody structure.
#Melody2
notes = [:E, :G, :G, :A, :A]
#use_random_seed 1010892
live_loop :melody , sync: :met do
#use_synth_defaults attack: 0.5, decay 0.5,
5.times do
use_synth :piano
play notes.choose
sleep 1
end
sleep 6
notes2 = [:E5, :G5, :G5, :A5, :A5]
7.times do
use_synth :piano
play notes2.choose
sleep 0.5
end
sleep 6
end
22:00, 2024-06-13
gravity-inspiredSonicPi
Was inspired by the structure of ‘Gravity’ by John Mayer. Attempted to recreate logically on SonicPi.
The track has a high-hat that runs every beat.
#inspired by Gravity
use_bpm 124
sample :drum_splash_hard
#Making a metronome
live_loop :met do
sleep 1
end
#Setting ticker pattern
define :pattern do |pattern|
return pattern.ring.tick === 'x'
end
live_loop :hh, sync: :met do
sample :drum_cymbal_closed if pattern "xxxxxx"
sleep 1
end
Then, there’s the snare and the double kick-drum.
#Drums
live_loop :kickDrum , sync: :met do
with_fx :echo , decay: 0.08 , phase: 0.15 do
sample :drum_heavy_kick , amp: 0.7 if pattern "x-----"
sleep 1
end
end
live_loop :snare , sync: :met do
sample :drum_snare_hard if pattern "---x--"
sleep 1
end
Essentially sounding like this:
Then came the tricky part that I’m yet to figure out: the melody. For now, it’s the chords with an ugly-sounding dpulse synth.
#melody
melody_pattern = "-----------x------------"
notes = [:E, :G, :G, :A, :A]
live_loop :notes1, sync: :met do
use_synth :dpulse
if melody_pattern.look == "x" # Use look to check the current step in the pattern
play :E
sleep 1
play :G
sleep 0.5
play :G
sleep 1
play :A
sleep 1
play :A , decay: 1
sleep 1
# No need for an else statement, just tick at the end
tick # Move to the next step in the pattern
else
sleep 1
tick # Move to the next step in the pattern even if not playing
end
end
melody_pattern2 = "----------------------x"
live_loop :notes2, sync: :met do
use_synth :dpulse
if melody_pattern2.look == "x" # Use look to check the current step in the pattern
play :E
sleep 1
play :G
sleep 0.5
play :G
sleep 1
play :A
sleep 0.5
play :A
sleep 0.5
play :A , decay: 1
sleep 1
# No need for an else statement, just tick at the end
tick # Move to the next step in the pattern
else
sleep 1
tick # Move to the next step in the pattern even if not playing
end
end
Together sounding like this:
I think instead of chasing after Gravity, I can now start to play around with the structure that is created. Let’s see what comes of it, might scrap the whole melody bit. It ain’t working.
12:42, 2024-06-12
city gridpunctual
Was meaning to try some text manipulation but ended up making a zooming in / out of a city grid like structure with some noise.
a << 0.1;
zoom [osc(0.005)] $
tile [1, osc(frt*0.2)*20] $
circle [0, 0] [10] * img "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSt6AfgR9v6HaWpAYVjMgHiYGmKYTwo136uyg&s" * 0.4
>> video;
20:10, 2024-06-11
even breathing is exhaustingp5
Worked peacefully to try and understand how text is being processed, so that I can draw more effectively while maintaining the message. Made a simple sketch.
//Full code
//evenBreathingisExhausting, May 2024.
let message = "even breathing is exhausting";
let angle = 0;
let radius = 90;
function setup() {
createCanvas(800, 800);
background(255); //set background before sketch starts
textAlign(CENTER, CENTER);
textSize(14);
fill(0);
angleMode(DEGREES); //Radians to degrees
}
function draw() {
background(255);
for (let i = 0; i < message.length; i++) {
let angle = ((TWO_PI * message.length * i) / message.length) * 2; //change i divisor to reduce gap between letters
let x = width / 2 + cos(angle) * radius;
let y = height / 2 + sin(angle) * radius;
push();
translate(x, y);
rotate(map(i, 0, message.length, 0, 360));
text(message[i], 0, 0);
pop();
radius += sin(frameCount) / 25; //increase divisor to make it smaller
}
}
function mousePressed() {
//save("frame.jpeg");
}
22:11, 2024-05-24
more textp5
for (let i = 0; i < message.length; i++) {
for (let r = 20; r<=400; r+=5){
let angle = (TWO_PI * message.length) * i;
let x = width / 2 + cos(r+angle3) * r/2;
let y = height / 2 + sin(r+angle) * 300;
push();
translate(x, y);
//rotate(angle);
text(message[i], 0, 0);
pop();
//radius+=0.04;
angle3 +=0.0008;
}
}
17:08, 2024-05-24
text spiralp5
for (let i = 0; i < message.length; i++) {
for (let r = 20; r<=400; r+=15){
let angle = (TWO_PI * message.length) * i*20;
let x = width / 2 + cos(r+angle3) * i;
let y = height / 2 + sin(angle) * r;
push();
translate(x, y);
//rotate(angle);
text(message[i], 0, 0);
pop();
//radius+=0.04;
angle3 +=0.008;
}
}
16:56, 2024-05-24
more text stuffp5
I think the effect is pretty cool but it loses readability. But is that even important? Can’t this just be a piece made from the aesthetics of letters?
In all fairness, I have zero idea about what’s happening in the code. I was just fiddling around with previous algorithms. But here:
for (let r = 20; r<=800; r+=8){
for (let i = 0; i < message.length; i++) {
let angle = (TWO_PI * message.length) * i*20;
let x = width / 2 + cos(r+angle) * r;
let y = height / 2 + sin(angle) * r;
push();
translate(x, y);
//rotate(angle);
text(message[i], 0, 0);
pop();
}
}
It can also move apparently (?)
16:52, 2024-05-24
using beatbox-samplesSonicPi
Messed around with some beatbox samples from the internet for some quick exploration.
use_bpm 120
#Making a metronome
live_loop :met do
sleep 1
end
#Setting ticker pattern
define :pattern do |pattern|
return pattern.ring.tick === 'x'
end
"
Custom loaded samples here
"
live_loop :kick, sync: :met do
sample k, amp: 3 if pattern 'x-x-x-x-'
sleep 0.5
end
live_loop :snare, sync: :met do
sample s, amp: 3 if pattern '-x--xx-xx-x-x--'
sleep 0.25
end
live_loop :sh, sync: :met do
sample whisp, amp: 5 if pattern '-------x'
sleep 0.5
end
"
live_loop :snare2, sync: :met do
sample snare if pattern '---xx--xx'
sleep 0.25
end
"
we keep going around in spiralsp5
Similar idea as the one before, doing drawing manipulations with each letter of a sentence.
angleMode(DEGREES);
let angle = 0;
let radius = 0;
for (let i = 0; i < message.length; i++) {
let x = width / 2 + cos(angle) * radius;
let y = height / 2 + sin(angle) * radius;
push();
translate(x, y);
rotate(angle);
text(message[i], 0, 0);
pop();
angle += baseAngleStep;
radius += baseRadiusStep;
baseAngleStep += 0.1;
baseRadiusStep += 0.03;
}
14:22, 2024-05-23
text-recursionp5
Played around with the idea of making typography through recursion.
First, I figured out a way to go through the “array” of a sentence. For example, if the sentence is:
let message = "i'm so messed up";
for (let i = 0; i < message.length; i++) {
//Treats each character as an object – so you can do drawing manipulations.
}
Then, I used some nested loops which I’ve been studying in the Stanford Code in Place course.
function draw() {
background(255);
for (let x = 50; x <= width; x += 200) {
for (let y = 0; y < height-90; y += 50) {
for (let i = 0; i < message.length; i++) {
push();
translate (x + i * 9, 400+sin(y)*(i*100));
rotate(sin(i*angle)*200);
text(message[i], 0,0 );
angle+=0.0003;
pop();
}
}
}
}
14:55, 2024-05-22
sonic-pi learning jam, 21 maySonicPi
Boilerplate like DJ_Dave (https://www.youtube.com/watch?v=vuSZQnkOB_Y&t=389s) to set a metronome and ticker pattern.
use_bpm 60
#Making a metronome
live_loop :met do
sleep 1
end
#Setting ticker pattern
define :pattern do |pattern|
return pattern.ring.tick === 'x'
end
Using patterns:
use_bpm 120
#Making a metronome
live_loop :met do
sleep 1
end
#Setting ticker pattern
define :pattern do |pattern|
return pattern.ring.tick === 'x'
end
live_loop :kickDrum, sync: :met do
sample :bd_ada, amp: 1 if pattern "x--xxx--x----xx-"
sleep 0.25
end
live_loop :hh, sync: :met do
sample :drum_cymbal_closed if pattern "xxxx--xx--xxxx--"
sleep 0.25
end
Basically, everything with ”-” is a break. So, “xxxxxxxxxxxxxxxx” is the same as playing a loop with a certain amount of sleep between sounds.
Made this with the above-mentioned logic:
Here’s the code:
use_bpm 120
#Making a metronome
live_loop :met do
sleep 1
end
#Setting ticker pattern
define :pattern do |pattern|
return pattern.ring.tick === 'x'
end
live_loop :kickDrum, sync: :met do
sample :bd_ada, amp: 1 if pattern "x--xxx--x----xx-"
sleep 0.25
end
live_loop :hh, sync: :met do
sample :drum_cymbal_closed if pattern "xxxx--xx--xxxx--"
sleep 0.25
end
live_loop :vinyl, onset: 3, sustain: -2, decay: -2, sync: :met do
sample :vinyl_scratch, amp: 0.2 if pattern "---------------x"
sleep 1
end
#Piano
notes = (ring :E4, :Fs4, :B4, :Cs5, :D5, :Fs4, :E4, :Cs5, :B4, :Fs4, :D5)
live_loop :piano, sync: :met do
6.times do
use_synth :piano
play notes.choose, amp: 0.5, release: 0.1
sleep 0.25
end
1.times do
play notes.tick , amp: 0.7, release: 3, sustain: 2
sleep 4
end
end
Used an array of notes for the piano, i.e notes = (ring :E4, :Fs4, :B4, :Cs5, :D5, :Fs4, :E4, :Cs5, :B4, :Fs4, :D5)
.
Then, the computer chooses a note 6 times in the first loop:
6.times do
use_synth :piano
play notes.choose, amp: 0.5, release: 0.1
sleep 0.25
end
And ticks through the array once every loop for the 7th note:
1.times do
play notes.tick , amp: 0.7, release: 3, sustain: 2
sleep 4
end
21:15, 2024-05-21
making a hand-synthesiserp5
Using my previous study on hand landmarks, I made a synthesiser that operates via the hand.
First, the program calculates the distance between each finger on a single hand and returns this distances.
function distCalc() {
var dIndex = dist(thumbTip[0], thumbTip[1], indexTip[0], indexTip[1]);
var dMid = dist(thumbTip[0], thumbTip[1], middleTip[0], middleTip[1]);
var dRing = dist(thumbTip[0], thumbTip[1], ringTip[0], ringTip[1]);
var dPinky = dist(thumbTip[0], thumbTip[1], pinkyTip[0], pinkyTip[1]);
textAlign (LEFT);
textSize(10);
fill(0);
noStroke();
text("thumb-index: " + int(dIndex), 50, 30 + 15);
text("thumb-middle: " + int(dMid), 50, 30 + 30);
text("thumb-ring: " + int(dRing), 50, 30 + 45);
text("thumb-pinky: " + int(dPinky), 50, 30 + 60);
textAlign(RIGHT);
text ("frequency playing: "+ freqPlaying, width-50, 30+15);
perform(
dIndex,
dMid,
dRing,
dPinky,
thumbTip[0],
indexTip[1],
middleTip[1],
ringTip[1],
pinkyTip[1]
);
}
Then, a function called ‘perform’ maps distances to frequencies based on the ‘note’ assigned to each finger (index is A, middle is B … and so on). Furthermore, horizontal position of the thumb determines the amplitude whereas vertical position of the fingers determine the pitch (high to low).
function perform(
dIndex,
dMid,
dRing,
dPinky,
thumbTipX,
indexTipY,
middleTipY,
ringTipY,
pinkyTipY
) {
//Changing amplitude based on horizontal position of thumb on screen.
amp = constrain(map(thumbTipX, width, 0, 0, 1), 0, 1);
//Mapping frequencies to position of finger on screen.
//Used music references from Tom Cortina's Class: 15-104 Introduction to Computing for Creative Practice (24, More Sound).
indexFreq = map(indexTipY, height, 0, 27.5, 880); //A0-A5
middleFrequency = map(middleTipY, height, 0, 30.868, 987.77); //B0-B5
ringFrequency = map(ringTipY, height, 0, 32.703, 1046.5); //C1-C6
pinkyFrequency = map(pinkyTipY, height, 0, 43.654, 1318.5); //E1-E6
//Consider boilerplate for playing. True means amp is set based on the mapping and oscillator starts, else oscillator amp is 0.
if (playing) {
osc.amp(amp, 0.1);
osc.start();
playing=false;
} else {
osc.amp(0, 0.1);
}
//Main playing mapping – each bucket takes a distance threshold and plays a certain frequency.
if ((dIndex <= 80) & (dIndex != 0)) {
//for index
osc.freq(indexFreq, 0.1);
playing = true;
freqPlaying = indexFreq;
} else if ((dMid <= 80) & (dMid != 0)) {
//for middle
osc.freq(middleFrequency, 0.1);
playing = true;
freqPlaying = middleFrequency;
} else if ((dRing <= 80) & (dRing != 0)) {
//for ring
osc.freq(ringFrequency, 0.1);
playing = true;
freqPlaying = ringFrequency;
} else if ((dPinky <= 80) & (dRing != 0)) {
//for pinky
osc.freq(pinkyFrequency, 0.1);
playing = true;
freqPlaying = pinkyFrequency;
}else if (dPinky <= 80 & dMid<=80 & dRing<=80 & dIndex<=80){ //Fingers are clumped or off the screen, so play nothing.
playing = false;
} else {
freqPlaying = 0;
playing = false;
}
}
Try to make a song from this? Program available here: https://arjunmakesthings.github.io/hand-synthesiser/index.html
13:06, 2024-05-15
accessing specific landmarksp5
After filling predictions array with results, one can access specific parts of the landmarks according to this diagram:
//Using specific landmarks
if (predictions.length > 0) {
let hand = predictions[0].landmarks; // Extracting landmarks from the first prediction
// Accessing specific landmark points
let thumbTip = hand[4]; // Thumb tip
let indexTip = hand[8]; // Index finger tip
let middleTip = hand[12]; // Middle finger tip
let ringTip = hand[16]; // Ring finger tip
let pinkyTip = hand[20]; // Pinky finger tip
}
13:50, 2024-05-05
rotational studiesp5
Messed around with earlier rotational studies. Re-used the idea of a particle moving in a circular motion from the previous program.
//Base
for (let x = margin; x <= width - margin; x += s) {
for (let y = margin; y <= height - margin; y += s) {
let x1 = cos(x + inc) * diam;
let y1 = sin(y + inc) * diam;
push();
translate(x1, y1);
square(x, y, s, s / 8); //used rounding of corners for squares
pop();
}
}
inc += 0.02;
If I let the program draw itself out without replacing the background, it looks like this:
Parameter changes (such as diameter incrementing / spacing between individual squares) result in these:
14:14, 2024-04-18
we go around in circlesp5
Still working on typographic treatment using interesting waves. Thought about each particle rotating in a circle by using cos and sin waves.
let x = cos(angle) * circleRadius;
let y = sin(angle) * circleRadius;
// while
angle +=0.02
Also thought of a neat way to assign colours. Once particles are assigned an x & y coordinate:
//declare array of colours
let col = ['#941b0c', '#bc3908', '#f6aa1c'];
// run through x / y array and assign random value from colour array.
for (let i = 0; i<xPos.length; i++){
n.push(random(col));
}
// in draw
fill (n[i]);
For size, I also used noise for some variability. Main draw code:
function draw() {
background("#130108");
for (let i = 0; i < xPos.length; i += 1) {
let x = cos(i + mult) * diam;
let y = sin(i + mult) * diam;
fill(n[i]);
ellipse(xPos[i] + x, yPos[i] + y, (noise(x) * 30) / 2.2); // I think the division is redundant but somehow it reduced speed of the particles (?)
}
mult += inc;
}
16:54, 2024-04-15
boilerplate for hand-trackingp5ml5
Simple boilerplate for single hand tracking. Going to use it for the body synthesizer. Used a bit of ChatGPT to understand what’s happening.
//Single Hand Tracker
let video;
let handpose;
let predictions = [];
function setup() {
createCanvas(640, 480);
video = createCapture(VIDEO);
video.hide();
handpose = ml5.handpose(video, modelReady);
handpose.on('predict', gotPredictions);
}
//To tell whether model has loaded or not
function modelReady() {
text ("Model loaded", 50, 50);
}
function gotPredictions(results) {
predictions = results;
}
function draw() {
background(255);
// Flip the video horizontally to match hand to video
translate(width, 0);
scale(-1, 1);
image(video, 0, 0, width, height);
drawKeypoints();
}
function drawKeypoints() {
for (let i = 0; i < predictions.length; i++) {
let prediction = predictions[i];
for (let j = 0; j < prediction.landmarks.length; j++) {
let point = prediction.landmarks[j];
fill(255, 0, 0);
noStroke();
ellipse(point[0], point[1], 10, 10);
}
}
}
12:36, 2024-04-14
light shining on waterbody in the nightp5
Was inspired by lights glimmering on a waterbody, seen during the night on my last trip to Ahmedabad (near the Riverfront).
Made this while listening to Perfect by Ed Sheeran.
for (let i = 0; i < xPos.length; i += 2) {
let wave = sin(i + waveOffset) * waveHeight;
line(xPos[i] + wave, yPos[i], xPos[i], yPos[i]);
}
// Update wave offset for animation
waveOffset += waveSpeed;
I like how it came out. You can also play around with the parameters, manipulating the legibility.
17:32, 2024-04-12
night code jams with Spunctual
S was around and I excitedly showed her Punctual. We messed around with a few blocks of code, without letting logic govern us.
--bg
o << 0.4;
r << 0.1;
g << 0.2;
b << 0.08;
-- top square
move [osc(rnd)] $
spin [osc(0.02)] $
zoom [osc(0.080)] $
move [osc(fr*0.0002)] $
tile [5,3] $
spin[osc(0.09)] $
circle [0,0] [2,2, 2] * o * hsvrgb[cam, r,g,b]>> video;
-- osc (62) >> audio;
-- [0,0,0] >> video;
--bg
o << 0.4;
r << 0.1;
g << 0.02;
b << 0.08;
-- top square
zoom [osc(0.02)] $
move [osc(fr*0.0002)] $
tile [3,3] $
spin[osc(0.2)] $
rect [0,0] [2,2, 2] * o * hsvh[r,g,b,cam]>> video;
-- osc (62) >> audio;
-- [0,0,0] >> video;
-- flower
[0,0,0] >> video;
o << 0.6;
x << 0;
y << 0;
d << 1;
rot << [0, 0.3 .. 1];
r << 0.87;
g << 0.19;
b << 0.38;
zoom [2,2] $
fit (1/1) $
spin ([rot]) $
fit [0.5/2] $
circle [x,y] [d] * o * [cam] >> video;
23:10, 2024-04-08
it’s just a wave and i knowp5
Used the same text manipulations as earlier with mapping sine waves. Made while thinking of John Mayer’s song.
Love the treatment it produces.
for (let i = 0; i < xPos.length; i++) {
//let wa = int(noise((i + waveOffset) / 70) * waveHeight);
let wa = map(sin(i*waveOffset), -1,1, 0, 10);
let wave = wa*waveHeight;
let col2 = map(wave, -25, 25, 10, 40);
fill (h,s,col2);
push();
translate(xPos[i], yPos[i]+wave);
ellipse (0,0,gridSize*3, gridSize+wave*1.2);
pop();
waveOffset += yPos[i]*waveSpeed;
}
17:27, 2024-04-04
portrait makerpunctual
-- flower
[0,0,0] >> video;
o << 0.6;
x << 0;
y << 0;
d << 0.8;
rot << [0, 0.3 .. 1];
r << 0.87;
g << 0.19;
b << 0.38;
fit (1/1) $
spin ([rot]) $
fit [0.5/2] $
circle [x,y] [d] * o * rgbs[r,g,b] >> video;
17:09, 2024-04-03
cam flowerpunctual
Flower with video input.
-- flower
[0,0,0] >> video;
o << 0.6;
x << 0;
y << 0;
d << 0.8;
rot << [0, 0.3 .. 1];
r << 0.87;
g << 0.19;
b << 0.38;
fit (1/1) $
spin ([rot]) $
fit [0.5/2] $
circle [x,y] [d] * o * rgbs[r,g,b] >> video;
17:05, 2024-04-03
wippunctual
o << 0.6;
rot << [0,0.2 .. 1.2];
-- pink: https://htmlcolorcodes.com/colors/shades-of-pink/
r << 0.87;
g << 0.19;
b << 0.38;
zoom [2,2] $
fit [1/1] $
spin [osc(rot*0.02)] $
fit [0.5/2] $
circle [0,0] [0.3] * o * rgbs[cam] >> video;
Rotating Flowerpunctual
16:54, 2024-04-02
o << 0.06;
rot << [0,0.2 .. 1.2];
-- pink: https://htmlcolorcodes.com/colors/shades-of-pink/
r << 0.87;
g << 0.19;
b << 0.38;
fit [1/1] $
spin [osc(rot*0.02)] $
fit [0.5/2] $
circle [0,0] [0.3] * o * [r,g,b] >> video;
o << 0.006;
r << [0,0.2 .. 1.2];
spin [osc(r*0.02)] $
fit [0.5/2] $
circle [0,0] [0.3] * o >> video;
16:48, 2024-04-02
petalpunctual
Making a petal. No ellipse on Punctual so distorting a circle.
o << 0.6;
fit [0.5/2] $
circle [0,0] [0.3] * o >> video;
16:40, 2024-04-02
I’m Shattering But It Doesn’t Matterp5
Lately been re-excited by the idea of using code for expressive typography.
//I'm Shattering But It Doesn't Matter
let xPos = [];
let yPos = [];
let gridSize = 5;
let waveOffset = 0; // Starting wave offset for animation
let waveSpeed = 1.2; // Adjust speed of wave movement
let waveHeight = 100; // Amplitude of the waves
let h = 211;
let s = 82;
let l = 24;
function setup() {
createCanvas(1000, 1000);
noStroke();
colorMode(HSL);
convertLetterToPoints();
}
function draw() {
//background(h,s,l-40);
background(0);
fill(255);
for (let i = 0; i < xPos.length; i++) {
let wave = int(noise((i + waveOffset) / 70) * waveHeight);
let col2 = map(wave, -25, 25, 30, 70);
// fill(h, s, col2);
//square(xPos[i]+random(-2,2)+wave, yPos[i]+random(-2,2), wave/4);
push();
translate(xPos[i], yPos[i] + wave);
rotate(wave / 10);
textSize(32);
text(":)", 0, 0);
pop();
}
waveOffset += waveSpeed;
/*
// Generate a wave pattern using sine function
for (let y = 0; y <= height; y += 50) {
let wave = sin((y + waveOffset) / 50) * waveHeight;
fill(100 + wave, 150 + wave, 255); // Light blue water with wave height variation
// Draw water based on y position and wave offset
circle(500, y, 300+wave);
}
// Update wave offset for animation
waveOffset += waveSpeed;
*/
}
function convertLetterToPoints() {
textAlign(LEFT, CENTER);
//TypeToPoint
let points = [];
background(255);
fill(0);
//Text Properties
//textFont(font);
var tSize = 170;
textFont("IBM Plex Serif");
textSize(tSize);
textLeading(tSize);
text(
"i'm shattering but it doesn't matter", 60, -40, width / 2 + width / 2, height / 2 + height / 2
);
loadPixels();
var change = 3;
for (let y = 0; y < height; y += gridSize + change) {
for (let x = 0; x < width; x += gridSize + change) {
let px = get(x, y);
let r = px[0];
if (r < 200) {
points.push(createVector(x, y));
}
}
}
for (let i = 0; i < points.length; i += 2) {
let x = points[i].x;
let y = points[i].y;
xPos.push(x);
yPos.push(y);
}
}
15:04, 2024-03-28
Won’t you stand by me – typographic sketchp5
Wrote a sketch with particles that oscillate between two defined positions on the screen.
Used sin(inc) to give a number between -1 and 1. To smooth out the animation, the inc is incremented by 0.02 every frame.
update() {
this.x = map(sin(this.inc), -1, 1, this.x1, this.x2, true);
this.y = map(sin(this.inc), -1, 1, this.y1, this.y2, true);
this.s = map(sin(this.inc+this.inc), -1,1, gridSize*3, gridSize/2, true);
this.inc += 0.02;
}
16:08, 2024-03-25
Washed up potential – text as a water wavep5
Wanted to treat text like a wave hitting the beach with many particles. First figured out what a wave would look like:
for (let y = 0; y <= height; y += 50) {
let wave = sin((y + waveOffset) / 50) * waveHeight;
fill(100 + wave, 150 + wave, 255);
circle(500, y, 300+wave);
}
waveOffset += waveSpeed;
Then used my convertToText function to make the same happen for a piece of text:
//Washed Up Potential
let xPos = [];
let yPos = [];
let gridSize = 5;
let waveOffset = 50; // Starting wave offset for animation
let waveSpeed = 1.2; // Adjust speed of wave movement
let waveHeight = 30; // Amplitude of the waves
let h = 211;
let s = 82;
let l = 24;
function setup() {
createCanvas(1000, 1000);
noStroke();
colorMode (HSL);
convertLetterToPoints();
}
function draw() {
//background(h,s,l-40);
background(h,s,l+73);
for (let i = 0; i<xPos.length; i++){
let wave = int(sin((i + waveOffset) / 50) * waveHeight);
console.log(wave);
let col2 = map(wave, -25 ,25, 30, 70);
fill (h,s,col2);
square (xPos[i]-wave/20, yPos[i], int(wave/1.8));
}
waveOffset += waveSpeed;
}
function convertLetterToPoints() {
textAlign(LEFT, CENTER);
//TypeToPoint
let points = [];
background(255);
fill(0);
//Text Properties
//textFont(font);
var tSize = 240;
textFont("Garamond");
textSize(tSize);
textLeading (tSize/1.2);
text('am i just washed up potential?', 60, -5, width/2+width/2, height/2+height/2);
loadPixels();
for (let y = 0; y < height; y += gridSize) {
for (let x = 0; x < width; x += gridSize) {
let px = get(x, y);
let r = px[0];
if (r < 200) {
points.push(createVector(x, y));
}
}
}
for (let i = 0; i < points.length; i+=2) {
let x = points[i].x;
let y = points[i].y;
xPos.push(x);
yPos.push(y);
}
}
12:27, 2024-03-24
rotational studiesp5
Simple rotational studies based on yesterday’s logic, but no animation. Used iteration through the array as variance.
16:27, 2024-03-22
looping animationsp5
Wanted to study how perfect loops could be made with simple shapes. Made something with squares, but still can’t figure out the math for the sketch to make a loop, will have to do it on a video editor for now.
//Rotate based on odd-even; March, 2024.
let margin = 50;
let s = 75;
let tiles = [];
function setup() {
createCanvas(1000, 1000);
rectMode(CENTER);
noStroke();
angleMode = DEGREES;
for (let x = margin; x <= width - margin; x += s) {
for (let y = margin; y <= height - margin; y += s) {
tiles.push(new Tile(x, y));
}
}
}
function draw() {
background(0);
for (let i = 0; i < tiles.length; i++) {
var r = 0;
if (i % 2 == 0) {
r = 45;
} else {
r = 90;
}
tiles[i].display(r);
}
}
The class:
class Tile {
constructor(x, y) {
this.x = x;
this.y = y;
this.s = s;
this.r = 0;
}
display(r) {
push();
translate(this.x, this.y);
this.r = r;
var t = frameCount / 60;
this.rot = map(sin(this.r * t * 0.00003), -1, 1, 0, 360);
fill(255);
rotate(this.rot);
square(0, 0, this.s);
pop();
}
}
The problem because of which it isn’t perfectly looping via code is that I slow down rotation by multiplying values with 00003. Need to figure this out.
Ooh! Maybe I could use radians instead of degrees, maybe that value progression is better.
16:09, 2024-03-21
kucch crazy ho gayapunctual
--bg
o << 0.2;
r << 0.1;
g << 0.02;
b << 0.08;
-- top square
spin[osc(cam*0.002)] $
rect [cam,0] [2,2] * o * [r,cam/2,cam/0.8]* o>> video;
[0,0,0] >> video;
22:55, 2024-03-20
face in rectanglepunctual
Trying to clip face to make typography. I don’t understand what’s happening, but let’s see. I’ll figure it out.
[0,0,0] >> video;
o << 1;
rect [0, 0] $
[cam] * o >> video;
22:32, 2024-03-20
in progresspunctual
o << 0.8;
x << [-2, -1.9 .. 2];
y << 0;
w << 0.2;
-- [1,1,1] >> video;
[0,0,0] >> video;
r << 0.2;
g << 0.8;
b << 0.1;
w << 0.02;
spin [osc(pi*0.02)] $ fit (1/1) $ rect [x, y] [w,w] * o >> video;
repeating video input in the shape of a flowerpunctual
Repeat video input in the shape of a flower.
-- video flower
z << 0.8;
a << [0, 0.2 .. 1];
o << 0.3;
r << 1;
g << 0.31;
b << 0.61;
col << [r,g,b]*o;
z2 << 0.9;
zoom [z2*(-1), z2] $ tile [2, 2] [[fit (1/1) $ spin [a] $ [zoom[(z*(-1)),z] [cam]]]]* o * [col]>> video;
22:20, 2024-03-17
making an ‘a’ with video inputpunctual
Made a lower-case ‘a’ with shaders on Punctual.
-- creating an A
s << 0.1;
x << [0, 0.1 .. 0.5];
y << [0];
o << 0.4;
r << 0.1;
g << [x]*0.08;
b << 0.8;
z << 0.18;
spinVal << 0;
-- bar
spin [osc(spinVal)] [move [x,0.7] [zoom [(z*(-1)), z] (fit (0.02/0.02) $ cam) * o *[r,g,b]]] >> video;
-- center
midStem << [-0, -0.1 .. 0.85];
spin [ osc(spinVal)] [move [0.5,midStem] [zoom [(z*(-1)), 0.5] (fit (0.02/0.02) $ cam) * o *[r,g,b]]] >> video;
-- bottom
spin [ osc(spinVal)] [move [x,-0.5] [zoom [(z*(-1)), z] (fit (0.02/0.02) $ cam) * o *[r,g,b]]] >> video;
spin [osc(spinVal)] [move [x,midStem+0.2] [zoom [(z*(-1)), 0.05] (fit (0.02/0.02) $ cam)* o *[r,g,b]]] >> video;
spin [osc(spinVal)] [move [-0.0005,midStem-0.29] [zoom [(z*(-1)), 0.5] (fit (0.02/0.02) $ cam) * o *[r,g,b]]] >> video;
21:02, 2024-03-16
make rows of video feed
z << 0.1;
x << [0, 0.1 .. 0.5];
move [x,0] [zoom [(z*(-1)), z] (fit (0.02/0.02) $ cam)] >> video;
noisy backgroundpunctual
Grey, noisy background.
0, 0, 0 >> video;
x << osc ([fx*0.2]*0.08);
y << osc ([fy*0.0002]*0.2);
w << osc(fr*0.5)*0.7;
h << 1;
-- r << 0.5;
-- g << 0.5;
-- b << 0.5;
rect [x, y] [w, h] *0.3 >> video;
---
0, 0, 0 >> video;
-----------------------
r << [0.1, osc (fx)*0.7, fr*0.2];
g << 0;
b << [1, 0, 0.3];
x1 << osc [((fr*fy)), fr], fr;
y1 << 0;
w << [0.1, 0.2, 0.2];
h << [fy, fx, 2];
rect [x1,y1] [w, h] * [0.8] * [r,g,b] >> video;
ripplepunctual
Makes a water ripple.
0, 0, 0 >> video;
w << fr/0.02;
h << 2;
v << (ft*0.02);
spin [osc(fr*0.002)*sin(fx*0.0002)*cos(fx)] (move [osc(fx*0.000008), ft*4] (hline [v*0.002] [w*10, h] * 0.8 * [osc(fx*0.002),0.1*v, osc(v*0.3)])) >> video;
waterpunctual {{date}}
Simulates something of a water kind.
x << [0.3,0.2,0.3,0.8];
move[sin(fx+fy*(1/4*fr)*fr), 0] [circle [x, fy][1.4]*0.8 * [0.1, 0.2, 0.3]] >> video;