Final Project

Concept:

This was a game I designed for the final project of Parsons MFADT Physical Computing class. The goal of this game is to control and mix R/G/B color values to match the background color within 10 seconds each level. I used three photoresistors connected to arduino uno to sense the color value controlled by 1 to 3 players, and use openframeworks to build the user interface of this game.

DSC01912DSC01928 DSC01922 DSC01927 _DSC2363 _DSC2370

Code:

Arduino:

int a;
int b;
int c;
int rPin = 9;
int gPin = 10;
int bPin = 11;
int rVal, gVal, bVal;
void setup() {
Serial.begin(9600);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}
void loop() {
a = analogRead(0);
b = analogRead(1);
c = analogRead(2);

rVal = 255 – map(a, 250, 500, 0, 255) + 25;
gVal = 255 – map(b, 250, 500, 0, 255);
bVal = 255 – map(c, 250, 550, 0, 255);

analogWrite(rPin, rVal);
analogWrite(gPin, gVal);
analogWrite(bPin, bVal);

Serial.println(“R”);
Serial.print(“”);
Serial.println(rVal);
Serial.print(“”);
Serial.println(“G”);
Serial.print(“”);
Serial.println(gVal);
Serial.print(“”);
Serial.println(“B”);
Serial.print(“”);
Serial.println(bVal);
Serial.print(“”);

}

OpenFrameworks:

ofApp.h
————————————

#pragma once

#include “ofMain.h”

typedef struct {

float x;
float y;
bool bBeingDragged;
bool bOver;
float radius;

}draggableVertex;

class ofApp : public ofBaseApp{

public:
void setup();
void update();
void draw();

void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);

float distribute(float color);

ofTrueTypeFont NanumScript;
ofTrueTypeFont Title;
ofTrueTypeFont Myriad;
ofTrueTypeFont Time;
ofSerial serial;
bool nextLevel;
bool bingo;
bool alreadyCheckedCount;
int pin;

int nCurveVertices;
draggableVertex curveVertices[7];

int posX;
int posY;
float time1;
float time2;
int count;
int level;
int score;

float sensor1;
float sensor2;
float sensor3;
float sensor1t;
float sensor2t;
float sensor3t;
float color1;
float color2;
float color3;
float bColor1;
float bColor2;
float bColor3;
};

————————————
ofApp.cpp
————————————

#include “ofApp.h”

//————————————————————–
void ofApp::setup(){
serial.setup(“/dev/tty.usbmodem1411”, 9600);

ofBackground(255);
ofSetCircleResolution(50);
ofSetRectMode(OF_RECTMODE_CENTER);
posX = ofGetWindowWidth() * 0.5;
posY = ofGetWindowHeight() * 0.5;

alreadyCheckedCount = false;
nextLevel = true;
bingo = false;
time1 = ofGetElapsedTimef();

NanumScript.loadFont(“NanumScript.ttc”, 50, true, true);
NanumScript.setLineHeight(34.0f);
NanumScript.setLetterSpacing(1.035);

Title.loadFont(“NanumScript.ttc”, 50, true, true);
Myriad.loadFont(“MyriadHebrew-Regular.otf”, 30, true, true);
Time.loadFont(“MyriadHebrew-Regular.otf”, 100, true, true);

nCurveVertices = 7;

int a = 200;
curveVertices[0].x = 496 + a;
curveVertices[0].y = 209;
curveVertices[1].x = 476 + a;
curveVertices[1].y = 279;
curveVertices[2].x = 435 + a;
curveVertices[2].y = 331;
curveVertices[3].x = 474 + a;
curveVertices[3].y = 383;
curveVertices[4].x = 544 + a;
curveVertices[4].y = 383;
curveVertices[5].x = 588 + a;
curveVertices[5].y = 309;
curveVertices[6].x = 515 + a;
curveVertices[6].y = 279;
}

string ofxTrimStringRight(string str) {
size_t endpos = str.find_last_not_of(” \t\r\n”);
return (string::npos != endpos) ? str.substr( 0, endpos+1) : str;
}

// trim trailing spaces
string ofxTrimStringLeft(string str) {
size_t startpos = str.find_first_not_of(” \t\r\n”);
return (string::npos != startpos) ? str.substr(startpos) : str;
}

string ofxTrimString(string str) {
return ofxTrimStringLeft(ofxTrimStringRight(str));
}

string ofxGetSerialString(ofSerial &serial, char until) {
static string str;
stringstream ss;
char ch;
int ttl=1000;
while ((ch=serial.readByte())>0 && ttl–>0 && ch!=until) {
ss << ch; } str+=ss.str(); if (ch==until) { string tmp=str; str=””; return ofxTrimString(tmp); } else { return “”; } serial.flush(); } float ofApp::distribute(float color) { if (color >= 40 && color < 60) { return 50; } else if (color >= 60 && color < 80) { return 70; } else if (color >= 80 && color < 100) { return 90; } else if (color >= 100 && color < 120) { return 110; } else if (color >= 120 && color < 140) { return 130; } else if (color >= 140 && color < 160) { return 150; } else if (color >= 160 && color < 180) { return 170; } else if (color >= 180 && color < 200) { return 190; } else if (color >= 200 && color < 220) { return 210; } else if (color >= 220 && color < 240) { return 230; } else if (color >= 240 && color <= 255) { return 250; } } //————————————————————– void ofApp::update(){ if (ofxGetSerialString(serial, ‘\n’) == “R”) { sensor1 = ofToFloat(ofxGetSerialString(serial, ‘\n’)); if (ofxGetSerialString(serial, ‘\n’) == “G”) { sensor2 = ofToFloat(ofxGetSerialString(serial, ‘\n’)); if (ofxGetSerialString(serial, ‘\n’) == “B”) { sensor3 = ofToFloat(ofxGetSerialString(serial, ‘\n’)); } } } if (sensor1 != 0 && (abs(sensor1-sensor1t) > 20)) {
sensor1t = sensor1;
}
if (sensor2 != 0 && (abs(sensor2-sensor2t) > 20)) {
sensor2t = sensor2;
}
if (sensor3 != 0 && (abs(sensor3-sensor3t) > 20)) {
sensor3t = sensor3;
}

color1 = (255 – sensor1t) * 2;
color2 = (255 – sensor2t) * 2;
color3 = (255 – sensor3t) * 2;

time2 = ofGetElapsedTimef();
count = 10 – int(time2-time1);

if(nextLevel == true) {
time1 = ofGetElapsedTimef();
level ++;

bColor1 = distribute(ofRandom(40, 255));
bColor2 = distribute(ofRandom(40, 255));
bColor3 = distribute(ofRandom(40, 255));
nextLevel = false;
}
if (abs(bColor1-color1) <= 50 && abs(bColor2-color2) <= 50 && abs(bColor3-color3) <= 50) {
nextLevel = true;
bingo = true;
score += 10;
}
else if (count == 0) {
if(alreadyCheckedCount){
alreadyCheckedCount = false;
}
else {
alreadyCheckedCount = true;
nextLevel = true;
}
}
}

//————————————————————–
void ofApp::draw(){

ofBackground(bColor1, bColor2, bColor3);

ofSetColor(255);
Title.drawString(“Palatte”, posX-100, 90);
ofSetColor(0);
Myriad.drawString(“Level: ” + ofToString(level), 20, 120);
Myriad.drawString(“Score: ” + ofToString(score), posX*2-200, 120);

ofSetColor(255);
Myriad.drawString(ofToString(bColor1) + “, ” + ofToString(bColor2) + “, ” + ofToString(bColor3), posX-110, 450);
ofSetColor(255);
Time.drawString(ofToString(count), 50, 250);

ofSetColor(color1, color2, color3);
ofBeginShape();

for (int i = 0; i < nCurveVertices; i++){
if (i == 0){
ofCurveVertex(curveVertices[0].x, curveVertices[0].y); // we need to duplicate 0 for the curve to start at point 0
ofCurveVertex(curveVertices[0].x, curveVertices[0].y); // we need to duplicate 0 for the curve to start at point 0
} else if (i == nCurveVertices-1){
ofCurveVertex(curveVertices[i].x, curveVertices[i].y);
ofCurveVertex(curveVertices[0].x, curveVertices[0].y); // to draw a curve from pt 6 to pt 0
ofCurveVertex(curveVertices[0].x, curveVertices[0].y); // we duplicate the first point twice
} else {
ofCurveVertex(curveVertices[i].x, curveVertices[i].y);
}
}

ofEndShape();

if(bingo == true) {
ofSetColor(255);
Title.drawString(“Bingo!”, posX-65, posY-75);
ofSleepMillis(1000);
bingo = false;
}

int circleW = 60;
int circleX1 = posX – 250;
int circleX2 = posX;
int circleX3 = posX + 250;
int circleY = posY+200;

ofSetColor(255);
ofCircle(circleX1, circleY, circleW + 1);
ofCircle(circleX2, circleY, circleW + 1);
ofCircle(circleX3, circleY, circleW + 1);

ofSetColor(color1, 0, 0);
ofCircle(circleX1, circleY, circleW);

ofSetColor(0, color2, 0);
ofCircle(circleX2, circleY, circleW);

ofSetColor(0, 0, color3);
ofCircle(circleX3, circleY, circleW);

}