Camera Keyboard - Joeny Thipsidakhom
Contents
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;
}
}