// mouse incs, shift-drag decs // reset from keyboard // no need to reset at first anymore // why doesn't netscape 4.0.5 with awt 1.1.5 deal? import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class Life extends Applet { myCanvas cvs; Applet thisApplet; int delay = 80; int last_x, last_y, numImgs=9+4; public static final boolean glider[/*dir*/][/*x*/][/*y*/] = {{{false,false,true}, {true,false,true}, {false,true,true}}, //SE {{true,true,true}, {false,false,true}, {false,true,false}}, //SW {{true,true,false}, {true,false,true}, {true,false,false}}, //NW {{false,true,false}, {true,false,false}, {true,true,true}}}; //NE public static final int SE = 0; public static final int SW = 1; public static final int NW = 2; public static final int NE = 3; int[][] res = new int[24][24]; Image[] imgs, gliderImgs, theImg; MediaTracker mt; class myCanvas extends Canvas { Image img; public myCanvas() { super(); // setSize(w,h); img = null; } public void update(Graphics g) { paint(g); } public void paint() { paint(getGraphics()); } public void paint(Graphics g) { if ((g!=null)&&(img!=null)) g.drawImage(img, 0,0, this); } } public void init() { thisApplet = this; images(); gui(); listeners(); } void images() { for (int i=0; i<24; i++) for (int j=0; j<24; j++) res[i][j] = 0; mt = new MediaTracker(thisApplet); imgs = new Image[9]; for(int i=0; i<9; i++) { imgs[i] = getImage (getDocumentBase(), "imgs/hand" + i + ".jpeg"); mt.addImage(imgs[i],i); } gliderImgs = new Image[4]; for(int i=0; i<4; i++) { gliderImgs[i] = getImage (getDocumentBase(), "imgs/glider" + i + ".jpeg"); mt.addImage(gliderImgs[i],9+i); } } void gui() { thisApplet.setLayout(new BorderLayout(0,0)); thisApplet.setBackground(Color.darkGray); cvs = new myCanvas(); cvs.setSize(64+256+64, 64+256+64); cvs.setBackground(Color.darkGray); thisApplet.add(cvs, "Center"); validate(); } void listeners() { cvs.addMouseListener (new MouseAdapter() { public void mouseEntered(MouseEvent e) { cvs.requestFocus(); } public void mousePressed(MouseEvent e) { last_x = e.getX(); last_y = e.getY(); } public void mouseReleased(MouseEvent e) { if ((last_x>63) && (last_x < 256+64) && (last_y>63) && (last_y < 256+64)) return; boolean[][] gliderArray = new boolean[24][24]; boolean[][] newGliderArray = new boolean[24][24]; boolean[][] incedRes = new boolean[24][24]; // these need to be reset for each glider for(int i=0; i<24; i++) for(int j=0; j<24; j++) { gliderArray[i][j] = false; incedRes[i][j] = false; } int x = e.getX(), y = e.getY(); int gx, gy, dir; int sum; Graphics g = cvs.img.getGraphics(); gx = last_x/16; gy = last_y/16; // Presumably 0<=gx<4 or 20<=gx<24, &||gy. // Want to maintain outer border (0 or 23) always 0; // so want to center 3x3 glider on 2 or 21. if ((gx<2) || (gx==3)) gx=2; else if ((gx>21) || (gx==20)) gx=21; if ((gy<2) || (gy==3)) gy=2; else if ((gy>21) || (gy==20)) gy=21; dir = last_xy? NE:SE) : (last_y>y? NW:SW); // start up the directionally appropriate glider[dir][][] // e.g. for SE from top-left, gx=gy=2; // paste g[SE][0,1,2][0,1,2] to gA[1,2,3][1,2,3] for (int i=0; i<3; i++) for (int j=0; j<3; j++) gliderArray[gx-1+i][gy-1+j] = glider[dir][i][j]; // Now the glider update/draw loop: test: while (true) { // No need to draw it the first time -- // it's not in the image area yet. for (int i=0; i<23; i++) if (gliderArray[i][0] || gliderArray[i][23] || gliderArray[0][i] || gliderArray[23][i]) { break test; } for (int i=0; i<24; i++) for (int j=0; j<24; j++) { // inc sum for all live neighbors sum = 0; if ((i>0) && gliderArray[i-1][j]) sum++; if ((i<23) && gliderArray[i+1][j]) sum++; if ((j>0) && gliderArray[i][j-1]) sum++; if ((j<23) && gliderArray[i][j+1]) sum++; if ((i>0) && (j>0) && gliderArray[i-1][j-1]) sum++; if ((i>0) && (j<23) && gliderArray[i-1][j+1]) sum++; if ((i<23) && (j>0) && gliderArray[i+1][j-1]) sum++; if ((i<23) && (j<23) && gliderArray[i+1][j+1]) sum++; if (!gliderArray[i][j]) { if (sum==3) // cell was empty, now alive newGliderArray[i][j] = true; else // cell was empty -- still is. newGliderArray[i][j] = false; } else // (gliderArray[i][j]) if ((sum==2)||(sum==3)) // cell was alive -- still is newGliderArray[i][j] = true; else // cell was alive, now empty { newGliderArray[i][j] = false; if (!incedRes[i][j]) // This is the first update for this pass, // so inc resolution, and make a note of it. { if((e.getModifiers() & e.SHIFT_MASK)==0) { if (res[i][j]<8) res[i][j]++; } else { if (res[i][j]>0) res[i][j]--; } incedRes[i][j] = true; } } } // for // Do all the drawing of f->t and t->f boxes at once: // hoping the gliders will look right for (int i=4; i<20; i++) for (int j=4; j<20; j++) { if (!gliderArray [i][j] && newGliderArray[i][j]) // cell was empty, now alive g.drawImage (gliderImgs[dir], 16*i,16*j, // between 0+64&255+64 cvs); else if (gliderArray[i][j] && !newGliderArray[i][j]) // cell was alive, now empty g.drawImage (//imgs[ res[i][j] <= 8 ? res[i][j] : 8], imgs[res[i][j]], // dx1,dy1 -- between 0+64&255+64 16*i,16*j, // dx2, dy2 -- between 0+64&255+64 16*i+16, 16*j+16, // sx1,sy1 -- between 0&255 16*i-64,16*j-64, // sx2, sy2 -- between 0&255 16*i+16-64, 16*j+16-64, cvs); } cvs.paint(); // Update glider array & go again. for (int i=0; i<24; i++) for (int j=0; j<24; j++) gliderArray[i][j] = newGliderArray[i][j]; try { Thread.sleep(delay); } catch (InterruptedException ie) { ; } } //while } //mouseReleased } //MouseAdapter ); cvs.addKeyListener (new KeyAdapter() { public void keyPressed(KeyEvent e) { if ((e.getKeyCode()==10) || (e.getKeyChar()=='\n') || (e.getKeyChar()==' ')) { cvs.img.getGraphics().drawImage(imgs[0], 64,64, cvs); cvs.paint(); for (int i=0; i<24; i++) for (int j=0; j<24; j++) res[i][j] = 0; } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { delay +=10; // slower } else if (e.getKeyCode() == KeyEvent.VK_UP) { if (delay>=10) delay-=10; } } } ); } public void show() { for(int i=0; i