Camera Keyboard - Joeny Thipsidakhom
Description
- Motivation
Same as Midterm
I’m interested in virtual space/realms and how it interacts with the physical world or how the physical world interacts with virtual space, whether it’s through games and a controller, being a part of a physical place in a parallel virtual world, or through actual physical movement. I’m also what people may consider a “gamer” and interested in the whole interaction interface they use, whether its web-cams, standard controllers, motion controllers, etc and how those affect the way we interact with the virtual.
- Interactive paradigm
I'm going to attempt to create a sort of game/animation that uses the brightness tracking of Processing and an external controller for inputs. As the brightness spot moves so will the character in the game would too (left, right, up, down) and as you press a button on the controller it would cause something on screen.
UPDATE: I'm going to be using Processing's brightness tracking along with a virtual keyboard created in Processing to control the movements of a game character. The user/users will have to navigate virtual space using hand held light sources and a web-cam paired with Processing's brightness tracking.
- Technical Description
Processing and an external controller. Brightness tracking would allow for character movement while the external controller would allow for user inputs and secondary interaction. I'll create some sort of simple game/environment/animation in processing which to user would have to interact with.
UPDATE: Processing and two external light sources along with a web-cam. Brightness tracking will track the two light sources and depending on the area Processing picks up the light sources it will cause virtual typing of the keyboard. This will be paired with another Processing sketch in the form of a game. Either two people can control the game, or a single person by themselves.
Visualization
- Functional Diagrams
[USER] -> [Camera + Lights] -> [Processing] -> [Processing Game]
- Visual Concept
Coming Soon...
Documentation
Coming Soon...
Virtual Keyboard Code
//KEYS final int VK_A = 65; final int VK_S = 83; final int VK_D = 68; final int VK_W = 87; final int VK_RIGHT = 39; final int VK_LEFT = 37; final int VK_UP = 38; final int VK_DOWN = 40; final int VK_SHIFT = 16; final int VK_SPACE = 32;
//FONT PFont font;
//Press Character Once String lastButton = "";
Robot r;
//VIDEO import processing.video.*; Capture video;
void setup(){
size(633,480); background(10); noFill(); smooth();
//VIDEO video = new Capture(this, width, height, 30);
//TEXT font = loadFont("Univers66.vlw"); textFont(font, 25);
//BOUNDARY LINES. //UPPER LEFT rect(0,0,320,200); noFill(); //UPPER RIGHT rect(320,0,320,200); noFill(); //LOWER LEFT rect(0,280,320,240); noFill(); //LOWER RIGHT rect(320,280,320,240); noFill();
//TEXT text("UPPER Left",100,50); text("UPPER Right",390,50); text("LOWER Left",100,330); text("LOWER Right",390,330); text("VOID", 285,250);
try{ r = new Robot(); } catch(AWTException a){ }
}
void draw() {
//VIDEO if (video.available()) { video.read(); image(video, 0, 0, width, height); // Draw the webcam video onto the screen int brightestRX = 0; // X-coordinate of the brightest video pixel int brightestRY = 0; // Y-coordinate of the brightest video pixel int brightestLX = 0; int brightestLY = 0; float brightestValueL = 0; float brightestValueR = 0; // Brightness of the brightest video pixel // Search for the brightest pixel: For each row of pixels in the video image and // for each pixel in the yth row, compute each pixel's index in the video video.loadPixels(); int index = 0; for (int y = 0; y < video.height; y++) { for (int x = 0; x < video.width; x++) { // Get the color stored in the pixel int pixelValue = video.pixels[index]; // Determine the brightness of the pixel float pixelBrightnessR = green(pixelValue); float pixelBrightnessL = red(pixelValue); // If that value is brighter than any previous, then store the // brightness of that pixel, as well as its (x,y) location if (pixelBrightnessR > brightestValueR) { brightestValueR = pixelBrightnessR; brightestRY = y; brightestRX = x; } //Follows RED if (pixelBrightnessL > brightestValueL) { brightestValueL = pixelBrightnessL; brightestLY = y; brightestLX = x; } index++; } } // Draw a large, yellow circle at the brightest pixel fill(0, 75, 255, 128); ellipse(brightestRX, brightestRY, 50, 50); fill(0, 75, 100, 128); rect(brightestLX, brightestLY, 100 ,100);
//TYPING WASD
// //UPPER LEFT = A // if ((brightestRX <= 320 && brightestRY <= 200) || (brightestLX <= 320 && brightestLY <= 200)){ //// if(lastButton!="a") { // r.keyPress(VK_A); // r.keyRelease(VK_A); //// lastButton="a"; //// } // delay(500); // } // //UPPER RIGHT = D // if ((brightestRX >= 320 && brightestRY <= 200) || (brightestLX >= 320 && brightestLY <= 200)){ //// if(lastButton!="d") { // r.keyPress(VK_D); // r.keyRelease(VK_D); //// lastButton="d"; //// } // delay(500); // } // //LOWER LEFT = W // if ((brightestRX <= 320 && brightestRY >= 280) || (brightestLX <= 320 && brightestLY >= 280)){ // r.keyPress(VK_W); // r.keyRelease(VK_W); // delay(500); // } // //LOWER RIGHT = S // if ((brightestRX >= 320 && brightestRY >= 280) || (brightestLX >= 320 && brightestLY >= 280)){ // r.keyPress(VK_S); // r.keyRelease(VK_S); // delay(500); // }
// TYPING ARROWS
//UPPER LEFT = UP if ((brightestRX <= 320 && brightestRY <= 200) || (brightestLX <= 320 && brightestLY <= 200)){
// if(lastButton!="a") {
r.keyPress(VK_UP); r.keyRelease(VK_UP);
// lastButton="a"; // }
delay(500); } //UPPER RIGHT = DOWN if ((brightestRX >= 320 && brightestRY <= 200) || (brightestLX >= 320 && brightestLY <= 200)){
// if(lastButton!="d") {
r.keyPress(VK_DOWN); r.keyRelease(VK_DOWN);
// lastButton="d"; // }
delay(500); } //LOWER LEFT = LEFT if ((brightestRX <= 320 && brightestRY >= 280) || (brightestLX <= 320 && brightestLY >= 280)){ r.keyPress(VK_LEFT); r.keyRelease(VK_LEFT); delay(500); } //LOWER RIGHT = RIGHT if ((brightestRX >= 320 && brightestRY >= 280) || (brightestLX >= 320 && brightestLY >= 280)){ r.keyPress(VK_RIGHT); r.keyRelease(VK_RIGHT); delay(500); } //BOUNDARY LINES. //UPPER LEFT rect(0,0,320,200); noFill(); //UPPER RIGHT rect(320,0,320,200); noFill(); //LOWER LEFT rect(0,280,320,240); noFill(); //LOWER RIGHT rect(320,280,320,240); noFill();
//TEXT //UPPER LEFT text("UP",100,50); //UPPER RIGHT text("DOWN",390,50); //LOWER LEFT text("LEFT",100,330); //LOWER RIGHT text("RIGHT",390,330); //CENTER text("VOID", 285,250);
}
}
Snake Game Code
ArrayList ellipseList; Ellipse head; int SEGMENT_SIZE = 10; int dir; int prevPosX, prevPosY; PFont f; String mesaj=""; boolean ok=false; Ellipse food; void setup() {
size(400, 400); f=loadFont("Univers66.vlw"); textFont(f); ellipseList = new ArrayList(); head = new Ellipse(width/2, height/2); ellipseList.add(head); dir=2; // Start with head and small body ellipseList.add(new Ellipse(width/2 - 2 * SEGMENT_SIZE, height/2)); addFood(); mesaj="MOUSE"; frameRate(10);
} void draw() {
fill(0); background(100); text(mesaj,width/2-100,height/2); if(ok) { food.createEllipse(); tryToEatAndMove(ellipseList.size()); }
}
boolean tryToEatAndMove(int p) {
int x = head.getX(); int y = head.getY(); if (dist(x, y, food.getX(), food.getY()) < 6) { // Move the body move(); // Get last two segments Ellipse e1 = (Ellipse) ellipseList.get(ellipseList.size() - 1); Ellipse e2 = (Ellipse) ellipseList.get(ellipseList.size() - 2); int dX = e1.getX() - e2.getX(); int dY = e1.getY() - e2.getY(); // Add another segment at the end ellipseList.add(new Ellipse(e1.getX() + dX, e1.getY() + dY)); // Add food to replace the one being eat addFood(); println("Length: " + ellipseList.size()); return true; }
move(); return false;
} void addFood() {
food = new Ellipse(int(random(10, 390)), int(random(10, 390)),6);
} void move() {
prevPosX = head.getX(); prevPosY = head.getY(); switch(dir) { case 0:
head.moveUp(); break;
case 1:
head.moveDown(); break;
case 2:
head.moveRight(); break;
case 3:
head.moveLeft(); break;
} followHead();
}
void followHead() {
fill(0); head.createEllipse(); fill(255); for (int i = 1; i < ellipseList.size(); i++) { Ellipse e = (Ellipse) ellipseList.get(i); int ppX = e.getX(); int ppY = e.getY(); // Move the segment where the previous one was e.x = prevPosX; e.y = prevPosY; prevPosX = ppX; prevPosY = ppY; e.createEllipse(); }
}
void mousePressed() {
mesaj=""; ok=true; dir=2;
}
void keyPressed() {
if(key==CODED) { if(keyCode==UP) {
dir=0;
} if(keyCode==DOWN) {
dir=1;
} if(keyCode==RIGHT) {
dir=2;
} if(keyCode==LEFT) {
dir=3;
} }
}
class Ellipse {
int x; int y; int l; Ellipse(int _x, int _y) { x=_x; y=_y; l=10; } Ellipse(int _x, int _y, int _l) { x=_x; y=_y; l=_l; } void createEllipse() { ellipse(x,y,l,l); } void createEllipse(int a,int b) { ellipse(a,b,l,l); } void moveUp() { y-=l; if(y<0) y=height; } void moveDown() { y+=l; if(y>height) y=0; } void moveRight() { x+=l; if(x>width) x=0; } void moveLeft() { x-=l; if(x<0) x=width; } int getX() { return x; } int getY() { return y; } int getL() { return l; }
}