My project is a generative drawing project where the user gets to draw with hands/joystick and then save the work they drew.
I started my work by exploring different shapes and types of brushes to choose one. After some time and looking around I decided it was best to give the user the option to use more than one brush in one piece.
I am still not done with the brush class but after testing the brushes separately, that is my unedited code for the brush class:
letters = "It isn't true that my mattress is made of cotton candy. It was the first time he had ever seen someone cook dinner on an elephant. Homesickness became contagious in the young campers' cabin. Every manager should be able to recite at least ten nursery rhymes backward.";
// for(int i; i<8; i++){
// numX = (float)acos()
// }
}
voidsetbrush(int brushn){
brushN=brushn;
}
voidsetSize(int size){
stepSize=size;
}
voiddraw(){
switch(brushN){
case 1:
blur();
break;
case 2:
randomprisms();
break;
case 3:
dynamicShapes();
break;
case 4:
textlines();
break;
default :
rotatingLines();
break;
}
}
...
}
class ColorWheel{
}
import java.util.*;
class Brush {
int brushN;
float stepSize;
float angle;
float x, y, tempX, tempY;
color col;
//
int counter;
PFont font;
float fontSize;
String letters;
float fontSizeMin;
//
float [] blurX={ -stepSize, -stepSize, 0, stepSize, stepSize, stepSize, 0, -stepSize};
float [] blurY={ 0, stepSize, stepSize, stepSize, 0, -stepSize, -stepSize, -stepSize};
//linemoduelw
PShape lineModule;
float linelength=100;
float [] numX={ -100, -70, 0, 70, 100, 70, 0, -70};
float [] numY={ 0, 70, 100, 70, 0, -70, -100, -70};
Brush(int defaultt, float step_size) {
// 1 blur
// 2 random cylinder
// 3 dynamic shapes
// 4 text lines
// 5 rotating lines
brushN = defaultt;
stepSize = step_size;
angle = 270;
x = mouseX;
y = mouseY;
col = color(255);
fontSizeMin=200;
fontSize=50;
letters = "It isn't true that my mattress is made of cotton candy. It was the first time he had ever seen someone cook dinner on an elephant. Homesickness became contagious in the young campers' cabin. Every manager should be able to recite at least ten nursery rhymes backward.";
// for(int i; i<8; i++){
// numX = (float)acos()
// }
}
void setbrush(int brushn) {
brushN=brushn;
}
void setSize(int size) {
stepSize=size;
}
void draw() {
switch (brushN) {
case 1:
blur();
break;
case 2:
randomprisms();
break;
case 3:
dynamicShapes();
break;
case 4:
textlines();
break;
default :
rotatingLines();
break;
}
}
...
}
class ColorWheel{
}
import java.util.*;
class Brush {
int brushN;
float stepSize;
float angle;
float x, y, tempX, tempY;
color col;
//
int counter;
PFont font;
float fontSize;
String letters;
float fontSizeMin;
//
float [] blurX={ -stepSize, -stepSize, 0, stepSize, stepSize, stepSize, 0, -stepSize};
float [] blurY={ 0, stepSize, stepSize, stepSize, 0, -stepSize, -stepSize, -stepSize};
//linemoduelw
PShape lineModule;
float linelength=100;
float [] numX={ -100, -70, 0, 70, 100, 70, 0, -70};
float [] numY={ 0, 70, 100, 70, 0, -70, -100, -70};
Brush(int defaultt, float step_size) {
// 1 blur
// 2 random cylinder
// 3 dynamic shapes
// 4 text lines
// 5 rotating lines
brushN = defaultt;
stepSize = step_size;
angle = 270;
x = mouseX;
y = mouseY;
col = color(255);
fontSizeMin=200;
fontSize=50;
letters = "It isn't true that my mattress is made of cotton candy. It was the first time he had ever seen someone cook dinner on an elephant. Homesickness became contagious in the young campers' cabin. Every manager should be able to recite at least ten nursery rhymes backward.";
// for(int i; i<8; i++){
// numX = (float)acos()
// }
}
void setbrush(int brushn) {
brushN=brushn;
}
void setSize(int size) {
stepSize=size;
}
void draw() {
switch (brushN) {
case 1:
blur();
break;
case 2:
randomprisms();
break;
case 3:
dynamicShapes();
break;
case 4:
textlines();
break;
default :
rotatingLines();
break;
}
}
...
}
class ColorWheel{
}
Blur:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidblur(){
float diam = 1;
if(mousePressed){
float d = dist(x, y, mouseX, mouseY);
if(d > stepSize){
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
tempX = x;
tempY = y;
pushMatrix();
//
translate(x, y);
rotate(angle);
noStroke();
fill(col, 40);
//
for(int i=0; i<200; i++){
int dir = int(random(0, 7));
rotate(random(5));
tempX=blurX[dir]*random(1, 10);
tempY=blurY[dir]*random(1, 10);
circle(tempX, tempY, diam);
}
//
popMatrix();
x=x+(float)Math.cos((angle))*stepSize;
y=y+(float)Math.sin((angle))*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
void blur() {
float diam = 1;
if (mousePressed) {
float d = dist(x, y, mouseX, mouseY);
if (d > stepSize) {
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
tempX = x;
tempY = y;
pushMatrix();
//
translate(x, y);
rotate(angle);
noStroke();
fill(col, 40);
//
for (int i=0; i<200; i++) {
int dir = int(random(0, 7));
rotate(random(5));
tempX=blurX[dir]*random(1, 10);
tempY=blurY[dir]*random(1, 10);
circle(tempX, tempY, diam);
}
//
popMatrix();
x=x+(float)Math.cos((angle))*stepSize;
y=y+(float)Math.sin((angle))*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
void blur() {
float diam = 1;
if (mousePressed) {
float d = dist(x, y, mouseX, mouseY);
if (d > stepSize) {
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
tempX = x;
tempY = y;
pushMatrix();
//
translate(x, y);
rotate(angle);
noStroke();
fill(col, 40);
//
for (int i=0; i<200; i++) {
int dir = int(random(0, 7));
rotate(random(5));
tempX=blurX[dir]*random(1, 10);
tempY=blurY[dir]*random(1, 10);
circle(tempX, tempY, diam);
}
//
popMatrix();
x=x+(float)Math.cos((angle))*stepSize;
y=y+(float)Math.sin((angle))*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
Random Size Prisms Brush:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidrandomprisms(){
if(mousePressed){
float d = dist(x, y, mouseX, mouseY);
if(d>stepSize){
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
void dynamicShapes() {
if (mousePressed) {
float d = dist(x, y, mouseX, mouseY);
if (d>stepSize) {
//
lineModule = createShape();
stroke(col);
strokeWeight(10);
noFill();
lineModule.beginShape();
lineModule.vertex(100, 0); // first point
lineModule.vertex(0, 100);// /
lineModule.vertex(-100, 0);// \
lineModule.vertex(0, -100);// /
lineModule.vertex(100, 0);// \
lineModule.endShape();
// lineModule = createShape();
// stroke(col);
// strokeWeight(10);
// fill(col);
// lineModule.beginShape();
// lineModule.vertex(50, 75); // first point
// lineModule.bezierVertex(100, 100, 500, 100, 400, 300);
// lineModule.endShape();
//
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
pushMatrix();
//
translate(mouseX, mouseY);
rotate((angle+PI));
shape(lineModule, 0, 0, d, noise(1+frameCount*0.0001)*10);
//
popMatrix();
x=x+(float)Math.cos((angle))*stepSize;
y=y+(float)Math.sin((angle))*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
void dynamicShapes() {
if (mousePressed) {
float d = dist(x, y, mouseX, mouseY);
if (d>stepSize) {
//
lineModule = createShape();
stroke(col);
strokeWeight(10);
noFill();
lineModule.beginShape();
lineModule.vertex(100, 0); // first point
lineModule.vertex(0, 100);// /
lineModule.vertex(-100, 0);// \
lineModule.vertex(0, -100);// /
lineModule.vertex(100, 0);// \
lineModule.endShape();
// lineModule = createShape();
// stroke(col);
// strokeWeight(10);
// fill(col);
// lineModule.beginShape();
// lineModule.vertex(50, 75); // first point
// lineModule.bezierVertex(100, 100, 500, 100, 400, 300);
// lineModule.endShape();
//
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
pushMatrix();
//
translate(mouseX, mouseY);
rotate((angle+PI));
shape(lineModule, 0, 0, d, noise(1+frameCount*0.0001)*10);
//
popMatrix();
x=x+(float)Math.cos((angle))*stepSize;
y=y+(float)Math.sin((angle))*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
Text Brush:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidtextlines(){
if(mousePressed){
float d = dist(x, y, mouseX, mouseY);
d= constrain(d, 60, 7000);
if(d>stepSize){
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
fontSize= fontSizeMin*60/d;
println("d: "+d);
font = createFont("Calibri", fontSize);
textFont(font, fontSize);
char newLetter = letters.charAt(counter);
stepSize = textWidth(newLetter);
fill(col);
//stroke(col);
pushMatrix();
//
translate(x, y);
rotate(angle);
text(newLetter, 0, 0);
//
popMatrix();
counter++;
if(counter>letters.length()-1) counter=0;
x = x + (float)Math.cos(angle)*stepSize;
y = y + (float)Math.sin(angle)*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
void textlines() {
if (mousePressed) {
float d = dist(x, y, mouseX, mouseY);
d= constrain(d, 60, 7000);
if (d>stepSize) {
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
fontSize= fontSizeMin*60/d;
println("d: "+d);
font = createFont("Calibri", fontSize);
textFont(font, fontSize);
char newLetter = letters.charAt(counter);
stepSize = textWidth(newLetter);
fill(col);
//stroke(col);
pushMatrix();
//
translate(x, y);
rotate(angle);
text(newLetter, 0, 0);
//
popMatrix();
counter++;
if (counter>letters.length()-1) counter=0;
x = x + (float)Math.cos(angle)*stepSize;
y = y + (float)Math.sin(angle)*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
void textlines() {
if (mousePressed) {
float d = dist(x, y, mouseX, mouseY);
d= constrain(d, 60, 7000);
if (d>stepSize) {
// gets the angle between the mouse and the location of the brush so that next point is drawn in the right intended location
angle = (float)Math.atan2(mouseY-y, mouseX-x);
fontSize= fontSizeMin*60/d;
println("d: "+d);
font = createFont("Calibri", fontSize);
textFont(font, fontSize);
char newLetter = letters.charAt(counter);
stepSize = textWidth(newLetter);
fill(col);
//stroke(col);
pushMatrix();
//
translate(x, y);
rotate(angle);
text(newLetter, 0, 0);
//
popMatrix();
counter++;
if (counter>letters.length()-1) counter=0;
x = x + (float)Math.cos(angle)*stepSize;
y = y + (float)Math.sin(angle)*stepSize;
}
}
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
}
Rotating Brush:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidrotatingLines(){
if(mousePressed){
pushMatrix();
strokeWeight(3);
stroke(col);
//
translate(mouseX, mouseY);
rotate(radians(angle));
line(0, 0, linelength, 0);
//
popMatrix();
angle +=1;
col = color(noise(100+0.01*frameCount)*255, noise(200+0.01*frameCount)*255, noise(300+0.01*frameCount)*255, 255);
My idea is to make a drawing machine on Processing and to use Arduino-controlled Joy Sticks to control the mouse position on the screen.
The user would get to control the colors and save the image if desired.
If the user decides to save their generative art drawing, the 5 last saved drawings will show on the screen in a polaroid-like look.
Processing Inspiration:
I chose to make a generative art piece on processing because I feel that a drawing using a joystick can only get you so far without much practice, so I decided that a generative art algorithm would work better for this case.
These are some sources that I feel inspire my goal for the processing part of my project.
First design this is a randomly generated piece, but it is really close to what I thought of when I first thought of generative.
Second design This is a drawing piece where the letters are drawn instead of ink at the position of the mouse and the size is decided by the speed of the movement of the mouse.
Third design In this one the cursor is followed by randomly changing shape instead of a normal brush.
Fourth design This, like the first, does not follow the mouse, it is just random instead-but follows a random path and is not completely random.
I think this might be nice to add behind any of the other designs with a lower opacity to give a smoky look behind the drawing.
Arduino:
My plan is to have 2 joysticks, one to control the mouse location and one to change the color of the drawing at a certain point.
I also plan to add push buttons to toggle values that will reset/save/show prev saved images.
This is the arrangement I have in mind at the moment
I decided, after a struggle of thought, to make a simple water refill reminder. Drinking water is crucial and many people tend to try to forget. So I made this simple water that detects the weight of the bottle and knows how much water is left in the bottle/cup using a force sensor.
using the force sensor on its own did not give a range of weight enough for the water weight detector. so I decided to place the force sensor on a sponge.
I also used an on/off button that turns the circuit on when pressed and off when pressed once more
I also used 4 red lights that are more likely to capture someone’s attention and remind them to refill their water bottle when it’s empty.
and I used 4 blue led lights, more of the blue lights light up the more water there is in the bottle.
this is how my circuit looks:
the last set of wires that are neither connected to the button or the less is connected to the force sensor.
video:
the video shows how the circuit works:
Code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const int outs[] = {3, 5, 6, 9,
10, 11, 12, 13
};
const int ins[] = {A2, A3};
int var, var2, b, r, maxx = 0;
long timer;
bool turnon = 0, curr, prev;
voidsetup(){
Serial.begin(9600);
for(int i = 0; i <sizeof(outs); i++){
pinMode(outs[i], OUTPUT);
}
Serial.begin(9600);
for(int i = 0; i <sizeof(ins); i++){
pinMode(ins[i], INPUT);
}
}
voidloop(){
if(curr != prev && curr == 1){
turnon = !turnon;
}
curr = digitalRead(ins[1]);
timer = millis();
var = analogRead(ins[0]);//0-250
var = map(var, 0, 500, 0, 255);
var2 = constrain(var, 250, 255);
Serial.print(" on: ");
Serial.print(turnon);
Serial.print(" curr: ");
Serial.print(curr);
Serial.print(" prev: ");
Serial.println(prev);
if(turnon == 1){
on();
}
else{
for(int i = 0; i <8; i++){
analogWrite(outs[i], 0);
}
}
//
prev = digitalRead(ins[1]);
}
voidredled(int n){
if(timer % (n *4)<(n *1)){
analogWrite(outs[4], var2);
analogWrite(outs[5], 0);
analogWrite(outs[6], 0);
analogWrite(outs[7], 0);
}
elseif(timer % (n *4)<(n *2)){
analogWrite(outs[4], 0);
analogWrite(outs[5], var2);
analogWrite(outs[6], 0);
analogWrite(outs[7], 0);
}
elseif(timer % (n *4)<(n *3)){
analogWrite(outs[4], 0);
analogWrite(outs[5], 0);
analogWrite(outs[6], var2);
analogWrite(outs[7], 0);
}
else{
analogWrite(outs[4], 0);
analogWrite(outs[5], 0);
analogWrite(outs[6], 0);
analogWrite(outs[7], var2);
}
}
voidon(){
if(var <20){
b = -1;
r = 4;
}
elseif(var <140){
b = 0;
r = 0;
}
elseif(var <260){
b = 1;
r = 0;
}
elseif(var <380){
b = 2;
r = 0;
}
else{
b = 3;
r = 0;
}
// there is water
if(r == 0){
for(int i = 0; i < b + 1; i++){
analogWrite(outs[i], var2);
}
for(int i = 7; i > b; i--){
analogWrite(outs[i], 0);
}
}
else{
for(int i = 0; i <4; i++){
analogWrite(outs[i], 0);
}
redled(1000);
}
}
const int outs[] = {3, 5, 6, 9,
10, 11, 12, 13
};
const int ins[] = {A2, A3};
int var, var2, b, r, maxx = 0;
long timer;
bool turnon = 0, curr, prev;
void setup() {
Serial.begin(9600);
for (int i = 0; i < sizeof(outs); i++) {
pinMode(outs[i], OUTPUT);
}
Serial.begin(9600);
for (int i = 0; i < sizeof(ins); i++) {
pinMode(ins[i], INPUT);
}
}
void loop() {
if (curr != prev && curr == 1) {
turnon = !turnon;
}
curr = digitalRead(ins[1]);
timer = millis();
var = analogRead(ins[0]);//0-250
var = map(var, 0, 500, 0, 255);
var2 = constrain(var, 250, 255);
Serial.print(" on: ");
Serial.print(turnon);
Serial.print(" curr: ");
Serial.print(curr);
Serial.print(" prev: ");
Serial.println(prev);
if (turnon == 1) {
on();
}
else {
for (int i = 0; i < 8; i++) {
analogWrite(outs[i], 0);
}
}
//
prev = digitalRead(ins[1]);
}
void redled(int n) {
if (timer % (n * 4) < (n * 1)) {
analogWrite(outs[4], var2);
analogWrite(outs[5], 0);
analogWrite(outs[6], 0);
analogWrite(outs[7], 0);
}
else if (timer % (n * 4) < (n * 2)) {
analogWrite(outs[4], 0);
analogWrite(outs[5], var2);
analogWrite(outs[6], 0);
analogWrite(outs[7], 0);
}
else if (timer % (n * 4) < (n * 3)) {
analogWrite(outs[4], 0);
analogWrite(outs[5], 0);
analogWrite(outs[6], var2);
analogWrite(outs[7], 0);
}
else {
analogWrite(outs[4], 0);
analogWrite(outs[5], 0);
analogWrite(outs[6], 0);
analogWrite(outs[7], var2);
}
}
void on() {
if (var < 20) {
b = -1;
r = 4;
}
else if (var < 140) {
b = 0;
r = 0;
}
else if (var < 260) {
b = 1;
r = 0;
}
else if (var < 380) {
b = 2;
r = 0;
}
else {
b = 3;
r = 0;
}
// there is water
if (r == 0) {
for (int i = 0; i < b + 1; i++) {
analogWrite(outs[i], var2);
}
for (int i = 7; i > b; i--) {
analogWrite(outs[i], 0);
}
}
else {
for (int i = 0; i < 4; i++) {
analogWrite(outs[i], 0);
}
redled(1000);
}
}
const int outs[] = {3, 5, 6, 9,
10, 11, 12, 13
};
const int ins[] = {A2, A3};
int var, var2, b, r, maxx = 0;
long timer;
bool turnon = 0, curr, prev;
void setup() {
Serial.begin(9600);
for (int i = 0; i < sizeof(outs); i++) {
pinMode(outs[i], OUTPUT);
}
Serial.begin(9600);
for (int i = 0; i < sizeof(ins); i++) {
pinMode(ins[i], INPUT);
}
}
void loop() {
if (curr != prev && curr == 1) {
turnon = !turnon;
}
curr = digitalRead(ins[1]);
timer = millis();
var = analogRead(ins[0]);//0-250
var = map(var, 0, 500, 0, 255);
var2 = constrain(var, 250, 255);
Serial.print(" on: ");
Serial.print(turnon);
Serial.print(" curr: ");
Serial.print(curr);
Serial.print(" prev: ");
Serial.println(prev);
if (turnon == 1) {
on();
}
else {
for (int i = 0; i < 8; i++) {
analogWrite(outs[i], 0);
}
}
//
prev = digitalRead(ins[1]);
}
void redled(int n) {
if (timer % (n * 4) < (n * 1)) {
analogWrite(outs[4], var2);
analogWrite(outs[5], 0);
analogWrite(outs[6], 0);
analogWrite(outs[7], 0);
}
else if (timer % (n * 4) < (n * 2)) {
analogWrite(outs[4], 0);
analogWrite(outs[5], var2);
analogWrite(outs[6], 0);
analogWrite(outs[7], 0);
}
else if (timer % (n * 4) < (n * 3)) {
analogWrite(outs[4], 0);
analogWrite(outs[5], 0);
analogWrite(outs[6], var2);
analogWrite(outs[7], 0);
}
else {
analogWrite(outs[4], 0);
analogWrite(outs[5], 0);
analogWrite(outs[6], 0);
analogWrite(outs[7], var2);
}
}
void on() {
if (var < 20) {
b = -1;
r = 4;
}
else if (var < 140) {
b = 0;
r = 0;
}
else if (var < 260) {
b = 1;
r = 0;
}
else if (var < 380) {
b = 2;
r = 0;
}
else {
b = 3;
r = 0;
}
// there is water
if (r == 0) {
for (int i = 0; i < b + 1; i++) {
analogWrite(outs[i], var2);
}
for (int i = 7; i > b; i--) {
analogWrite(outs[i], 0);
}
}
else {
for (int i = 0; i < 4; i++) {
analogWrite(outs[i], 0);
}
redled(1000);
}
}
I have always been the worst when it came to forgetting different things at different places. Forgetting my card at the most random places was getting me locked out of my room more than I would have liked. So I decided to make a switch that reminds you to put your card back in its place sometime out.
I started by placing a switch in the circuit and making it work using a normal push-button switch. once I finished the circuit I replaced one end of the switch with a wire connected to the card and the other end with a wire connected to a cardholder that is to be stuck to a phone.
I connected the wires to copper tape that I stuck on contacting sides of the card and the cardholder so that when the card is in place, the switch is closed.
I used a yellow led light for the normal time when the card is placed in its location. when you remove the card from the cardholder, a timer starts, when the time span in the code ends, the red light starts to blink to remind you to put the card back in.
IMAGES:
Breadboard Circuit:
Whole Circuit:
Card Connection
Video:
CODE:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
long mytime=500, timer = 0;
const int outs[] = {2, 4};
const int ins = A2;
int curr = 0, prev=0;
bool flip=false;
long blinkk=0;
voidsetup(){
// put your setup code here, to run once:
Serial.begin(9600);
for(int i = 0; i <sizeof(outs); i++){
pinMode(outs[i], OUTPUT);
}
pinMode(ins, INPUT);
}
voidloop(){
curr = digitalRead(ins);// <500, <900, >900
if(curr == 0){
Serial.print(timer);
Serial.print(" ");
Serial.println(mytime);
if(mytime == timer){
if(blinkk<=millis()){
flip=!flip;
blinkk+=500;
}
digitalWrite(outs[0], flip);
digitalWrite(outs[1], LOW);
}
else{
timer+=1;
digitalWrite(outs[0], LOW);
digitalWrite(outs[1], LOW);
}
}
else{
{
timer=0;
digitalWrite(outs[1], HIGH);
digitalWrite(outs[0], LOW);
blinkk=millis();
}
}
prev = digitalRead(ins);
}
long mytime=500, timer = 0;
const int outs[] = {2, 4};
const int ins = A2;
int curr = 0, prev=0;
bool flip=false;
long blinkk=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
for (int i = 0; i < sizeof(outs); i++) {
pinMode(outs[i], OUTPUT);
}
pinMode(ins, INPUT);
}
void loop() {
curr = digitalRead(ins);// <500, <900, >900
if (curr == 0) {
Serial.print(timer);
Serial.print(" ");
Serial.println(mytime);
if (mytime == timer) {
if(blinkk<=millis()){
flip=!flip;
blinkk+=500;
}
digitalWrite(outs[0], flip);
digitalWrite(outs[1], LOW);
}
else{
timer+=1;
digitalWrite(outs[0], LOW);
digitalWrite(outs[1], LOW);
}
}
else {
{
timer=0;
digitalWrite(outs[1], HIGH);
digitalWrite(outs[0], LOW);
blinkk=millis();
}
}
prev = digitalRead(ins);
}
long mytime=500, timer = 0;
const int outs[] = {2, 4};
const int ins = A2;
int curr = 0, prev=0;
bool flip=false;
long blinkk=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
for (int i = 0; i < sizeof(outs); i++) {
pinMode(outs[i], OUTPUT);
}
pinMode(ins, INPUT);
}
void loop() {
curr = digitalRead(ins);// <500, <900, >900
if (curr == 0) {
Serial.print(timer);
Serial.print(" ");
Serial.println(mytime);
if (mytime == timer) {
if(blinkk<=millis()){
flip=!flip;
blinkk+=500;
}
digitalWrite(outs[0], flip);
digitalWrite(outs[1], LOW);
}
else{
timer+=1;
digitalWrite(outs[0], LOW);
digitalWrite(outs[1], LOW);
}
}
else {
{
timer=0;
digitalWrite(outs[1], HIGH);
digitalWrite(outs[0], LOW);
blinkk=millis();
}
}
prev = digitalRead(ins);
}
The purpose of this game is for the student, skeleton in the picture, to collect all the questions and then collect the final paper to get the full grade for their exam.
IDEA(details):
Background:
Originally, I intended to have clouds as the background with the stars, but even when I used images instead of pixels, the game’s frameRate dropped and the game was barely functioning so I settled for a clear starry night look.
I choose this because:
firstly, I have really sensitive eyes, and I find it easier on my eye to look at a dark screen.
Secondly, I am a night person, night always looks better ;).
For the stars, I used overlapping circles to give a faded look, which resembles actual stars more than normal circles would.
Code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Bg {
float[] x = new float[50];
float[] y = new float[50];
Bg(){
for(int i=0; i<50; i++){
x[i] = random(0, widthh);
y[i] = random(0, heightt);
}
}
voiddrawBG(){
if(frameCount%50==0){
for(int i=0; i<50; i++){
x[i] = random(0, width);
y[i] = random(0, height);
}
}
background(50, 50, 80);
for(int i=0; i<50; i++){
for(int j=0; j<10; j++){
noStroke();
fill(255, 25);
ellipse(x[i], y[i], 1+j, 1+j);
}
}
}
}
class Bg {
float[] x = new float[50];
float[] y = new float[50];
Bg() {
for (int i=0; i<50; i++) {
x[i] = random(0, widthh);
y[i] = random(0, heightt);
}
}
void drawBG() {
if (frameCount%50==0) {
for (int i=0; i<50; i++) {
x[i] = random(0, width);
y[i] = random(0, height);
}
}
background(50, 50, 80);
for (int i=0; i<50; i++) {
for (int j=0; j<10; j++) {
noStroke();
fill(255, 25);
ellipse(x[i], y[i], 1+j, 1+j);
}
}
}
}
class Bg {
float[] x = new float[50];
float[] y = new float[50];
Bg() {
for (int i=0; i<50; i++) {
x[i] = random(0, widthh);
y[i] = random(0, heightt);
}
}
void drawBG() {
if (frameCount%50==0) {
for (int i=0; i<50; i++) {
x[i] = random(0, width);
y[i] = random(0, height);
}
}
background(50, 50, 80);
for (int i=0; i<50; i++) {
for (int j=0; j<10; j++) {
noStroke();
fill(255, 25);
ellipse(x[i], y[i], 1+j, 1+j);
}
}
}
}
Creature:
Instead of making repetitive classes, I used class inheritance, where I made the Superclass, Creatures, for all the live items in the game.
Code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class Creature {
// Attributes
PVector pos;
PVector speed;
boolean alive;
float ground;
PVector size;
PVector imgSize;
int numFrames;
PImage imgs;
PImage[] img;
int frame;
boolean dir; //left = 0 right = 1
boolean secondJump = false;
public Creature(float x, float y, float r, float g, PImage _img, float w, float h, int num_frames){
For the player, I choose the skeleton, because obviously, we are all dead during midterm and final seasons. That also gave me the idea of the name “dead student“.
Sprite:
With the player, I struggled a little with the jumps. I wanted to only allow double jumps, which I thought was the case until my roommate tried it and I realized it didn’t. I tried to fix it, but that only made it worse, so I left it as it was when my roommate tried it. (I mean what works, works right?)
Code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Player extends Creature {
boolean left;
boolean up;
boolean right;
SoundFile jump;
int count;
Player(float x, float y, float r, float g, PImage _img, float w, float h, int num_frames, PApplet sketch){
class Player extends Creature {
boolean left;
boolean up;
boolean right;
SoundFile jump;
int count;
Player(float x, float y, float r, float g, PImage _img, float w, float h, int num_frames, PApplet sketch) {
super(x, y, r, g, _img, w, h, num_frames);
left = false;
up = false;
right = false;
jump = new SoundFile(sketch, "jump.wav");
count = frameCount;
}
void update() {
gravity();
//====================
if (left==true) {
speed.x=-3;
dir=false;
} else if (right==true) {
speed.x=3;
dir=true;
} else {
speed.x=0;
}
//====================
if (up==true && pos.y>=ground-size.y &&secondJump==false) {
jump.play();
speed.y = -6;
} else if (up==true && speed.y<0 && secondJump==true && pos.y<ground-size.y) {
jump.play();
speed.y = -8;
secondJump=false;
}
pos.x +=speed.x;
pos.y +=speed.y;
if (frameCount%5 == 0 && speed.x !=0 && speed.y ==0) {
frame= (frame+1)%numFrames;
} else if (speed.x==0) {
frame=8;
}
//====================
if (pos.x<=0) {
pos.x = 0;
}
//====================
if (pos.x+size.x>= widthh) {
pos.x = widthh- size.x;
} else if (pos.x<size.x) {
pos.x = size.x;
}
//====================
for (int i =0; i<game.myMonsters.length; i++) {
float numME = pow((pow(size.x, 2)+(pow(size.y, 2))), 0.5);
float numthem = pow((pow(game.myMonsters[i].size.x, 2)+(pow(game.myMonsters[i].size.y, 2))), 0.5);
if (game.myMonsters[i].distance(this)<=numME/2.5+numthem/2.5 && game.myMonsters[i].alive) {
if (speed.y>0) {
game.myMonsters[i].alive=false;
game.myMonsters[i].sound2.play();
} else {
game.myMonsters[i].sound1.play();
alive = false;
}
}
}
for (int i =0; i<game.myQuestions.length; i++) {
if (game.myQuestions[i].distance(this)<=size.x/2+game.myQuestions[i].size.x/2 && game.myQuestions[i].alive) {
game.score++;
game.myQuestions[i].sound.play();
game.myQuestions[i].alive = false;
}
}
if (game.myfinal.distance(this)<=size.x/2+game.myfinal.size.x/2 && game.myfinal.alive) {
game.score+=5;
game.myfinal.sound.play();
game.myfinal.alive = false;
game.won= true;
}
}
}
class Player extends Creature {
boolean left;
boolean up;
boolean right;
SoundFile jump;
int count;
Player(float x, float y, float r, float g, PImage _img, float w, float h, int num_frames, PApplet sketch) {
super(x, y, r, g, _img, w, h, num_frames);
left = false;
up = false;
right = false;
jump = new SoundFile(sketch, "jump.wav");
count = frameCount;
}
void update() {
gravity();
//====================
if (left==true) {
speed.x=-3;
dir=false;
} else if (right==true) {
speed.x=3;
dir=true;
} else {
speed.x=0;
}
//====================
if (up==true && pos.y>=ground-size.y &&secondJump==false) {
jump.play();
speed.y = -6;
} else if (up==true && speed.y<0 && secondJump==true && pos.y<ground-size.y) {
jump.play();
speed.y = -8;
secondJump=false;
}
pos.x +=speed.x;
pos.y +=speed.y;
if (frameCount%5 == 0 && speed.x !=0 && speed.y ==0) {
frame= (frame+1)%numFrames;
} else if (speed.x==0) {
frame=8;
}
//====================
if (pos.x<=0) {
pos.x = 0;
}
//====================
if (pos.x+size.x>= widthh) {
pos.x = widthh- size.x;
} else if (pos.x<size.x) {
pos.x = size.x;
}
//====================
for (int i =0; i<game.myMonsters.length; i++) {
float numME = pow((pow(size.x, 2)+(pow(size.y, 2))), 0.5);
float numthem = pow((pow(game.myMonsters[i].size.x, 2)+(pow(game.myMonsters[i].size.y, 2))), 0.5);
if (game.myMonsters[i].distance(this)<=numME/2.5+numthem/2.5 && game.myMonsters[i].alive) {
if (speed.y>0) {
game.myMonsters[i].alive=false;
game.myMonsters[i].sound2.play();
} else {
game.myMonsters[i].sound1.play();
alive = false;
}
}
}
for (int i =0; i<game.myQuestions.length; i++) {
if (game.myQuestions[i].distance(this)<=size.x/2+game.myQuestions[i].size.x/2 && game.myQuestions[i].alive) {
game.score++;
game.myQuestions[i].sound.play();
game.myQuestions[i].alive = false;
}
}
if (game.myfinal.distance(this)<=size.x/2+game.myfinal.size.x/2 && game.myfinal.alive) {
game.score+=5;
game.myfinal.sound.play();
game.myfinal.alive = false;
game.won= true;
}
}
}
Monsters:
Finding Sprites for the monsters was not easy. I was trying to find monsters that represent the distractions we have while studying. So instead of finding different monsters, I made my own using emojis and clip art images.
I used the facial features from the emojis and the body of what I think represents distractions. I made them alternate between an Innocent look and an evil look because distractions usually don’t look so bad.
For this one, I thought it was better to have a bouncy still image, as it was the only one that was completely dead. I used the same class for both as they had the same charactaristics.
Sprites:
Questions:
Final:
Code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Question extends Creature {
SoundFile sound;
Question(float x, float y, float r, float g, PImage _img, float w, float h, int num_frames, PApplet sketch){
For the full game, I made a game class that allows me to create a game object whenever I want to start the game. This helps with restarting and waiting for the user to press a key to start; as I just create a game object if the player is dead and the user presses enter at the welcom screen.
My game class only had the creation of all the game objects and the display call for them.
There is a game played a while back that I really liked, and as recreating that game will take much longer than the time I have now, I got an idea that is similar in a way, but simpler.
The game I got inspired by is called HUE.
In this game, hue needs to save his mom by collecting pieces of the color ring in the picture above.
My Idea:
My idea, similarly, the student needs to collect a few questions and the exam to pass.
Game Parts:
– The player/student needs to collect all the questions on the screen and get to the final before the timer ends.
– If the student collects all the questions, they can collect the final exam paper and get the full grade on the exam. Otherwise, they get points for the questions they collected.
-each question is guarded by a monster(monsters are inspired by the monsters that face students like anxiety, procrastination, and distractions).
This is a rough draft of what the game is supposed to look like:
Progress:
I started with the background. Instead of using a still image, I used loadPixels() to make the background look something like a night sky.
Code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Bg {
float[] x = new float[50];
float[] y = new float[50];
Bg(){
for(int i=0; i<50; i++){
x[i] = random(0, widthh);
y[i] = random(0, heightt);
}
}
voiddrawBG(){
loadPixels();
for(int y=0; y<heightt; y++){
for(int x=0; x<widthh; x++){
float n = noise(x*.002, y*.005);
//n = frameCount%width+n;
//n= map(n,0,width,0,255);
pixels[x+y*width]=color(n*150);
}
}
updatePixels();
if(frameCount%5==0){
for(int i=0; i<50; i++){
x[i] = random(0, width);
y[i] = random(0, height);
}
}
for(int i=0; i<50; i++){
for(int j=0; j<10; j++){
noStroke();
fill(255, 25);
ellipse(x[i], y[i], 1+j, 1+j);
}
}
}
}
class Bg {
float[] x = new float[50];
float[] y = new float[50];
Bg() {
for (int i=0; i<50; i++) {
x[i] = random(0, widthh);
y[i] = random(0, heightt);
}
}
void drawBG() {
loadPixels();
for (int y=0; y<heightt; y++) {
for (int x=0; x<widthh; x++) {
float n = noise(x*.002, y*.005);
//n = frameCount%width+n;
//n= map(n,0,width,0,255);
pixels[x+y*width]=color(n*150);
}
}
updatePixels();
if (frameCount%5==0) {
for (int i=0; i<50; i++) {
x[i] = random(0, width);
y[i] = random(0, height);
}
}
for (int i=0; i<50; i++) {
for (int j=0; j<10; j++) {
noStroke();
fill(255, 25);
ellipse(x[i], y[i], 1+j, 1+j);
}
}
}
}
class Bg {
float[] x = new float[50];
float[] y = new float[50];
Bg() {
for (int i=0; i<50; i++) {
x[i] = random(0, widthh);
y[i] = random(0, heightt);
}
}
void drawBG() {
loadPixels();
for (int y=0; y<heightt; y++) {
for (int x=0; x<widthh; x++) {
float n = noise(x*.002, y*.005);
//n = frameCount%width+n;
//n= map(n,0,width,0,255);
pixels[x+y*width]=color(n*150);
}
}
updatePixels();
if (frameCount%5==0) {
for (int i=0; i<50; i++) {
x[i] = random(0, width);
y[i] = random(0, height);
}
}
for (int i=0; i<50; i++) {
for (int j=0; j<10; j++) {
noStroke();
fill(255, 25);
ellipse(x[i], y[i], 1+j, 1+j);
}
}
}
}
I added platforms, which the questions and monsters will be on at random, saved, x-locations:
I wrote a code that reads from the billboard top 100 songs (not the most recent). I edit the .csv file I found online to remove redundant data that I did not need and I used the left data to draw circles at random locations for each of the top 100.
I added a small alpha value to show the layering of circles as they are random.
I had to deal with longer song names and make them wrap around.
Instead of trying to find a library that works, I decided to try to make the wrap work myself to explore and know what I can do to manipulate a string.
key:
Code:
I started with a circle class to draw each circle at a random location and depending on circle details. I added an array to save the circles.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
String names[];
int ranks[];
int weeks[];
boolean arrDone[] = new boolean[100];
boolean flag = false;
int counterDone = 0;
PFont myFont;
class Circles {
//attributes
PVector pos ;
int col;
int diam;
String text;
// number of weeks on board gives color shade, and rank determines radius
Here, I declared the circle’s object array and then loaded and processed the data from the .csv file.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidreadData(){
String stuff[] = loadStrings("charts.csv");
String data[]= new String[3];
// Convert String into an array of integers using ',' as a delimiter
// string array is returned, which we cast to an int array
names = new String[stuff.length];
ranks = new int[stuff.length];
weeks = new int[stuff.length];
for(int i=1; i<stuff.length; i++){
data = split(stuff[i], ',');
//fill arrays with data
ranks[i] = int(data[0]);
names[i] = data[1];
weeks[i] = int(data[2]);
}
}
void readData() {
String stuff[] = loadStrings("charts.csv");
String data[]= new String[3];
// Convert String into an array of integers using ',' as a delimiter
// string array is returned, which we cast to an int array
names = new String[stuff.length];
ranks = new int[stuff.length];
weeks = new int[stuff.length];
for (int i=1; i<stuff.length; i++) {
data = split(stuff[i], ',' );
//fill arrays with data
ranks[i] = int(data[0]);
names[i] = data[1];
weeks[i] = int(data[2]);
}
}
void readData() {
String stuff[] = loadStrings("charts.csv");
String data[]= new String[3];
// Convert String into an array of integers using ',' as a delimiter
// string array is returned, which we cast to an int array
names = new String[stuff.length];
ranks = new int[stuff.length];
weeks = new int[stuff.length];
for (int i=1; i<stuff.length; i++) {
data = split(stuff[i], ',' );
//fill arrays with data
ranks[i] = int(data[0]);
names[i] = data[1];
weeks[i] = int(data[2]);
}
}
in the creat function here I added a boolean array to check if the song has been output on the screen or not to avoid repitition.
void create() {
int num = int(random(1, 99));
boolean flag = false;
if (arrDone[num]) {
flag= true;
} else {
arrDone[num] = true;
}
if (!flag && count<=100) {
// int weeks, int ranks, String _text){
circle[count] = new Circles(weeks[num], ranks[num], names[num]);
circle[count].draw_circle();
count++;
}
}
void create() {
int num = int(random(1, 99));
boolean flag = false;
if (arrDone[num]) {
flag= true;
} else {
arrDone[num] = true;
}
if (!flag && count<=100) {
// int weeks, int ranks, String _text){
circle[count] = new Circles(weeks[num], ranks[num], names[num]);
circle[count].draw_circle();
count++;
}
}
I only used the draw function for the text to appear at the beginning of the code running time. I generated the circles with mouse clicks instead to give time for the user to analyze each new circle.
This was inspired by one of the things we saw in class. For some reason, I cannot seem to find it, but it was a piece where lines go from a circumference of a circle inwards to fill the circle.
I had a plan in mind to have lines growing out of the center into a circle, but I did not like how it looked, as the lines were too sharp for my preference.
So instead I used the noise function to make random dots, on a 360-degree variation.
I wanted to make it look more natural, however, so I decided to also add some cloudy form around it.
When I saw this, I felt like it reminded me of a laptop screen saver, as the circles grow out and it progresses into what it is. Screen savers though, unlike this design above, have different circles it would usually be more than one, so using a random function, I generated the circles starting from a different center point every 100 frameCounts.
That, if I would let go on I would have gotten into a huge mesh after some time, so I called the background function after every 5 circular things are created.
Later I also edited the colors and added an alpha value to make the circles a little easier on the eye.
and to make it a little user-controlled, I called the background function and reset the center with each click on the screen.
I also decided to make it a full screen like a real screen saver.
I did this design using both circles and “center” mode rects.
In the beginning, I tried using the normal formula for a circle to decide the midpoints of each layer of rect/circles, but for some reason, it did not work as required. So, after a long bugging session, I changed my equations, and I used sin and cos instead.
I started the code with the center circle starting at the top left corner, as it has (0,0) coordinates, making it easier to figure out what I was trying to do.
After getting this part to work, I made the center point based on the center of the canvas.
I started with the centric shape being all circles with random-fill colors.
But I then thought, why not make a random alternation between both squares and rectangles? It would make it more interesting.
I also wanted to make it a little interactive, so I made the center point follow the mouse press as shown in the video.