home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-12-14 | 12.4 KB | 608 lines |
- import java.util.*;
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.image.ImageObserver;
- import java.awt.image.PixelGrabber;
-
- /*
- * class that manages a generation
- */
- class LifeGenerator {
-
- /*
- * array containing packed cells
- * n - number of elements in the CellList array
- */
- int CellList[], n;
- int a[];
- int b[];
- int c[];
-
- /*
- * the current generation number
- */
- int generations;
-
- /*
- * background and foreground colors
- */
- Color background;
- Color foreground;
-
- int statusheight;
- int displaywidth;
- int displayheight;
-
- int originx;
- int originy;
-
- int maxcells;
-
- static int countmsk=0x1f;
- static int posmsk=0x7fffffe0;
- static int maxval=0x7fffffff;
-
- String statusLine;
- String loading;
-
- int scroll;
-
- /*
- * the rules of life
- */
- static boolean rules[]={
- false, false,
- false, false,
- false, true,
- true, true,
- false, false,
- false, false,
- false, false,
- false, false,
- false, false
- };
-
- /*
- * constructor initializes variables
- */
- public LifeGenerator() {
-
- n=0;
- generations=0;
- maxcells=0;
- background=Color.white;
- foreground=Color.black;
-
- originx=0;
- originy=0;
-
- loading=null;
- scroll=10;
-
- statusLine=new String("");
- }
-
- public void loading(String init_loading) {
-
- loading=init_loading;
- }
-
- public void setScroll(int init_scroll) {
-
- scroll=init_scroll;
- }
-
- public void setColors(Color init_background,Color init_foreground) {
-
- background=init_background;
- foreground=init_foreground;
- }
-
- public void setDisplaySize(int width, int height) {
-
- statusheight=35;
-
- displaywidth=width;
- displayheight=height-statusheight;
- }
-
- /**
- * translate the origin
- * @param dx, dy - offsets to translate
- */
- public void translate(int dx, int dy) {
-
- originx+=dx;
- originy+=dy;
- }
-
- public void recenter(int x, int y) {
-
- translate(displaywidth/2-x, displayheight/2-y);
- }
-
- public void approachcenter(int x, int y) {
-
- translate((displaywidth/2-x)/scroll,
- (displayheight/2-y)/scroll);
- }
-
- public void findPattern() {
-
- if (n>0) {
- int packed=CellList[n/2];
- int plotx=(((packed>>5)&0x1fff)-(1<<12))*2+originx;
- int ploty=((packed>>18)-(1<<12))*2+originy;
- recenter(plotx, ploty);
- }
- }
-
- /**
- * print status message
- * @param g - destination graphics object
- */
- public void updateStatusLine(Graphics g) {
-
- g.setColor(background);
- g.drawString(statusLine,0,displayheight+15);
-
- if (loading!=null) {
- statusLine="Loading: " + loading;
- } else {
- statusLine="Generations: " + generations + " Cells: " + n;
- }
- g.setColor(foreground);
- g.drawString(statusLine,0,displayheight+15);
- }
-
- void resizeIfNeeded(int cellcount) {
-
- int tmp[];
- int i;
-
- if (cellcount>maxcells) {
-
- int newsize=2*cellcount;
-
- tmp=new int[newsize];
- for (i=0; i<maxcells; i++) tmp[i]=CellList[i];
- CellList=tmp;
-
- tmp=new int[newsize];
- for (i=0; i<maxcells; i++) tmp[i]=a[i];
- a=tmp;
-
- tmp=new int[newsize];
- for (i=0; i<maxcells; i++) tmp[i]=b[i];
- b=tmp;
-
- tmp=new int[newsize];
- for (i=0; i<maxcells; i++) tmp[i]=c[i];
- c=tmp;
-
- maxcells=newsize;
- }
- }
-
- static int combineLists(int a[], int na, int b[], int nb,int c[]) {
-
- int i,j,nc;
- i=0; j=0; nc=0;
- a[na]=maxval;
- b[nb]=maxval;
- while (i<na || j<nb) {
- if ((a[i]^b[j])<=countmsk) {
- c[nc++]=(a[i++]&countmsk)+b[j++];
- } else if (a[i]<b[j]) {
- c[nc++]=a[i++];
- } else {
- c[nc++]=b[j++];
- }
- }
- return nc;
- }
-
- static void extractCenterCells(int list[], int n, int counts[]) {
-
- int i=0, j=0;
-
- while (i<n) {
- if ((list[i]^counts[j])<=countmsk) {
- counts[j]-;
- i++;
- j++;
- } else j++;
- }
- }
-
- static int Cell(int x, int y, int value) {
-
- return ((y+(1<<12))<<18) +((x+(1<<12))<<5) + value;
- }
-
- /**
- * plot an individual cell
- * @param packed - a set of packed cells
- * @param g - destination graphics object
- */
- void plotCell(int packed, Graphics g) {
-
- int plotx=(((packed>>5)&0x1fff)-(1<<12))*2+originx;
- int ploty=((packed>>18)-(1<<12))*2+originy;
-
- if (plotx > 3 && plotx < displaywidth-5 &&
- ploty > 3 && ploty < displayheight-5 ) {
- g.fillRect(plotx, ploty, 2, 2);
- }
- }
-
- /**
- * paint the current generation
- * @param g - destination graphics object
- */
- public void paintAll(Graphics g) {
-
- g.clearRect(0,0,displaywidth, displayheight+statusheight);
- g.drawRect(0,0,displaywidth-1, displayheight-1);
-
- g.setColor(foreground);
- for (int i=0; i<n; i++) {
- plotCell(CellList[i],g);
- }
- updateStatusLine(g);
- }
-
- int nextGen(int counts[], int ncounts, int list[], Graphics g) {
-
- int nlist=0;
- for (int i=0; i<ncounts; i++) {
- int count=counts[i]&countmsk;
- if (rules[count]) {
- list[nlist++]=(counts[i]&posmsk)+2;
- if ((count&1)==0) {
- g.setColor(foreground);
- plotCell(counts[i],g);
- }
- } else {
- if ((count&1)==1) {
- g.setColor(background);
- plotCell(counts[i],g);
- }
- }
- }
- return nlist;
- }
-
- public void generate(Graphics g) {
-
- int na, nb, nc;
-
- for (na=0; na<n; na++) a[na]=CellList[na]-(1<<18);
- resizeIfNeeded(n+na);
- nb=combineLists(CellList,n,a,na,b);
-
- for (na=0; na<n; na++) a[na]=CellList[na]+(1<<18);
- resizeIfNeeded(na+nb);
- nc=combineLists(a,na,b,nb,c);
-
- for (na=0; na<nc; na++) a[na]=c[na]-(1<<5);
- resizeIfNeeded(na+nc);
- nb=combineLists(a,na,c,nc,b);
-
- for (na=0; na<nc; na++) a[na]=c[na]+(1<<5);
- resizeIfNeeded(na+nb);
- nc=combineLists(a,na,b,nb,c);
-
- extractCenterCells(CellList, n, c);
-
- n=nextGen(c, nc, CellList, g);
-
- generations++;
- }
-
- /**
- * load a new initial image
- * @param img - the image to load
- * @param imgobs - the image observer
- */
- public boolean loadLifePattern(Image img, ImageObserver imgobs) {
-
- int w=img.getWidth(imgobs);
- int h=img.getHeight(imgobs);
-
- if (w<0 || h<0) return false;
-
- originx= (displaywidth-w*2)/2;
- originy= (displayheight-h*2)/2;
-
- int[] pixels = new int[w * h];
-
- PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pixels, 0, w);
-
- try {
- pg.grabPixels();
- } catch (InterruptedException e) {
- return false;
- }
-
- int i,j;
-
- int pix0= pixels[0];
- int pix1= -1;
- int count1= 0;
-
- for (i=0; i<h; i++) {
- for (j=0; j<w; j++) {
- if (pixels[i*w+j]!=pix0) {
- pix1= pixels[i*w+j];
- count1++;
- }
- }
- }
-
- /* figure out which pixel color denotes a live cell */
-
- if (pix0==0xffffff) {}
- else if (pix1==0xffffff || count1 > w*h-count1) {
- pix1=pix0;
- count1=w*h-count1;
- }
-
- resizeIfNeeded(count1);
-
- n=0;
- for (i=0; i<h; i++) {
- for (j=0; j<w; j++) {
- if (pixels[i*w+j]==pix1) {
- CellList[n++]=Cell(j,i,2);
- }
- }
- }
-
- return true;
- }
- }
-
- /*
- * the applet class
- */
- public class LifeApp extends java.applet.Applet implements MouseListener,
- ActionListener, Runnable {
-
- LifeGenerator LifeList;
-
- /*
- * the thread controlling generations
- */
- Thread killme=null;
- int speed=50;
- boolean neverPainted=true;
- int count=0;
-
- /*
- * the image name text field
- */
- TextField patfield;
- Button pausebutton;
- Button stepbutton;
- Button recenterbutton;
- Button loadbutton;
- boolean generating=false;
- int stepsleft=0;
- int scrollfraction=5;
-
- /*
- * called when applet is loaded
- * create user interface and parse applet parameters
- */
- public void init() {
-
- setLayout(new FlowLayout(FlowLayout.RIGHT, 0, getSize().height-30));
- add(pausebutton=new Button("Start"));
- add(stepbutton = new Button("Step"));
- add(recenterbutton = new Button("Recenter"));
- add(loadbutton = new Button("Load:"));
-
- pausebutton.addActionListener(this);
- stepbutton.addActionListener(this);
- recenterbutton.addActionListener(this);
- loadbutton.addActionListener(this);
-
- addMouseListener(this);
-
- String patname=getParameter("pattern");
- if (patname==null) patname="gun30";
-
- if (getParameter("started")!=null) {
- pausebutton.setLabel("Stop");
- generating=true;
- }
-
- String pstring;
-
- if ((pstring=getParameter("speed"))!=null) {
- speed=Integer.valueOf(pstring).intValue();
- }
-
- if ((pstring=getParameter("scrollfraction"))!=null) {
- scrollfraction=Integer.valueOf(pstring).intValue();
- }
-
- add(patfield=new TextField(patname,8));
-
- LifeList=null;
- }
-
- /*
- * called when applet is started
- * start the life thread
- */
- public void start() {
-
- if (killme==null) {
- killme=new Thread(this);
- killme.start();
- }
- }
-
- /*
- * called when the applet is stopped
- * stop the life thread
- */
- public void stop() {
-
-
- killme=null;
- }
-
-
- //********************************************************
- public void mouseClicked(MouseEvent e){}
- public void mouseEntered(MouseEvent e){}
- public void mouseExited(MouseEvent e){}
-
- public void mouseReleased(MouseEvent e)
- {
- }
-
- public void mousePressed(MouseEvent e)
- {
- int x =e.getX();
- int y =e.getY();
-
- LifeList.approachcenter(x,y);
- LifeList.paintAll(getGraphics());
- }
-
- /**
- * reorder the images, depending on which button is clicked
- * @param evt - event object
- * @param arg - target object
- */
- public void actionPerformed(ActionEvent evt)
- {
- boolean acted=true;
- boolean damage=true;
-
- Object object1 = evt.getSource();
-
- if (object1 == pausebutton)
- {
- String label= pausebutton.getLabel();
- if (label == "Stop")
- {
- pausebutton.setLabel("Start");
- generating=false;
- } else if (label == "Start")
- {
- pausebutton.setLabel("Stop");
- generating=true;
- }
- }
-
- if (object1 == stepbutton)
- {
- stepsleft=1;
- if (generating)
- {
- pausebutton.setLabel("Start");
- generating=false;
- }
- }
- if (object1 == recenterbutton)
- {
- LifeList.findPattern();
- }
- if (object1 == loadbutton)
- {
- stop();
- LifeList=null;
- start();
- }
- if (acted && damage) LifeList.paintAll(getGraphics());
-
- }
-
-
- //***********************************************************
-
-
- /**
- * add .gif to the filename
- * @param patname - base filename
- */
- static String makeGifName(String patname) {
-
- int i=patname.indexOf(".");
- String base=(i<0)?patname:patname.substring(0,i);
- return base.concat(".gif");
- }
-
- /**
- * load new image file
- * @parame patname - name of image file
- */
- void loadNew(String patname) {
-
- Image img=getImage(getCodeBase(), makeGifName(patname));
- LifeList.loading(patname);
- LifeList.paintAll(getGraphics());
-
- while(killme!=null && !LifeList.loadLifePattern(img,
- σthis)) {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {}
- }
-
- LifeList.loading(null);
- LifeList.paintAll(getGraphics());
- }
-
- /*
- * life thread
- * causes new generations to be created
- */
- public void run() {
-
- Graphics g=getGraphics();
-
- if (LifeList==null) {
- LifeList = new LifeGenerator();
- LifeList.setColors(getBackground(), Color.black);
- LifeList.setScroll(scrollfraction);
- LifeList.setDisplaySize(getSize().width, getSize().height);
- loadNew(patfield.getText());
- }
-
- while (killme != null) {
- try {
- Thread.sleep(speed);
- } catch (InterruptedException e) {}
- repaint();
- }
- killme=null;
- }
-
- /**
- * paint the current generation
- * @param g - destination graphics object
- */
- public void paint(Graphics g) {
-
- LifeList.paintAll(g);
- }
-
- /**
- * override update to avoid erase flicker
- * @param g - destination graphics object
- */
- public void update(Graphics g) {
-
- if (generating || stepsleft- > 0) {
- LifeList.generate(g);
- LifeList.updateStatusLine(g);
- }
- }
- }
-