Skip to content

Instantly share code, notes, and snippets.

@tjthejuggler
Last active March 14, 2018 17:45
Show Gist options
  • Select an option

  • Save tjthejuggler/61dddba6d67d44cfe4055841d70e233c to your computer and use it in GitHub Desktop.

Select an option

Save tjthejuggler/61dddba6d67d44cfe4055841d70e233c to your computer and use it in GitHub Desktop.
tobii eyetracker game
//YOU NEED AN IMAGE OF A CURSOR IN ORDER TO RUN THIS CODE:
//https://cdn.pixabay.com/photo/2012/04/01/12/39/cursor-23231_960_720.png
import gazetrack.*;
import java.awt.Toolkit;
PImage cursor;
GazeTrack gazeTrack;
void setup()
{
fullScreen();
// Gaze cursor param.
noFill();
stroke(50, 100);
strokeWeight(4);
rectMode(CENTER);
cursor = loadImage("cursor.png");
cursor.resize(0,30);
// Create an empty ArrayList (will store Ball objects)
balls = new ArrayList<Ball>();
// Start by adding one element
//balls.add(new Ball(width/2, 0, ballWidth));
gazeTrack = new GazeTrack(this, "1");
}
float score = 1;
float scoreExt = 0;
float scorePosX = width;
int scorePosY = 200;
//float easing = 0;
Boolean currentlyPlaying = true;
Boolean mustLookBack = false;
Boolean yellowUnlocked = false;
int lookingAwayCounter = 0;
Boolean minusExists = false;
int stillnessCounter = 0;
Boolean becameStill = false;
ArrayList<Ball> balls;
int ballWidth = 48;
int fadingScoreFill = 255;
int ballCount = 0;
ArrayList<Float> plusX = new ArrayList<Float>();
ArrayList<Float> plusY = new ArrayList<Float>();
ArrayList<Float> minusX = new ArrayList<Float>();
ArrayList<Float> minusY = new ArrayList<Float>();
ArrayList<Integer> minusB = new ArrayList<Integer>();
void mousePressed() {
if(yellowUnlocked){
// A new ball object is added to the ArrayList (by default to the end)
if (ballCount<600){
balls.add(new Ball(mouseX, mouseY, ballWidth));
ballCount++;
}
}
}
Boolean almostWon = false;
Boolean reallyWon = false;
Boolean seenGreen = false;
void draw()
{
if(reallyWon){
background(0);
//print("You won.");
fill(0,0,255);
textAlign(CENTER,CENTER);
textSize(50);
text("Actually, you won.", 800, 370);
}else{
if(almostWon){
//print("almost won");
fill(0,255,0);
textAlign(CENTER,CENTER);
textSize(50);
text("You almost won!", 800, 370);
text("Turn head to play", 800, 450);
stroke(0,255,0);
line(600, 455,1000,455);
text("look rapidly from side to side.", 800, 530);
if(eyeShake()){//this checks to see if they have looked back and forth rapidly
print("eyeShook");
clear();
balls.clear();
currentlyPlaying = true;
stillnessCounter = 0;
becameStill = false;
fadingScoreFill = 255;
ballCount = 0;
score = 1;
scoreExt = 0;
almostWon = false;
seenGreen = true;
}
}else{
if(fadingScoreFill < 2){
//if(wtf){
score = 5;
if(!becameStill){
if (random(100)>70){
if (ballCount<600){
balls.add(new Ball(random(width), random(height), ballWidth));
ballCount++;
}
}
}else{
if(ballCount<3){
almostWon = true;
}
}
//rectMode(CENTER);
textAlign(RIGHT,TOP);
background(0);
textSize(50);
//easing = 0;
updateBalls();
}else{
if (currentlyPlaying){
if (!gazeTrack.gazePresent()) {//if the player looks away for too long then they lose
lookingAwayCounter++;
if (lookingAwayCounter > 50 && !mustLookBack){
if (score >1){
mustLookBack = true;
print("inhere");
lookingAwayCounter = 0;
youlose();
}
}
}
//if gazetrack is present
else{
lookingAwayCounter = 0;
//rectMode(CENTER);
textAlign(RIGHT,TOP);
background(0);
textSize(50);
//easing = 0;
updateBalls();
//draws the eyes
//fill(255);
//ellipse(gazeTrack.getGazeX(),gazeTrack.getGazeY(),10,10);
if(score>0){
score = score + .02;
if (score>5){
if (random(100)>98){
if (ballCount<600){
balls.add(new Ball(random(width), random(height), ballWidth));
ballCount++;
}
}
}
if(score > 9){
score = score + .08;
//textSize(60);
//easing = .001;
//createPlusAndMinusPositions();
}else{//if score is less than 9
scorePosX = width;
scorePosY = 0;
}
if(score > 99){
score = score+2;
//textSize(70);
//easing = .002;
}
if(score > 999){
//textSize(150);
//easing = .003;
}
//float dx = gazeTrack.getGazeX() - scorePosX;
//scorePosX += dx * easing;
//float dy = gazeTrack.getGazeY() - scorePosY;
//scorePosY += dy * easing;
//print("width =" + width);
//print("scorePosX ="+scorePosX);
//IDEA:
// once the score fades away the new circles made could just start going to random corners when
// looked at, but once none have been looked at for awhile, that is when they quit being made
fill(255,0,0);
}else{//if the score is less than 0
score = score + .02;
if (random(100)>90){
if(fadingScoreFill>1){
if (ballCount<600){
balls.add(new Ball(random(width), random(height), ballWidth));
ballCount++;
}
}
}
fill(255);
}
if(fadingScoreFill<255){
fill(fadingScoreFill);
fadingScoreFill= max(0,fadingScoreFill-3);
}
textAlign(RIGHT,TOP);
textSize(50);
if(scoreExt>0){
text("Score: " + str(int(score))+ str(int(scoreExt)), scorePosX, scorePosY);
}else{
text("Score: " + str(int(score)), scorePosX, scorePosY);
}
if (dist(gazeTrack.getGazeX(), gazeTrack.getGazeY(),scorePosX, scorePosY) < 200){
if (score > 0){
youlose();
}else{
if(fadingScoreFill>254){
print("fadingScoreFill");
fadingScoreFill = 254;
}
}
}
// Print the tracker's timestamp for the gaze cursor above
//println("Latest gaze data at: " + gazeTrack.getTimestamp());
}
//if not currently playing
}else{
if(gazeTrack.gazePresent()){
mustLookBack = false;
if(eyeShake()){
reallyWon = true;
}
}else{
if (!mustLookBack){
clear();
currentlyPlaying = true;
//print("dointhis");
}
}
}
}
}
}
}
int framesSinceRight = 200;
int framesSinceRightLeft = 200;
int framesSinceRightLeftRight= 200;
int framesSinceRightLeftRightLeft =200;
int framesSinceRightLeftRightLeftRight =200;
int framesSinceRightLeftRightLeftRightLeft = 200;
Boolean eyeShake(){
if (gazeTrack.getGazeX()>width*.75 &&
framesSinceRightLeft > 200 &&
framesSinceRightLeftRight > 200 &&
framesSinceRightLeftRightLeft > 200 &&
framesSinceRightLeftRightLeftRight > 200){
framesSinceRight=0;
}else{
framesSinceRight++;
}
if (gazeTrack.getGazeX()<width*.25 &&
framesSinceRight < 200){
framesSinceRightLeft = 0;
}else{
framesSinceRightLeft++;
}
if (gazeTrack.getGazeX()>width*.75 &&
framesSinceRight < 200 &&
framesSinceRightLeft < 200){
framesSinceRightLeftRight = 0;
}else{
framesSinceRightLeftRight++;
}
if (gazeTrack.getGazeX()<width*.25 &&
framesSinceRight < 200 &&
framesSinceRightLeft < 200 &&
framesSinceRightLeftRight < 200){
framesSinceRightLeftRightLeft = 0;
}else{
framesSinceRightLeftRightLeft++;
}
if (gazeTrack.getGazeX()>width*.75 &&
framesSinceRight < 200 &&
framesSinceRightLeft < 200 &&
framesSinceRightLeftRight < 200 &&
framesSinceRightLeftRightLeft < 200){
framesSinceRightLeftRightLeftRight = 0;
}else{
framesSinceRightLeftRightLeftRight++;
}
if (gazeTrack.getGazeX()<width*.25 &&
framesSinceRight < 200 &&
framesSinceRightLeft < 200 &&
framesSinceRightLeftRight < 200 &&
framesSinceRightLeftRightLeft < 200 &&
framesSinceRightLeftRightLeftRight < 200){
return true;
}else{
return false;
}
}
void updateBalls(){
//print("updat");
// With an array, we say balls.length, with an ArrayList, we say balls.size()
// The length of an ArrayList is dynamic
// Notice how we are looping through the ArrayList backwards
// This is because we are deleting elements from the list
for (int i = balls.size()-1; i >= 0; i--) {
// An ArrayList doesn't know what it is storing so we have to cast the object coming out
Ball ball = balls.get(i);
//ball.move();
ball.display();
if (ball.seen){
ball.move();
}else{
ball.checkIfSeen();
}
if (ball.finished()) {
// Items can be deleted with remove()
balls.remove(i);
ballCount--;
}
}
}
void youlose(){
clear();
balls.clear();
currentlyPlaying = false;
yellowUnlocked = false;
stillnessCounter = 0;
becameStill = false;
fadingScoreFill = 255;
ballCount = 0;
fill(255,0,0);
textAlign(CENTER,CENTER);
textSize(50);
text("You win!", 800, 370);
stroke(255,0,0);
line(700, 380,900,380);
stroke(0);
text("You lose!", 800, 450);
if (scoreExt>0){
text("Score: "+str(int(score))+str(int(scoreExt)), 800, 530);
}else{
text("Score: "+str(int(score)), 800, 530);
}
text("Turn head to play.", 800, 610);
score = 1;
scoreExt = 0;
framesSinceRight = 200;
framesSinceRightLeft = 200;
framesSinceRightLeftRight= 200;
framesSinceRightLeftRightLeft =200;
framesSinceRightLeftRightLeftRight =200;
framesSinceRightLeftRightLeftRightLeft = 200;
}
class Ball {
float x;
float y;
float speed;
float gravity;
float w;
float life = 255;
boolean seen = false;
boolean minus = false;
boolean isYellow = false;
int age = 0;
Ball(float tempX, float tempY, float tempW) {
x = tempX;
y = tempY;
w = tempW;
speed = 0;
//print(random(2));
gravity = 0.1;
if(yellowUnlocked && random(10)>8){
isYellow = true;
}
if(random(2)>1){
minus = true;
}
}
void move() {
if(!isYellow){
// Add gravity to speed
speed = speed + gravity;
// Add speed to y location
if(fadingScoreFill>5){
if (y>0){
y = y - speed;
}
if (x<width+1){
x = x + speed;
}
}else{//this is how the balls move if the score is currently faded
if(x<3 || y<3 || x>width-3 || y>height-3){
life = -1;//this will get it finished, if i put finished in here it breaks
}
if(y<height/2){
if (y>0){
y = y - speed;
}
}else{
if (y<height+1){
y = y + speed;
}
}
if(x<width/2){
if (x>0){
x = x - speed;
}
}else{
if (x<width+1){
x = x + speed;
}
}
}
}
//after we move it, we check to see if it is in the corner,
// if it isthen we do the points and make it finished
if(dist(x, y,scorePosX, scorePosY) < 200){
if (age<100){
if (score>9){
score = score/2;
}else if(score<10 && score>0){
score = score - .5;
}else if(score < 1 && score > -100000){
score = score - (-score);
}
}else{
//print("x"+score);
if (score>1000){
yellowUnlocked = true;
}
if (score<4843672 && score>0){
score = score+(score/10);
}else if(score>4843672){
scoreExt++;
scoreExt = scoreExt+(scoreExt/10);
}else if(score<1){
score = (score/2)+1;
}
//print("z"+score);
}
life = -1;//this means it will be finished
}
}
void checkIfSeen(){
age++;
//life = 255;
if (dist(gazeTrack.getGazeX(),gazeTrack.getGazeY(), x,y)<80){
seen = true;
if(fadingScoreFill<5){
stillnessCounter= 0;
becameStill= false;
}
}else{
seen = false;
if(fadingScoreFill<5){
stillnessCounter++;
if (stillnessCounter>300){
becameStill= true;
}
}
}
}
boolean finished() {
// Balls fade out
if (isYellow){
life=life-2;
}else{
life=life-.3;
}
if (life < 0) {
return true;
} else {
return false;
}
}
void display() {
if(fadingScoreFill < 2){
fill(int(random(255)),int(random(255)),int(random(255)));
ellipse(x,y,w,w);
}else{
if (isYellow){
fill(255,255,0);
ellipse(x,y,w,w);
imageMode(CENTER);
image(cursor,x,y);
}else{
// Display the circle
if (age<100){
fill(255,life);
}else{
fill(255,0,0,life);
}
//stroke(0,life);
ellipse(x,y,w,w);
fill(0);
textAlign(CENTER,BOTTOM);
textSize(60);
if (age<100){
text("-",x,y+30);
}else{
text("+",x,y+30);
}
}
}
if(seenGreen){
if(random(50)>48){
fill(0,255,0);
ellipse(x,y,w,w);
}
}
}
}
//score should slowly become more and more inviting to look at, then it should start moving slowly,
// once it is moving fast enough to actually be a threat it should no longer be deadly,
// once it touches you it goes away, maybe it would be best to make it so that as soon as a certain
// new badguy shows up it no longer is dangerous. YES! The deadliness moves from the score to
// something that is obviously bad, a red X, over time the red X fades white and has a number
// beside it, this number makes your score go crazy high(At this point the score has returned to its
// purch)
//when the score is getting higher and higher it should also get bigger and bigger and eventually snuff out the player
//as your score gets bigger it could start moving, maybe even chasing you down. Score size
// could be directly related to score
//it would be cool if the score got more and more snakelike as it got longer as it chases your
// eyes around screen
//after a certain score it is ok that the score gets you, maybe shortly after that the score could totaly
// fade away. maybe everything could eventually fade away and you just have to keep doing
// stuff on a blank screen, maybe then eventually things start coming back.
//maybe we want to have really old balls fade away so they dont just stay there reminding us of bad
// calibration
//maybe we want to have some thing that you only get if you go high, like a new color ball,
// you must have unlocked the new color ball before going negative and looking at the score to
// go to the next round
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment