movesprat m; movesprat boxes[]; int BOXCOUNT = 10; void setup(){ frameRate(30); size(400,400); m = new movesprat(220,230,"lam.gif",10,.99,.5); boxes = new movesprat[BOXCOUNT]; for(int i = 0; i < BOXCOUNT; i++){ boxes[i] = new movesprat((int)random(width),(int)random(height),"lin.gif",10,.99,.5); } } int c; HashSet currentKeys = new HashSet(); void keyPressed(KeyEvent e){ currentKeys.add(new Integer(e.getKeyCode())); } void keyReleased(KeyEvent e){ currentKeys.remove(new Integer(e.getKeyCode())); } boolean isKeyDown(int c){ return currentKeys.contains(new Integer(c)); } void draw(){ if(isKeyDown(37)){ m.xs -= .3; } if(isKeyDown(39)){ m.xs += .3; } if(isKeyDown(32)){ m.ys -= .3; } m.ys += .2; for(int i = 0; i < BOXCOUNT; i++){ boxes[i].ys += .2; } m.move(); for(int i = 0; i < BOXCOUNT; i++){ boxes[i].move(); } m.bounds(); for(int i = 0; i < BOXCOUNT; i++){ boxes[i].bounds(true); } c++; if(c % 50 == 0){ // m.changeframe(m.currentframe==0?1:0); } for(int i = 0; i < BOXCOUNT; i++){ if(m.overlap(boxes[i],true)){ m.collide(boxes[i]); } } //round robin collisions... for(int i = 0; i < BOXCOUNT; i++){ for(int j = i+1; j < BOXCOUNT; j++){ if(boxes[i].overlap(boxes[j],true)){ boxes[i].collide(boxes[j]); } } } background(128); for(int i = 0; i < BOXCOUNT; i++){ boxes[i].draw(); } m.draw(); } class movesprat extends sprat { float xs, ys; float mass,friction, rebound; //pmass = mass, pfriction is multipler to speed per frame, rebound is multiplier of speed on wall/floor collision movesprat(int px,int py, String imgname, float pmass, float pfriction, float prebound){ super(px,py,imgname); friction = pfriction; mass = pmass; rebound = prebound; } movesprat(int px,int py, String[] imgname, float pmass, float pfriction, float prebound){ super(px,py,imgname); friction = pfriction; mass = pmass; rebound = prebound; } void collide(movesprat o){ float temp; temp = o.xs; o.xs = xs; xs = temp; temp = o.ys; o.ys = ys; ys = temp; //figure out which overlap is less, and make that the point where they push out float hlap = spratOverlapHoriz(o).magnitude(); float vlap = spratOverlapVert(o).magnitude(); if(hlap < vlap){ if(x < o.x){ x -= hlap / 2.0; o.x += hlap / 2.0; } else { x += hlap / 2.0; o.x -= hlap / 2.0; } } else { if(y < o.y){ y -= hlap / 2.0; o.y += hlap / 2.0; } else { y += hlap / 2.0; o.y -= hlap / 2.0; } } } void move(){ xs *= friction; ys *= friction; x += xs; y += ys; } void bounds(boolean b){ print("height is "+height); println(" y +w is "+(y+w)); bounds(); } void bounds(){ if(x < 0) { x = 0; xs = abs(xs) * rebound; } if(x+w > width) { x = width-w; xs = abs(xs) * -rebound; } if(y < 0) { y = 0; ys = abs(ys) * rebound; } if(y+h > height) { // print("ys is "+ys); y = height-h; ys = abs(ys) * -rebound; // println("ys to "+ys); println("hit"); } } } class sprat{ float x,y; int w,h; int framecount; int currentframe; PImage img[]; sprat(int px,int py, String imgname){ String s[] = new String[1]; s[0] = imgname; init(px,py,s); } sprat(int px,int py, String[] imgname){ init(px,py,imgname); } void init (int px,int py, String[] imgname){ x = px; y = py; img = new PImage[imgname.length]; for(int i = 0; i < imgname.length; i++){ img[i] = loadImage(imgname[i]); } changeframe(0); } void changeframe(int whatframe){ currentframe = whatframe; w = img[currentframe].width; h = img[currentframe].height; } void draw(){ image(img[currentframe],x,y); rect(x,y,w,h); } //so we have a physical x and y on screen //find the pixel for this thing //WARNING no bounds checking color pixelAtPhysicalLocation(int px, int py){ int rx = px - int(x); int ry = py - int(y); return img[currentframe].pixels[rx + (ry * w)]; } boolean overlap(sprat other){ return overlap(other, false); } boolean overlap(sprat other, boolean boxonly){ intRange vOverlap = spratOverlapVert(other); intRange hOverlap = spratOverlapHoriz(other); if(vOverlap == null || hOverlap == null){ return false; } if(boxonly) return true; //hrrm, why couldn't this be <= ???? for(int a = hOverlap.min; a < hOverlap.max; a++){ for(int b = vOverlap.min; b < vOverlap.max; b++){ if(alpha(this.pixelAtPhysicalLocation(a,b)) > 128 && alpha(other.pixelAtPhysicalLocation(a,b)) > 128 ){ return true; } } } return false; } // to see if things overlap on one dimension // we sort the 4 points. if both points of // one thing are lesser than both points of the other, // they can't be overlapping... intRange spratOverlapHoriz(sprat b){ sprat a = this; intWithRef vals[] = new intWithRef[4]; vals[0] = new intWithRef((int)a.x,a); vals[1] = new intWithRef((int)(a.x+a.w),a); vals[2] = new intWithRef((int)b.x,b); vals[3] = new intWithRef((int)(b.x+b.w),b); Arrays.sort(vals); if (vals[0].src == vals[1].src){ return null; } return new intRange(vals[1].val,vals[2].val); } intRange spratOverlapVert(sprat b){ sprat a = this; intWithRef vals[] = new intWithRef[4]; vals[0] = new intWithRef((int)a.y,a); vals[1] = new intWithRef((int)(a.y+a.h),a); vals[2] = new intWithRef((int)b.y,b); vals[3] = new intWithRef((int)(b.y+b.h),b); Arrays.sort(vals); if (vals[0].src == vals[1].src){ return null; } return new intRange(vals[1].val,vals[2].val); } } class intRange{ int min, max; intRange(int p1, int p2){ min = p1p2?p1:p2; } int magnitude(){ return abs(max-min) ; } } class intWithRef implements Comparable{ int val; Object src; intWithRef(int pval,Object psrc){ val = pval; src = psrc; } public int compareTo(Object o){ return val - ((intWithRef)o).val; } }