This is my final project about collecting raindrops. Your health starts to lose from dehydration and the one way to survive is through collecting raindrops!. Watch out for those black ones, as they deplete your health if you touch them!
//Yunfeng Jiang
//Section E
//setting up variables
var myCanvas;
var waterN = 10;
var water = [];
var p;
var plat;
var waterSlopeProj = []
var acc = 0.5;
var size = 40;
var score = 0;
var health = 100;
function setup() {
myCanvas = createCanvas(500, 300);
//push water object to water array
for(var i = 0; i < waterN; i++){
var w = createWater(random(20, width-20), random(-200, -10), 2);
water.push(w);
}
//add platform object
if(random()<0.5){
plat = createPlatform(-125, random(25, 50), random(200, 250), 0);
}
else{
plat = createPlatform(width+125, random(25, 50), random(200, 250), 1);
}
//push waterslopeProj to array
for(var i = 0; i < waterN; i++){
var k = plat.h / plat.w; //slope
if(plat.sdir > 0.5){
var wsp = 100-tan(k)*(-water[i].x+plat.x+0.5*plat.w)
}
else{
var wsp = 100-tan(k)*(-water[i].x+plat.x-0.5*plat.w)
} //expression of the slope
waterSlopeProj.push(wsp);
}
//add player object
p = player();
}
function draw() {
//draw scene
background(176, 192, 200);
myCanvas.parent('canvasPlaceholder');
scene();
strokeWeight(1)
//add rain
updateWater();
addWater();
//update player
p.display(size);
p.moveY();
playerMove();
//add platform
updatePlatform();
addPlatform();
//gameplay properties
updateHealth();
updateProj();
checkHitRain();
checkHitPlat();
}
//draw scene
function scene(){
rectMode(CORNER)
strokeWeight(0);
fill(128, 96, 67);
rect(0, 250, width, 50)
text('score = '+ score, 10, 20);
text('health = '+ health, 10, 50)
}
//jump
function keyPressed(){
if (keyCode === 32 & p.y == 230){
p.dy = -10
}
}
//move player left and right
function playerMove(){
if (keyIsPressed === true){
if (keyIsDown(65) || keyIsDown(LEFT_ARROW)){
if(p.x > size/2){
p.moveX(-5);
}
}
if (keyIsDown(68) || keyIsDown(RIGHT_ARROW)){
if(p.x < width-size/2){
p.moveX(5);
}
}
}
}
//update health
function updateHealth(){
//deplete health
if (frameCount%30 == 0){
health = health - 1
}
//game over
if (health < 0){
textAlign(CENTER, CENTER)
fill(255, 0, 0);
textSize(50);
text("GAME OVER", width/2, height/2)
noLoop()
}
}
//check player location to raindrops
function checkHitRain(){
//check distance from player to rain
for(var i = 0 ; i < waterN; i++){
if(dist(p.x, p.y, water[i].x, water[i].y) < size*0.75){
score += 1;
//water that hits platform are considered bad water that depletes health
if(water[i].bad == false){
health += 1;
}
else{
health -= 1;
}
var w = createWater(random(20, width-20), random(-200, -10), 2);
water[i] = w;
}
}
}
function updateProj(){
for(var i = 0; i < waterN; i++){
var k = plat.h / plat.w; //slope
if(plat.sdir == 1){
waterSlopeProj[i] = 100-tan(k)*(-water[i].x+plat.x+0.5*plat.w) //expression of the slope
}
else{
waterSlopeProj[i] = 100+tan(k)*(-water[i].x+plat.x-0.5*plat.w) //expression of the slope
}
}
}
function checkHitPlat(){
for(var i = 0 ; i < waterN; i++){
var k = plat.h / plat.w
if(water[i].x > plat.x-plat.w*0.5 & water[i].x < plat.x + plat.w*0.5 && water[i].y > waterSlopeProj[i] && water[i].y < 100){
water[i].bad = true;
if(plat.sdir == 1){
water[i].x += 0.25*water[i].v/k
water[i].y += 0.25*water[i].v
}
else{
water[i].x -= 0.25*water[i].v/k
water[i].y += 0.25*water[i].v
}
}
else{
water[i].y += water[i].v
}
}
}
]]>I took inspiration from a scene in cyberpunk edgerunner and made a city landscape based on that. I am surprised by the flexibility of object, the properties can be manipulated in different ways to create completely different stuff. For example, the pillars, foreground, and background buildings are created with one single object.
//Jason Jiang
//Section E
//setting up arrays of objects
var bldg = [];
var bldgBack = []
var pillar = []
var vhc = []
//number of objects in each array
var bldgN = 6;
var bldgBackN = 11;
var vhcN = 2;
//color palatte for buildings
var palatte = ['#7670b2', '#5ab6b0', '#5ab6b0', '#3f5c60', '#1c4167', '#3f5c60', '#7e9868'];
//image links of assets
var facadeLink = [
"https://i.imgur.com/oPA4x4y.png",
"https://i.imgur.com/xeOW3sz.png",
"https://i.imgur.com/gbr6ySL.png",
"https://i.imgur.com/WqUehK3.png"];
var facadeImg = [];
var vehicleLink = [
"https://i.imgur.com/gFtwhqV.png",
"https://i.imgur.com/KX1dLCi.png",
"https://i.imgur.com/Fo43Kep.png"];
var vehicleImg = [];
//load assets
function preload(){
train = loadImage("https://i.imgur.com/BFxe31d.png");
for (var i = 0; i < facadeLink.length; i++){
facadeImg[i] = loadImage(facadeLink[i]);
}
for (var i = 0; i < vehicleLink.length; i++){
vehicleImg[i] = loadImage(vehicleLink[i]);
}
}
function setup() {
createCanvas(400, 200);
imageMode(CENTER);
colorMode(HSB);
//create front building arrays
for(var i = 0; i < bldgN; i++){
//randomly pick color from array
var palatteIndex = floor(random(palatte.length));
//randomly pick an image from array
var facadeIndex = floor(random(facadeImg.length));
var b = building(80*i, random(-height/3, height/3), random(80, 100), color(palatte[palatteIndex]), facadeImg[facadeIndex]);
bldg.push(b);
}
//create back building arrays
for(var i = 0; i < bldgBackN; i++){
var b = building(40*i, random(150), 40, color(20, 10, 30, 0.5), -1);
bldgBack.push(b);
}
//create pillars
for (var i = 0; i < 2; i++) {
var p = building(200*i, 70, 20, color(80), -1);
pillar.push(p);
}
//creating vehicles
for (var i = 0; i < 2; i++) {
//randomly pick an image from array
var vehicleIndex = floor(random(vehicleImg.length));
//randomize vehicle moving direction
if (random(1) <= 0.5){
//vehicles from left to right
var v = vehicle(random(-width/2, 0), random(50, 150), random(5, 10), vehicleImg[vehicleIndex]);
}
else{
//vehicles from right to left
var v = vehicle(random(width, 1.5*width), random(50, 150), random(-5, -10), vehicleImg[vehicleIndex]);
}
vhc.push(v);
}
}
function draw() {
background(200, 20, 100);
//update information in each frame
updateObjs();
updateArray();
//add train image
image(train, 200, 90);
}
function updateObjs(){
//updating building background
for(var i = 0; i < bldgBack.length; i++){
bldgBack[i].move(2);
bldgBack[i].display();
}
//updating building foreground
for(var i = 0; i < bldg.length; i++){
bldg[i].move(5);
bldg[i].display();
}
//updating pillars
for(var i = 0; i < pillar.length; i++){
pillar[i].move(5);
pillar[i].display();
}
//updating vehicles
for (var i = 0; i < vhc.length; i++) {
vhc[i].move();
vhc[i].display();
}
}
//displaying buildings
function buildingDisplay(){
//draw rectangles
noStroke();
fill(this.color);
rect(this.x, this.y, this.w, height-this.y);
var centerX = this.x + 0.5*this.w ;
var centerY = this.y + 0.5*(height - this.y);
//see if the detail property of object is an image, since not pillars and background buildings dont need facade details on them
if (this.detail != -1){
//add details on building facade
push();
translate(centerX, centerY);
image(this.detail, 0, 0, 0.8*this.w, 0.95*(height-this.y));
pop();
}
}
//update building position
function buildingMove(s){
this.x -= s;
}
//displaying vehicles
function vehicleDisplay(){
push();
//flip the image if going from right to left
if(this.s < 0){
scale(-1, 1);
image(this.detail, -this.x, this.y);
}
else{
image(this.detail, this.x, this.y);
}
pop();
}
//update vehicles position and age
function vehicleMove(){
this.x += this.s;
this.age += 1;
}
function updateArray(){
//replacing foreground buildings outside canvas
for(var i = 0; i < bldg.length; i++){
if (bldg[i].x <= -bldg[i].w){
var palatteIndex = floor(random(palatte.length));
var facadeIndex = floor(random(facadeImg.length));
var b = building(400, random(-height/3, height/3), random(80, 100), color(palatte[palatteIndex]), facadeImg[facadeIndex]);
bldg[i] = b;
}
}
//replacing background buildings outside canvas
for(var i = 0; i < bldgBack.length; i++){
if (bldgBack[i].x <= -bldgBack[i].w){
var b = building(400, random(150), 40, color(20, 10, 30, 0.5), -1);
bldgBack[i] = b;
}
}
//replacing pillars outside canvas
for(var i = 0; i < pillar.length; i++){
if (pillar[i].x <= -pillar[i].w){
var p = building(400, 70, 20, color(80), -1);
pillar[i] = p;
}
}
//replacing vehicles after a certain time
for(var i = 0; i < vhc.length; i++){
if (vhc[i].age > 200){
var vehicleIndex = floor(random(vehicleImg.length));
if (random(1) <= 0.5){
var v = vehicle(random(-width/2, 0), random(50, 150), random(5, 10), vehicleImg[vehicleIndex]);
}
else{
var v = vehicle(random(width, 1.5*width), random(50, 150), random(-5, -10), vehicleImg[vehicleIndex]);
}
vhc[i] = v;
}
}
}
//create building objects
function building(buildingX, buildingY, buildingWidth, buildingColor, buildingDetail) {
var b = { x: buildingX,
y: buildingY,
w: buildingWidth,
color: buildingColor,
detail: buildingDetail,
display: buildingDisplay,
move: buildingMove
}
return b;
}
//create vehicle objects
function vehicle(vehicleX, vehicleY, vehicleSpeed, vehicleDetail) {
var v = { x: vehicleX,
y: vehicleY,
s: vehicleSpeed,
age: 0,
detail: vehicleDetail,
display: vehicleDisplay,
move: vehicleMove
}
return v;
}
]]>The reading discusses NFT (Non-fungible tokens) and how it impacts digital artists and collectors. NFT adds authenticity to digital artwork like images, music, or videos, and it helps protect the artwork’s ownership to prevent people from stealing the artwork online through screenshots. The author embraces this new trend in the digital art market because it “economically legitimizes an emerging artform.”
The reading mentions an artist called Andre Benson, who had been experimenting with digital video works for years but had not received any financial rewards. He had to work in a software company to support his career as an artist. However, after selling his work through NFT, he could sustain himself solely through art, which liberated him from doing tedious but necessary jobs.
Despite its benefit to artists and collectors, NFT has its setbacks. Like bitcoins, NFT relies on blockchain technology to add uniqueness to each artwork, which relies on a tremendous amount of computing power that is not environmentally friendly. Moreover, it does not legally prevent people from stealing artwork; it merely protects the metadata of the artwork rather than the work itself. Therefore, NFT is not the prime solution to add ownership to artwork.
]]>The spaceship engages in fights with enemies by using energy machine guns and lasers. The most challenging part actually comes in making all the visuals work correctly.
Four characters/sounds:
//Jason Jiang
//Section E
///Storyline: The spaceship engages fights with enemies through using energy machine gun and laser.
//setting up variables for stars
var star = [];
var N = 10; //number of starts
var dx = 10; //speed of star
var w = 600; //x location of enemy
var dShip = 10; //speed of enemy
var a = 0;//scale of laser beam
var imgX = 120;//x location of ship
var imgY = 100;//y location of ship
var angle = 0;//angle of ship
var laserCharged = false; //whether laser is charged
var laserFired = false; //whether laser is fired
var enemyDestroyed = false; //whether enemy is destroyed
//defining assets
var machineGun;
var explosion1;
var explosion2;
var explosion3;
var laserEnergy;
var laserBeam;
var flyEngine;
var machineGun;
var explosion;
var charge;
var laser;
//add assets
function preload(){
spaceShip = loadImage("https://i.imgur.com/D1QDG4A.png");
spaceShipFire = loadImage("https://i.imgur.com/h8bQMXa.png");
enemy1 = loadImage("https://i.imgur.com/OE8l2tK.png");
explosion1 = loadImage("https://i.imgur.com/c9tLLTo.png");
explosion2 = loadImage("https://i.imgur.com/kLTBXIa.png");
explosion3 = loadImage("https://i.imgur.com/0zhmrzn.png");
laserEnergy = loadImage("https://i.imgur.com/bmn9wZX.png");
laserBeam = loadImage("https://i.imgur.com/ABposfH.png");
machineGun = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/machineGun.mp3");
explosion = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/explosion.wav");
charge = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/charge.wav")
laser = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/laser.wav")
}
// setup for audio generation
function soundSetup() {
machineGun.setVolume(0.1);
explosion.setVolume(0.1);
charge.setVolume(0.2);
laser.setVolume(0.1);
}
//Create galaxy background
function updateStar(){
this.x -= dx;
}
function createStar(){
strokeWeight(3);
stroke(255);
point(this.x, this.y);
}
function generateStar(sx, sy){
for (var i=0; i<N; i++){
var s = {
x: sx, y: sy,
stepFunction: updateStar,
drawFunction: createStar
}
}
return s;
}
function setup() {
createCanvas(400, 200);
frameRate(10);
imageMode(CENTER);
for (var i=0; i<N; i++){
var s = generateStar(random(width), random(height))
star.push(s);
}
useSound();
}
function draw() {
background(0);
//setting up sequence for charging laser and firing laser
if (a >= 1){
if(laserCharged == false){
laserCharged = true
a = 0
charge.stop()
laser.play();
}
else if(laserCharged == true & laserFired == false){
laserFired = true
a = 0
laser.pause();
}
}
//resetting enemy position if destroyed
if (enemyDestroyed == true){
w = 600;
}
//Update star
for (var i=0; i<N; i++){
var s = star[i]
s.stepFunction();
s.drawFunction();
//Remove star that is out of bounds
if (s.x < 0) {
var s = generateStar(random(width+5, width+500), random(height))
star.splice(i, 1, s);
}
}
//flying spaceship
if (frameCount >= 0 & frameCount < 30) {
flyinSpace(imgX, imgY, 0);
}
//killing enemy
if (frameCount >= 30 & frameCount < 60) {
//play ship firing sound
if (w == 600){
machineGun.loop();
}
//ship firing
shipFiring(w);
//enemy Ship approaching
enemyShip(w, height/2);
w -= dShip;
}
if (frameCount >= 60 & frameCount < 70) {
//stop firing
flyinSpace(imgX, imgY, 0);
//play explosion sound when the enemy is close
if(frameCount == 60){
machineGun.stop();
explosion.play()
}
explode(w, height/2, 60);
}
if (frameCount >= 70 & frameCount < 110) {
//setting up next enemy
enemyDestroyed = false;
if(frameCount == 70){
charge.loop();
}
//dodge laser
if(dist(imgX, imgY, 120, 160)>0 & laserCharged == true){
flyinSpace(imgX, imgY, 0);
imgY += dShip;
}
else{
flyinSpace(imgX, imgY, 0);
}
//enemy Ship
enemyShip(w, height/2);
w -= 0.5*dShip;
//charge laser
if (laserCharged == false){
laserCharge(w, height/2, a);
a+=0.05;
}
//fire laser
else if(laserCharged == true & laserFired == false){
laserCharge(w, height/2, 1);
laserFire(w, height/2, -a);
a+=0.05;
}
}
if (frameCount >= 110 & frameCount < 140) {
//preparing for next shot
if (frameCount == 110){
laserCharged = false;
laserFired = false;
charge.loop();
}
//enemy Ship
enemyShip(w, height/2);
w -= 0.5*dShip;
//ship fire laser
//rotate ship
if (angle>=-18){
flyinSpace(imgX, imgY, angle);
angle-=3;
}
//fire laser after rotation
else{
//charge laser
flyinSpace(imgX, imgY, angle)
if (laserCharged == false){
laserCharge(imgX, imgY, a);
a+=0.1;
}
//fire laser
else if(laserCharged == true & laserFired == false){
laserCharge(imgX, imgY, 1);
laserFire(imgX, imgY, a, angle);
a+=0.1;
}
}
}
if (frameCount >= 140 & frameCount < 150) {
flyinSpace(imgX, imgY, angle);
//play explosion sound when the enemy is close
if(frameCount == 140){
explosion.play();
}
explode(w, height/2, 140);
}
if (frameCount >= 150){
background(0);
noLoop();
}
}
//adding spaceship
function flyinSpace(x, y, a){
push()
translate(x, y);
rotate(radians(a));
image(spaceShip, 0, 0);
pop()
}
function shipFiring(w){
//ship firing
if(w%20 == 0){
image(spaceShipFire, 120, height/2);
}
else{
image(spaceShip, 120, height/2);
}
}
function enemyShip(w, h){
//enemy ship flying
image(enemy1, w, h);
}
function explode(w, h, f){
//create explosion when the enemy is close
image(explosion1, w, h);
if(frameCount-f >= 3){
image(explosion2, w, h);
}
if(frameCount-f >= 6){
image(explosion3, w, h);
enemyDestroyed = true;
}
}
//adding laser charge
function laserCharge(x, y, a){
push()
translate(x, y);
scale(a);
image(laserEnergy, 0, 0);
pop()
}
//adding laser beam
function laserFire(x, y, a, angle){
push()
translate(x, y);
rotate(radians(angle));
scale(-a, 1);
image(laserBeam, -211, -0.5);
pop()
}
]]>This is my self-portrait. I try to use parabola lines instead of points to draw my image. The shape of lines is varied by adding an acceleration variable to change dx and dy. The portrait is looped and redrawn every 500 lines.
//Jason Jiang
//Section E
//Setting up variables
var np = 0;
var particleSetup = [];
var myProtrait
function preload(){
myProtrait = loadImage("https://i.imgur.com/huB83xd.jpg");
}
//Updating properties of particles each step
function particleStep(){
//Getting pixel color of the location of each particle on the image
this.c = myProtrait.get(this.x, this.y);
//Adding acceleration to create parabola curve
this.dx += this.ax;
this.dy += this.ay;
//Updating x,y locations of particles
this.x += this.dx;
this.y += this.dy;
//Updating x,y locations of particles in next step
this.x1 = this.x + this.dx;
this.y1 = this.y + this.dy;
}
//Drawing lines between two particles
function particleDraw(){
stroke(this.c);
strokeWeight(this.s);
line(this.x, this.y, this.x1, this.y1);
}
//Creating particles
function particle(px, py, pdx, pdy, pax, pay, pc, px1, py1, ps){
var p = {
x: px,
y: py,
dx: pdx,
dy: pdy,
ax: pax,
ay: pay,
c: pc,
x1: px1,
y1: py1,
s: ps,
stepfunction: particleStep,
drawfunction: particleDraw
}
return p;
}
function setup(){
createCanvas(400, 400);
}
function draw(){
//Constraining number of particles
if (np < 500){
//Creating objects and adding them into array
c = color(random(255), random(255), random(255))
var p = particle(random(width), random(height), random(5), random(10), random(0.5, -0.5), random(0.5, -0.5), c, 0, 0, random(1,8));
particleSetup.push(p);
np+=1
}
//Resetting canvas if num of particles exceeds 500
if (np == 500){
background(255);
np = 0;
particleSetup = [];
}
//Running particles
for(i = 0; i < np; i++){
var p = particleSetup[i];
p.stepfunction();
p.drawfunction();
}
}
]]>As a pioneer in 3D animation and VR/AR simulation, Claudia focuses on adapting virtual simulations to historical subjects. She studied art and architectural history at NYU and Columbia University and now works in New York. Being a feminist artist, her work has huge historical references where she subverts canonical male rulers into something more fantastical with digital technology.
As a student majoring in architecture, I am interested in the representation of buildings and how it changes their expressions. Her project, THE DOLLS HOUSE, showcases historical empire buildings like The Arch of Labna and the Roman Forum of Caesar being thrown away like toys inside a giant warehouse. She also adds a rotating light source that casts shadows on those buildings, simulating the idea of sunrise and sunset, which showcases the passage of time and the decay of nations. What draws me most is her play with algorithmic flickering patterns on walls filled with symbols of decayed nations and also logos of multinational companies, hinting that nothing could last forever. The result looks surreal and hypnotic, but at the same time refreshing and enlightening, which encourages the audience to contemplate on time.
]]>Moritz Stefaner is a data visualizer focusing on UI design. He aims to create unique data representations to raise people’s awareness of problems and encourage them to develop solutions. In the lecture, he mentioned the concept of a hyperobject, an entity that challenges people’s traditional way of thinking. A dataset could similarly be viewed differently from not just pie charts or bar charts. For example, a heat map is not the only option to show a range of temperatures. This revolutionary mindset makes me interested in his work that reflects hyperobject.
To achieve this, he tried to make the data more tangible and experiential. One of his projects involved using food as a tool to represent data. The information was revealed through the recipe, the layout, and the flavor, which was a more effective way to understand the data. One of the dishes was a series of coffins made of chocolate with different fills inside. Each fill represented a cause of death. It humorously referred to the line, “Life is a bottle of chocolate; you never know what you get.”. I never realized that taste could reflect data. In my work, I will try to break the conventions of traditional representation and link the data to something unexpected but exciting.
]]>The project I choose is about visualizing several food searches on the Internet. The designer Moritz Stefaner investigates how people change preferences for particular food over months and years and how it creates a rhythm to showcase the seasonality of food queries. I love how they investigate this topic from many aspects, such as among different countries, different food, or different time.
Stefaner also puts a lot of effort into visualizing how food queries change monthly and yearly. He designed a circle with bars surrounding it clockwise to show different months. Each bar represents the number of times a keyword is searched. After that, he overlayed bars on one another with different colors across different years. Furthermore, he creates an animation to visualize the process more clearly. The rigidity in the structure of the data and clarity in its presentation makes me admire his effort.
Finally, Stefaner also provides clues to help the audience understand patterns in data. For example, in months with holidays like Halloween and Christmas. He puts a marker on that day in the graph to show how the frequency of food searches might change around that day.
]]>This is my curve project. I am using mouseX to control the rotation, scale, and color of curves while using mouseY to control the number of iterations. Also, when you click, the curve changes. I really like how Hypocychoid and Epitrochoid are constructed and how different iterations of them overlap one another.
//Jason Jiang
//Section E
//Setting up variables
var nPts = 200;
var a = 80;
var N;
var b
var x;
var y;
var crvMode = 1;
function setup() {
createCanvas(400, 400);
frameRate(10)
colorMode(HSB);
}
function draw() {
//Mapping mouseY value to number of iterations
N = map(mouseY, 0, height, 0, 25);
b = a/N;
background(0);
//Draw Hypocychoid
if (crvMode%2 == 0) {
for(var i = 3; i <= N; i++) {
//Decreasing strokeWeight each iteration
strokeWeight(2-i*0.05)
//Changing color according to mouseX
stroke(255-mouseX*0.1, 100-i, 200-i*5)
crv1(i);
stroke(255-mouseX*0.1, 100-i, 100-i*5)
crv1(PI+i);
}
}
//Draw Epitrochoid
else {
for(var i = 3; i <= N; i++){
//Decreasing strokeWeight each iteration
strokeWeight(2-i*0.05)
//Changing color according to mouseX
stroke(mouseX*0.1, 100-i, 200-i*5)
crv2(i);
stroke(mouseX*0.1, 100-i, 100-i*5)
crv2(PI+i);
}
}
}
//Hypocychoid
function crv1(m) {
//Changing scale and rotation according to mouseX
h = map(mouseX, 0, width, 1, 2, true)*m*0.05;
angle = map(mouseX, 0, width, 0, PI);
push()
translate(width/2, height/2);
//Rotate curve according to mouseX
rotate(angle + m);
//Drawing curves
noFill();
beginShape()
for(var i = 0; i < nPts; i++){
var t1 = map(i, 0, nPts, 0, TWO_PI)
var t2 = t1*(a-b)/b
x = h*((a-b)*cos(t1)+b*cos(t2))
y = h*((a-b)*sin(t1)-b*sin(t2))
//Adding random movement to the curve
vertex(random(x+4, x-4), random(y+4, y-4));
}
endShape(CLOSE);
pop();
}
//Epitrochoid
function crv2(m) {
//Changing scale and rotation according to mouseX
h = map(mouseX, 0, width, 1, 2, true)*m*0.05;
angle = map(mouseX, 0, width, 0, TWO_PI);
push()
translate(width/2, height/2);
//Rotate curve according to mouseX
rotate(angle + m);
//Drawing curves
noFill();
beginShape()
for(var i = 0; i < nPts; i++){
var t1 = map(i, 0, nPts, 0, TWO_PI)
var t2 = t1*(a-b)/b
x = h*((a-b)*cos(t1)+b*sin(t2))
y = h*((a-b)*sin(t1)-b*cos(t2))
vertex(x, y);
}
endShape(CLOSE)
pop();
}
//Change curves when press mouse
function mousePressed(){
crvMode++
print(crvMode);
}
]]>I am interested in David Mignot’s work in using python codes to generate a series of objects in Blender. The randomness is expressed through the random function to vary the type, height, and material of objects. Each time the function creates a different rendered scene that would take days to model by hand. David expressed his artistic sensibilities in attempting to control the randomness of variables so that the final result looks harmonic. It showcases how randomness needs to be controlled in computational art so that the generated work still looks “designed” rather than messy and purely random.
The work intrigues me in terms of creating generative art in 3d forms. Typically, Blender is used for 3d modeling individual objects for the CG industry. However, David opened up a new possibility in utilizing randomness to generate 3d scenes by coding, which might be a helpful method to create large repetitive scenes quickly.
]]>