import java.awt.Font; import java.util.ArrayList; import java.util.TimerTask; import java.util.Timer; import keel.runtime.Application; import keel.runtime.KeelRuntime; import keel.runtime.event.KeyEvent; import keel.runtime.event.KeyAdapter; import keel.gfx.GLGraphics; import keel.gfx.GLConstants; import keelx.gfx.font.SystemFont; public class Life implements Application { private int width = 640; private int height = 480; public static int size = 50; private Camera camera; private Light light; private Timer timer; private LifeTree lifeTree; private Object monitor = new Object(); private Material target; public Life() { target = new Material(size/2, size/2, 0); camera = new Camera(size*2, size*2, size*20, width / (double) height, 10, target); light = new Light(size, size, size * 10); lifeTree = new LifeTree(size); timer = new Timer(true); timer.schedule(new TimerTask() { public void run() { synchronized (monitor) { step(); } } }, 0, 500); timer.schedule(new TimerTask() { public void run() { synchronized (monitor) { light.rotate(); camera.rotate(); } } }, 0, 100); } private void step() { lifeTree.step(); light.step(); camera.step(); target.setZ(target.getZ() + 2); } public void keelMain(KeelRuntime runtime,String argv[]) { runtime.createWindow("", width, height); runtime.createGraphicsWithDefaultPixelFormat(); runtime.addKeyListener(new Controller()); runtime.run(); } public void initGraphics(GLGraphics g) { g.glViewport(0, 0, width, height); g.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); g.glEnable(GLConstants.GL_BLEND); g.glBlendFunc(GLConstants.GL_SRC_ALPHA, GLConstants.GL_ONE_MINUS_SRC_ALPHA); } public void update(GLGraphics g) { synchronized (monitor) { g.glClear(GLConstants.GL_COLOR_BUFFER_BIT | GLConstants.GL_DEPTH_BUFFER_BIT); g.glPushMatrix(); int[] enables = { GLConstants.GL_DEPTH_TEST, GLConstants.GL_LIGHTING, GLConstants.GL_CULL_FACE, }; for (int i = 0; i < enables.length; i++) { g.glEnable(enables[i]); } g.glMatrixMode(GLConstants.GL_PROJECTION); g.glLoadIdentity(); camera.update(g); g.glMatrixMode(GLConstants.GL_MODELVIEW); g.glLoadIdentity(); g.glPushMatrix(); light.update(g); g.glPopMatrix(); g.glPushMatrix(); lifeTree.update(g); g.glPopMatrix(); for (int i = enables.length - 1; i >= 0; i--) { g.glDisable(enables[i]); } g.glPopMatrix(); } } public void quitRequested() { KeelRuntime.getRuntime().disposeDisplay(); System.exit(0); } class Controller extends KeyAdapter { public void keyPressed(KeyEvent ev) { switch (ev.getKeyCode()) { case KeyEvent.VK_Q: System.exit(0); break; default: break; } } } } class LifeTree { public LifeTree(int aSize) { size = aSize; boolean[][] cells = new boolean[size][size]; for (int i = size / 3; i < 2*size/3; i++) { for (int j = size / 3; j < 2*size/3; j++) { cells[i][j] = (Math.random() > 0.5); } } tree.add(cells); } public void step() { boolean[][] cells = new boolean[size][size]; boolean[][] top = (boolean[][]) tree.get(tree.size() - 1); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { int l = i - 1 < 0 ? 1 : i - 1; int r = i + 1 >= size ? size - 2 : i + 1; int u = j - 1 < 0 ? 1 : j - 1; int d = j + 1 >= size ? size - 2 : j + 1; int count = (top[l][u] ? 1 : 0) + (top[i][u] ? 1 : 0) + (top[r][u] ? 1 : 0) + (top[l][j] ? 1 : 0) + + (top[r][j] ? 1 : 0) + (top[l][d] ? 1 : 0) + (top[i][d] ? 1 : 0) + (top[r][d] ? 1 : 0); cells[i][j] = count == 3 || (count == 2 && top[i][j]); } } tree.add(cells); } public void update(GLGraphics g) { for (int i = tree.size() - 1; i >= 0; i--) { boolean[][] cells = (boolean[][]) tree.get(i); for (int j = 0; j < size; j++) { for (int k = 0; k < size; k++) { if (cells[j][k]) { g.glPushMatrix(); new Cube(j*2, k*2, i*2).update(g); g.glPopMatrix(); } } } } } private ArrayList tree = new ArrayList(); private int size; } class Light extends Material { public Light(int x, int y, int z) { super(x, y, z); radius = getX(); } private double radius = 10; private double angle = 0; private float[] ambient = {0.0f, 0.0f, 0.0f, 1.0f}; private float[] diffuse = {1.0f, 1.0f, 1.0f, 1.0f}; private float[] specular = {1.0f, 1.0f, 1.0f, 1.0f}; public void update(GLGraphics g) { g.glLightModeli(GLConstants.GL_LIGHT_MODEL_TWO_SIDE, 1); int light = GLConstants.GL_LIGHT0; g.glLightfv(light, GLConstants.GL_AMBIENT, ambient); g.glLightfv(light, GLConstants.GL_DIFFUSE, diffuse); g.glLightfv(light, GLConstants.GL_SPECULAR, specular); g.glLightfv(light, GLConstants.GL_POSITION, new float[]{getX(), getY(), getZ(), 1f}); g.glEnable(light); } public void step() { setZ(getZ() + getSpeed()); } public void rotate() { angle -= getSpeed(); setX((int) (radius * Math.cos(Math.toRadians(angle)))); setY((int) (radius * Math.sin(Math.toRadians(angle)))); } } class Camera extends Material { public Camera(int x, int y, int z, double anAspectRatio, int aViewAngle, Material aTarget) { super(x, y, z, 1); target = aTarget; aspectRatio = anAspectRatio; viewAngle = aViewAngle; radius = getX() * 2; } private Material target; private double aspectRatio; private int viewAngle; int angle = 0; int radius; public void setTarget(Material aTarget) { target = aTarget; } public void update(GLGraphics g) { g.gluPerspective(viewAngle, aspectRatio, 1.0d, getZ()*10); g.gluLookAt( getX(), getY(), getZ(), target.getX(), target.getY(), target.getZ(), 0, 0, 1); } public void narrower() { viewAngle--; } public void wider() { viewAngle++; } public String toString() { return "View angle:" + viewAngle + " at: (" + getX() + "," + getY() + "," + getZ() + ") target: (" + target.getX() + "," + target.getY() + "," + target.getZ() + ")"; } public void step() { setZ(getZ() + getSpeed()); } public void rotate() { angle += getSpeed(); setX((int) (radius * Math.cos(Math.toRadians(angle))) - radius / 2); setY((int) (radius * Math.sin(Math.toRadians(angle))) - radius / 2); } } class Cube extends Material { public Cube(int x, int y, int z) { super(x, y, z); } public Cube() { super(0, 0, 0); } private double width = 1d; private static double[][] vertexList = { { -1, -1, -1}, { +1, -1, -1}, { +1, +1, -1}, { -1, +1, -1}, { -1, -1, +1}, { +1, -1, +1}, { +1, +1, +1}, { -1, +1, +1}, }; private static int[][] faceList = { {0, 3, 2, 1}, {1, 2, 6, 5}, {5, 6, 7, 4}, {4, 7, 3, 0}, {4, 0, 1, 5}, {3, 7, 6, 2}, }; private static double[][] normalList = { {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 1.0, 0.0}, }; float[] color = { 1.0f, 0.1f, 0.1f, 1.0f }; float[] diffuse = { 0.8f, 0.8f, 0.8f, 1.0f }; float[] specular = { 0.0f, 0.0f, 0.0f, 1.0f }; float[] ambient = { 0.2f, 0.2f, 0.2f, 1.0f }; float[] emission = { 0.0f, 0.0f, 0.0f, 1.0f }; float shininess = 0.0f; public void update(GLGraphics g) { g.glTranslated(getX(), getY(), getZ()); g.glScaled(width, width, width); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_DIFFUSE, color); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_AMBIENT, color); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_SPECULAR, specular); g.glMaterialfv(GLConstants.GL_FRONT, GLConstants.GL_EMISSION, emission); g.glMaterialf(GLConstants.GL_FRONT, GLConstants.GL_SHININESS, shininess); g.glBegin(GLConstants.GL_QUADS); for (int i = 0; i < faceList.length; i++) { int[] face = faceList[i]; g.glNormal3dv(normalList[i]); for (int j = 0; j < face.length; j++) { int vertexIndex = face[j]; g.glVertex3dv(vertexList[vertexIndex]); } } g.glEnd(); } public String toString() { return "Cube at: (" + getX() + "," + getY() + "," + getZ() + ") width: " + width; } } class Material { public Material(int aX, int aY, int aZ) { this(aX, aY, aZ, 2); } public Material(int aX, int aY, int aZ, int aSpeed) { x = aX; y = aY; z = aZ; speed = aSpeed; } private int x = 0; private int y = 0; private int z = 0; private int speed = 2; public void setX(int newX) { x = newX; } public void setY(int newY) { y = newY; } public void setZ(int newZ) { z = newZ; } public int getX() { return x; } public int getY() { return y; } public int getZ() { return z; } public int getSpeed() { return speed; } public void right() { x += speed; } public void left() { x -= speed; } public void forward() { y += speed; } public void backward() { y -= speed; } public void up() { z += speed; } public void down() { z -= speed; } public void update(GLGraphics g) { } }