// Setup the width and height we'll be using for the simulation. // We're doing this as final int values because we use these values // in a few places throughout the code final int W = 600; final int H = 400; // Set the scale of the grid we'll overlay on the screen for the Creatures to // use as part of their DNA final int gridscale = 24; // The calculated DNA length final int DNASIZE = (W / gridscale) * (H / gridscale); // How many cycles does the animation run per generation final int lifetime = 150; // global speed controls float maxspeed = 8.0f; float maxforce = 1.0f; // Our creature population Population pop; // Current step in the lifetime int lifeCycle; // Fastest time a creature has reached the target int recordTime; // The start and target points for the creatures Vector3D target; Vector3D start; // The diameter of the target float diam = 24.0f; // Our font PFont f; // Our obstacles on the screen ArrayList obstacles; void setup() { // setup the environment //size(W, H); size(600, 400); colorMode(RGB, 255, 255, 255, 100); smooth(); f = loadFont("CourierNewPS-BoldMT-16.vlw"); // initailize our control variables lifeCycle = 0; recordTime = lifetime; target = new Vector3D(width - diam, height / 2, 0); start = new Vector3D(diam, height / 2, 0); // Create a population with our mutation rate, and max population int popMax = 2000; float mutationRate = 0.05f; pop = new Population(mutationRate, popMax); // Create our obstacles obstacles = new ArrayList(); // We use this array of numbers (0/7, 1/7, 2/7, ... 7/7) to place our // obstacles on screen float[] fracs = {0.0, 0.142, 0.285, 0.428, 0.571, 0.714, 0.857, 1.0}; // Create 4 columns of barriers for (int cols = 0; cols < 4; cols++) { // For each column we'll be drawing a certain // number of barriers, using the 'offset' to determine // where in the fracs array we start looking for // values to position our Obstacles. int offset = cols % 2; int rowCount = 0; if (offset == 1) { rowCount = 3; } else { rowCount = 4; } // Draw the barriers in our column. There will be either // 3 or 4 obstacles in each column. for (int rows = 0; rows < rowCount; rows++) { // Get the number describing the top of our barrier float top = fracs[rows * 2 + offset]; // get the number describing the bottom of our barrier float bottom = fracs[rows * 2 + 1 + offset]; // We create an Obstacle with four values, each between 0 and 1, // describing what percentage of the screen the barrier is covering // 0.2 * cols + 0.2 -> the horizontal position of the barrier // top -> the vertical position of the barrier // 0.03 obstacles.add(new Obstacle(0.2 * cols + 0.2, top, 0.03, 0.142)); } } } void draw() { // clear the screen background(0); // Draw the start and end points ellipseMode(CENTER); noStroke(); fill(0, 100, 200); ellipse(start.getX(), start.getY(), diam, diam); ellipse(target.getX(), target.getY(), diam, diam); // Draw the obstacles for (int i = 0; i < obstacles.size(); i++) { Obstacle o = (Obstacle)obstacles.get(i); o.render(); } // Check if the lifeCycle has count down yet if (lifeCycle < lifetime) { // run the creatures pop.simulate(obstacles); // see if anyone has reached the target if ( (pop.targetReached()) && (lifeCycle < recordTime) ) { recordTime = lifeCycle; } lifeCycle++; } else { // New generation lifeCycle = 0; pop.calcFitness(); pop.naturalSelection(); pop.generate(); } // showGrid(); // draw our information display textFont(f); fill(255); textAlign(RIGHT); text("Generation #" + pop.getGenerations(), width - 10, 18); text("Time Left: " + (lifetime - lifeCycle), width - 10, 36); text("Record Time: " + recordTime, width - 10, 54); } void mousePressed() { // move our target to a new position target = new Vector3D(mouseX, mouseY, 0); // reset the recordTime to maximum recordTime = lifetime; } void showGrid() { for (int x = 0; x < gridscale; x++) { for (int y = 0; y < gridscale; y++) { set((W / gridscale) * x + gridscale, (H / gridscale) * y + gridscale, color(255, 0, 0)); } } }