"Game" of Life

Here’s a fun little example app. It’s Conway’s Game of Life. Each cell is rendered as a sphere.



You need a file named life_rules.txt to set the properties:


width=100
height=100
texture=tri2.jpg

#divergent gliders
#rows=5
#row0=111110000001000
#row1=100001000100010
#row2=100000000000001
#row3=010001000100001
#row4=000100000011111

#star
rows=5
row0=10101
row1=10001
row2=10001
row3=10001
row4=10101



And here is the code for it:


import java.io.*;
import java.util.Properties;
import java.util.Enumeration;

import com.jme.app.SimpleGame;
import com.jme.bounding.*;
import com.jme.math.Vector3f;
import com.jme.scene.shape.*;
import com.jme.scene.state.*;
import com.jme.util.*;
import com.jme.image.*;
import com.jme.scene.*;
import com.jme.renderer.ColorRGBA;
import com.jme.input.*;
import com.jme.light.*;

public class Life extends SimpleGame
{
  private Node scene;
  private Vector3f currentPos;
  int width = 100;
  int height = 100;
  int thisData[][] = new int[width][height];
  int nextData[][] = new int[width][height];
  Sphere cells[][] = new Sphere[width][height];
  TextureState ts = null;
  Timer timer = null;
  float lastTime = -3.0f;

  public static void main(String[] args)
  {
    Life app = new Life();
    app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
    app.start();
  }


  protected void simpleUpdate()
  {
   if(timer.getTimeInSeconds() > lastTime + 1.0f)
   {
        //display
       for(int x=0; x<width; x++){for(int y=0; y<height; y++){
        if(thisData[x][y] == 0)
        {
          if(cells[x][y] != null){scene.detachChild(cells[x][y]); cells[x][y] = null;}
        }
        else
        {
          if(cells[x][y] == null)
         {
           Sphere s1 = new Sphere("Sphere", new Vector3f(x*2 - width, y*2 - height, -20), 10, 10, 1);
           cells[x][y] = s1;
             s1.setModelBound(new BoundingBox());
             s1.updateModelBound();
             s1.setRenderState(ts);
           s1.updateRenderState();
             scene.attachChild(s1);
         }
        }
      }}
      
      //update
       for(int x=1; x<width-1; x++){for(int y=1; y<height-1; y++){
        int nbrAround = thisData[x-1][y-1] + thisData[x][y-1] + thisData[x+1][y-1] +
                       thisData[x-1][y] + thisData[x+1][y] +
                     thisData[x-1][y+1] + thisData[x][y+1] + thisData[x+1][y+1];
        if(thisData[x][y] == 0)
        {
           if(nbrAround == 3)
         {
           nextData[x][y] = 1;
         }
         else
         {
           nextData[x][y] = 0;
         }
        }
        else
        {
          if(nbrAround < 2 || nbrAround > 3)
         {
           nextData[x][y] = 0;
         }
         else
         {
           nextData[x][y] = 1;
         }
        }
      }}
      
       for(int x=1; x<width-1; x++){for(int y=1; y<height-1; y++){
        thisData[x][y] = nextData[x][y];
      }}
      lastTime = timer.getTimeInSeconds();
   }
  }

  protected void simpleInitGame()
  {
    display.setTitle("3D Life");

   scene = new Node("3D Life");
   
   timer = Timer.getTimer(properties.getRenderer());

    PropertyReader properties = new PropertyReader("life_rules.txt");
   width = Integer.parseInt(properties.getProperty("width"));
   height = Integer.parseInt(properties.getProperty("height"));
    thisData = new int[width][height];
    nextData = new int[width][height];
    cells = new Sphere[width][height];

    //initializes
    for(int x=0; x<width; x++){for(int y=0; y<height; y++){
     thisData[x][y] = 0;
     nextData[x][y] = 0;
   }}

   String texture = properties.getProperty("texture");
   
   int rows = Integer.parseInt(properties.getProperty("rows"));
   int maxWidth = 0;
   int thisWidth = 0;
   for(int r=0; r<rows; r++)
   {
      thisWidth = properties.getProperty("row" + r).length();
      if(thisWidth > maxWidth){maxWidth = thisWidth;}
   }
   int xOffset = width/2 - maxWidth;
   int yOffset = height/2 - rows;
   for(int r=0; r<rows; r++)
   {
      String row = properties.getProperty("row" + r);
      thisWidth = row.length();
      for(int c=0; c<thisWidth; c++)
      {
        if(row.charAt(c) == '0'){thisData[xOffset + c][yOffset + r] = 0;}
        else{thisData[xOffset + c][yOffset + r] = 1;}
      }
   }


    ts = display.getRenderer().getTextureState();
    ts.setEnabled(true);

    ts.setTexture(
        TextureManager.loadTexture(
        Life.class.getClassLoader().getResource(
        texture),
        Texture.MM_LINEAR,
        Texture.FM_LINEAR,
        true));
    

    rootNode.attachChild(scene);
   

   CullState cs = display.getRenderer().getCullState();
   cs.setCullMode(CullState.CS_BACK);
   cs.setEnabled(true);
   rootNode.setRenderState(cs);
  }
}





class PropertyReader
{
   private Properties properties;
   
   public PropertyReader(String file)
   {
      try
      {
         properties = new Properties();
         FileInputStream propFile = new FileInputStream(file);
         properties.load(propFile);
         propFile.close();
      }
      catch(Exception e){e.printStackTrace();}
   }

   public String getProperty(String key)
   {
      return (String)properties.getProperty(key);
   }
   
   public Enumeration propertyNames()
   {
      return properties.propertyNames();
   }
}

Very cool! That’s quite interesting to watch. I did find one line you need to add to the update so that newly added nodes are properly updated with the states. That is, so the new spheres get the lighting and texture, etc.



if you put a call to rootNode.updateRenderState() after you are done adding the new spheres it will keep everything looking good.



I’d love to put that as part of the example demos, perhaps linking off the page. With full credit to you of course. Let me know if you are interested.

OK, thanks for letting me know about that line of code to add.



Please feel free to add that code to the demos.

Interesting little game using JME and does work pretty fast. One thing though, it doesnt seem to have a depth as such. The spehere’s seem a bit 2D (even after I addeded Mojo’s code fix) or may be its my eyes.



tomcat

What do you mean they look 2D? Are you not getting the light shading? The suggested fix should have fixed that issue. If not, describe what it looks like and perhaps it can be worked out.

Ok, I have a screenshot of the game, but I dont seem to figure how to put the image into the body of this message. Any suggestions?

tomcat

I have emailed you the screenshot now as I didnt figure out how to attach it to the message. What do you think?

tomcat,

Your screenshot looked correct. Looks 3D to me :slight_smile:

8-O, Ok we’ll have my eyes examined tomorrow.

tomcat