A. Painter – Tawan Kondhorn – Rodolfo Cossovich
B. CONCEPTION AND DESIGN:
This project was inspired by a multiplayer game where 2 users control a paintbrush to paint as much area as they can in a specific time. We also decided to include power-ups in order to make the game more interesting. In terms of interaction, we decided to create a “steering wheel”, where the users would feel as if they’re actually steering the paintbrush in the game. We’ve received multiple constructive criticisms about our project. The main point was that the design made it for the player to look at the screen while also playing the game. The next main point was that after a while, the user complained that it was difficult to locate the head of the paint. These feedbacks allow us to change the design of our project as well as add some codes to fix those problems. The first thing we did was remove the handle and reposition it to be horizontal instead of vertical. This allows the user to look at the screen and navigate the paint better than the previous design. The other adjustment we made was coding the head of the paint to have a stroke around it in order to make it easier to navigate. Both adjustments turned out to be effective since they were able to fix the problem.
C. FABRICATION AND PRODUCTION:
The hardest part of our project was figuring out which component to use for detecting the rotation. We first started with using 2 BNOs, but we later found out that using that is very highly complex to make it work and might result in us not finishing the project in time. After that, we decided to go with what we’re familiar with – a potentiometer. The next step that was difficult was the coding. However, we’ve already had some experiences with coding from our midterm project, so we didn’t struggle as much. My task in the group project was to figure out the hardware components and put them together as well as design the project. My partner Jim worked on the code for the game.
D. CONCLUSIONS:
Our project’s goal is to create a game that involves the domination of the area. We wanted to create a 2 player game, where each one will control a “paintbrush”, and the goal is to paint as much area as they can in a specific amount of time. We included power-ups and designed an actual steering wheel in order to make the game more interesting. Based on our audience’s responses, they seemed to love the game. However, they said that we could’ve taken this project a step further and made it more complex and interesting, which we would’ve done so if we had more time. There are many values that I’ve learned from this project’s setback, where one of them is that if there’s a failure in a specific part, there’s always another way out.
E. Annex:
Arduino:
#include "SerialRecord.h"
// Change this number to send a different number of values
SerialRecord writer(2);
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
int sensorValue1 = analogRead(A1);
writer[0] = sensorValue;
writer[1] = sensorValue1;
writer.send();
// This delay slows down the loop, so that it runs less frequently. This can
// make it easier to debug the sketch, because new values are printed at a
// slower rate.
delay(100);
}
Processing:
import processing.serial.*; import processing.sound.*; import osteele.processing.SerialRecord.*; Serial serialPort; SoundFile sound; SerialRecord serialRecord; float x1_direction, y1_direction; float x2_direction, y2_direction; float x1, y1, x2, y2; float prex1, prey1, prex2, prey2; long countred=0; long countblue=0; int flag=1; int buff, x, y; boolean buff21=false; boolean buff22=false; boolean buff31=false; boolean buff32=false; boolean e=true; long pre21=0; long pre31=0; long pre22=0; long pre32=0; int r1=200; int r2=200; long gamestart; int gamestarted; void setup() { fullScreen(); background(0); rectMode(CENTER); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); ellipseMode(CENTER); // If the Arduino sketch sends a different number of values, modify the number // `2` on the next line to match the number of values that it sends. serialRecord = new SerialRecord(this, serialPort, 2); sound = new SoundFile(this, "final.mp3"); buff=18250; x=floor(random(0, width)); y=floor(random(0, height)); } void setbuff(int bx, int by) { push(); noStroke(); translate(bx, by); rotate(PI/4); fill(#FFCD43); circle(0, 0, 200); fill(0); textAlign(CENTER, CENTER); textSize(170); text("?", 0, 0); pop(); } void getbuff1(int effect) { switch(effect) { case 1: case 2: { fill(255, 0, 0); noStroke(); for (int size=200; size<=1200; size+=10) { circle(x, y, size); } break; } case 3: case 4: { pre21=millis()-gamestart; buff21=true; break; } case 5: case 6: { pre31=millis()-gamestart; buff31=true; break; } case 7: background(255*floor(random(0, 2)), 0, 255*floor(random(0, 2))); } } void getbuff2(int effect) { switch(effect) { case 1: case 2: { fill(0, 0, 255); noStroke(); for (int size=200; size<=1200; size+=10) { circle(x, y, size); } break; } case 3: case 4: { pre22=millis()-gamestart; buff22=true; break; } case 5: case 6: { pre32=millis()-gamestart; buff32=true; break; } case 7: { background(255*floor(random(0, 2)), 0, 255*floor(random(0, 2))); } } } void draw() { noStroke(); strokeWeight(3); if (gamestarted==0) { textAlign(CENTER, CENTER); textSize(80); text("CLICK TO START", width/2, height/2); if (mousePressed) { gamestarted=1; fill(0); noStroke(); rect(width/2, height/2, 800, 800); gamestart=millis(); sound.play(); } } if (gamestarted==1) { if (millis()-gamestart<=4000) { x1=width/4; y1=height/2; x2=width*3/4; y2=height/2; fill(255, 0, 0); noStroke(); ellipse(x1, y1, 200, 200); fill(0, 0, 255); ellipse(x2, y2, 200, 200); fill(0); rect(width/2, height/2, 650, 650); fill(255); textSize(80); textAlign(CENTER, CENTER); text("WHO PAINTS MORE", width/2, height/2); } if (millis()-gamestart>4000&&millis()-gamestart<=5000) { fill(0); rect(width/2, height/2, 650, 650); fill(#74EAC0); textSize(300); textAlign(CENTER, CENTER); text("5", width/2, height/2); } if (millis()-gamestart>5000&&millis()-gamestart<=6000) { fill(0); rect(width/2, height/2, 320, 320); fill(#74BCEA); textSize(300); textAlign(CENTER, CENTER); text("4", width/2, height/2); } if (millis()-gamestart>6000&&millis()-gamestart<=7000) { fill(0); rect(width/2, height/2, 320, 320); fill(#5D59F5); textSize(300); textAlign(CENTER, CENTER); text("3", width/2, height/2); } if (millis()-gamestart>7000&&millis()-gamestart<=8000) { fill(0); rect(width/2, height/2, 320, 320); fill(#F00F52); textSize(300); textAlign(CENTER, CENTER); text("2", width/2, height/2); } if (millis()-gamestart>8000&&millis()-gamestart<=9000) { fill(0); rect(width/2, height/2, 320, 320); fill(#F00F52); textSize(300); textAlign(CENTER, CENTER); text("1", width/2, height/2); } if (millis()-gamestart>9000&&millis()-gamestart<=10000) { fill(0); rect(width/2, height/2, 320, 320); if (millis()-gamestart<=9900) { fill(#F00F52); textSize(200); textAlign(CENTER, CENTER); text("GO", width/2, height/2); } } if (millis()-gamestart>10001&&millis()-gamestart<=73000) { if (millis()-gamestart-pre21>=5000&&millis()-gamestart-pre21<=5100) { buff21=false; } if (millis()-gamestart-pre22>=5000&&millis()-gamestart-pre22<=5100) { buff22=false; } if (millis()-gamestart-pre31>=5000&&millis()-gamestart-pre31<=5100) { buff31=false; } if (millis()-gamestart-pre32>=5000&&millis()-gamestart-pre32<=5100) { buff32=false; } serialRecord.read(); int value1 = serialRecord.values[0]; int value2 = serialRecord.values[1]; float angle1 = map(value1, 0, 1024, 0, 360); float angle2 = map(value2, 0, 1024, 0, 360); x1_direction=15*cos(radians(angle1)); y1_direction=15*sin(radians(angle1)); x2_direction=15*cos(radians(angle2)); y2_direction=15*sin(radians(angle2)); prex1=x1; prex2=x2; prey1=y1; prey2=y2; stroke(0); if (buff31) { x1=x1+2*x1_direction; y1=y1+2*y1_direction; } else { x1=x1+x1_direction; y1=y1+y1_direction; } if (buff32) { x2=x2+2*x2_direction; y2=y2+2*y2_direction; } else { x2=x2+x2_direction; y2=y2+y2_direction; } if (x1<0) x1+=width; if (x1>width) x1-=width; if (y1<0) y1+=height; if (y1>height) y1-=height; if (x2<0) x2+=width; if (x2>width) x2-=width; if (y2<0) y2+=height; if (y2>height) y2-=height; fill(255, 0, 0); if (buff21) { ellipse(x1, y1, 2*r1, 2*r1); push(); noStroke(); ellipse(prex1, prey1, 2*r1+4, 2*r2+4); pop(); } else { ellipse(x1, y1, r1, r1); push(); noStroke(); ellipse(prex1, prey1, r1+4, r2+4); pop(); } fill(0, 0, 255); if (buff22) { ellipse(x2, y2, 2*r2, 2*r2); push(); noStroke(); ellipse(prex2, prey2, 2*r2+4, 2*r2+4); pop(); } else { ellipse(x2, y2, r2, r2); push(); noStroke(); ellipse(prex2, prey2, r2+4, r2+4); pop(); } if (abs(millis()-gamestart-buff)<20&&e) { setbuff(x, y); e=false; } if (dist(x1, y1, x, y)<=100&&millis()-gamestart>buff) { getbuff1(floor(random(1, 8))); e=true; noStroke(); fill(255, 0, 0); circle(x, y, 210); buff=floor(random(millis()-gamestart+5000, millis()-gamestart+10000)); x=floor(random(0, width)); y=floor(random(0, height)); } if (dist(x2, y2, x, y)<=100&&millis()-gamestart>buff) { getbuff2(floor(random(1, 8))); e=true; noStroke(); fill(0, 0, 255); circle(x, y, 210); buff=floor(random(millis()-gamestart+5000, millis()-gamestart+10000)); x=floor(random(0, width)); y=floor(random(0, height)); } } if (millis()-gamestart>73000&&flag==1) { loadPixels(); flag=0; for (int i=0; i<height*width; i++) { if (pixels[i]==color(0, 0, 255)) { countblue++; } if (pixels[i]==color(255, 0, 0)) { countred++; } pixels[i]=color(0, 0, 0); } updatePixels(); fill(#221D23); rect(width/2, height/2, width, height); textSize(300); textAlign(CENTER, CENTER); int ratioblue=floor(countblue*100/(countred+countblue)+0.5); int ratiored=floor(countred*100/(countred+countblue)+0.5); if (countblue>countred) { fill(0, 0, 255); text("BLUE WINS", width/2, height/3); ratioblue++; text(ratiored+":"+ratioblue, width/2, height*2/3); } else { fill(255, 0, 0); text("RED WINS", width/2, height/3); ratiored++; text(ratiored+":"+ratioblue, width/2, height*2/3); } delay(10000); } } }