/******************************************************************
* Project Name: Toy Knife
* Author: Gabriel Duarte
* Student Number: 991433574
* Date: Oct 22, 2016
* Description: The user cuts the skin of a human by clicking the
left mouse button until that hooman dies *evil laugh*. There
is a lot of blood (cool particle system).
Read the console.
******************************************************************/
//Knife object:
Knife myKnife;
//If the knife has cut once:
boolean hasCut;
//Group of cuts:
ArrayList<Cut> cuts;
//Group of Particle emitters:
ArrayList<ParticleSystem> p;
//Randomize skin color:
color bgColor;
//"Voice" of the person:
Voice voice;
void setup() {
size(640, 480);
noCursor();
smooth(2);
//Selects a skin color:
bgColor = chooseColor();
//Nothing has been cut yet:
hasCut = false;
//Creates a voice instance:
voice = new Voice();
createCutsArray();
createKnife();
createParticleSystems();
}
//Creates group of cuts:
void createCutsArray() {
cuts = new ArrayList<Cut>();
}
//Creates knife:
void createKnife() {
myKnife = new Knife(180);
}
//Creates group of particle emitters:
void createParticleSystems() {
p = new ArrayList<ParticleSystem>();
}
void draw() {
background(bgColor);
drawEachCut();
drawBlood();
myKnife.drawKnife();
noStroke();
fill(149, 21, 21, p.size()*10);
rect(0, 0, width, height);
}
//For each particle system, draw their blood:
void drawBlood() {
for (int i = 0; i < p.size(); i++) {
ParticleSystem ps = p.get(i);
ps.addParticle();
ps.run();
}
}
//Draws each cut on the screen:
void drawEachCut() {
for (int i = 0; i < cuts.size(); i++) {
Cut c = cuts.get(i);
c.drawCut();
}
}
//Click interaction:
void mousePressed() {
//If nothing was cut before, it is now:
if (!hasCut) {
hasCut = true;
}
//Add a cut:
cuts.add(new Cut(mouseX, mouseY-myKnife.mySize));
//Add a particle emitter:
p.add(new ParticleSystem(mouseX, mouseY-myKnife.mySize));
//If the person is dead:
if (p.size()*10 >= 255) {
println("*silence*");
} else {
//Say things:
voice.shout();
}
}
//Reset by pressing "r":
void keyPressed() {
if (key == 'r') {
setup();
}
}
//Choose a skin color:
color chooseColor() {
if (random(-5, 5) > 0) {
return color(126, 98, 70);
} else {
return color(235, 240, 201);
}
}
class Cut {
//Index of cut shape:
int myIndex;
//Position of cut:
PVector pos;
//Cut constructor:
Cut(float x, float y) {
//Choose a shape:
myIndex = int(random(4));
pos = new PVector(x, y);
}
void drawCut() {
noStroke();
fill(0);
//Chooses between different shapes of cuts:
switch (myIndex) {
case 0:
case1();
break;
case 1:
case2();
break;
case 2:
case3();
break;
case 3:
case4();
break;
default:
case1();
break;
}
}
//Shape 1:
void case1() {
triangle(pos.x+10, pos.y-5, pos.x-50, pos.y+10, pos.x+8, pos.y-15);
}
//Shape 2:
void case2() {
triangle(pos.x+80, pos.y-5, pos.x-50, pos.y+10, pos.x+8, pos.y-15);
}
//Shape 3:
void case3() {
triangle(pos.x+60, pos.y+5, pos.x-20, pos.y+10, pos.x+15, pos.y+15);
}
//Shape 4:
void case4() {
triangle(pos.x-30, pos.y-80, pos.x-20, pos.y+10, pos.x+15, pos.y+60);
}
}
class Knife {
//Size of the knife:
float mySize;
//Knife constructor:
Knife(float sze) {
mySize = sze;
}
//Drawing the knife at the mouse position:
void drawKnife() {
noStroke();
fill(191, 189, 189);
triangle(mouseX, mouseY, mouseX-mySize/2, mouseY, mouseX, mouseY-mySize);
fill(175, 152, 115);
rectMode(CORNERS);
rect(mouseX-mySize/4, mouseY, mouseX, mouseY+mySize/1.2);
ellipse(mouseX-(mySize/3)/2, mouseY+mySize/1.2, mySize/3, mySize/3);
fill(219, 237, 84);
ellipse(mouseX-(mySize/3)/2, mouseY+mySize/1.2, mySize/8, mySize/8);
ellipse(mouseX-mySize/8, mouseY+mySize/10, mySize/10, mySize/10);
//Draw blood stains if the knife has cut something:
if (hasCut) {
fill(185, 66, 66);
noStroke();
ellipse(mouseX-mySize/3, mouseY-mySize/6, 26, 32);
ellipse(mouseX-mySize/6, mouseY-mySize/4, 16, 16);
ellipse(mouseX-mySize/6.5, mouseY-mySize/2, 20, 15);
ellipse(mouseX-mySize/18, mouseY-mySize/1.2, 8, 10);
fill(185, 66, 66, 100);
triangle(mouseX, mouseY, mouseX-mySize/2, mouseY, mouseX, mouseY-mySize);
}
}
}
class Particle {
//Particle position:
PVector position;
//Particle speed:
PVector speed;
//Particle acceleration:
PVector acceleration;
//Particle lifeTime (alpha):
float lifeTime = 255;
float lifeSpeed;
//Particle constructor:
Particle(PVector l, float lSpd) {
acceleration = new PVector(0, 0.5);
speed = new PVector(random(-1, 1), random(-1, 1));
position = l.get();
lifeSpeed = lSpd;
}
//Update the position of each particle:
void update() {
speed.add(acceleration);
position.add(speed);
//Turn transparent over time:
lifeTime -= lifeSpeed;
}
//Test if particle has gone completly transparent:
boolean isDead() {
if (lifeTime <= 0) {
return true;
} else {
return false;
}
}
//Draw particle:
void display() {
noStroke();
fill(185, 66, 66, lifeTime);
ellipse(position.x, position.y, 30, 25);
}
}
class ParticleSystem {
//Group of particels:
ArrayList<Particle> particles;
//Origin of particles:
PVector origin;
//System constructor:
ParticleSystem(float x, float y) {
origin = new PVector(x, y);
particles = new ArrayList<Particle>();
}
//Adds particles to the system:
void addParticle() {
particles.add(new Particle(origin, 2));
}
//Run particle system and render every particle:
void run() {
for (int i = 0; i < particles.size(); i++) {
Particle p = particles.get(i);
p.update();
p.display();
//Destroy them if they are "dead":
if (p.isDead()) {
particles.remove(i);
}
}
}
}
class Voice {
//Text displayed in the console:
String text;
//Voice constructor:
Voice() {
}
//Display text:
void shout() {
//Choose a random number:
int rand = int(random(1, 5));
//Display text according to the number chosen:
switch (rand) {
case 1:
text = "Stop it";
break;
case 2:
text = "Baby don't hurt me";
break;
case 3:
text = "I'd rather drink bleach";
break;
case 4:
text = "Anakin you're breaking my heart";
break;
case 5:
text = "This doesn't even hurt :(";
break;
default:
//Gets
text = "Hi human, If this appears on the console, something went horribly wrong...";
break;
}
//Print selected text to console:
println(text);
}
}