ArrayList ships = new ArrayList(); ArrayList rocks = new ArrayList(); ArrayList bullets = new ArrayList(); ArrayList shipsToKill = new ArrayList(); ArrayList rocksToKill = new ArrayList(); ArrayList bulletsToKill = new ArrayList(); ArrayList rocksToAdd = new ArrayList(); int level = 1; int extralives = 0; int score; void setup(){ size(800,800); frameRate(30); startShips(); addRocks(); } void startShips(){ shipsToKill = new ArrayList(); for(int i = 0; i < 20; i++){ ships.add(new Ship(random(100,700),random(100,700))); } } void keyPressed(){ if(key == 's' || key == 'S'){ ships.add(new Ship(400,400)); extralives++; } if(key == 'r' || key == 'R'){ extralives = 0; score = 0; rocks = new ArrayList(); startShips(); bullets = new ArrayList(); rocksToAdd = new ArrayList(); } } void draw(){ shipsToKill = new ArrayList(); rocksToKill = new ArrayList(); bulletsToKill = new ArrayList(); rocksToAdd = new ArrayList(); background(0); fill(255); text("aRTSeroids",20,20); text("(mousedrag to select, click to send, s for extra ship, r to reset)",120,20); text("score:"+score,520,20); text("extra ships used:"+extralives,620,20); for(Ship s : ships){ s.move(); s.draw(); for(Rock r : rocks){ if(r.hit(s)){ shipsToKill.add(s); rocksToKill.add(r); r.split(); } } } for(Rock r : rocks){ r.move(); r.draw(); } for(Bullet b : bullets){ if(! b.move()){ bulletsToKill.add(b); }; b.draw(); for(Rock r : rocks){ if(r.hit(b)){ rocksToKill.add(r); r.split(); bulletsToKill.add(b); } } } stroke(255); if(mousePressed){ fill(255,64); rect(sx,sy,mouseX-sx,mouseY-sy); } rocks.removeAll(rocksToKill); bullets.removeAll(bulletsToKill); ships.removeAll(shipsToKill); rocks.addAll(rocksToAdd); if(rocks.size() == 0){ level++; addRocks(); } } void addRocks(){ for(int i = 0; i < 5+(3*level); i++){ rocks.add(new Rock(random(100,700),random(100,700),3)); } } float sx, sy,ex,ey; ArrayList selectedShips; void mousePressed(){ sx = mouseX; sy = mouseY; } void mouseReleased(){ if(dist(mouseX,mouseY,sx,sy) < 5){ if(selectedShips != null){ for(Ship s : selectedShips){ s.tx = sx; s.ty = sy; // s.selected = false; } //selectedShips = null; } return; } selectedShips = new ArrayList(); float left = min(sx,mouseX); float right = max(sx,mouseX); float top = min(sy,mouseY); float bottom = max(sy,mouseY); for(Ship s : ships){ if(s.x > left && s.x < right && s.y > top && s.y < bottom){ s.selected = true; selectedShips.add(s); } else { s.selected = false; } } } class Thing{ float x,y,xs,ys,a; float sz; void bounds(){ if(x < 0) x = 800; if(y < 0) y = 800; if(y > 800) y = 0; if(x > 800) x = 0; } boolean hit(Thing t){ return (dist(x,y,t.x,t.y) < sz+t.sz); } } class Bullet extends Thing{ Bullet(Ship s){ x = s.x + s.sz * cos(s.a); y = s.y + s.sz * sin(s.a); xs = s.xs +(cos(s.a) * 3); ys = s.ys + (sin(s.a) * 3); sz = 1; } int life = 100; boolean move(){ x += xs; y += ys; bounds(); life -= 1; if(life < 0) return false; return true; } void draw(){ stroke(255); line(x,y,x,y); } } class Rock extends Thing{ boolean splitted = false; int scale = 3; float max = 1; float[] ptx = new float[6];; float[] pty = new float[6]; void split(){ if(splitted) return; splitted = true; score++; if(scale > 2){ rocksToAdd.add(new Rock(x,y,scale-1)); rocksToAdd.add(new Rock(x,y,scale-1)); } } Rock(float px, float py, int ps){ scale = ps; x = px; y = py; sz = ps*10; xs = random(-max,max)/ps; ys = random(-max,max)/ps; for(int i = 0; i < 6; i++){ float d = random(sz * .5,sz); float a = i*(2*PI)/6; ptx[i] = d * cos(a); pty[i] = d * sin(a); } } void draw(){ noFill(); stroke(200+random(50),100+random(50),0); pushMatrix(); translate(x,y); // ellipse(0,0,sz,sz); line(ptx[5],pty[5],ptx[0],pty[0]); for(int i = 1; i < 6; i++){ line(ptx[i-1],pty[i-1],ptx[i],pty[i]); } popMatrix(); } void move(){ x += xs; y += ys; bounds(); } } class Ship extends Thing{ float tx= 400; float ty = 400; float spd = .1; float tspd = .1; Rock followingRock = null; float power = random(100); boolean selected; Ship(float px, float py){ sz = 20; a = random(2*PI); // a = 0; x = px; y = py; } float dangerDist = 120; void move(){ if(power < 100) power += 10; if(followingRock == null){ //look for target... for(Rock r : rocks){ if(dist(x,y,r.x,r.y) < dangerDist){ followingRock = r; break; } } } else { // see if too far if(followingRock.splitted || dist(x,y,followingRock.x,followingRock.y) > dangerDist){ followingRock = null; } } if(followingRock != null && power >= 100){ bullets.add(new Bullet(this)); power = 0; } float rtx = tx; float rty = ty; if(followingRock != null){ rtx = followingRock.x; rty = followingRock.y; } float dx = (rtx - x); float dy = ( rty - y); //this trick seems to work to deal with the overlap.. //they consider the shortest path even if other side of screen if(abs(dx) > width/2){ dx *= -1.0; } if(abs(dy) > height/2){ dy *= -1.0; } float wantangle = atan2(dy, dx); float anglediff = (a - wantangle); anglediff /= PI; //this next bit catches the "runaround" if(anglediff > 1){ anglediff -= 2; } if(anglediff < -1){ anglediff += 2; } if(abs(anglediff) > .1){ if(anglediff > 0){ a -= tspd; } else { a += tspd; } } xs += cos(a) * spd; ys += sin(a) * spd; xs *= .99; ys *= .99; x += xs; y += ys; bounds(); } void draw(){ if(followingRock != null){ // line(x,y,followingRock.x,followingRock.y); } pushMatrix(); noFill(); if(selected) stroke(random(128) + 127); else stroke(0,random(127)+128,0); translate(x,y); // ellipse(0,0,sz,sz); rotate(a); //line(0,0,20,0); triangle(0+sz,0,-sz/2,-sz/2,-sz/2,sz/2); popMatrix(); } }