Walkthrough
--Operating System-- The eBox needs to have a fast and reliable operating system in order for it to be able to handle this project. Puppy Linux (Version 4.31) was chosen for the operating system. It is small (only 100 MB) and it runs completely on RAM. This allows it to run faster, because it does not have to read or write to disk.--OpenCV-- OpenCV is an open source computer vision library with many useful and optimized functions. The installation can be tricky, but you should be able to get it up and running by following this tutorial to install OpenCV on Puppy Linux
--Code-- The code contains the game logic, blue LED feature recognition, and game display updates.
#include "highgui.h"
#include "cv.h"
#include "iostream"
#include "stdlib.h"
#include "stdio.h"
#include "math.h"
int main( int argc, char** argv ) {
//cvNamedWindow( "NewFrame",0);
//cvResizeWindow("NewFrame",600,600);
//cvMoveWindow("NewFrame",0,0);
cvNamedWindow( "DrawnFrame",0);
cvResizeWindow("DrawnFrame",600,600);
cvMoveWindow("DrawnFrame",0,0);
CvCapture* capture = cvCreateCameraCapture(0);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 160);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 120);
CvPoint pt1, pt2, pt3, pt4;
int ballx=80,bally=60,ballslopex=1,ballslopey=1,radius=3;
int paddle1x=0,paddle1y=60,paddle2x=150,paddle2y=60;
int pixelvalue=0,pixelindex=0,pixelcol=0,pixelrow=0,pixelindex1=0,pixelindex2=0;
double distpaddle1=0,distpaddle2=0;
int score1=0,score2=0;
char score1text[10],score2text[10];
IplImage*newframe,*drawnframe;
newframe = cvQueryFrame(capture);
IplImage* channelRed = cvCreateImage(cvGetSize(newframe), 8, 1);
IplImage* channelGreen = cvCreateImage(cvGetSize(newframe), 8, 1);
IplImage* channelBlue = cvCreateImage(cvGetSize(newframe), 8, 1);
IplImage* Result = cvCreateImage(cvGetSize(newframe), 8, 1);
drawnframe=newframe;
CvFont font;
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.4, 0.4, 0, 1, CV_AA);
sprintf(score1text,"%d",0);
sprintf(score2text,"%d",0);
while(1) {
newframe = cvQueryFrame(capture);
drawnframe=newframe;
//cvShowImage("NewFrame",newframe);
cvSplit(newframe, channelBlue, channelGreen, channelRed, NULL);
cvAdd(channelRed, channelGreen,channelRed);
cvSub(channelBlue, channelRed, channelBlue);
cvThreshold(channelBlue, Result, 100, 255, CV_THRESH_BINARY);
drawnframe=newframe;
for(int i=0;i<Result->imageSize;i+=1){
pixelindex=i;
pixelrow=pixelindex/160;
pixelcol=pixelindex-(pixelrow*160);
//Find First Player Paddle
if(pixelcol<80){
if((Result->imageData[i]==-1)){
distpaddle1=sqrt(pow(pixelcol-pt2.x,2)+pow(pixelrow-pt2.y,2));
//if(distpaddle1<100){
pixelindex1=i*0.05+pixelindex1*0.95;
//}
}
}
//Find Second Player Paddle
if(pixelcol>=80){
if((Result->imageData[i]==-1)){
distpaddle2=sqrt(pow(pixelcol-pt3.x,2)+pow(pixelrow-pt3.y,2));
//if(distpaddle2<100){
pixelindex2=i*0.05+pixelindex2*0.95;
//}
}
}
}
pixelrow=pixelindex1/160;
pt2=cvPoint(0,pixelrow);
pixelrow=pixelindex2/160;
pt3=cvPoint(115,pixelrow);
//Ball Movement and Collision Detection
ballx=ballx+7*ballslopex;
bally=bally+7*ballslopey;
sprintf(score2text,"%d",score2);
sprintf(score1text,"%d",score1);
//Wall Checks
if(ballx-radius<0){
score2=score2+1;
ballx=80;
bally=60;
ballslopex=-ballslopex;
}
if(ballx+radius>160){
score1=score1+1;
ballx=80;
bally=60;
ballslopex=-ballslopex;
}
if((ballx-radius<5)&&(bally<pt2.y+10)&&(bally>pt2.y-10)){
ballx=radius+5;
ballslopex=-ballslopex;
}
if((ballx+radius>=155)&&(bally<pt3.y+10)&&(bally>pt3.y-10)){
ballx=155-radius;
ballslopex=-ballslopex;
}
if(bally-radius<=0){
bally=radius;
ballslopey=-ballslopey;
}
if(bally+radius>120){
bally=120-radius;
ballslopey=-ballslopey;
}
pt1.x=ballx;
pt1.y=bally;
cvPutText(drawnframe,score1text,cvPoint(65,20),&font,cvScalar(255,0,255,0));
cvPutText(drawnframe,score2text,cvPoint(90,20),&font,cvScalar(255,0,255,0));
if(score1>=3){
cvPutText(drawnframe,"Player 1 Wins!",cvPoint(40,60),&font,cvScalar(0,255,0,0));
ballslopex=0;
ballslopey=0;
}
if(score2>=3){
cvPutText(drawnframe,"Player 2 Wins!",cvPoint(60,60),&font,cvScalar(0,255,0,0));
ballslopey=0;
ballslopex=0;
}
//Draw Paddles, Ball, Screen Divider
cvRectangle(drawnframe,cvPoint(80,0),cvPoint(81,120),CV_RGB(255,0,0), CV_FILLED);
cvRectangle(drawnframe,cvPoint(0,pt2.y-10),cvPoint(5,pt2.y+10),CV_RGB(255,0,0), CV_FILLED);
cvRectangle(drawnframe,cvPoint(155,pt3.y-10),cvPoint(160,pt3.y+10),CV_RGB(255,0,0), CV_FILLED);
cvCircle(drawnframe, pt1, radius, CV_RGB(0,255,0), CV_FILLED);
cvShowImage("DrawnFrame",drawnframe);
char c = cvWaitKey(33);
char d = cvWaitKey(33);
if( c == 27 )break;
if( d == 32){
score1=0;
score2=0;
ballslopex=1;
ballslopey=1;
}
}
cvReleaseImage(&drawnframe);
cvReleaseImage(&newframe);
cvReleaseImage(&channelRed);
cvReleaseImage(&channelGreen);
cvReleaseImage(&channelBlue);
cvReleaseImage(&Result);
cvDestroyWindow( "NewFrame" );
cvDestroyWindow( "DrawnFrame" );
}
Reference:J. Yore, R. Thomas, P. Swanson, "Airsoft Sentry Turret", ECE 4180, 2010, http://jyore.com/4180/software.html