color GREEN = color(100,255,100); HashSet apples = new HashSet(); Snake s = new Snake(); int score = -1; boolean playing = false; void startGame(){ score = 0; playing = true; apples = new HashSet(); for(int i = 0; i < 10; i++){ apples.add(new Apple()); } s = new Snake(); } void setup() { size(500,500); textSize(20); // smooth(); } boolean virgin = true; color bg = color(200); void draw() { background(bg); fill(120);stroke(0);strokeWeight(3); ellipse(250,250,500,500); if(playing){ s.move(); } s.draw(); for(Apple a : apples){ a.move(); a.draw(); } if(!playing){ fill(0); text("SNAKEDRIVE",100,100); if(score != -1){ text("SCORE:"+score,200,200); } text("SPACE TO PLAY",200,300); text("LEFT & RIGHT STEERS",200,325); text("EAT MICE",200,350); text("AVOID WALLS & SELF",200,375); } else { fill(0); text("SCORE:"+score,345,495); } } class Segment{ float x,y; Segment(float px, float py ){ x = px; y = py; } } class Apple{ float x, y; float ang; float as; Apple(){ float a = random(2*PI); x = 250+250 * cos(a); y = 250+250 * sin(a); ang = a-PI; } float sp = 1; void move(){ if(random(1) < .2){ as += random(-.05,.05); ang += as; if(as > .2) as = .2; if(as < -.2) as = -.2; } x += cos(ang)*sp; y += sin(ang)*sp; if(s.appleHit(this)){ ang += PI; } if(dist(x,y,250,250) >250){ ang = atan2(y-250,x-250)-PI; } } float size = 10; void draw(){ fill(200);stroke(200); strokeWeight(2); ellipse(x,y,size,size); line(x,y,x+cos(ang-PI) * 14,y+sin(ang-PI) * 14); strokeWeight(1);stroke(0); float nx = x+cos(ang) * 5; float ny = y+sin(ang) * 5; float nl = 5; float na; float nd = .3; na =ang+ PI/2+nd; line(nx,ny, nx+cos(na)*nl,ny+sin(na)*nl); na =ang+ PI/2-nd; line(nx,ny, nx+cos(na)*nl,ny+sin(na)*nl); na =ang- PI/2+nd; line(nx,ny, nx+cos(na)*nl,ny+sin(na)*nl); na =ang- PI/2-nd; line(nx,ny, nx+cos(na)*nl,ny+sin(na)*nl); } } class Snake{ float x,y,a; ArrayListtail = new ArrayList(); Snake(){ x = 250; y = 250; a = -PI/2; } float TURN = .1; float MAX = 50; float speed = 1; void move(){ if(leftPressed) a -= TURN; if(rightPressed) a += TURN; tail.add(new Segment(x,y)); x += speed*cos(a); y += speed * sin(a); if(dist(x,y,250,250) > 250){ playing = false; } bg = color(200); HashSetapplesToKill = new HashSet(); for(Apple a: apples){ if(dist(x,y,a.x,a.y) < a.size){ bg = color(255,0,0); applesToKill.add(a); MAX += 30; speed += .04; score++; } } apples.removeAll(applesToKill); for(int i = 0; i < applesToKill.size();i++){ apples.add(new Apple()); } } void draw(){ if(playing || score == -1){ fill(GREEN); stroke(GREEN); } else { fill(0); stroke(0); } strokeWeight(4); if(tail.size() > MAX){ tail.remove(0); } float lastX = x; float lastY = y; for(int i = tail.size() -1; i >= 0; i--){ Segment s = tail.get(i); // print(lastX+","+lastY+" "); line(lastX,lastY,s.x,s.y); lastX = s.x; lastY = s.y; } int c = tail.size() - 3; if(c >= 0){ lastX = tail.get(c).x; lastY = tail.get(c).y; stroke(0); for(int i = c; i >= 0; i--){ Segment s = tail.get(i); if(circleLineIntersect(lastX,lastY,s.x,s.y,x,y,2)){ playing = false; } lastX = s.x; lastY = s.y; } } noStroke(); ellipse(x,y,10,10); fill(0);noStroke(); ellipse(x + cos(a - PI/4)* 3,y + sin(a - PI/4)* 3,4,4); ellipse(x + cos(a + PI/4)* 3,y + sin(a + PI/4)* 3,4,4); } boolean appleHit(Apple a){ float lastX,lastY; int c = tail.size()-1; if(c > 0){ lastX = tail.get(c).x; lastY = tail.get(c).y; stroke(0); for(int i = c; i >= 0; i--){ Segment s = tail.get(i); if(circleLineIntersect(lastX,lastY,s.x,s.y,a.x,a.y,a.size)){ return true; } lastX = s.x; lastY = s.y; } } return false; } } boolean leftPressed, rightPressed, shiftPressed; void keyPressed(){ if(keyCode == LEFT){ leftPressed = true; } if(keyCode == RIGHT){ rightPressed = true; } if(key == ' '){ if(!playing){ startGame(); } } } void keyReleased(){ if(keyCode == LEFT){ leftPressed = false; } if(keyCode == RIGHT){ rightPressed = false; } if(key=='z'){ shiftPressed = false; } } //from http://www.openprocessing.org/visuals/?visualID=8009 boolean circleLineIntersect(float x1, float y1, float x2, float y2, float cx, float cy, float cr ) { float dx = x2 - x1; float dy = y2 - y1; float a = dx * dx + dy * dy; float b = 2 * (dx * (x1 - cx) + dy * (y1 - cy)); float c = cx * cx + cy * cy; c += x1 * x1 + y1 * y1; c -= 2 * (cx * x1 + cy * y1); c -= cr * cr; float bb4ac = b * b - 4 * a * c; //println(bb4ac); if (bb4ac < 0) { // Not intersecting return false; } else { float mu = (-b + sqrt( b*b - 4*a*c )) / (2*a); float ix1 = x1 + mu*(dx); float iy1 = y1 + mu*(dy); mu = (-b - sqrt(b*b - 4*a*c )) / (2*a); float ix2 = x1 + mu*(dx); float iy2 = y1 + mu*(dy); // The intersection points //ellipse(ix1, iy1, 10, 10); //ellipse(ix2, iy2, 10, 10); float testX; float testY; // Figure out which point is closer to the circle if (dist(x1, y1, cx, cy) < dist(x2, y2, cx, cy)) { testX = x2; testY = y2; } else { testX = x1; testY = y1; } if (dist(testX, testY, ix1, iy1) < dist(x1, y1, x2, y2) || dist(testX, testY, ix2, iy2) < dist(x1, y1, x2, y2)) { return true; } else { return false; } } }