// Generation of fractle mountains // // Author Matthew Caryl // Created 6.4.97 // // Although under copywrite to the author (Matthew Caryl) this code can be copied and modified for non-commercial // purposes as long as any derivatives contain this condition. package Mountains; import java.awt.Color; import java.awt.Button; import java.awt.Image; import java.awt.Event; import java.awt.Panel; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.FlowLayout; import java.awt.BorderLayout; import ADT.Random; import ADT.Vector; import ADT.Entity; import ADT.Camera; import ADT.Universe; import ADT.Light; import java.applet.Applet; import java.lang.Runnable; public final class World extends Applet { // // Private interface // private Graphics graphics; private Random random = new Random(); private Button triangle_button; private Button square_button; private Button hexagon_button; private Camera camera; private Universe world; private Light light; private Image image; private Graphics igraphics; private FloorPlan mountain; private Entity current; // camera back to starting position private void resetCamera() { camera.moveTo(0f, 0f, 200f); camera.turnTo(0f, 0f, 0f); world.clear(igraphics, Color.black); world.render(igraphics); paint(graphics); } // camera moved in world coordinates private void moveCamera(float x, float y, float z) { camera.moveBy(x, y, z); world.clear(igraphics, Color.black); world.render(igraphics); paint(graphics); } // camera turned in world coordinates private void turnCamera(float x, float y, float z) { camera.turnBy(x, y, z); world.clear(igraphics, Color.black); world.render(igraphics); paint(graphics); } // just display new image private void renderCamera() { world.clear(igraphics, Color.black); world.render(igraphics); paint(graphics); } // // Public world interface // // set up control panel public void init() { Panel controls = new Panel(); controls.setBackground(Color.black); controls.setLayout(new GridLayout(1, 3, 5, 5)); triangle_button = new Button("Triangle"); triangle_button.setBackground(Color.white); controls.add(triangle_button); square_button = new Button("Square"); square_button.setBackground(Color.white); controls.add(square_button); hexagon_button = new Button("Hexagon"); hexagon_button.setBackground(Color.white); controls.add(hexagon_button); Panel align = new Panel(); align.setBackground(Color.black); align.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); align.add(controls); this.setLayout(new BorderLayout()); this.add("South", align); // save graphics context for later // note: this seems to reduce garbage collection problems graphics = this.getGraphics(); String mountain_type = this.getParameter("floorPlan"); if ("square".equals(mountain_type)) mountain = new Square(random, 0f, 0f, 0f, 200f, 0.5f); else if ("hexagon".equals(mountain_type)) mountain = new Hexagon(random, 0f, 0f, 0f, 200f, 0.5f); else mountain = new Triangle(random, 0f, 0f, 0f, 200f, 0.5f); current = mountain.getObject(); // prepare world with light and camera light = new Light(0.1f, 0.9f); camera = new Camera(200f); world = new Universe(size().width, size().height, camera, light); light.moveTo(300f, 300f, 500f); world.addEntity(current); image = this.createImage(size().width, size().height); igraphics = image.getGraphics(); resetCamera(); requestFocus(); } // get rid of graphics and thread public void destroy() { if (graphics != null) graphics.dispose(); if (igraphics != null) igraphics.dispose(); super.destroy(); } // display either black or rendered image public void paint(Graphics g) { if (image == null) { g.setColor(Color.black); g.fillRect(0, 0, size().width, size().height); } else g.drawImage(image, 0, 0, this); } // movement or turning by keyboard // space resets camera position // return increases detail of model public boolean keyDown(Event e, int key) { float a = 0f, b = 0f, c = 0f; switch (key) { case Event.UP: case '8': b = -1f; break; case Event.DOWN: case '2': b = 1f; break; case Event.LEFT: case '4': a = -1f; break; case Event.RIGHT: case '6': a = 1f; break; case Event.PGUP: case '7': c = 1f; break; case Event.PGDN: case '1': c = -1f; break; case ' ': resetCamera(); return true; case '\n': mountain.recurse(random); world.subEntity(current); current = mountain.getObject(); world.addEntity(current); renderCamera(); return true; default: return false; } if (!e.shiftDown()) moveCamera(10f * a, 10f * b, 10f * c); else turnCamera(-0.03f * b, -0.03f * a, 0.03f * c); return true; } // generate new model of appropriate type public boolean handleEvent(Event e) { if (e.id == Event.ACTION_EVENT) { if (e.target == triangle_button) { mountain = new Triangle(random, 0f, 0f, 0f, 400f, 0.5f); world.subEntity(current); current = mountain.getObject(); world.addEntity(current); renderCamera(); return true; } if (e.target == square_button) { mountain = new Square(random, 0f, 0f, 0f, 400f, 0.5f); world.subEntity(current); current = mountain.getObject(); world.addEntity(current); renderCamera(); return true; } if (e.target == hexagon_button) { mountain = new Hexagon(random, 0f, 0f, 0f, 400f, 0.5f); world.subEntity(current); current = mountain.getObject(); world.addEntity(current); renderCamera(); return true; } } return super.handleEvent(e); } public String[][] getParameterInfo() { String[][] info = {{"floorPlan", "triangle/square/hexagon", "floor type to start with"}}; return info; } } // floor plan will define how the mountain is made abstract class FloorPlan { abstract public void recurse(Random R); abstract public int getSize(); abstract public Entity getObject(); }