Artistic Inspiration Research2: Mark Nappier’s net.flag

  • Net Art: 

Forms of Art that can be presented on the Internet, especially those can be interacted online or make use of other nature of internet.

  • Introduction:

This project was created in 2002 in Java, and modified in JavaScript in 2019. It was created by Mark Napier, and supported by the Guggenheim. The website includes thousands of flags created by visitors to the website, based on the existing national flags. The website aims to manifest the different ideologies and concepts of people from different geographical areas. It is public, inclusive, and interactive. In 2002, when the internet began to popularize globally, this website was a public archive for people to share their thoughts through pictures.

  • Discussion: 

According to the reading, the nature of Net Art is process-based, interactive, and mostly ephemeral. This project fits the definition of Net Art in the reading, but though the heading flag will be replaced by any new flag made by a new visitor, the flags are well archived, so it is not so “ephemeral”. It is written in JavaScript, which is the same coding language used in CCLab. It draws our attention to the art of reassembly and collage, which can be done in JavaScript.

The most significant features of the internet for our research subject are its interactivity and publicity. This website can not be web art if there are no visitors who would visit and edit the flags. This project is purely made of code, which encourages us to express our opinions and concepts by coding.

  • Individual Conclusion*: 

Rebecca’s conclusion: This project shows an insight on how the audience can become a part of the artwork. Though it is not exclusive to web art, through the web’s unique specialty of interactivity and publicity, it can be done exceptionally well. It inspires me to create some content that can be further edited by the audience for Project B.

Sean’s conclusion This project explores the potential of establishing new artwork from the existing art. The project provides the user a chance to combine existing flags into a new piece of work. By utilizing different elements users could explore and extend the hypothesis ideology, social construction, nationality culture background, which inspired me to ensure user could conduct their exploration via various dimensions.

CClab Mini Project: OOP Dancer.

Project Title: Dancing Pumpkin Man

Link to project:https://n-a-e-s.github.io/oop-dancer/

https://github.com/N-A-E-S/oop-dancer

Description: When I was told that we were going to make a dancing object, the first image that came into my mind was a meme:https://www.bilibili.com/video/BV14y4y1g7Ex/(which is a meme generated from the movie: Mobile Suit Gundam: Hathaway’s Flash)

Still, the large amount of movement here makes it hard to complete all the steps inside. Thus, I decided to only conduct the first step, which mainly consists of the Pendulum motion of the body and the repetitive striking of two arms.

The final version of the work:

Coding:

/*
Check our the GOAL and the RULES of this exercise at the bottom of this file.

After that, follow these steps before you start coding:

1. rename the dancer class to reflect your name (line 35).
2. adjust line 20 to reflect your dancer’s name, too.
3. run the code and see if a square (your dancer) appears on the canvas.
4. start coding your dancer inside the class that has been prepared for you.
5. have fun.
*/

let dancer;

function setup() {
// no adjustments in the setup function needed…
let canvas = createCanvas(windowWidth, windowHeight);
canvas.parent(“p5-canvas-container”);

// …except to adjust the dancer’s name on the next line:
dancer = new SeanDancer(width / 2, height / 2);
}

function draw() {
// you don’t need to make any adjustments inside the draw loop
background(0);
drawFloor(); // for reference only

dancer.update();
dancer.display();
}

// You only code inside this class.
// Start by giving the dancer your name, e.g. LeonDancer.
class SeanDancer {
constructor(startX, startY) {
this.x = startX;
this.y = startY;
this.angle = 0;
this.rotationSpeed = 0.04;
this.radius = 50;
this.amplitude = 20;
this.action1 = 0;
this.action2 = 0;
this.timebreak = 0;
this.angle2 = 0;
// add properties for your dancer here:
//..
//..
//..
}
update() {
this.angle += this.rotationSpeed;
this.angle2 += 0.1
}
display() {
// the push and pop, along with the translate
// places your whole dancer object at this.x and this.y.
// you may change its position on line 19 to see the effect.
// ******** //
// ⬇️ draw your dancer from here ⬇️
//head
push();
translate(this.x, this.y);
rotate(0.35 * sin(this.angle));
//neck
fill(255, 204, 153);
rect(-10, -45, 20, 10);
fill(255, 153, 51);
ellipse(0, -65, 50, 50);
fill(“green”);
rect(-5, -95, 10, 5);
fill(0);
triangle(-15, -80, -5, -80, -10, -70);
triangle(15, -80, 5, -80, 10, -70);
triangle(0, -65, -5, -60, 5, -60);
strokeWeight(3);
line(0, -55, -6, -50);
line(0, -55, 6, -50);
line(-6, -50, -10, -55);
line(6, -50, 10, -55);
//body
fill(96, 96, 96);
noStroke();
rect(-20, -35, 40, 10);
beginShape();
vertex(-20, -25);
vertex(-30, -20);
vertex(30, -20);
vertex(20, -25);
endShape(CLOSE);
beginShape();
vertex(-30, -20);
vertex(-30, -15);
vertex(30, -15);
vertex(30, -20);
endShape(CLOSE);
beginShape();
vertex(-25, -15);
vertex(-18, 30);
vertex(18, 30);
vertex(25, -15);
endShape(CLOSE);
strokeWeight(1);
stroke(0);
line(-18, -5, -18, 30);
line(18, -5, 18, 30);
line(-25, -15, -18, -5);
line(25, -15, 18, -5);
fill(96, 96, 96);
//legs
if (sin(this.angle) > 0) {
beginShape();
vertex(-20, 30);
vertex(-20, 50);
vertex(-10, 50);
vertex(-10, 30);
endShape(CLOSE);
beginShape();
vertex(-20, 50);
vertex(-20 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10 + (50 * sin(0.35 * sin(this.angle))), 50 – tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10, 50 – tan(0.35 * sin(this.angle)));
endShape(CLOSE);
beginShape();
vertex(20, 30);
vertex(20, 50);
vertex(10, 50);
vertex(10, 30);
endShape(CLOSE);
beginShape();
vertex(20, 50);
vertex(20 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10 + (50 * sin(0.35 * sin(this.angle))), 50 – tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10, 50 – tan(0.35 * sin(this.angle)));
endShape(CLOSE);
//feet
beginShape();
vertex(-25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10 + (50 * sin(0.35 * sin(this.angle))), 50 – tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10 + (50 * sin(0.35 * sin(this.angle))), 50 – tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle))) – 10);
vertex(-25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle))) – 10);
endShape(CLOSE);
beginShape();
vertex(25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10 + (50 * sin(0.35 * sin(this.angle))), 50 – tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10 + (50 * sin(0.35 * sin(this.angle))), 50 – tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle))) – 10);
vertex(25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle))) – 10);
endShape(CLOSE);
//arms
strokeWeight(0.5);
stroke(0);
beginShape();
vertex(-30, -15);
vertex(-45, -5);
vertex(-45, 5);
vertex(-20, -10);
vertex(-20, -15);
endShape(CLOSE);
beginShape();
vertex(-45, -5);
vertex(-60 – 5 * sin(this.angle2), -5 – 5 * cos(this.angle2));
vertex(-60 – 5 * sin(this.angle2), 5 – 5 * cos(this.angle2));
vertex(-45, 5);
endShape(CLOSE);
beginShape();
vertex(30, -15);
vertex(0 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(0 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(30, -5);
endShape(CLOSE);
beginShape();
vertex(0 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(-20 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(-20 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(0 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
endShape(CLOSE);
fill(255, 204, 153);
beginShape();
vertex(-20 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(-20 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(-25 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(-25 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
endShape(CLOSE);
beginShape();
vertex(-60 – 5 * sin(this.angle2), -5 – 5 * cos(this.angle2));
vertex(-60 – 5 * sin(this.angle2), 5 – 5 * cos(this.angle2));
vertex(-65 – 5 * sin(this.angle2), 5 – 5 * cos(this.angle2));
vertex(-65 – 5 * sin(this.angle2), -5 – 5 * cos(this.angle2));
endShape(CLOSE);

}
else {
if (sin(this.angle) < 0) {
beginShape();
vertex(-20, 30);
vertex(-20, 50);
vertex(-10, 50);
vertex(-10, 30);
endShape(CLOSE);
beginShape();
vertex(-20, 50 – tan(0.35 * sin(this.angle)));
vertex(-20 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10, 50);
endShape(CLOSE);
beginShape();
vertex(20, 30);
vertex(20, 50);
vertex(10, 50);
vertex(10, 30);
endShape(CLOSE);
beginShape();
vertex(20, 50 – tan(0.35 * sin(this.angle)));
vertex(20 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10, 50);
endShape(CLOSE);
//feet
beginShape();
vertex(-25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(-10 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle))) – 10);
vertex(-25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle))) – 10);
endShape(CLOSE);
beginShape();
vertex(25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20));
vertex(10 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle))) – 10);
vertex(25 + (50 * sin(0.35 * sin(this.angle))), 50 + (50 * cos(0.35 * sin(this.angle))) – 10);
endShape(CLOSE);
//arms
strokeWeight(0.5);
stroke(0);
beginShape();
vertex(30, -15);
vertex(45, -5);
vertex(45, 5);
vertex(20, -5);
vertex(20, -15);
endShape(CLOSE);
beginShape();
vertex(45, -5);
vertex(60 – 5 * sin(this.angle2), -5 – 5 * cos(this.angle2));
vertex(60 – 5 * sin(this.angle2), 5 – 5 * cos(this.angle2));
vertex(45, 5);
endShape(CLOSE);
beginShape();
vertex(-30, -15);
vertex(0 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(0 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(-30, -5);
endShape(CLOSE);
beginShape();
vertex(0 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(20 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(20 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(0 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
endShape(CLOSE);
fill(255, 204, 153);
beginShape();
vertex(20 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
vertex(20 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(25 + 10 * sin(this.angle2), -5 + 10 * cos(this.angle2));
vertex(25 + 10 * sin(this.angle2), -15 + 10 * cos(this.angle2));
endShape(CLOSE);
beginShape();
vertex(60 – 5 * sin(this.angle2), -5 – 5 * cos(this.angle2));
vertex(60 – 5 * sin(this.angle2), 5 – 5 * cos(this.angle2));
vertex(65 – 5 * sin(this.angle2), 5 – 5 * cos(this.angle2));
vertex(65 – 5 * sin(this.angle2), -5 – 5 * cos(this.angle2));
endShape(CLOSE);
}
}
pop();

 

// ⬆️ draw your dancer above ⬆️
// ******** //

// the next function draws a SQUARE and CROSS
// to indicate the approximate size and the center point
// of your dancer.
// it is using “this” because this function, too,
// is a part if your Dancer object.
// comment it out or delete it eventually.
push();
translate(this.x, this.y);
this.drawReferenceShapes()
pop();
}
drawReferenceShapes() {
noFill();
stroke(255, 0, 0);
line(-5, 0, 5, 0);
line(0, -5, 0, 5);
stroke(255);
rect(-100, -100, 200, 200);
fill(255);
stroke(0);
}
}

 

/*
GOAL:
The goal is for you to write a class that produces a dancing being/creature/object/thing. In the next class, your dancer along with your peers’ dancers will all dance in the same sketch that your instructor will put together.

RULES:
For this to work you need to follow one rule:
– Only put relevant code into your dancer class; your dancer cannot depend on code outside of itself (like global variables or functions defined outside)
– Your dancer must perform by means of the two essential methods: update and display. Don’t add more methods that require to be called from outside (e.g. in the draw loop).
– Your dancer will always be initialized receiving two arguments:
– startX (currently the horizontal center of the canvas)
– startY (currently the vertical center of the canvas)
beside these, please don’t add more parameters into the constructor function
– lastly, to make sure our dancers will harmonize once on the same canvas, please don’t make your dancer bigger than 200×200 pixels.
*/
The coding mainly consists of two parts: update and display.

In the upload function, we update the two angles that determine the moving parament of the body and arms. 

In the display part, we draw the whole figure.

First, we draw the Pumpkinhead and body of the figure, then we rotate using sin(angle1) to achieve the “Pendulum motion” of the main body. Then comes the legs and arms. in this part, I used a lot of maths function to calculate the location, such a paraments like (-10 + (50 * sin(0.35 * sin(this.angle))), 50 + tan(0.35 * sin(this.angle)) + (50 * cos(0.35 * sin(this.angle)) – 20)), which contribute to the movement of legs.

Reflection:

OOP could be a powerful function, which I’ve already learned during the midterm process. Yet to make a project, especially combined with visual art would take a lot of effort. It may be a significant focus to find a efficient way to beautify the work.

 

 

ProjectA:Pixelime(part 2)

Process: Design and Composition:

This project’s inspiration and design have undergone multiple iterations. Its earliest version stemmed from a sketch inspired by Conway’s Game of Life while I was working on a project proposal (Project A). It simulated sexual reproduction of creatures, where their appearance was simplified to circles and squares, and they were differentiated by gender and behavioral patterns.

Link to this sketch:https://editor.p5js.org/N-A-E-S/sketches/nweZqmRem

In subsequent versions, I removed gender differentiation, unifying them under the image of the same kind of pixel slime. Then, I incorporated a food system completed in another sketch(Which takes a lot inspiration from the user testing part in the interaction day.).

To make them behave more like slimes, I replaced the original random movement with a bouncing motion to simulate the movement of living organisms. Additionally, to reflect the concept of ecological cycles, a unit of food is generated at the location where a pixelime dies.
In the final version, when two pixelimes come into contact and are mature enough, they produce a new offspring. The surname of the offspring is a blend of the surnames of the two parents, while the given name is randomly generated. Additionally, the color of the offspring is a blend of the colors of the parents.

Some other changes made include:

  1. Implementing a lifespan for food items.
  2.  Adding a new background image referenced from YouTube.
  3. Introducing gravity for slime individuals.
  4. Limiting the movement range of slimes.

 

Process: Technical 

Code:

//Reference of background image: https://www.youtube.com/watch?v=MIq1QW0ycI8&t=247s
var img;
var gameStarted = false; // Track game state
var startButton;
var startSlime; // Store the start slime
var foods = []; // Array to store food objects
var foodBreak = 0; // Track food deployment
var recentFood = false; // Track recent food deployment
function preload() {
print(“lo123123ed”);
img = loadImage(‘img.png’);
myfont = loadFont(‘MZPXorig.ttf’);
}
function setup() {
let canvas = createCanvas(800, 500);
canvas.parent(“p5-canvas-container”)
startButton = createButton(‘Start’);
startButton.size(100, 50); // Set button size
var canvasPosition = canvas.position();
startButton.position(canvasPosition.x + windowWidth / 2 – 50, canvasPosition.y + windowHeight / 2 – 25);
startButton.mousePressed(startGame);

}
function startGame() {
gameStarted = true;
startButton.hide(); // Hide the button when game starts
}
class creature//class for the creature, pixel slime shape
{
constructor(x, y, size, r, g, b, name) {
this.x = x;
this.y = y;
this.r = r;
this.g = g;
this.b = b;
this.size = size;
this.color = color;
this.hp = 100;
this.hunger = 100;
this.name = name;
this.lifetime = 0;
this.speedx = 0;
this.speedy = 0;
this.jumpduration = 0;
this.startheight = y;
this.jump = false;
this.jumpbreak = 0;
this.jumpdirection = 0;
this.jumpforceX = 0;
this.jumpforceY = 0;
this.reproductionbreak = 0;
this.lately_reproduction = false;

}
display() {
push();;
translate(this.x, this.y);
fill(0);
noStroke();
//text of name and hp
text(this.name, -10, -50);
fill(‘red’);
rect(-20, -40, this.hp * 0.4, 5);
fill(0)
//text(“Hunger: “+this.hunger,0,-10);
//border for the whole slime
rectMode(CENTER);
if (this.jumpdirection < 0)
scale(1, 1);
else
scale(-1, 1);
rect(0, 0, this.size * 75, this.size * 10);//bottom of the slime
rect(-1.25, 7.5, this.size * 72.5, this.size * 5);
rect(-2.5, 11.25, this.size * 70, this.size * 2.5);
rect(-2.5, 13.75, this.size * 65, this.size * 2.5);
rect(-2.5, 16.25, this.size * 55, this.size * 2.5);
rect(0, -7.5, this.size * 70, this.size * 5);//top of the slime
rect(0, -12.5, this.size * 65, this.size * 5);
rect(0, -17.5, this.size * 55, this.size * 5);
rect(0, -20, this.size * 50, this.size * 2.5);
rect(0, -22.5, this.size * 45, this.size * 2.5);
rect(0, -25, this.size * 35, this.size * 2.5);
rect(-2.5, -27.5, this.size * 22.5, this.size * 2.5);
//body
fill(this.r, this.g, this.b);
scale(0.95);
noStroke();
rect(0, 0, this.size * 75, this.size * 10.5);//bottom of the slime
rect(-1.25, 7.5, this.size * 72.5, this.size * 6);
rect(-2.5, 11.25, this.size * 70, this.size * 3);
rect(-2.5, 13.75, this.size * 65, this.size * 3);
rect(-2.5, 16.25, this.size * 55, this.size * 3);
rect(0, -7.5, this.size * 70, this.size * 5.75);//top of the slime
rect(0, -12.5, this.size * 65, this.size * 5.75);
rect(0, -17.5, this.size * 55, this.size * 5.75);
rect(0, -20, this.size * 50, this.size * 3.25);
rect(0, -22.5, this.size * 45, this.size * 3.25);
rect(0, -25, this.size * 35, this.size * 3.25);
rect(-2.5, -27.5, this.size * 22.5, this.size * 2.5);
//eyes
fill(“white”);
rect(-15, -10, this.size * 5, this.size * 10);
rect(10.5, -10, this.size * 10, this.size * 10);
//outline for the lefteyes
fill(“black”);
rect(-18.75, -10, this.size * 2.5, this.size * 10);
rect(-15, -3.75, this.size * 5, this.size * 2.5);
rect(-15, -16.25, this.size * 5, this.size * 2.5);
rect(-11.25, -10, this.size * 2.5, this.size * 15);
//outline for the righteyes
rect(4.25, -10, this.size * 2.5, this.size * 10)
rect(10.5, -3.75, this.size * 10, this.size * 2.5);
rect(10.5, -16.25, this.size * 10, this.size * 2.5);
rect(16.75, -10, this.size * 2.5, this.size * 10);
//mouth, “W” shape
fill(this.r – 30, this.g – 30, this.b – 30);
rect(-5, 5, this.size * 15, this.size * 2.5);
fill(10);
rect(-5, 5, this.size * 10, this.size * 2.5);
rect(-11.25, 2.5, this.size * 2.5, this.size * 2.5);
rect(1.25, 2.5, this.size * 2.5, this.size * 2.5);
rect(-5, 2.5, this.size * 2.5, this.size * 2.5);
pop();
}
move()//update the position of the slime
{
if (this.y < 250 || this.jump == true)
this.y += 3 + this.jumpduration * 2;
if (this.y + this.speedy < 500 && this.y + this.speedy > 0 && this.x + this.speedx < 800 && this.x + this.speedx > 0) {
this.x += this.speedx;
this.y += this.speedy;
}
}
step()//jumping function
{
if (this.jump == true) {
this.jumpduration++;

if (this.jumpdirection < 0) {
if (this.speedx > -5)
this.speedx -= this.jumpforceX;
this.speedy = this.jumpforceY;
}
if (this.jumpdirection > 0) {
if (this.speedx < 5)
this.speedx += this.jumpforceX;
this.speedy = this.jumpforceY;
}
if (this.jumpduration > 1 && this.y >= this.startheight) {
this.jump = false;
this.jumpduration = 0;
this.speedy = 0;
this.speedx = 0;
this.y = this.startheight;
}
}
}
print() {
console.log(this.name)
}
}
alllife = []
deployBreak = 0;
newdeploy = false
var alphabet = new Array(‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’, ‘Y’, ‘Z’)//alphabet for name generate
function name(len, inhen = null) {

let name = ”
if (inhen == null)
for (i = 0; i < len; i++) {
let w = int(random(1, 52))
name += alphabet[w]
}
else {
name += inhen
for (i = 0; i < len; i++) {
let w = int(random(1, 52))
name += alphabet[w]
}
}
return name
}
function findCloseSlimes() {
let closeSlimes = [];
for (let i = 0; i < alllife.length; i++) {
for (let j = i + 1; j < alllife.length; j++) {
let distance = dist(alllife[i].x, alllife[i].y, alllife[j].x, alllife[j].y);
if (distance < 50) {
closeSlimes.push(alllife[i]);
closeSlimes.push(alllife[j]);
}
}
}
return closeSlimes;
}
class Food {
constructor(x, y) {
this.x = x;
this.y = y;
this.radius = 10;
this.lifetime = 0;
}

display() {
fill(“gold”); // Red color for food
noStroke();
// Draw pixel ball
for (let i = 0; i < this.radius * 2; i++) {
for (let j = 0; j < this.radius * 2; j++) {
if (dist(i, j, this.radius, this.radius) < this.radius) {
rect(this.x + i – this.radius, this.y + j – this.radius, 1, 1);
}
}
}
}

checkCollision(creature) {
let distance = dist(this.x, this.y, creature.x, creature.y);
if (distance < this.radius + creature.size * 75 / 2) {
creature.hp += 20; // Increase creature’s hp
return true;
}
return false;
}
}

function draw() {
background(255);
imageMode(CENTER);
image(img, 400, 250, 800, 500);
if (!gameStarted) {
textFont(myfont);
textSize(50);
fill(“gold”);
text(“Press b to create a slime”, 100, 80);
text(“Click mouse to provide food”, 100, 140);
text(“Observe how their family develop”, 50, 200);
//text(“New slimes will inherit the name and color from both of their parents”, 50, 220);
//startSlime = new Creature(400, 300, 1, 0, 255, 0, “PIXEL”);
//startSlime.display();
}
else {
textFont(myfont);
textSize(20);
fill(0);
text(“current slimes: ” + alllife.length, 15, 90);
//text(foodBreak, 15, 110);
if (keyIsPressed === true)
if (key == ‘b’ && newdeploy == false) {
r = random(255);
g = random(255);
b = random(255);
let new_name = name(3, null)
console.log(new_name)
alllife.push(new creature(mouseX, mouseY, 1, r, g, b, new_name));
newdeploy = true;
}
if (newdeploy == true) {
deployBreak++;
}
if (deployBreak > 50) {
newdeploy = false;
deployBreak = 0;
}
for (var i = 0; i < alllife.length; i++) {
alllife[i].display();
alllife[i].lifetime++;
alllife[i].hp -= 0.05 + alllife.length * 0.001;
alllife[i].hunger -= 0.05;
alllife[i].move();
alllife[i].step();
if (alllife[i].jump == false) {
alllife[i].jumpbreak++;
}
if (alllife[i].jumpbreak > 200) {
alllife[i].jump = true;
alllife[i].jumpdirection = random(-1, 1);
alllife[i].jumpforceX = random(0.5, 1.5);
alllife[i].jumpforceY = random(-20, -15);
alllife[i].startheight = alllife[i].y;
alllife[i].jumpbreak = 0;
}
if (alllife[i].lately_reproduction == true) {
alllife[i].reproductionbreak++;
}
if (alllife[i].reproductionbreak > 400) {
alllife[i].lately_reproduction = false;
alllife[i].reproductionbreak = 0;
}
if (alllife[i].hp <= 0) {
foods.push(new Food(alllife[i].x, alllife[i].y));
alllife.splice(i, 1);
}
}
let closeSlimes = findCloseSlimes();
for (let i = 0; i < closeSlimes.length; i += 2) {
if (closeSlimes[i].lately_reproduction == false && closeSlimes[i + 1].lately_reproduction == false && closeSlimes[i].lifetime > 600 && closeSlimes[i + 1].lifetime > 600) {
let new_name = name(2, closeSlimes[i].name[0] + closeSlimes[i + 1].name[0] + ‘.’)
alllife.push(new creature((closeSlimes[i].x + closeSlimes[i + 1].x) / 2, closeSlimes[i].y, 1, closeSlimes[i].r, closeSlimes[i + 1].g, (closeSlimes[i].b + closeSlimes[i + 1].b) / 2, new_name));
closeSlimes[i].lately_reproduction = true;
closeSlimes[i + 1].lately_reproduction = true;
}
}
// Deploy food
for (let i = foods.length – 1; i >= 0; i–) {
foods[i].display();
if (foods[i].y < 250) {
foods[i].y += 5;
}
foods[i].lifetime++;
if (foods[i].lifetime > 300) {
foods.splice(i, 1);
continue;
}
// Check collision with each creature
for (let j = 0; j < alllife.length; j++) {
if (foods[i].checkCollision(alllife[j])) {
foods.splice(i, 1); // Remove food if consumed
break; // Exit the loop after collision detected
}
}
}
}

}
function mouseClicked() {
if (gameStarted) {
// Add food at mouse click location
foods.push(new Food(mouseX, mouseY));
}
}

The whole code for this sketch can be divided into  several sections:

Initialization and Setup:

  • The code begins by loading a background image and a custom font in the preload() function.
  • In the setup() function, a canvas is created and attached to the position of the canvas, and a start button is added to initiate the game.
  • Creature Class:
    • The creature class represents individual pixelime creatures.
    • In this section, I utilized the skill of Object Oriented Programming(OOP) to deal with the task of multi objects issue.
    • Each creature has properties such as position (x and y), size, color, health points (hp), hunger, name, and various flags to control behavior.
    • The display() method draws the creature on the canvas using various rect() shapes for body parts and features like eyes and mouth.
    • The move() method updates the position of the creature, including a jumping motion controlled by the step() method.
    • There are methods for generating random names and finding close slimes for reproduction.

Food Class:

  • The Food class represents food items for the creatures.
  • Each food item has properties for position, radius, and lifespan.
  • The display() method draws the food item on the canvas, and the checkCollision() method checks if a creature consumes the food.

Game Loop:

  • The draw() function serves as the game loop.
  • It starts by displaying instructions if the game hasn’t started yet.
  • If the game has started, it updates and displays all creatures, checks for reproduction opportunities, and deploys food items.
  • Due to the requirement of iterating through each elements in the allife list and food list, this part can be quite time consuming, which sets a limit on the amount of slimes.

Challenges faced:

  • Implementing realistic creature behavior, such as jumping and movement.
  • Managing interactions between creatures and food items efficiently.
  • Ensuring smooth gameplay and avoiding performance issues with a large number of creatures and food items.(Which still required a lot of works todo)

Discoveries made:

  • Experimenting with different algorithms and approaches to simulate creature behavior and interactions.
  • Utilizing OOP in the management of various sorts of elements.

Reflection and Future Development

Although this project has achieved most of my expectations, there are still several areas for improvement:

  1. Lack of visual appeal: While the project has a significant amount of code to implement functionality, there is still a deficiency in visual artistry.
  2. UI design and interaction logic are not rational: The logic of pressing the ‘b’ key and mouse operations should have been reversed. Additionally, once the game starts, the instructional prompts disappear, which is not user-friendly.
  3. Failure to fully utilize OOP features: The distinctive features of the slimes are not prominent enough, indicating a missed opportunity to fully leverage object-oriented programming principles.

Takeaways:

  1. Setting appropriate goals is crucial. An overly ambitious proposal not only consumes significant energy but may also never be completed.
  2. While complex mechanisms are the core of a sketch, visually appealing presentation is also important to attract attention.
  3. A reasonable UI/UX interface can have a significant impact on the user-friendly aspects of the work.

Credits & References

Background Image:https://www.youtube.com/watch?v=MIq1QW0ycI8&t=247s

 
 

ProjectA-Pixelime(Part1)

Pixelime

——A story of how life expands and vanishes

Description: Pixelime is a hypothetical soft-bodied creature living in the wetlands of Southeast Asia. Please create your slimes in this simulator, feed them, witness their offspring, build families, and ultimately witness the end of life.

Abstruct: This project utilizes p5.js and HTML to construct a web simulator, simulating the evolution and life cycle of an interactive pixelime community. The inspiration for this work comes from the classic fantasy depiction of slimes and pixel art style found in various fantasy works. Users primarily use the mouse and keyboard to create new pixelime individuals and feed them. Afterward, users can observe the evolution of various slime communities.

A pixelime individual is primarily composed of appearance, color, name, and HP (health points). Individuals deployed directly by users have completely random names and colors. New individuals bred from existing ones inherit the family name from their parents and receive a random given name. Additionally, their color is a blend of their parents’ colors.